Run-time loaded versions of these keyboard and ps2mouse drivers are now
in 'keyboard' and 'ps2mouse' subdirectories of src/add-ons/kernel/drivers/arch/x86/, making these old ones obsoletes. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@253 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
2b94bc7ba9
commit
32ef543544
@ -1,3 +0,0 @@
|
||||
SubDir OBOS_TOP src kernel drivers arch x86 keyboard ;
|
||||
|
||||
KernelObjects keyboard.c : -fno-pic ;
|
@ -1,317 +0,0 @@
|
||||
/*
|
||||
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
#include <kernel.h>
|
||||
#include <debug.h>
|
||||
#include <memheap.h>
|
||||
#include <int.h>
|
||||
#include <OS.h>
|
||||
#include <string.h>
|
||||
#include <lock.h>
|
||||
#include <devfs.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <Errors.h>
|
||||
|
||||
#include <arch/x86/keyboard.h>
|
||||
|
||||
|
||||
#define LSHIFT 42
|
||||
#define RSHIFT 54
|
||||
#define SCRLOCK 70
|
||||
#define NUMLOCK 69
|
||||
#define CAPS 58
|
||||
#define SYSREQ 55
|
||||
#define F11 87
|
||||
#define F12 88
|
||||
|
||||
#define LED_SCROLL 1
|
||||
#define LED_NUM 2
|
||||
#define LED_CAPS 4
|
||||
|
||||
static bool shift;
|
||||
static int leds;
|
||||
static sem_id keyboard_sem;
|
||||
static mutex keyboard_read_mutex;
|
||||
static char keyboard_buf[1024];
|
||||
static unsigned int head, tail;
|
||||
|
||||
// stolen from nujeffos
|
||||
const char unshifted_keymap[128] = {
|
||||
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 8, '\t',
|
||||
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0, 'a', 's',
|
||||
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', 'x', 'c', 'v',
|
||||
'b', 'n', 'm', ',', '.', '/', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
'\\', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
const char shifted_keymap[128] = {
|
||||
0, 27, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 8, '\t',
|
||||
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', 0, 'A', 'S',
|
||||
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', 0, '\\', 'Z', 'X', 'C', 'V',
|
||||
'B', 'N', 'M', '<', '>', '?', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
const char caps_keymap[128] = {
|
||||
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 8, '\t',
|
||||
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '[', ']', '\n', 0, 'A', 'S',
|
||||
'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', '\'', '`', 0, '\\', 'Z', 'X', 'C', 'V',
|
||||
'B', 'N', 'M', '<', '>', '?', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
'\\', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static void wait_for_output(void)
|
||||
{
|
||||
while(in8(0x64) & 0x2)
|
||||
;
|
||||
}
|
||||
|
||||
static void set_leds(void)
|
||||
{
|
||||
wait_for_output();
|
||||
out8(0xed, 0x60);
|
||||
wait_for_output();
|
||||
out8(leds, 0x60);
|
||||
}
|
||||
|
||||
static ssize_t _keyboard_read(void *_buf, size_t len)
|
||||
{
|
||||
unsigned int saved_tail;
|
||||
char *buf = _buf;
|
||||
size_t copied_bytes = 0;
|
||||
size_t copy_len;
|
||||
int rc;
|
||||
|
||||
if(len > sizeof(keyboard_buf) - 1)
|
||||
len = sizeof(keyboard_buf) - 1;
|
||||
|
||||
retry:
|
||||
// block here until data is ready
|
||||
rc = acquire_sem_etc(keyboard_sem, 1, B_CAN_INTERRUPT, 0);
|
||||
if(rc == EINTR) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// critical section
|
||||
mutex_lock(&keyboard_read_mutex);
|
||||
|
||||
saved_tail = tail;
|
||||
if(head == saved_tail) {
|
||||
mutex_unlock(&keyboard_read_mutex);
|
||||
goto retry;
|
||||
} else {
|
||||
// copy out of the buffer
|
||||
if(head < saved_tail)
|
||||
copy_len = min(len, saved_tail - head);
|
||||
else
|
||||
copy_len = min(len, sizeof(keyboard_buf) - head);
|
||||
memcpy(buf, &keyboard_buf[head], copy_len);
|
||||
copied_bytes = copy_len;
|
||||
head = (head + copy_len) % sizeof(keyboard_buf);
|
||||
if(head == 0 && saved_tail > 0 && copied_bytes < len) {
|
||||
// we wrapped around and have more bytes to read
|
||||
// copy the first part of the buffer
|
||||
copy_len = min(saved_tail, len - copied_bytes);
|
||||
memcpy(&buf[len], &keyboard_buf[0], copy_len);
|
||||
copied_bytes += copy_len;
|
||||
head = copy_len;
|
||||
}
|
||||
}
|
||||
if(head != saved_tail) {
|
||||
// we did not empty the keyboard queue
|
||||
release_sem_etc(keyboard_sem, 1, B_DO_NOT_RESCHEDULE);
|
||||
}
|
||||
|
||||
mutex_unlock(&keyboard_read_mutex);
|
||||
|
||||
return copied_bytes;
|
||||
}
|
||||
|
||||
static void insert_in_buf(char c)
|
||||
{
|
||||
unsigned int temp_tail = tail;
|
||||
|
||||
// see if the next char will collide with the head
|
||||
temp_tail++;
|
||||
temp_tail %= sizeof(keyboard_buf);
|
||||
if(temp_tail == head) {
|
||||
// buffer overflow, ditch this char
|
||||
return;
|
||||
}
|
||||
keyboard_buf[tail] = c;
|
||||
tail = temp_tail;
|
||||
release_sem_etc(keyboard_sem, 1, B_DO_NOT_RESCHEDULE);
|
||||
}
|
||||
|
||||
static int handle_keyboard_interrupt(void* data)
|
||||
{
|
||||
unsigned char key;
|
||||
int retval = INT_NO_RESCHEDULE;
|
||||
|
||||
key = in8(0x60);
|
||||
// dprintf("handle_keyboard_interrupt: key = 0x%x\n", key);
|
||||
|
||||
if(key & 0x80) {
|
||||
// keyup
|
||||
if(key == LSHIFT + 0x80 || key == RSHIFT + 0x80)
|
||||
shift = false;
|
||||
} else {
|
||||
switch(key) {
|
||||
case LSHIFT:
|
||||
case RSHIFT:
|
||||
shift = true;
|
||||
break;
|
||||
case CAPS:
|
||||
if(leds & LED_CAPS)
|
||||
leds &= ~LED_CAPS;
|
||||
else
|
||||
leds |= LED_CAPS;
|
||||
set_leds();
|
||||
break;
|
||||
case SCRLOCK:
|
||||
if(leds & LED_SCROLL) {
|
||||
leds &= ~LED_SCROLL;
|
||||
dbg_set_serial_debug(false);
|
||||
} else {
|
||||
leds |= LED_SCROLL;
|
||||
dbg_set_serial_debug(true);
|
||||
}
|
||||
set_leds();
|
||||
break;
|
||||
case NUMLOCK:
|
||||
if(leds & LED_NUM)
|
||||
leds &= ~LED_NUM;
|
||||
else
|
||||
leds |= LED_NUM;
|
||||
set_leds();
|
||||
break;
|
||||
case SYSREQ:
|
||||
panic("Keyboard Requested Halt\n");
|
||||
break;
|
||||
case F11:
|
||||
dbg_set_serial_debug(dbg_get_serial_debug()?false:true);
|
||||
break;
|
||||
case F12:
|
||||
reboot();
|
||||
break;
|
||||
default: {
|
||||
char ascii;
|
||||
|
||||
if(shift)
|
||||
ascii = shifted_keymap[key];
|
||||
else
|
||||
if (leds & LED_CAPS)
|
||||
ascii = caps_keymap[key];
|
||||
else
|
||||
ascii = unshifted_keymap[key];
|
||||
|
||||
// dprintf("ascii = 0x%x, '%c'\n", ascii, ascii);
|
||||
if(ascii != 0) {
|
||||
insert_in_buf(ascii);
|
||||
retval = INT_RESCHEDULE;
|
||||
} else {
|
||||
// dprintf("keyboard: unknown scan-code 0x%x\n",key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int keyboard_open(const char *name, uint32 flags, void * *cookie)
|
||||
{
|
||||
*cookie = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int keyboard_close(void * cookie)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int keyboard_freecookie(void * cookie)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int keyboard_seek(void * cookie, off_t pos, int st)
|
||||
{
|
||||
return EPERM;
|
||||
}
|
||||
|
||||
static ssize_t keyboard_read(void * cookie, off_t pos, void *buf, size_t *len)
|
||||
{
|
||||
int rv;
|
||||
if (*len < 0)
|
||||
return 0;
|
||||
|
||||
rv = _keyboard_read(buf, *len);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
*len = rv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t keyboard_write(void * cookie, off_t pos, const void *buf, size_t *len)
|
||||
{
|
||||
return EROFS;
|
||||
}
|
||||
|
||||
static int keyboard_ioctl(void * cookie, uint32 op, void *buf, size_t len)
|
||||
{
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
device_hooks keyboard_hooks = {
|
||||
&keyboard_open,
|
||||
&keyboard_close,
|
||||
&keyboard_freecookie,
|
||||
&keyboard_ioctl,
|
||||
&keyboard_read,
|
||||
&keyboard_write,
|
||||
NULL,
|
||||
NULL,
|
||||
// NULL,
|
||||
// NULL
|
||||
};
|
||||
|
||||
static int setup_keyboard(void)
|
||||
{
|
||||
keyboard_sem = create_sem(0, "keyboard_sem");
|
||||
if(keyboard_sem < 0)
|
||||
panic("could not create keyboard sem!\n");
|
||||
|
||||
if(mutex_init(&keyboard_read_mutex, "keyboard_read_mutex") < 0)
|
||||
panic("could not create keyboard read mutex!\n");
|
||||
|
||||
shift = 0;
|
||||
leds = 0;
|
||||
// have the scroll lock reflect the state of serial debugging
|
||||
if(dbg_get_serial_debug())
|
||||
leds |= LED_SCROLL;
|
||||
set_leds();
|
||||
|
||||
head = tail = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int keyboard_dev_init(kernel_args *ka)
|
||||
{
|
||||
setup_keyboard();
|
||||
int_set_io_interrupt_handler(0x21,&handle_keyboard_interrupt, NULL);
|
||||
|
||||
devfs_publish_device("keyboard", NULL, &keyboard_hooks);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
SubDir OBOS_TOP src kernel drivers arch x86 ps2mouse ;
|
||||
|
||||
KernelObjects ps2mouse.c : -D_PS2MOUSE_ ;
|
@ -1,340 +0,0 @@
|
||||
/*
|
||||
* ps2mouse.c:
|
||||
* PS/2 mouse device driver for NewOS and OpenBeOS.
|
||||
* Author: Elad Lahav (elad@eldarshany.com)
|
||||
* Created: 21.12.2001
|
||||
* Modified: 11.1.2002
|
||||
*/
|
||||
|
||||
/*
|
||||
* A PS/2 mouse is connected to the IBM 8042 controller, and gets its
|
||||
* name from the IBM PS/2 personal computer, which was the first to
|
||||
* use this device. All resources are shared between the keyboard, and
|
||||
* the mouse, referred to as the "Auxiliary Device".
|
||||
* I/O:
|
||||
* ~~~
|
||||
* The controller has 3 I/O registers:
|
||||
* 1. Status (input), mapped to port 64h
|
||||
* 2. Control (output), mapped to port 64h
|
||||
* 3. Data (input/output), mapped to port 60h
|
||||
* Data:
|
||||
* ~~~~
|
||||
* Since a mouse is an input only device, data can only be read, and
|
||||
* not written. A packet read from the mouse data port is composed of
|
||||
* three bytes:
|
||||
* byte 0: status byte, where
|
||||
* - bit 0: Y overflow (1 = true)
|
||||
* - bit 1: X overflow (1 = true)
|
||||
* - bit 2: MSB of Y offset
|
||||
* - bit 3: MSB of X offset
|
||||
* - bit 4: Syncronization bit (always 1)
|
||||
* - bit 5: Middle button (1 = down)
|
||||
* - bit 6: Right button (1 = down)
|
||||
* - bit 7: Left button (1 = down)
|
||||
* byte 1: X position change, since last probed (-127 to +127)
|
||||
* byte 2: Y position change, since last probed (-127 to +127)
|
||||
* Interrupts:
|
||||
* ~~~~~~~~~~
|
||||
* The PS/2 mouse device is connected to interrupt 12, which means that
|
||||
* it uses the second interrupt controller (handles INT8 to INT15). In
|
||||
* order for this interrupt to be enabled, both the 5th interrupt of
|
||||
* the second controller AND the 3rd interrupt of the first controller
|
||||
* (cascade mode) should be unmasked.
|
||||
* The controller uses 3 consecutive interrupts to inform the computer
|
||||
* that it has new data. On the first the data register holds the status
|
||||
* byte, on the second the X offset, and on the 3rd the Y offset.
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <Errors.h>
|
||||
#include <memheap.h>
|
||||
#include <int.h>
|
||||
#include <debug.h>
|
||||
#include <devfs.h>
|
||||
#include <arch/int.h>
|
||||
#include <string.h>
|
||||
|
||||
#define _PS2MOUSE_
|
||||
#include <arch/x86/ps2mouse.h>
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// interrupt
|
||||
|
||||
/*
|
||||
* handle_mouse_interrupt:
|
||||
* Interrupt handler for the mouse device. Called whenever the I/O
|
||||
* controller generates an interrupt for the PS/2 mouse. Reads mouse
|
||||
* information from the data port, and stores it, so it can be accessed
|
||||
* by read() operations. The full data is obtained using 3 consecutive
|
||||
* calls to the handler, each holds a different byte on the data port.
|
||||
* Parameters:
|
||||
* void*, ignored
|
||||
* Return value:
|
||||
* int, ???
|
||||
*/
|
||||
static int handle_mouse_interrupt(void* data)
|
||||
{
|
||||
char c;
|
||||
static int next_input = 0;
|
||||
|
||||
// read port
|
||||
c = in8(PS2_PORT_DATA);
|
||||
|
||||
// put port contents in the appropriate data member, according to
|
||||
// current cycle
|
||||
switch(next_input) {
|
||||
// status byte
|
||||
case 0:
|
||||
md_int.status = c;
|
||||
break;
|
||||
|
||||
// x-axis change
|
||||
case 1:
|
||||
md_int.delta_x += c;
|
||||
break;
|
||||
|
||||
// y-axis change
|
||||
case 2:
|
||||
md_int.delta_y += c;
|
||||
|
||||
// check if someone is waiting to read data
|
||||
if(in_read) {
|
||||
// copy data to read structure, and release waiting process
|
||||
memcpy(&md_read, &md_int, sizeof(mouse_data));
|
||||
memset(&md_int, 0, sizeof(mouse_data));
|
||||
in_read = false;
|
||||
release_sem_etc(mouse_sem, 1, B_DO_NOT_RESCHEDULE);
|
||||
} // if
|
||||
break;
|
||||
} // switch
|
||||
|
||||
next_input = (next_input + 1) % 3;
|
||||
return INT_NO_RESCHEDULE;
|
||||
} // handle_mouse_interrupt
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// file operations
|
||||
|
||||
/*
|
||||
* mouse_open:
|
||||
*/
|
||||
static int mouse_open(const char *name, uint32 flags, void **cookie)
|
||||
{
|
||||
*cookie = NULL;
|
||||
return 0;
|
||||
} // mouse_open
|
||||
|
||||
/*
|
||||
* mouse_close:
|
||||
*/
|
||||
static int mouse_close(void * cookie)
|
||||
{
|
||||
return 0;
|
||||
} // mouse_close
|
||||
|
||||
/*
|
||||
* mouse_freecookie:
|
||||
*/
|
||||
static int mouse_freecookie(void * cookie)
|
||||
{
|
||||
return 0;
|
||||
} // mouse_freecookie
|
||||
|
||||
/*
|
||||
* mouse_seek:
|
||||
*/
|
||||
static int mouse_seek(void * cookie, off_t pos, int st)
|
||||
{
|
||||
return EPERM;
|
||||
} // mouse_seek
|
||||
|
||||
/*
|
||||
* mouse_read:
|
||||
* Gets a mouse data packet.
|
||||
* Parameters:
|
||||
* void *, ignored
|
||||
* void*, pointer to a buffer that accepts the data
|
||||
* off_t, ignored
|
||||
* ssize_t, buffer size, must be at least the size of the data packet
|
||||
*/
|
||||
static ssize_t mouse_read(void * cookie, off_t pos, void* buf, size_t *len)
|
||||
{
|
||||
// inform interrupt handler that data is being waited for
|
||||
in_read = true;
|
||||
|
||||
// wait until there is data to read
|
||||
if(acquire_sem_etc(mouse_sem, 1, B_CAN_INTERRUPT, 0) ==
|
||||
EINTR) {
|
||||
return 0;
|
||||
} // if
|
||||
|
||||
// verify user's buffer is of the right size
|
||||
if(*len < PACKET_SIZE) {
|
||||
*len = 0;
|
||||
/* XXX - should return an error here */
|
||||
return 0;
|
||||
}
|
||||
|
||||
// copy data to user's buffer
|
||||
((char*)buf)[0] = md_read.status;
|
||||
((char*)buf)[1] = md_read.delta_x;
|
||||
((char*)buf)[2] = md_read.delta_y;
|
||||
|
||||
*len = PACKET_SIZE;
|
||||
return 0;
|
||||
} // mouse_read
|
||||
|
||||
/*
|
||||
* mouse_write:
|
||||
*/
|
||||
static ssize_t mouse_write(void * cookie, off_t pos, const void *buf, size_t *len)
|
||||
{
|
||||
*len = 0;
|
||||
return EROFS;
|
||||
} // mouse_write
|
||||
|
||||
/*
|
||||
* mouse_ioctl:
|
||||
*/
|
||||
static int mouse_ioctl(void * cookie, uint32 op, void *buf, size_t len)
|
||||
{
|
||||
return EINVAL;
|
||||
} // mouse_ioctl
|
||||
|
||||
/*
|
||||
* function structure used for file-op registration
|
||||
*/
|
||||
device_hooks ps2_mouse_hooks = {
|
||||
&mouse_open,
|
||||
&mouse_close,
|
||||
&mouse_freecookie,
|
||||
&mouse_ioctl,
|
||||
&mouse_read,
|
||||
&mouse_write,
|
||||
NULL,
|
||||
NULL,
|
||||
// NULL,
|
||||
// NULL
|
||||
}; // ps2_mouse_hooks
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// initialization
|
||||
|
||||
/*
|
||||
* wait_write_ctrl:
|
||||
* Wait until the control port is ready to be written. This requires that
|
||||
* the "Input buffer full" and "Output buffer full" bits will both be set
|
||||
* to 0.
|
||||
*/
|
||||
static void wait_write_ctrl()
|
||||
{
|
||||
while(in8(PS2_PORT_CTRL) & 0x3);
|
||||
} // wait_for_ctrl_output
|
||||
|
||||
/*
|
||||
* wait_write_data:
|
||||
* Wait until the data port is ready to be written. This requires that
|
||||
* the "Input buffer full" bit will be set to 0.
|
||||
*/
|
||||
static void wait_write_data()
|
||||
{
|
||||
while(in8(PS2_PORT_CTRL) & 0x2);
|
||||
} // wait_write_data
|
||||
|
||||
/*
|
||||
* wait_read_data:
|
||||
* Wait until the data port can be read from. This requires that the
|
||||
* "Output buffer full" bit will be set to 1.
|
||||
*/
|
||||
static void wait_read_data()
|
||||
{
|
||||
while((in8(PS2_PORT_CTRL) & 0x1) == 0);
|
||||
} // wait_read_data
|
||||
|
||||
/*
|
||||
* write_command_byte:
|
||||
* Writes a command byte to the data port of the PS/2 controller.
|
||||
* Parameters:
|
||||
* unsigned char, byte to write
|
||||
*/
|
||||
static void write_command_byte(unsigned char b)
|
||||
{
|
||||
wait_write_ctrl();
|
||||
out8(PS2_CTRL_WRITE_CMD, PS2_PORT_CTRL);
|
||||
wait_write_data();
|
||||
out8(b, PS2_PORT_DATA);
|
||||
} // write_command_byte
|
||||
|
||||
/*
|
||||
* write_aux_byte:
|
||||
* Writes a byte to the mouse device. Uses the control port to indicate
|
||||
* that the byte is sent to the auxiliary device (mouse), instead of the
|
||||
* keyboard.
|
||||
* Parameters:
|
||||
* unsigned char, byte to write
|
||||
*/
|
||||
static void write_aux_byte(unsigned char b)
|
||||
{
|
||||
wait_write_ctrl();
|
||||
out8(PS2_CTRL_WRITE_AUX, PS2_PORT_CTRL);
|
||||
wait_write_data();
|
||||
out8(b, PS2_PORT_DATA);
|
||||
} // write_aux_byte
|
||||
|
||||
/*
|
||||
* read_data_byte:
|
||||
* Reads a single byte from the data port.
|
||||
* Return value:
|
||||
* unsigned char, byte read
|
||||
*/
|
||||
static unsigned char read_data_byte()
|
||||
{
|
||||
wait_read_data();
|
||||
return in8(PS2_PORT_DATA);
|
||||
} // read_data_byte
|
||||
|
||||
/*
|
||||
* mouse_dev_init:
|
||||
* Called by the kernel to setup the device. Initializes the driver.
|
||||
* Parameters:
|
||||
* kernel_args*, ignored
|
||||
* Return value:
|
||||
* int, 0 if successful, negative error value otherwise
|
||||
*/
|
||||
int mouse_dev_init(kernel_args *ka)
|
||||
{
|
||||
dprintf("Initializing PS/2 mouse\n");
|
||||
|
||||
// init device driver
|
||||
memset(&md_int, 0, sizeof(mouse_data));
|
||||
|
||||
// register interrupt handler
|
||||
int_set_io_interrupt_handler(INT_BASE + INT_PS2_MOUSE,
|
||||
&handle_mouse_interrupt, NULL);
|
||||
|
||||
// must enable the cascade interrupt
|
||||
arch_int_enable_io_interrupt(INT_BASE + INT_CASCADE);
|
||||
|
||||
// enable auxilary device, IRQs and PS/2 mouse
|
||||
write_command_byte(PS2_CMD_DEV_INIT);
|
||||
write_aux_byte(PS2_CMD_ENABLE_MOUSE);
|
||||
|
||||
// controller should send ACK if mouse was detected
|
||||
if(read_data_byte() != PS2_RES_ACK) {
|
||||
dprintf("No PS/2 mouse found\n");
|
||||
return -1;
|
||||
} // if
|
||||
|
||||
dprintf("A PS/2 mouse has been successfully detected\n");
|
||||
|
||||
// create the mouse semaphore, used for synchronization between
|
||||
// the interrupt handler and the read() operation
|
||||
mouse_sem = create_sem(0, "ps2_mouse_sem");
|
||||
if(mouse_sem < 0)
|
||||
panic("failed to create PS/2 mouse semaphore!\n");
|
||||
|
||||
// register device file-system like operations
|
||||
devfs_publish_device("ps2mouse", NULL, &ps2_mouse_hooks);
|
||||
|
||||
return 0;
|
||||
} // mouse_dev_init
|
Loading…
Reference in New Issue
Block a user