123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- /* vim: tabstop=4 shiftwidth=4 noexpandtab
- * This file is part of ToaruOS and is released under the terms
- * of the NCSA / University of Illinois License - see LICENSE.md
- * Copyright (C) 2014-2018 K. Lange
- *
- * Mouse driver
- *
- */
- #include <kernel/system.h>
- #include <kernel/logging.h>
- #include <kernel/pipe.h>
- #include <kernel/module.h>
- #include <kernel/mouse.h>
- #include <kernel/args.h>
- static uint8_t mouse_cycle = 0;
- static uint8_t mouse_byte[4];
- #define PACKETS_IN_PIPE 1024
- #define DISCARD_POINT 32
- #define MOUSE_IRQ 12
- #define MOUSE_PORT 0x60
- #define MOUSE_STATUS 0x64
- #define MOUSE_ABIT 0x02
- #define MOUSE_BBIT 0x01
- #define MOUSE_WRITE 0xD4
- #define MOUSE_F_BIT 0x20
- #define MOUSE_V_BIT 0x08
- #define MOUSE_DEFAULT 0
- #define MOUSE_SCROLLWHEEL 1
- #define MOUSE_BUTTONS 2
- static int8_t mouse_mode = MOUSE_DEFAULT;
- static fs_node_t * mouse_pipe;
- void (*ps2_mouse_alternate)(void) = NULL;
- static void mouse_wait(uint8_t a_type) {
- uint32_t timeout = 100000;
- if (!a_type) {
- while (--timeout) {
- if ((inportb(MOUSE_STATUS) & MOUSE_BBIT) == 1) {
- return;
- }
- }
- debug_print(INFO, "mouse timeout");
- return;
- } else {
- while (--timeout) {
- if (!((inportb(MOUSE_STATUS) & MOUSE_ABIT))) {
- return;
- }
- }
- debug_print(INFO, "mouse timeout");
- return;
- }
- }
- static void mouse_write(uint8_t write) {
- mouse_wait(1);
- outportb(MOUSE_STATUS, MOUSE_WRITE);
- mouse_wait(1);
- outportb(MOUSE_PORT, write);
- }
- static uint8_t mouse_read(void) {
- mouse_wait(0);
- char t = inportb(MOUSE_PORT);
- return t;
- }
- static int mouse_handler(struct regs *r) {
- uint8_t status = inportb(MOUSE_STATUS);
- while ((status & MOUSE_BBIT) && (status & MOUSE_F_BIT)) {
- if (ps2_mouse_alternate) {
- ps2_mouse_alternate();
- break;
- }
- int8_t mouse_in = inportb(MOUSE_PORT);
- switch (mouse_cycle) {
- case 0:
- mouse_byte[0] = mouse_in;
- if (!(mouse_in & MOUSE_V_BIT)) break;
- ++mouse_cycle;
- break;
- case 1:
- mouse_byte[1] = mouse_in;
- ++mouse_cycle;
- break;
- case 2:
- mouse_byte[2] = mouse_in;
- if (mouse_mode == MOUSE_SCROLLWHEEL || mouse_mode == MOUSE_BUTTONS) {
- ++mouse_cycle;
- break;
- }
- goto finish_packet;
- case 3:
- mouse_byte[3] = mouse_in;
- goto finish_packet;
- }
- goto read_next;
- finish_packet:
- mouse_cycle = 0;
- /* We now have a full mouse packet ready to use */
- mouse_device_packet_t packet;
- packet.magic = MOUSE_MAGIC;
- int x = mouse_byte[1];
- int y = mouse_byte[2];
- if (x && mouse_byte[0] & (1 << 4)) {
- /* Sign bit */
- x = x - 0x100;
- }
- if (y && mouse_byte[0] & (1 << 5)) {
- /* Sign bit */
- y = y - 0x100;
- }
- if (mouse_byte[0] & (1 << 6) || mouse_byte[0] & (1 << 7)) {
- /* Overflow */
- x = 0;
- y = 0;
- }
- packet.x_difference = x;
- packet.y_difference = y;
- packet.buttons = 0;
- if (mouse_byte[0] & 0x01) {
- packet.buttons |= LEFT_CLICK;
- }
- if (mouse_byte[0] & 0x02) {
- packet.buttons |= RIGHT_CLICK;
- }
- if (mouse_byte[0] & 0x04) {
- packet.buttons |= MIDDLE_CLICK;
- }
- if (mouse_mode == MOUSE_SCROLLWHEEL && mouse_byte[3]) {
- if ((int8_t)mouse_byte[3] > 0) {
- packet.buttons |= MOUSE_SCROLL_DOWN;
- } else if ((int8_t)mouse_byte[3] < 0) {
- packet.buttons |= MOUSE_SCROLL_UP;
- }
- }
- mouse_device_packet_t bitbucket;
- while (pipe_size(mouse_pipe) > (int)(DISCARD_POINT * sizeof(packet))) {
- read_fs(mouse_pipe, 0, sizeof(packet), (uint8_t *)&bitbucket);
- }
- write_fs(mouse_pipe, 0, sizeof(packet), (uint8_t *)&packet);
- read_next:
- break;
- }
- irq_ack(MOUSE_IRQ);
- return 1;
- }
- static int ioctl_mouse(fs_node_t * node, int request, void * argp) {
- if (request == 1) {
- mouse_cycle = 0;
- return 0;
- }
- return -1;
- }
- static int mouse_install(void) {
- debug_print(NOTICE, "Initializing PS/2 mouse interface");
- uint8_t status, result;
- IRQ_OFF;
- while ((inportb(0x64) & 1)) {
- inportb(0x60);
- }
- mouse_pipe = make_pipe(sizeof(mouse_device_packet_t) * PACKETS_IN_PIPE);
- mouse_wait(1);
- outportb(MOUSE_STATUS, 0xA8);
- mouse_read();
- mouse_wait(1);
- outportb(MOUSE_STATUS, 0x20);
- mouse_wait(0);
- status = inportb(0x60) | 3;
- mouse_wait(1);
- outportb(MOUSE_STATUS, 0x60);
- mouse_wait(1);
- outportb(MOUSE_PORT, status);
- mouse_write(0xF6);
- mouse_read();
- mouse_write(0xF4);
- mouse_read();
- /* Try to enable scroll wheel (but not buttons) */
- if (!args_present("nomousescroll")) {
- mouse_write(0xF2);
- mouse_read();
- result = mouse_read();
- mouse_write(0xF3);
- mouse_read();
- mouse_write(200);
- mouse_read();
- mouse_write(0xF3);
- mouse_read();
- mouse_write(100);
- mouse_read();
- mouse_write(0xF3);
- mouse_read();
- mouse_write(80);
- mouse_read();
- mouse_write(0xF2);
- mouse_read();
- result = mouse_read();
- if (result == 3) {
- mouse_mode = MOUSE_SCROLLWHEEL;
- }
- }
- /* keyboard scancode set */
- mouse_wait(1);
- outportb(MOUSE_PORT, 0xF0);
- mouse_wait(1);
- outportb(MOUSE_PORT, 0x02);
- mouse_wait(1);
- mouse_read();
- irq_install_handler(MOUSE_IRQ, mouse_handler, "ps2 mouse");
- IRQ_RES;
- uint8_t tmp = inportb(0x61);
- outportb(0x61, tmp | 0x80);
- outportb(0x61, tmp & 0x7F);
- inportb(MOUSE_PORT);
- while ((inportb(0x64) & 1)) {
- inportb(0x60);
- }
- mouse_pipe->flags = FS_CHARDEVICE;
- mouse_pipe->ioctl = ioctl_mouse;
- vfs_mount("/dev/mouse", mouse_pipe);
- return 0;
- }
- static int mouse_uninstall(void) {
- /* TODO */
- return 0;
- }
- MODULE_DEF(ps2mouse, mouse_install, mouse_uninstall);
|