⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sparcspkr.c

📁 linux 内核源代码
💻 C
字号:
/* *  Driver for PC-speaker like devices found on various Sparc systems. * *  Copyright (c) 2002 Vojtech Pavlik *  Copyright (c) 2002, 2006 David S. Miller (davem@davemloft.net) */#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/input.h>#include <linux/platform_device.h>#include <asm/io.h>#include <asm/ebus.h>#include <asm/isa.h>MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");MODULE_DESCRIPTION("Sparc Speaker beeper driver");MODULE_LICENSE("GPL");struct sparcspkr_state {	const char		*name;	unsigned long		iobase;	int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);	spinlock_t		lock;	struct input_dev	*input_dev;};static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value){	struct sparcspkr_state *state = dev_get_drvdata(dev->dev.parent);	unsigned int count = 0;	unsigned long flags;	if (type != EV_SND)		return -1;	switch (code) {		case SND_BELL: if (value) value = 1000;		case SND_TONE: break;		default: return -1;	}	if (value > 20 && value < 32767)		count = 1193182 / value;	spin_lock_irqsave(&state->lock, flags);	/* EBUS speaker only has on/off state, the frequency does not	 * appear to be programmable.	 */	if (state->iobase & 0x2UL)		outb(!!count, state->iobase);	else		outl(!!count, state->iobase);	spin_unlock_irqrestore(&state->lock, flags);	return 0;}static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value){	struct sparcspkr_state *state = dev_get_drvdata(dev->dev.parent);	unsigned int count = 0;	unsigned long flags;	if (type != EV_SND)		return -1;	switch (code) {		case SND_BELL: if (value) value = 1000;		case SND_TONE: break;		default: return -1;	}	if (value > 20 && value < 32767)		count = 1193182 / value;	spin_lock_irqsave(&state->lock, flags);	if (count) {		/* enable counter 2 */		outb(inb(state->iobase + 0x61) | 3, state->iobase + 0x61);		/* set command for counter 2, 2 byte write */		outb(0xB6, state->iobase + 0x43);		/* select desired HZ */		outb(count & 0xff, state->iobase + 0x42);		outb((count >> 8) & 0xff, state->iobase + 0x42);	} else {		/* disable counter 2 */		outb(inb_p(state->iobase + 0x61) & 0xFC, state->iobase + 0x61);	}	spin_unlock_irqrestore(&state->lock, flags);	return 0;}static int __devinit sparcspkr_probe(struct device *dev){	struct sparcspkr_state *state = dev_get_drvdata(dev);	struct input_dev *input_dev;	int error;	input_dev = input_allocate_device();	if (!input_dev)		return -ENOMEM;	input_dev->name = state->name;	input_dev->phys = "sparc/input0";	input_dev->id.bustype = BUS_ISA;	input_dev->id.vendor = 0x001f;	input_dev->id.product = 0x0001;	input_dev->id.version = 0x0100;	input_dev->dev.parent = dev;	input_dev->evbit[0] = BIT_MASK(EV_SND);	input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);	input_dev->event = state->event;	error = input_register_device(input_dev);	if (error) {		input_free_device(input_dev);		return error;	}	state->input_dev = input_dev;	return 0;}static int __devexit sparcspkr_remove(struct of_device *dev){	struct sparcspkr_state *state = dev_get_drvdata(&dev->dev);	struct input_dev *input_dev = state->input_dev;	/* turn off the speaker */	state->event(input_dev, EV_SND, SND_BELL, 0);	input_unregister_device(input_dev);	dev_set_drvdata(&dev->dev, NULL);	kfree(state);	return 0;}static int sparcspkr_shutdown(struct of_device *dev){	struct sparcspkr_state *state = dev_get_drvdata(&dev->dev);	struct input_dev *input_dev = state->input_dev;	/* turn off the speaker */	state->event(input_dev, EV_SND, SND_BELL, 0);	return 0;}static int __devinit ebus_beep_probe(struct of_device *dev, const struct of_device_id *match){	struct linux_ebus_device *edev = to_ebus_device(&dev->dev);	struct sparcspkr_state *state;	int err;	state = kzalloc(sizeof(*state), GFP_KERNEL);	if (!state)		return -ENOMEM;	state->name = "Sparc EBUS Speaker";	state->iobase = edev->resource[0].start;	state->event = ebus_spkr_event;	spin_lock_init(&state->lock);	dev_set_drvdata(&dev->dev, state);	err = sparcspkr_probe(&dev->dev);	if (err) {		dev_set_drvdata(&dev->dev, NULL);		kfree(state);	}	return 0;}static struct of_device_id ebus_beep_match[] = {	{		.name = "beep",	},	{},};static struct of_platform_driver ebus_beep_driver = {	.name		= "beep",	.match_table	= ebus_beep_match,	.probe		= ebus_beep_probe,	.remove		= __devexit_p(sparcspkr_remove),	.shutdown	= sparcspkr_shutdown,};static int __devinit isa_beep_probe(struct of_device *dev, const struct of_device_id *match){	struct sparc_isa_device *idev = to_isa_device(&dev->dev);	struct sparcspkr_state *state;	int err;	state = kzalloc(sizeof(*state), GFP_KERNEL);	if (!state)		return -ENOMEM;	state->name = "Sparc ISA Speaker";	state->iobase = idev->resource.start;	state->event = isa_spkr_event;	spin_lock_init(&state->lock);	dev_set_drvdata(&dev->dev, state);	err = sparcspkr_probe(&dev->dev);	if (err) {		dev_set_drvdata(&dev->dev, NULL);		kfree(state);	}	return 0;}static struct of_device_id isa_beep_match[] = {	{		.name = "dma",	},	{},};static struct of_platform_driver isa_beep_driver = {	.name		= "beep",	.match_table	= isa_beep_match,	.probe		= isa_beep_probe,	.remove		= __devexit_p(sparcspkr_remove),	.shutdown	= sparcspkr_shutdown,};static int __init sparcspkr_init(void){	int err = of_register_driver(&ebus_beep_driver, &ebus_bus_type);	if (!err) {		err = of_register_driver(&isa_beep_driver, &isa_bus_type);		if (err)			of_unregister_driver(&ebus_beep_driver);	}	return err;}static void __exit sparcspkr_exit(void){	of_unregister_driver(&ebus_beep_driver);	of_unregister_driver(&isa_beep_driver);}module_init(sparcspkr_init);module_exit(sparcspkr_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -