xref: /titanic_44/usr/src/uts/common/io/beep.c (revision c35aa225b9ae500f1d14f0d39a94f1eb6cda333d)
1*c35aa225Smarx /*
2*c35aa225Smarx  * CDDL HEADER START
3*c35aa225Smarx  *
4*c35aa225Smarx  * The contents of this file are subject to the terms of the
5*c35aa225Smarx  * Common Development and Distribution License (the "License").
6*c35aa225Smarx  * You may not use this file except in compliance with the License.
7*c35aa225Smarx  *
8*c35aa225Smarx  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*c35aa225Smarx  * or http://www.opensolaris.org/os/licensing.
10*c35aa225Smarx  * See the License for the specific language governing permissions
11*c35aa225Smarx  * and limitations under the License.
12*c35aa225Smarx  *
13*c35aa225Smarx  * When distributing Covered Code, include this CDDL HEADER in each
14*c35aa225Smarx  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*c35aa225Smarx  * If applicable, add the following below this CDDL HEADER, with the
16*c35aa225Smarx  * fields enclosed by brackets "[]" replaced with your own identifying
17*c35aa225Smarx  * information: Portions Copyright [yyyy] [name of copyright owner]
18*c35aa225Smarx  *
19*c35aa225Smarx  * CDDL HEADER END
20*c35aa225Smarx  */
21*c35aa225Smarx /*
22*c35aa225Smarx  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*c35aa225Smarx  * Use is subject to license terms.
24*c35aa225Smarx  */
25*c35aa225Smarx 
26*c35aa225Smarx #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*c35aa225Smarx 
28*c35aa225Smarx /*
29*c35aa225Smarx  * This is the Beep module for supporting keyboard beep for keyboards
30*c35aa225Smarx  * that do not have the beeping feature within themselves
31*c35aa225Smarx  *
32*c35aa225Smarx  */
33*c35aa225Smarx 
34*c35aa225Smarx #include <sys/types.h>
35*c35aa225Smarx #include <sys/conf.h>
36*c35aa225Smarx 
37*c35aa225Smarx #include <sys/ddi.h>
38*c35aa225Smarx #include <sys/sunddi.h>
39*c35aa225Smarx #include <sys/modctl.h>
40*c35aa225Smarx #include <sys/ddi_impldefs.h>
41*c35aa225Smarx #include <sys/kmem.h>
42*c35aa225Smarx 
43*c35aa225Smarx #include <sys/beep.h>
44*c35aa225Smarx #include <sys/inttypes.h>
45*c35aa225Smarx 
46*c35aa225Smarx /*
47*c35aa225Smarx  * Debug stuff
48*c35aa225Smarx  * BEEP_DEBUG used for errors
49*c35aa225Smarx  * BEEP_DEBUG1 prints when beep_debug > 1 and used for normal messages
50*c35aa225Smarx  */
51*c35aa225Smarx #ifdef DEBUG
52*c35aa225Smarx int beep_debug = 0;
53*c35aa225Smarx #define	BEEP_DEBUG(args)	if (beep_debug) cmn_err args
54*c35aa225Smarx #define	BEEP_DEBUG1(args)	if (beep_debug > 1) cmn_err args
55*c35aa225Smarx #else
56*c35aa225Smarx #define	BEEP_DEBUG(args)
57*c35aa225Smarx #define	BEEP_DEBUG1(args)
58*c35aa225Smarx #endif
59*c35aa225Smarx 
60*c35aa225Smarx int beep_queue_size = BEEP_QUEUE_SIZE;
61*c35aa225Smarx 
62*c35aa225Smarx /*
63*c35aa225Smarx  * Note that mutex_init is not called on the mutex in beep_state,
64*c35aa225Smarx  * But assumes that zeroed memory does not need to call mutex_init,
65*c35aa225Smarx  * as documented in mutex.c
66*c35aa225Smarx  */
67*c35aa225Smarx 
68*c35aa225Smarx beep_state_t beep_state;
69*c35aa225Smarx 
70*c35aa225Smarx beep_params_t beep_params[] = {
71*c35aa225Smarx 	{BEEP_CONSOLE,	900,	200},
72*c35aa225Smarx 	{BEEP_TYPE4,	2000,	0},
73*c35aa225Smarx 	{BEEP_DEFAULT,	1000,	200},	/* Must be last */
74*c35aa225Smarx };
75*c35aa225Smarx 
76*c35aa225Smarx 
77*c35aa225Smarx /*
78*c35aa225Smarx  * beep_init:
79*c35aa225Smarx  * Allocate the beep_queue structure
80*c35aa225Smarx  * Initialize beep_state structure
81*c35aa225Smarx  * Called from beep driver attach routine
82*c35aa225Smarx  */
83*c35aa225Smarx 
84*c35aa225Smarx int
beep_init(void * arg,beep_on_func_t beep_on_func,beep_off_func_t beep_off_func,beep_freq_func_t beep_freq_func)85*c35aa225Smarx beep_init(void *arg,
86*c35aa225Smarx     beep_on_func_t beep_on_func,
87*c35aa225Smarx     beep_off_func_t beep_off_func,
88*c35aa225Smarx     beep_freq_func_t beep_freq_func)
89*c35aa225Smarx {
90*c35aa225Smarx 	beep_entry_t *queue;
91*c35aa225Smarx 
92*c35aa225Smarx 	BEEP_DEBUG1((CE_CONT,
93*c35aa225Smarx 	    "beep_init(0x%lx, 0x%lx, 0x%lx, 0x%lx) : start.",
94*c35aa225Smarx 	    (unsigned long) arg,
95*c35aa225Smarx 	    (unsigned long) beep_on_func,
96*c35aa225Smarx 	    (unsigned long) beep_off_func,
97*c35aa225Smarx 	    (unsigned long) beep_freq_func));
98*c35aa225Smarx 
99*c35aa225Smarx 	mutex_enter(&beep_state.mutex);
100*c35aa225Smarx 
101*c35aa225Smarx 	if (beep_state.mode != BEEP_UNINIT) {
102*c35aa225Smarx 		mutex_exit(&beep_state.mutex);
103*c35aa225Smarx 		BEEP_DEBUG((CE_WARN,
104*c35aa225Smarx 		    "beep_init : beep_state already initialized."));
105*c35aa225Smarx 		return (DDI_SUCCESS);
106*c35aa225Smarx 	}
107*c35aa225Smarx 
108*c35aa225Smarx 	queue = kmem_zalloc(sizeof (beep_entry_t) * beep_queue_size,
109*c35aa225Smarx 	    KM_SLEEP);
110*c35aa225Smarx 
111*c35aa225Smarx 	BEEP_DEBUG1((CE_CONT,
112*c35aa225Smarx 	    "beep_init : beep_queue kmem_zalloc(%d) = 0x%lx.",
113*c35aa225Smarx 	    (int)sizeof (beep_entry_t) * beep_queue_size,
114*c35aa225Smarx 	    (unsigned long)queue));
115*c35aa225Smarx 
116*c35aa225Smarx 	if (queue == NULL) {
117*c35aa225Smarx 		BEEP_DEBUG((CE_WARN,
118*c35aa225Smarx 		    "beep_init : kmem_zalloc of beep_queue failed."));
119*c35aa225Smarx 		return (DDI_FAILURE);
120*c35aa225Smarx 	}
121*c35aa225Smarx 
122*c35aa225Smarx 	beep_state.arg = arg;
123*c35aa225Smarx 	beep_state.mode = BEEP_OFF;
124*c35aa225Smarx 	beep_state.beep_freq = beep_freq_func;
125*c35aa225Smarx 	beep_state.beep_on = beep_on_func;
126*c35aa225Smarx 	beep_state.beep_off = beep_off_func;
127*c35aa225Smarx 	beep_state.timeout_id = 0;
128*c35aa225Smarx 
129*c35aa225Smarx 	beep_state.queue_head = 0;
130*c35aa225Smarx 	beep_state.queue_tail = 0;
131*c35aa225Smarx 	beep_state.queue_size = beep_queue_size;
132*c35aa225Smarx 	beep_state.queue = queue;
133*c35aa225Smarx 
134*c35aa225Smarx 	mutex_exit(&beep_state.mutex);
135*c35aa225Smarx 
136*c35aa225Smarx 	BEEP_DEBUG1((CE_CONT, "beep_init : done."));
137*c35aa225Smarx 	return (DDI_SUCCESS);
138*c35aa225Smarx }
139*c35aa225Smarx 
140*c35aa225Smarx 
141*c35aa225Smarx int
beep_fini(void)142*c35aa225Smarx beep_fini(void)
143*c35aa225Smarx {
144*c35aa225Smarx 	BEEP_DEBUG1((CE_CONT, "beep_fini() : start."));
145*c35aa225Smarx 
146*c35aa225Smarx 	(void) beeper_off();
147*c35aa225Smarx 
148*c35aa225Smarx 	mutex_enter(&beep_state.mutex);
149*c35aa225Smarx 
150*c35aa225Smarx 	if (beep_state.mode == BEEP_UNINIT) {
151*c35aa225Smarx 		mutex_exit(&beep_state.mutex);
152*c35aa225Smarx 		BEEP_DEBUG((CE_WARN,
153*c35aa225Smarx 		    "beep_fini : beep_state already uninitialized."));
154*c35aa225Smarx 		return (0);
155*c35aa225Smarx 	}
156*c35aa225Smarx 
157*c35aa225Smarx 	if (beep_state.queue != NULL)
158*c35aa225Smarx 		kmem_free(beep_state.queue,
159*c35aa225Smarx 		    sizeof (beep_entry_t) * beep_state.queue_size);
160*c35aa225Smarx 
161*c35aa225Smarx 	beep_state.arg = (void *)NULL;
162*c35aa225Smarx 	beep_state.mode = BEEP_UNINIT;
163*c35aa225Smarx 	beep_state.beep_freq = (beep_freq_func_t)NULL;
164*c35aa225Smarx 	beep_state.beep_on = (beep_on_func_t)NULL;
165*c35aa225Smarx 	beep_state.beep_off = (beep_off_func_t)NULL;
166*c35aa225Smarx 	beep_state.timeout_id = 0;
167*c35aa225Smarx 
168*c35aa225Smarx 	beep_state.queue_head = 0;
169*c35aa225Smarx 	beep_state.queue_tail = 0;
170*c35aa225Smarx 	beep_state.queue_size = 0;
171*c35aa225Smarx 	beep_state.queue = (beep_entry_t *)NULL;
172*c35aa225Smarx 
173*c35aa225Smarx 	mutex_exit(&beep_state.mutex);
174*c35aa225Smarx 
175*c35aa225Smarx 	BEEP_DEBUG1((CE_CONT, "beep_fini() : done."));
176*c35aa225Smarx 
177*c35aa225Smarx 	return (0);
178*c35aa225Smarx }
179*c35aa225Smarx 
180*c35aa225Smarx 
181*c35aa225Smarx int
beeper_off(void)182*c35aa225Smarx beeper_off(void)
183*c35aa225Smarx {
184*c35aa225Smarx 	BEEP_DEBUG1((CE_CONT, "beeper_off : start."));
185*c35aa225Smarx 
186*c35aa225Smarx 	mutex_enter(&beep_state.mutex);
187*c35aa225Smarx 
188*c35aa225Smarx 	if (beep_state.mode == BEEP_UNINIT) {
189*c35aa225Smarx 		mutex_exit(&beep_state.mutex);
190*c35aa225Smarx 		return (ENXIO);
191*c35aa225Smarx 	}
192*c35aa225Smarx 
193*c35aa225Smarx 	if (beep_state.mode == BEEP_TIMED) {
194*c35aa225Smarx 		(void) untimeout(beep_state.timeout_id);
195*c35aa225Smarx 		beep_state.timeout_id = 0;
196*c35aa225Smarx 	}
197*c35aa225Smarx 
198*c35aa225Smarx 	if (beep_state.mode != BEEP_OFF) {
199*c35aa225Smarx 		beep_state.mode = BEEP_OFF;
200*c35aa225Smarx 
201*c35aa225Smarx 		if (beep_state.beep_off != NULL)
202*c35aa225Smarx 			(*beep_state.beep_off)(beep_state.arg);
203*c35aa225Smarx 	}
204*c35aa225Smarx 
205*c35aa225Smarx 	beep_state.queue_head = 0;
206*c35aa225Smarx 	beep_state.queue_tail = 0;
207*c35aa225Smarx 
208*c35aa225Smarx 	mutex_exit(&beep_state.mutex);
209*c35aa225Smarx 
210*c35aa225Smarx 	BEEP_DEBUG1((CE_CONT, "beeper_off : done."));
211*c35aa225Smarx 
212*c35aa225Smarx 	return (0);
213*c35aa225Smarx }
214*c35aa225Smarx 
215*c35aa225Smarx int
beeper_freq(enum beep_type type,int freq)216*c35aa225Smarx beeper_freq(enum beep_type type, int freq)
217*c35aa225Smarx {
218*c35aa225Smarx 	beep_params_t *bp;
219*c35aa225Smarx 
220*c35aa225Smarx 	BEEP_DEBUG1((CE_CONT, "beeper_freq(%d, %d) : start", type, freq));
221*c35aa225Smarx 
222*c35aa225Smarx 	/*
223*c35aa225Smarx 	 * The frequency value is limited to the range of [0 - 32767]
224*c35aa225Smarx 	 */
225*c35aa225Smarx 	if (freq < 0 || freq > INT16_MAX)
226*c35aa225Smarx 		return (EINVAL);
227*c35aa225Smarx 
228*c35aa225Smarx 	for (bp = beep_params; bp->type != BEEP_DEFAULT; bp++) {
229*c35aa225Smarx 		if (bp->type == type)
230*c35aa225Smarx 			break;
231*c35aa225Smarx 	}
232*c35aa225Smarx 
233*c35aa225Smarx 	if (bp->type != type) {
234*c35aa225Smarx 		BEEP_DEBUG((CE_WARN, "beeper_freq : invalid type."));
235*c35aa225Smarx 
236*c35aa225Smarx 		return (EINVAL);
237*c35aa225Smarx 	}
238*c35aa225Smarx 
239*c35aa225Smarx 	bp->frequency = freq;
240*c35aa225Smarx 
241*c35aa225Smarx 	BEEP_DEBUG1((CE_CONT, "beeper_freq : done."));
242*c35aa225Smarx 	return (0);
243*c35aa225Smarx }
244*c35aa225Smarx 
245*c35aa225Smarx /*
246*c35aa225Smarx  * beep :
247*c35aa225Smarx  *      Start beeping for period specified by the type value,
248*c35aa225Smarx  *      from the value in the beep_param structure in milliseconds.
249*c35aa225Smarx  */
250*c35aa225Smarx int
beep(enum beep_type type)251*c35aa225Smarx beep(enum beep_type type)
252*c35aa225Smarx {
253*c35aa225Smarx 
254*c35aa225Smarx 	beep_params_t *bp;
255*c35aa225Smarx 
256*c35aa225Smarx 	BEEP_DEBUG1((CE_CONT, "beep(%d) : start.", type));
257*c35aa225Smarx 
258*c35aa225Smarx 	for (bp = beep_params; bp->type != BEEP_DEFAULT; bp++) {
259*c35aa225Smarx 		if (bp->type == type)
260*c35aa225Smarx 			break;
261*c35aa225Smarx 	}
262*c35aa225Smarx 
263*c35aa225Smarx 	if (bp->type != type) {
264*c35aa225Smarx 
265*c35aa225Smarx 		BEEP_DEBUG((CE_WARN, "beep : invalid type."));
266*c35aa225Smarx 
267*c35aa225Smarx 		/* If type doesn't match, return silently without beeping */
268*c35aa225Smarx 		return (EINVAL);
269*c35aa225Smarx 	}
270*c35aa225Smarx 
271*c35aa225Smarx 	return (beep_mktone(bp->frequency, bp->duration));
272*c35aa225Smarx }
273*c35aa225Smarx 
274*c35aa225Smarx 
275*c35aa225Smarx /*ARGSUSED*/
276*c35aa225Smarx int
beep_polled(enum beep_type type)277*c35aa225Smarx beep_polled(enum beep_type type)
278*c35aa225Smarx {
279*c35aa225Smarx 	/*
280*c35aa225Smarx 	 * No-op at this time.
281*c35aa225Smarx 	 *
282*c35aa225Smarx 	 * Don't think we can make this work in general, as tem_safe
283*c35aa225Smarx 	 * has a requirement of no mutexes, but kbd sends messages
284*c35aa225Smarx 	 * through streams.
285*c35aa225Smarx 	 */
286*c35aa225Smarx 
287*c35aa225Smarx 	BEEP_DEBUG1((CE_CONT, "beep_polled(%d)", type));
288*c35aa225Smarx 
289*c35aa225Smarx 	return (0);
290*c35aa225Smarx }
291*c35aa225Smarx 
292*c35aa225Smarx /*
293*c35aa225Smarx  * beeper_on :
294*c35aa225Smarx  *      Turn the beeper on
295*c35aa225Smarx  */
296*c35aa225Smarx int
beeper_on(enum beep_type type)297*c35aa225Smarx beeper_on(enum beep_type type)
298*c35aa225Smarx {
299*c35aa225Smarx 	beep_params_t *bp;
300*c35aa225Smarx 	int status = 0;
301*c35aa225Smarx 
302*c35aa225Smarx 	BEEP_DEBUG1((CE_CONT, "beeper_on(%d) : start.", type));
303*c35aa225Smarx 
304*c35aa225Smarx 	for (bp = beep_params; bp->type != BEEP_DEFAULT; bp++) {
305*c35aa225Smarx 		if (bp->type == type)
306*c35aa225Smarx 			break;
307*c35aa225Smarx 	}
308*c35aa225Smarx 
309*c35aa225Smarx 	if (bp->type != type) {
310*c35aa225Smarx 
311*c35aa225Smarx 		BEEP_DEBUG((CE_WARN, "beeper_on : invalid type."));
312*c35aa225Smarx 
313*c35aa225Smarx 		/* If type doesn't match, return silently without beeping */
314*c35aa225Smarx 		return (EINVAL);
315*c35aa225Smarx 	}
316*c35aa225Smarx 
317*c35aa225Smarx 	mutex_enter(&beep_state.mutex);
318*c35aa225Smarx 
319*c35aa225Smarx 	if (beep_state.mode == BEEP_UNINIT) {
320*c35aa225Smarx 		status = ENXIO;
321*c35aa225Smarx 
322*c35aa225Smarx 	/* Start another beep only if the previous one is over */
323*c35aa225Smarx 	} else if (beep_state.mode == BEEP_OFF) {
324*c35aa225Smarx 		if (bp->frequency != 0) {
325*c35aa225Smarx 			beep_state.mode = BEEP_ON;
326*c35aa225Smarx 
327*c35aa225Smarx 			if (beep_state.beep_freq != NULL)
328*c35aa225Smarx 				(*beep_state.beep_freq)(beep_state.arg,
329*c35aa225Smarx 				    bp->frequency);
330*c35aa225Smarx 
331*c35aa225Smarx 			if (beep_state.beep_on != NULL)
332*c35aa225Smarx 				(*beep_state.beep_on)(beep_state.arg);
333*c35aa225Smarx 		}
334*c35aa225Smarx 	} else {
335*c35aa225Smarx 		status = EBUSY;
336*c35aa225Smarx 	}
337*c35aa225Smarx 
338*c35aa225Smarx 	mutex_exit(&beep_state.mutex);
339*c35aa225Smarx 
340*c35aa225Smarx 	BEEP_DEBUG1((CE_CONT, "beeper_on : done, status %d.", status));
341*c35aa225Smarx 
342*c35aa225Smarx 	return (status);
343*c35aa225Smarx }
344*c35aa225Smarx 
345*c35aa225Smarx 
346*c35aa225Smarx int
beep_mktone(int frequency,int duration)347*c35aa225Smarx beep_mktone(int frequency, int duration)
348*c35aa225Smarx {
349*c35aa225Smarx 	int next;
350*c35aa225Smarx 	int status = 0;
351*c35aa225Smarx 
352*c35aa225Smarx 	BEEP_DEBUG1((CE_CONT, "beep_mktone(%d, %d) : start.", frequency,
353*c35aa225Smarx 	    duration));
354*c35aa225Smarx 
355*c35aa225Smarx 	/*
356*c35aa225Smarx 	 * The frequency value is limited to the range of [0 - 32767]
357*c35aa225Smarx 	 */
358*c35aa225Smarx 	if (frequency < 0 || frequency > INT16_MAX)
359*c35aa225Smarx 		return (EINVAL);
360*c35aa225Smarx 
361*c35aa225Smarx 	mutex_enter(&beep_state.mutex);
362*c35aa225Smarx 
363*c35aa225Smarx 	if (beep_state.mode == BEEP_UNINIT) {
364*c35aa225Smarx 		status = ENXIO;
365*c35aa225Smarx 
366*c35aa225Smarx 	} else if (beep_state.mode == BEEP_TIMED) {
367*c35aa225Smarx 
368*c35aa225Smarx 		/* If already processing a beep, queue this one */
369*c35aa225Smarx 
370*c35aa225Smarx 		if (frequency != 0) {
371*c35aa225Smarx 			next = beep_state.queue_tail + 1;
372*c35aa225Smarx 			if (next == beep_state.queue_size)
373*c35aa225Smarx 				next = 0;
374*c35aa225Smarx 
375*c35aa225Smarx 			if (next != beep_state.queue_head) {
376*c35aa225Smarx 				/*
377*c35aa225Smarx 				 * If there is room in the queue,
378*c35aa225Smarx 				 * add this entry
379*c35aa225Smarx 				 */
380*c35aa225Smarx 
381*c35aa225Smarx 				beep_state.queue[beep_state.queue_tail].
382*c35aa225Smarx 				    frequency = (unsigned short)frequency;
383*c35aa225Smarx 
384*c35aa225Smarx 				beep_state.queue[beep_state.queue_tail].
385*c35aa225Smarx 				    duration = (unsigned short)duration;
386*c35aa225Smarx 
387*c35aa225Smarx 				beep_state.queue_tail = next;
388*c35aa225Smarx 			} else {
389*c35aa225Smarx 				status = EAGAIN;
390*c35aa225Smarx 			}
391*c35aa225Smarx 		}
392*c35aa225Smarx 
393*c35aa225Smarx 	} else if (beep_state.mode == BEEP_OFF) {
394*c35aa225Smarx 
395*c35aa225Smarx 		/* Start another beep only if the previous one is over */
396*c35aa225Smarx 
397*c35aa225Smarx 		if (frequency != 0) {
398*c35aa225Smarx 			beep_state.mode = BEEP_TIMED;
399*c35aa225Smarx 
400*c35aa225Smarx 			if (beep_state.beep_freq != NULL)
401*c35aa225Smarx 				(*beep_state.beep_freq)(beep_state.arg,
402*c35aa225Smarx 				    frequency);
403*c35aa225Smarx 
404*c35aa225Smarx 			if (beep_state.beep_on != NULL)
405*c35aa225Smarx 				(*beep_state.beep_on)(beep_state.arg);
406*c35aa225Smarx 
407*c35aa225Smarx 			/*
408*c35aa225Smarx 			 * Set timeout for ending the beep after the
409*c35aa225Smarx 			 * specified time
410*c35aa225Smarx 			 */
411*c35aa225Smarx 
412*c35aa225Smarx 			beep_state.timeout_id = timeout(beep_timeout, NULL,
413*c35aa225Smarx 			    drv_usectohz(duration * 1000));
414*c35aa225Smarx 		}
415*c35aa225Smarx 	} else {
416*c35aa225Smarx 		status = EBUSY;
417*c35aa225Smarx 	}
418*c35aa225Smarx 
419*c35aa225Smarx 	mutex_exit(&beep_state.mutex);
420*c35aa225Smarx 
421*c35aa225Smarx 	BEEP_DEBUG1((CE_CONT, "beep_mktone : done, status %d.", status));
422*c35aa225Smarx 
423*c35aa225Smarx 	return (status);
424*c35aa225Smarx }
425*c35aa225Smarx 
426*c35aa225Smarx 
427*c35aa225Smarx /*
428*c35aa225Smarx  * Turn the beeper off which had been turned on from beep()
429*c35aa225Smarx  * for a specified period of time
430*c35aa225Smarx  */
431*c35aa225Smarx /*ARGSUSED*/
432*c35aa225Smarx void
beep_timeout(void * arg)433*c35aa225Smarx beep_timeout(void *arg)
434*c35aa225Smarx {
435*c35aa225Smarx 	int frequency;
436*c35aa225Smarx 	int duration;
437*c35aa225Smarx 	int next;
438*c35aa225Smarx 
439*c35aa225Smarx 	BEEP_DEBUG1((CE_CONT, "beeper_timeout : start."));
440*c35aa225Smarx 
441*c35aa225Smarx 	mutex_enter(&beep_state.mutex);
442*c35aa225Smarx 
443*c35aa225Smarx 	beep_state.timeout_id = 0;
444*c35aa225Smarx 
445*c35aa225Smarx 	if (beep_state.mode == BEEP_UNINIT) {
446*c35aa225Smarx 		mutex_exit(&beep_state.mutex);
447*c35aa225Smarx 		BEEP_DEBUG1((CE_CONT, "beep_timeout : uninitialized."));
448*c35aa225Smarx 		return;
449*c35aa225Smarx 	}
450*c35aa225Smarx 
451*c35aa225Smarx 	if ((beep_state.mode == BEEP_ON) ||
452*c35aa225Smarx 	    (beep_state.mode == BEEP_TIMED)) {
453*c35aa225Smarx 
454*c35aa225Smarx 		beep_state.mode = BEEP_OFF;
455*c35aa225Smarx 
456*c35aa225Smarx 		if (beep_state.beep_off != NULL)
457*c35aa225Smarx 			(*beep_state.beep_off)(beep_state.arg);
458*c35aa225Smarx 	}
459*c35aa225Smarx 
460*c35aa225Smarx 	if (beep_state.queue_head != beep_state.queue_tail) {
461*c35aa225Smarx 
462*c35aa225Smarx 		next = beep_state.queue_head;
463*c35aa225Smarx 
464*c35aa225Smarx 		frequency = beep_state.queue[next].frequency;
465*c35aa225Smarx 
466*c35aa225Smarx 		duration = beep_state.queue[next].duration;
467*c35aa225Smarx 
468*c35aa225Smarx 		next++;
469*c35aa225Smarx 		if (next == beep_state.queue_size)
470*c35aa225Smarx 			next = 0;
471*c35aa225Smarx 
472*c35aa225Smarx 		beep_state.queue_head = next;
473*c35aa225Smarx 
474*c35aa225Smarx 		beep_state.mode = BEEP_TIMED;
475*c35aa225Smarx 
476*c35aa225Smarx 		if (frequency != 0) {
477*c35aa225Smarx 			if (beep_state.beep_freq != NULL)
478*c35aa225Smarx 				(*beep_state.beep_freq)(beep_state.arg,
479*c35aa225Smarx 				    frequency);
480*c35aa225Smarx 
481*c35aa225Smarx 			if (beep_state.beep_on != NULL)
482*c35aa225Smarx 				(*beep_state.beep_on)(beep_state.arg);
483*c35aa225Smarx 		}
484*c35aa225Smarx 
485*c35aa225Smarx 		/* Set timeout for ending the beep after the specified time */
486*c35aa225Smarx 
487*c35aa225Smarx 		beep_state.timeout_id = timeout(beep_timeout, NULL,
488*c35aa225Smarx 		    drv_usectohz(duration * 1000));
489*c35aa225Smarx 	}
490*c35aa225Smarx 
491*c35aa225Smarx 	mutex_exit(&beep_state.mutex);
492*c35aa225Smarx 
493*c35aa225Smarx 	BEEP_DEBUG1((CE_CONT, "beep_timeout : done."));
494*c35aa225Smarx }
495*c35aa225Smarx 
496*c35aa225Smarx 
497*c35aa225Smarx /*
498*c35aa225Smarx  * Return true (1) if we are sounding a tone.
499*c35aa225Smarx  */
500*c35aa225Smarx int
beep_busy(void)501*c35aa225Smarx beep_busy(void)
502*c35aa225Smarx {
503*c35aa225Smarx 	int status;
504*c35aa225Smarx 
505*c35aa225Smarx 	BEEP_DEBUG1((CE_CONT, "beep_busy : start."));
506*c35aa225Smarx 
507*c35aa225Smarx 	mutex_enter(&beep_state.mutex);
508*c35aa225Smarx 
509*c35aa225Smarx 	status = beep_state.mode != BEEP_UNINIT &&
510*c35aa225Smarx 	    beep_state.mode != BEEP_OFF;
511*c35aa225Smarx 
512*c35aa225Smarx 	mutex_exit(&beep_state.mutex);
513*c35aa225Smarx 
514*c35aa225Smarx 	BEEP_DEBUG1((CE_CONT, "beep_busy : status %d.", status));
515*c35aa225Smarx 
516*c35aa225Smarx 	return (status);
517*c35aa225Smarx }
518