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