-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbootspkr.c
More file actions
92 lines (77 loc) · 2.06 KB
/
Copy pathbootspkr.c
File metadata and controls
92 lines (77 loc) · 2.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*
* SPDX-FileCopyrightText: 2026 Harish
*
* SPDX-License-Identifier: GPL-3.0-only
*/
#include <linux/delay.h>
#include <linux/i8253.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/workqueue.h>
MODULE_DESCRIPTION("Boot PC Speaker beeper driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS_FS("bootspkr");
struct note {
unsigned int freq;
unsigned int duration;
};
static const struct note kiss[] = {
{293, 107}, // 8D4
{329, 107}, // 8E4
{349, 643}, // F4.
{392, 107}, // 8G4
{349, 429}, // F4
{329, 429}, // E4
{293, 429}, // D4
{261, 429}, // C4
{293, 857}, // 2D4
{293, 107}, // 8D4
{261, 107}, // 8C4
{293, 857}, // 2D4
{293, 107}, // 8D4
{329, 107}, // 8E4
{349, 643}, // F4.
{392, 107}, // 8G4
{349, 429}, // F4
{329, 429}, // E4
{261, 429}, // C4
{329, 429}, // E4
{293, 1286}, // 2D4.
};
static void play(unsigned int f_hz, unsigned int duration) {
unsigned int count = PIT_TICK_RATE / f_hz;
unsigned long flags = 0;
raw_spin_lock_irqsave(&i8253_lock, flags);
/* set command for counter 2, 2 byte write */
outb(0xB6, 0x43);
/* select desired HZ */
outb(count & 0xff, 0x42);
outb((count >> 8) & 0xff, 0x42);
/* enable counter 2 */
outb(inb_p(0x61) | 3, 0x61);
raw_spin_unlock_irqrestore(&i8253_lock, flags);
msleep(duration);
raw_spin_lock_irqsave(&i8253_lock, flags);
/* disable counter 2 */
outb(inb_p(0x61) & 0xFC, 0x61);
raw_spin_unlock_irqrestore(&i8253_lock, flags);
}
static void bootspkr_worker(struct work_struct *work) {
const struct note *seq = kiss;
int len = ARRAY_SIZE(kiss);
for (int i = 0; i < len; i++) {
play(seq[i].freq, seq[i].duration);
}
}
static DECLARE_WORK(bootspkr_work, bootspkr_worker);
static int __init bootspkr_init(void) {
printk("Initializing Bootspkr!\n");
schedule_work(&bootspkr_work);
return 0;
}
static void __exit bootspkr_exit(void) {
printk("Goodbye Cruel World!\n");
cancel_work_sync(&bootspkr_work);
}
module_init(bootspkr_init) module_exit(bootspkr_exit)