ps2_keyboard.c 5.5 KB

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