1 #include "ps2_keyboard.h"
2 #include <driver/interrupt/apic/apic.h>
3 #include <mm/mm.h>
4 #include <mm/slab.h>
5 #include <common/printk.h>
6 #include <filesystem/vfs/VFS.h>
7 #include <filesystem/devfs/devfs.h>
8 #include <common/wait_queue.h>
9 #include <common/spinlock.h>
10 #include <common/kfifo.h>
11
12 // 键盘输入缓冲区
13 static struct kfifo_t kb_buf;
14
15 // 缓冲区等待队列
16 static wait_queue_node_t ps2_keyboard_wait_queue;
17
18 // 缓冲区读写锁
19 static spinlock_t ps2_kb_buf_rw_lock;
20
21 /**
22 * @brief 重置ps2键盘输入缓冲区
23 *
24 * @param kbp 缓冲区对象指针
25 */
ps2_keyboard_reset_buffer(struct kfifo_t * kbp)26 static void ps2_keyboard_reset_buffer(struct kfifo_t *kbp)
27 {
28 kfifo_reset(kbp);
29 }
30 struct apic_IO_APIC_RTE_entry entry;
31
32 hardware_intr_controller ps2_keyboard_intr_controller =
33 {
34 .enable = apic_ioapic_enable,
35 .disable = apic_ioapic_disable,
36 .install = apic_ioapic_install,
37 .uninstall = apic_ioapic_uninstall,
38 .ack = apic_ioapic_edge_ack,
39
40 };
41
42 /**
43 * @brief 打开键盘文件
44 *
45 * @param inode 所在的inode
46 * @param filp 文件指针
47 * @return long
48 */
ps2_keyboard_open(struct vfs_index_node_t * inode,struct vfs_file_t * filp)49 long ps2_keyboard_open(struct vfs_index_node_t *inode, struct vfs_file_t *filp)
50 {
51 filp->private_data = &kb_buf;
52 ps2_keyboard_reset_buffer(&kb_buf);
53 return 0;
54 }
55
56 /**
57 * @brief 关闭键盘文件
58 *
59 * @param inode 所在的inode
60 * @param filp 文件指针
61 * @return long
62 */
ps2_keyboard_close(struct vfs_index_node_t * inode,struct vfs_file_t * filp)63 long ps2_keyboard_close(struct vfs_index_node_t *inode, struct vfs_file_t *filp)
64 {
65 filp->private_data = NULL;
66 ps2_keyboard_reset_buffer(&kb_buf);
67 return 0;
68 }
69
70 /**
71 * @brief 键盘io控制接口
72 *
73 * @param inode 所在的inode
74 * @param filp 键盘文件指针
75 * @param cmd 命令
76 * @param arg 参数
77 * @return long
78 */
ps2_keyboard_ioctl(struct vfs_index_node_t * inode,struct vfs_file_t * filp,uint64_t cmd,uint64_t arg)79 long ps2_keyboard_ioctl(struct vfs_index_node_t *inode, struct vfs_file_t *filp, uint64_t cmd, uint64_t arg)
80 {
81 switch (cmd)
82 {
83 case KEYBOARD_CMD_RESET_BUFFER:
84 ps2_keyboard_reset_buffer(&kb_buf);
85 break;
86
87 default:
88 break;
89 }
90 return 0;
91 }
92
93 /**
94 * @brief 读取键盘文件的操作接口
95 *
96 * @param filp 文件指针
97 * @param buf 输出缓冲区
98 * @param count 要读取的字节数
99 * @param position 读取的位置
100 * @return long 读取的字节数
101 */
ps2_keyboard_read(struct vfs_file_t * filp,char * buf,int64_t count,long * position)102 long ps2_keyboard_read(struct vfs_file_t *filp, char *buf, int64_t count, long *position)
103 {
104 // 缓冲区为空则等待
105 if (kfifo_empty(&kb_buf))
106 wait_queue_sleep_on(&ps2_keyboard_wait_queue);
107
108 count = (count > kb_buf.size) ? kb_buf.size : count;
109 return kfifo_out(&kb_buf, buf, count);
110 }
111
112 /**
113 * @brief 键盘文件写入接口(无作用,空)
114 *
115 * @param filp
116 * @param buf
117 * @param count
118 * @param position
119 * @return long
120 */
ps2_keyboard_write(struct vfs_file_t * filp,char * buf,int64_t count,long * position)121 long ps2_keyboard_write(struct vfs_file_t *filp, char *buf, int64_t count, long *position)
122 {
123 return 0;
124 }
125 /**
126 * @brief ps2键盘驱动的虚拟文件接口
127 *
128 */
129 struct vfs_file_operations_t ps2_keyboard_fops =
130 {
131 .open = ps2_keyboard_open,
132 .close = ps2_keyboard_close,
133 .ioctl = ps2_keyboard_ioctl,
134 .read = ps2_keyboard_read,
135 .write = ps2_keyboard_write,
136 };
137
138 /**
139 * @brief 键盘中断处理函数(中断上半部)
140 * 将数据存入缓冲区
141 * @param irq_num 中断向量号
142 * @param param 参数
143 * @param regs 寄存器信息
144 */
ps2_keyboard_handler(ul irq_num,ul buf_vaddr,struct pt_regs * regs)145 void ps2_keyboard_handler(ul irq_num, ul buf_vaddr, struct pt_regs *regs)
146 {
147 unsigned char x = io_in8(PORT_PS2_KEYBOARD_DATA);
148
149 uint8_t count = kfifo_in((struct kfifo_t*)buf_vaddr, &x, sizeof(unsigned char));
150 if (count == 0)
151 {
152 kwarn("ps2 keyboard buffer full.");
153 return;
154 }
155
156 wait_queue_wakeup(&ps2_keyboard_wait_queue, PROC_UNINTERRUPTIBLE);
157 }
158 /**
159 * @brief 初始化键盘驱动程序的函数
160 *
161 */
ps2_keyboard_init()162 void ps2_keyboard_init()
163 {
164
165 // ======= 初始化键盘循环队列缓冲区 ===========
166
167 // 初始化键盘循环队列缓冲区
168 kfifo_alloc(&kb_buf, ps2_keyboard_buffer_size, 0);
169
170 // ======== 初始化中断RTE entry ==========
171
172 entry.vector = PS2_KEYBOARD_INTR_VECTOR; // 设置中断向量号
173 entry.deliver_mode = IO_APIC_FIXED; // 投递模式:混合
174 entry.dest_mode = DEST_PHYSICAL; // 物理模式投递中断
175 entry.deliver_status = IDLE;
176 entry.trigger_mode = EDGE_TRIGGER; // 设置边沿触发
177 entry.polarity = POLARITY_HIGH; // 高电平触发
178 entry.remote_IRR = IRR_RESET;
179 entry.mask = MASKED;
180 entry.reserved = 0;
181
182 entry.destination.physical.reserved1 = 0;
183 entry.destination.physical.reserved2 = 0;
184 entry.destination.physical.phy_dest = 0; // 设置投递到BSP处理器
185
186 // ======== 初始化键盘控制器,写入配置值 =========
187 wait_ps2_keyboard_write();
188 io_out8(PORT_PS2_KEYBOARD_CONTROL, PS2_KEYBOARD_COMMAND_WRITE);
189 wait_ps2_keyboard_write();
190 io_out8(PORT_PS2_KEYBOARD_DATA, PS2_KEYBOARD_PARAM_INIT);
191 wait_ps2_keyboard_write();
192
193 // 执行一百万次nop,等待键盘控制器把命令执行完毕
194 for (int i = 0; i < 1000; ++i)
195 for (int j = 0; j < 1000; ++j)
196 nop();
197
198 wait_queue_init(&ps2_keyboard_wait_queue, NULL);
199 // 初始化键盘缓冲区的读写锁
200 spin_init(&ps2_kb_buf_rw_lock);
201
202 // 注册中断处理程序
203 irq_register(PS2_KEYBOARD_INTR_VECTOR, &entry, &ps2_keyboard_handler, (ul)&kb_buf, &ps2_keyboard_intr_controller, "ps/2 keyboard");
204
205 // 先读一下键盘的数据,防止由于在键盘初始化之前,由于按键被按下从而导致接收不到中断。
206 io_in8(PORT_PS2_KEYBOARD_DATA);
207 // 将设备挂载到devfs
208 devfs_register_device(DEV_TYPE_CHAR, CHAR_DEV_STYPE_PS2_KEYBOARD, &ps2_keyboard_fops, NULL);
209 kinfo("ps/2 keyboard registered.");
210 }
211
212 /**
213 * @brief 键盘驱动卸载函数
214 *
215 */
ps2_keyboard_exit()216 void ps2_keyboard_exit()
217 {
218 irq_unregister(PS2_KEYBOARD_INTR_VECTOR);
219 kfifo_free_alloc(&kb_buf);
220 }
221