ps2_keyboard.c 6.9 KB

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