4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Simple beeper support for PC platform, using standard timer 2 beeper.
30 #include <sys/types.h>
33 #include <sys/ksynch.h>
35 #include <sys/sunddi.h>
36 #include <sys/modctl.h>
38 #include <sys/inttypes.h>
40 #define PIT_BEEP_UNIT(dev) (getminor((dev)))
42 typedef struct pit_beep_state
{
43 /* Dip of pit_beep device */
49 #define PIT_BEEP_OFF 0
51 /* Pointer to the state structure */
52 static void *pit_beep_statep
;
54 static int pit_beep_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
);
55 static int pit_beep_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
);
56 static int pit_beep_info(dev_info_t
*dip
, ddi_info_cmd_t infocmd
,
57 void *arg
, void **result
);
58 static void pit_beep_freq(void *arg
, int freq
);
59 static void pit_beep_on(void *arg
);
60 static void pit_beep_off(void *arg
);
62 struct cb_ops pit_beep_cb_ops
= {
65 nulldev
, /* strategy */
75 ddi_prop_op
, /* cb_prop_op */
81 static struct dev_ops pit_beep_ops
= {
82 DEVO_REV
, /* Devo_rev */
84 pit_beep_info
, /* Info */
85 nulldev
, /* Identify */
87 pit_beep_attach
, /* Attach */
88 pit_beep_detach
, /* Detach */
90 &pit_beep_cb_ops
, /* Driver operations */
91 0, /* Bus operations */
93 ddi_quiesce_not_needed
, /* quiesce */
97 static struct modldrv modldrv
= {
98 &mod_driverops
, /* This one is a driver */
99 "Intel Pit_beep Driver", /* Name of the module. */
100 &pit_beep_ops
, /* Driver ops */
104 static struct modlinkage modlinkage
= {
105 MODREV_1
, (void *)&modldrv
, NULL
115 /* Initialize the soft state structures */
116 if ((error
= ddi_soft_state_init(&pit_beep_statep
,
117 sizeof (pit_beep_state_t
), 1)) != 0) {
122 /* Install the loadable module */
123 if ((error
= mod_install(&modlinkage
)) != 0) {
124 ddi_soft_state_fini(&pit_beep_statep
);
132 _info(struct modinfo
*modinfop
)
134 return (mod_info(&modlinkage
, modinfop
));
142 error
= mod_remove(&modlinkage
);
145 /* Release per module resources */
146 ddi_soft_state_fini(&pit_beep_statep
);
156 pit_beep_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
163 return (DDI_SUCCESS
);
166 return (DDI_FAILURE
);
171 (void) beep_init((void *)dip
, pit_beep_on
, pit_beep_off
,
174 /* Display information in the banner */
177 return (DDI_SUCCESS
);
186 pit_beep_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
192 * If a beep is in progress; fail suspend
196 return (DDI_SUCCESS
);
199 return (DDI_FAILURE
);
203 return (DDI_FAILURE
);
213 pit_beep_info(dev_info_t
*dip
, ddi_info_cmd_t infocmd
,
214 void *arg
, void **result
)
217 pit_beep_state_t
*statep
;
221 case DDI_INFO_DEVT2DEVINFO
:
223 instance
= PIT_BEEP_UNIT(dev
);
225 if ((statep
= ddi_get_soft_state(pit_beep_statep
,
226 instance
)) == NULL
) {
228 return (DDI_FAILURE
);
231 *result
= (void *)statep
->dip
;
235 case DDI_INFO_DEVT2INSTANCE
:
237 instance
= PIT_BEEP_UNIT(dev
);
239 *result
= (void *)(uintptr_t)instance
;
254 pit_beep_freq(void *arg
, int freq
)
261 counter
= PIT_HZ
/ freq
;
262 if (counter
> UINT16_MAX
)
263 counter
= UINT16_MAX
;
264 else if (counter
< 1)
268 outb(PITCTL_PORT
, PIT_C2
| PIT_READMODE
| PIT_RATEMODE
);
269 outb(PITCTR2_PORT
, counter
& 0xff);
270 outb(PITCTR2_PORT
, counter
>> 8);
276 pit_beep_on(void *arg
)
278 outb(PITAUX_PORT
, inb(PITAUX_PORT
) | (PITAUX_OUT2
| PITAUX_GATE2
));
284 pit_beep_off(void *arg
)
286 outb(PITAUX_PORT
, inb(PITAUX_PORT
) & ~(PITAUX_OUT2
| PITAUX_GATE2
));