xref: /titanic_52/usr/src/uts/intel/io/pit_beep.c (revision 193974072f41a843678abf5f61979c748687e66b)
1c35aa225Smarx /*
2c35aa225Smarx  * CDDL HEADER START
3c35aa225Smarx  *
4c35aa225Smarx  * The contents of this file are subject to the terms of the
5c35aa225Smarx  * Common Development and Distribution License (the "License").
6c35aa225Smarx  * You may not use this file except in compliance with the License.
7c35aa225Smarx  *
8c35aa225Smarx  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c35aa225Smarx  * or http://www.opensolaris.org/os/licensing.
10c35aa225Smarx  * See the License for the specific language governing permissions
11c35aa225Smarx  * and limitations under the License.
12c35aa225Smarx  *
13c35aa225Smarx  * When distributing Covered Code, include this CDDL HEADER in each
14c35aa225Smarx  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c35aa225Smarx  * If applicable, add the following below this CDDL HEADER, with the
16c35aa225Smarx  * fields enclosed by brackets "[]" replaced with your own identifying
17c35aa225Smarx  * information: Portions Copyright [yyyy] [name of copyright owner]
18c35aa225Smarx  *
19c35aa225Smarx  * CDDL HEADER END
20c35aa225Smarx  */
21c35aa225Smarx /*
22613b2871SRichard Bean  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23c35aa225Smarx  * Use is subject to license terms.
24c35aa225Smarx  */
25c35aa225Smarx 
26c35aa225Smarx /*
27c35aa225Smarx  * Simple beeper support for PC platform, using standard timer 2 beeper.
28c35aa225Smarx  */
29c35aa225Smarx 
30c35aa225Smarx #include <sys/types.h>
31c35aa225Smarx #include <sys/conf.h>
32c35aa225Smarx #include <sys/beep.h>
33c35aa225Smarx #include <sys/ksynch.h>
34c35aa225Smarx #include <sys/ddi.h>
35c35aa225Smarx #include <sys/sunddi.h>
36c35aa225Smarx #include <sys/modctl.h>
37c35aa225Smarx #include <sys/pit.h>
38c35aa225Smarx #include <sys/inttypes.h>
39c35aa225Smarx 
40c35aa225Smarx #define	PIT_BEEP_UNIT(dev)	(getminor((dev)))
41c35aa225Smarx 
42c35aa225Smarx typedef struct pit_beep_state {
43c35aa225Smarx 	/* Dip of pit_beep device */
44c35aa225Smarx 	dev_info_t	*dip;
45c35aa225Smarx 
46c35aa225Smarx } pit_beep_state_t;
47c35aa225Smarx 
48c35aa225Smarx #define	PIT_BEEP_ON	1
49c35aa225Smarx #define	PIT_BEEP_OFF	0
50c35aa225Smarx 
51c35aa225Smarx /* Pointer to the state structure */
52c35aa225Smarx static void *pit_beep_statep;
53c35aa225Smarx 
54c35aa225Smarx static int pit_beep_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
55c35aa225Smarx static int pit_beep_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
56c35aa225Smarx static int pit_beep_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
57c35aa225Smarx     void *arg, void **result);
58c35aa225Smarx static void pit_beep_freq(void *arg, int freq);
59c35aa225Smarx static void pit_beep_on(void *arg);
60c35aa225Smarx static void pit_beep_off(void *arg);
61c35aa225Smarx 
62c35aa225Smarx struct cb_ops pit_beep_cb_ops = {
63c35aa225Smarx 	nulldev,	/* open  */
64c35aa225Smarx 	nulldev,	/* close */
65c35aa225Smarx 	nulldev,	/* strategy */
66c35aa225Smarx 	nulldev,	/* print */
67c35aa225Smarx 	nulldev,	/* dump */
68c35aa225Smarx 	nulldev,	/* read */
69c35aa225Smarx 	nulldev,	/* write */
70c35aa225Smarx 	nulldev,	/* ioctl */
71c35aa225Smarx 	nulldev,	/* devmap */
72c35aa225Smarx 	nulldev,	/* mmap */
73c35aa225Smarx 	nulldev,	/* segmap */
74c35aa225Smarx 	nochpoll,	/* poll */
75c35aa225Smarx 	ddi_prop_op,	/* cb_prop_op */
76c35aa225Smarx 	NULL,		/* streamtab  */
77c35aa225Smarx 	D_MP | D_NEW
78c35aa225Smarx };
79c35aa225Smarx 
80c35aa225Smarx 
81c35aa225Smarx static struct dev_ops pit_beep_ops = {
82c35aa225Smarx 	DEVO_REV,		/* Devo_rev */
83c35aa225Smarx 	0,			/* Refcnt */
84c35aa225Smarx 	pit_beep_info,		/* Info */
85c35aa225Smarx 	nulldev,		/* Identify */
86c35aa225Smarx 	nulldev,		/* Probe */
87c35aa225Smarx 	pit_beep_attach,	/* Attach */
88c35aa225Smarx 	pit_beep_detach,	/* Detach */
89c35aa225Smarx 	nodev,			/* Reset */
90c35aa225Smarx 	&pit_beep_cb_ops,	/* Driver operations */
91c35aa225Smarx 	0,			/* Bus operations */
92*19397407SSherry Moore 	NULL,			/* Power */
93*19397407SSherry Moore 	ddi_quiesce_not_needed,		/* quiesce */
94c35aa225Smarx };
95c35aa225Smarx 
96c35aa225Smarx 
97c35aa225Smarx static struct modldrv modldrv = {
98c35aa225Smarx 	&mod_driverops, 		/* This one is a driver */
99613b2871SRichard Bean 	"Intel Pit_beep Driver",	/* Name of the module. */
100c35aa225Smarx 	&pit_beep_ops,			/* Driver ops */
101c35aa225Smarx };
102c35aa225Smarx 
103c35aa225Smarx 
104c35aa225Smarx static struct modlinkage modlinkage = {
105c35aa225Smarx 	MODREV_1, (void *)&modldrv, NULL
106c35aa225Smarx };
107c35aa225Smarx 
108c35aa225Smarx 
109c35aa225Smarx 
110c35aa225Smarx int
111c35aa225Smarx _init(void)
112c35aa225Smarx {
113c35aa225Smarx 	int error;
114c35aa225Smarx 
115c35aa225Smarx 	/* Initialize the soft state structures */
116c35aa225Smarx 	if ((error = ddi_soft_state_init(&pit_beep_statep,
117c35aa225Smarx 	    sizeof (pit_beep_state_t), 1)) != 0) {
118c35aa225Smarx 
119c35aa225Smarx 		return (error);
120c35aa225Smarx 	}
121c35aa225Smarx 
122c35aa225Smarx 	/* Install the loadable module */
123c35aa225Smarx 	if ((error = mod_install(&modlinkage)) != 0) {
124c35aa225Smarx 		ddi_soft_state_fini(&pit_beep_statep);
125c35aa225Smarx 	}
126c35aa225Smarx 
127c35aa225Smarx 	return (error);
128c35aa225Smarx }
129c35aa225Smarx 
130c35aa225Smarx 
131c35aa225Smarx int
132c35aa225Smarx _info(struct modinfo *modinfop)
133c35aa225Smarx {
134c35aa225Smarx 	return (mod_info(&modlinkage, modinfop));
135c35aa225Smarx }
136c35aa225Smarx 
137c35aa225Smarx int
138c35aa225Smarx _fini(void)
139c35aa225Smarx {
140c35aa225Smarx 	int error;
141c35aa225Smarx 
142c35aa225Smarx 	error = mod_remove(&modlinkage);
143c35aa225Smarx 
144c35aa225Smarx 	if (error == 0) {
145c35aa225Smarx 		/* Release per module resources */
146c35aa225Smarx 		ddi_soft_state_fini(&pit_beep_statep);
147c35aa225Smarx 	}
148c35aa225Smarx 
149c35aa225Smarx 	return (error);
150c35aa225Smarx }
151c35aa225Smarx 
152c35aa225Smarx /*
153c35aa225Smarx  * pit_beep_attach:
154c35aa225Smarx  */
155c35aa225Smarx static int
156c35aa225Smarx pit_beep_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
157c35aa225Smarx {
158c35aa225Smarx 	switch (cmd) {
159c35aa225Smarx 		case DDI_ATTACH:
160c35aa225Smarx 			break;
161c35aa225Smarx 		case DDI_RESUME:
162c35aa225Smarx 
163c35aa225Smarx 			return (DDI_SUCCESS);
164c35aa225Smarx 		default:
165c35aa225Smarx 
166c35aa225Smarx 			return (DDI_FAILURE);
167c35aa225Smarx 	}
168c35aa225Smarx 
169c35aa225Smarx 	pit_beep_off(dip);
170c35aa225Smarx 
171c35aa225Smarx 	(void) beep_init((void *)dip, pit_beep_on, pit_beep_off,
172c35aa225Smarx 	    pit_beep_freq);
173c35aa225Smarx 
174c35aa225Smarx 	/* Display information in the banner */
175c35aa225Smarx 	ddi_report_dev(dip);
176c35aa225Smarx 
177c35aa225Smarx 	return (DDI_SUCCESS);
178c35aa225Smarx }
179c35aa225Smarx 
180c35aa225Smarx 
181c35aa225Smarx /*
182c35aa225Smarx  * pit_beep_detach:
183c35aa225Smarx  */
184c35aa225Smarx /* ARGSUSED */
185c35aa225Smarx static int
186c35aa225Smarx pit_beep_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
187c35aa225Smarx {
188c35aa225Smarx 	switch (cmd) {
189c35aa225Smarx 		case DDI_SUSPEND:
190c35aa225Smarx 
191c35aa225Smarx 			/*
192c35aa225Smarx 			 * If a beep is in progress; fail suspend
193c35aa225Smarx 			 */
194c35aa225Smarx 			if (!beep_busy()) {
195c35aa225Smarx 
196c35aa225Smarx 				return (DDI_SUCCESS);
197c35aa225Smarx 			} else {
198c35aa225Smarx 
199c35aa225Smarx 				return (DDI_FAILURE);
200c35aa225Smarx 			}
201c35aa225Smarx 		default:
202c35aa225Smarx 
203c35aa225Smarx 			return (DDI_FAILURE);
204c35aa225Smarx 	}
205c35aa225Smarx }
206c35aa225Smarx 
207c35aa225Smarx 
208c35aa225Smarx /*
209c35aa225Smarx  * pit_beep_info:
210c35aa225Smarx  */
211c35aa225Smarx /* ARGSUSED */
212c35aa225Smarx static int
213c35aa225Smarx pit_beep_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
214c35aa225Smarx     void *arg, void **result)
215c35aa225Smarx {
216c35aa225Smarx 	dev_t dev;
217c35aa225Smarx 	pit_beep_state_t  *statep;
218c35aa225Smarx 	int instance, error;
219c35aa225Smarx 
220c35aa225Smarx 	switch (infocmd) {
221c35aa225Smarx 	case DDI_INFO_DEVT2DEVINFO:
222c35aa225Smarx 		dev = (dev_t)arg;
223c35aa225Smarx 		instance = PIT_BEEP_UNIT(dev);
224c35aa225Smarx 
225c35aa225Smarx 		if ((statep = ddi_get_soft_state(pit_beep_statep,
226c35aa225Smarx 		    instance)) == NULL) {
227c35aa225Smarx 
228c35aa225Smarx 			return (DDI_FAILURE);
229c35aa225Smarx 		}
230c35aa225Smarx 
231c35aa225Smarx 		*result = (void *)statep->dip;
232c35aa225Smarx 
233c35aa225Smarx 		error = DDI_SUCCESS;
234c35aa225Smarx 		break;
235c35aa225Smarx 	case DDI_INFO_DEVT2INSTANCE:
236c35aa225Smarx 		dev = (dev_t)arg;
237c35aa225Smarx 		instance = PIT_BEEP_UNIT(dev);
238c35aa225Smarx 
239c35aa225Smarx 		*result = (void *)(uintptr_t)instance;
240c35aa225Smarx 
241c35aa225Smarx 		error = DDI_SUCCESS;
242c35aa225Smarx 		break;
243c35aa225Smarx 	default:
244c35aa225Smarx 		error = DDI_FAILURE;
245c35aa225Smarx 
246c35aa225Smarx 	}
247c35aa225Smarx 
248c35aa225Smarx 	return (error);
249c35aa225Smarx }
250c35aa225Smarx 
251c35aa225Smarx 
252c35aa225Smarx /* ARGSUSED */
253c35aa225Smarx static void
254c35aa225Smarx pit_beep_freq(void *arg, int freq)
255c35aa225Smarx {
256c35aa225Smarx 	int counter;
257c35aa225Smarx 
258c35aa225Smarx 	if (freq == 0)
259c35aa225Smarx 		counter = 0;
260c35aa225Smarx 	else {
261c35aa225Smarx 		counter = PIT_HZ / freq;
262c35aa225Smarx 		if (counter > UINT16_MAX)
263c35aa225Smarx 			counter = UINT16_MAX;
264c35aa225Smarx 		else if (counter < 1)
265c35aa225Smarx 			counter = 1;
266c35aa225Smarx 	}
267c35aa225Smarx 
268c35aa225Smarx 	outb(PITCTL_PORT, PIT_C2 | PIT_READMODE | PIT_RATEMODE);
269c35aa225Smarx 	outb(PITCTR2_PORT, counter & 0xff);
270c35aa225Smarx 	outb(PITCTR2_PORT, counter >> 8);
271c35aa225Smarx }
272c35aa225Smarx 
273c35aa225Smarx 
274c35aa225Smarx /* ARGSUSED */
275c35aa225Smarx static void
276c35aa225Smarx pit_beep_on(void *arg)
277c35aa225Smarx {
278c35aa225Smarx 	outb(PITAUX_PORT, inb(PITAUX_PORT) | (PITAUX_OUT2 | PITAUX_GATE2));
279c35aa225Smarx }
280c35aa225Smarx 
281c35aa225Smarx 
282c35aa225Smarx /* ARGSUSED */
283c35aa225Smarx static void
284c35aa225Smarx pit_beep_off(void *arg)
285c35aa225Smarx {
286c35aa225Smarx 	outb(PITAUX_PORT, inb(PITAUX_PORT) & ~(PITAUX_OUT2 | PITAUX_GATE2));
287c35aa225Smarx }
288