Page 1 of 4

Mouse Problems

Posted: Thu Oct 05, 2006 9:33 am
by Jeko
I have readed the code in this forum for the mouse, and I have implemented it in my OS. But I have encountered some problems.
The mouse driver doesn't work! It happen nothing, but the keyboard stop working.
This is the code of the mouse driver:

Code: Select all

int x = 80, y = 80;
unsigned char data[3];
unsigned char mouse_type;
static volatile int button[3] = {0, 0, 0};

void left_button_down(int x, int y)
{
}

void left_button_up(int x, int y)
{
}

void right_button_down(int x, int y)
{
	asm("sti");
	outportb(0x64, 0xFE);
	asm("cli");
	asm("hlt");
}

void right_button_up(int x, int y)
{
}

void middle_button_down(int x, int y)
{
}

void middle_button_up(int x, int y)
{
}

void pos_mouse(int x, int y)
{
}

inline void mouse_wait(unsigned char a_type)
{
	unsigned int _time_out = 100000;
	if(a_type == 0)
	{
		while(_time_out--)
		{
			if((inportb(0x64) & 1) == 1)
			{
				return;
			}
		}
		return;
	}
	else
	{
		while(_time_out--)
		{
			if((inportb(0x64) & 2) == 0)
			{
				return;
			}
		}
		return;
	}
}

inline void mouse_write(unsigned char a_write)
{
	//Aspetta di essere in grado di mandare un segnale
	mouse_wait(1);
	//Diciamo al mouse che gli stiamo mandando un comando
	outportb(0x64, 0xD4);
	//Aspetta per la parte finale
	mouse_wait(1);
	//Alla fine scrivi
	outportb(0x60, a_write);
}

unsigned char mouse_read(void)
{
	//Aspetta e poi prende la risposta dal mouse
	mouse_wait(0);
	return inportb(0x60);
}

void ps2_mouse(void)
{
	printf("MOUSE INT\n");
    data[0] = inportb(0x60);
    data[1] = inportb(0x60);
    data[2] = inportb(0x60);

    if ((data[0] & 0x01) != button[0])
    {
        button[0] ^= 1;
        if (button[0]) left_button_down(x, y);
        else left_button_up(x, y);
    }
    if ((data[0] & 0x04) != button[1])
    {
        button[1] ^= 1;
        if (button[1]) middle_button_down(x, y);
        else middle_button_up(x, y);
    }
    if ((data[0] & 0x02) != button[2])
    {
        button[2] ^= 1;
        if (button[2]) right_button_down(x, y);
        else right_button_up(x, y);
    }
    if (data[0] & 0x10)
        x += (int)((256 - data[1]) * -1);
    else
        x += (int)data[1];
    if (data[0] & 0x20)
        y += (int) (256 - data[2]);
    else
        y += (int)(data[2] * -1);
    if (y > 184) y = 184;
    else if (y < 0) y = 0;
    if (x > 311) x = 311;
    else if (x < 0) x = 0;

    pos_mouse(x, y);
}

void mouse_install(void)
{
	unsigned char _status;

	//Abilita il dispositivo aux mouse
	mouse_wait(1);
	outportb(0x64, 0xA8);

	//Abilita gli interrupts
	mouse_wait(1);
	outportb(0x64, 0x20);
	mouse_wait(0);
	_status = (inportb(0x60) | 2);
	mouse_wait(1);
	outportb(0x64, 0x60);
	mouse_wait(1);
	outportb(0x60, _status);

	//Diciamo al mouse di utilizzare le opzioni di default
	mouse_write(0xF6);
	mouse_read();

	//Abilita il mouse
	mouse_write(0xF4);
	mouse_read();

	//Installa l'irq handler per il mouse
	add_irq(ps2_mouse, 12);
	abilita_irq(4, 0xA1);
}
And this is the code of the 8259:

Code: Select all

unsigned char irq_number[8] = {
			    0xfe,
			    0xfd,
			    0xfb,
			    0xf7,
			    0xef,
			    0xdf,
			    0xbf,
			    0x7f
			    };

void Init8259(void)
{
	int i;
	static const unsigned irq0_int = 0x20, irq8_int = 0x28;

	/* Initialization Control Word #1 (ICW1) */
	outportb(0x20, 0x11);
	outportb(0xA0, 0x11);

	/* Initialization Control Word #2 (ICW2) */

	//route IRQs 0-7 to INTs 20h-27h
	outportb(0x21, irq0_int);

	// route IRQs 8-15 to INTs 28h-2Fh
	outportb(0xA1, irq8_int);

	/* Initialization Control Word #3 (ICW3) */
	outportb(0x21, 0x04);
	outportb(0xA1, 0x02);

	/* Initialization Control Word #4 (ICW4) */
	outportb(0x21, 0x01);
	outportb(0xA1, 0x01);

	for(i=0; i <= 7; i++)
		disabilita_irq(i, 0x21);

	for(i=0; i <= 7; i++)
		disabilita_irq(i, 0xA1);
}

void abilita_irq(unsigned char irq_num, unsigned char port_num)
{
	char dato;
	dato = inportb(port_num);
	dato = dato & irq_number[irq_num];

	outportb(port_num, dato); 
}

void disabilita_irq(unsigned char irq_num, unsigned char port_num)
{
	char dato;
	dato = inportb(port_num);
	dato = dato | (1<<irq_num);

	outportb(port_num, dato); 
}

Posted: Fri Oct 06, 2006 7:18 am
by digo_rp
some kbd controller doesn´t enable irq12 for ps2mouse port
then you have to enable by your hand. you have too when you get your mouse working to change those lines below:

data[0] = inportb(0x60);
data[1] = inportb(0x60);
data[2] = inportb(0x60);

to
N++;
data[N] = inportb(0x60);

because the kdb controler generate irq12 each mouse byte;

Posted: Mon Oct 09, 2006 7:33 am
by Jeko
if I have the code for enabling irq12 from kbd controller, when I move the mouse I get this from bochs:
[CPU0 ] LOCK prefix unallowed (op1=0x53, attr=0x0, mod=0x0, nnn=0)

Also if I remove that code, when I move the mouse I get the error that the keyboard buffer is full.

Posted: Tue Oct 10, 2006 1:33 pm
by gaf
If I have the code for enabling irq12 from kbd controller, when I move the mouse I get this from bochs:
[CPU0 ] LOCK prefix unallowed (op1=0x53, attr=0x0, mod=0x0, nnn=0)
Sounds like a problem with your IVT/IDT setup: When the interrupt occures the processor faults trying to switch to the handler as the entry in the interrupt table isn't valid.

Does it work for the keyboard handler ?
Also if I remove that code, when I move the mouse I get the error that the keyboard buffer is full.
If the ISR doesn't read the position data from 0x60 the buffer remains full. Bochs informs you when the next packet arrives as it can't store it in the already keyboard buffer.

cheers,
gaf

Posted: Wed Oct 11, 2006 3:56 am
by Jeko
My keyboard handler works.
I resolved the problem, my ps/2 mouse works at IRQ2, I must enable both IRQ2 and IRQ12. Why?

Posted: Wed Oct 11, 2006 4:40 am
by digo_rp
I think cuz you have 2 8259 at your pc and one is connected to other one using IRQ2 - IRQ9 I think. then when you just enable irq12 and doesn´t enable IRQ2 from the first PIC, your processor doesn´t receive any IRQ from 8 to 15. sorry for my poor english

Posted: Wed Oct 11, 2006 4:46 am
by Jeko
really? in the IDT too I enabled the IRQ2(entry 34), but not the entry of IRQ12

Posted: Mon Oct 23, 2006 11:19 am
by inflater
Hi,
please, can you guide me to source code of function add_irq ? I need to convert it to Pascal from C (myself).

thanx !!
inflater

Posted: Tue Oct 24, 2006 7:03 am
by gaf
can you guide me to source code of function add_irq ?
The code wouldn't help you much as interrupt management is very operating system specific. You might want to have a look at some of the Bonafide tutorials on IDT, IRQs adn interrupts to find out how to write the missing functions yourself.

regards,
gaf

Posted: Tue Oct 24, 2006 8:10 am
by inflater
interrupt management is very operating system specific
I think not.

Dex (or other dude) has helped me with procedures GetIntVec/SetIntVec:

Code: Select all

Procedure SetIntVec(Vec:integer;VAddr:pointer);
begin
pointer(meml[0:vec*4]) := vaddr;
end;

Procedure GetIntVec(Vec:integer;VAddr:pointer);
begin
vaddr:=pointer(meml[0:vec*4]);
end;
(thx dex !!!)

I do not see here any OS specific functions, it is all about BIOS - Basic Input Output System. :!: I would like to have the function "add_irq" in this (Pascal) or, C declaration. I can (almost) translate any simpler codes to Pascal. The IDT or something must be handled trough BIOS, no? Or i am wrong then ;) and must learn more (please dont find, what age i have... :D)

besides, on Bonafide are only C tutes and i think that are protected mode interrupt descriptors... i am programming real mode (for now)

thx for answers ! :D
inflater

Posted: Tue Oct 24, 2006 8:41 am
by gaf
I am programming real mode (for now)
The vast majority of developers on this board uses flat protected-mode. If you're running something different you probably should mention it..
Besides, on Bonafide are only C tutes and i think that are protected mode interrupt descriptors
Except for the different tables (IVT/IDT) the basic ideas of interrupt handling is pretty much the same for real-mode. It would probably be a good idea to read at least some of the tutorials to learn how it all works behind the scenes. Otherwise you'll eventually run into problems as you can't understand the snippets you're using for operating system without knowing about the theory.

regards,
gaf

Posted: Tue Oct 24, 2006 9:31 am
by inflater
If you're running something different you probably should mention it
Sorry then; i think that is impossible to build an protected mode OS in BORLAND PASCAL 7.0 - it requires that DPMI - DOS protected blah blah.
Otherwise you'll eventually run into problems as you can't understand the snippets you're using for operating system without knowing about the theory
I can understand (partially) these things; i need only a Pascal function that will do it. Like that interrupt vector handling (getintvec-setintvec), a simple syntax:

add_irq(X,Y)

will do the trick. (i tested the setintvec functions, i know what i am are doing ! :D - i created a simple OS interrupt with I/O functions and other stuff on INT 30h :D :D)

I know that IRQs are trigerred by hardware peripherals and other stuff. I just need some Pascal function that will do it... only code of the fn. The rest will be on me completely, dont worry.

inflater

Posted: Tue Oct 24, 2006 9:38 am
by Brendan
Hi,
inflater wrote:I do not see here any OS specific functions, it is all about BIOS - Basic Input Output System. :!: I would like to have the function "add_irq" in this (Pascal) or, C declaration. I can (almost) translate any simpler codes to Pascal. The IDT or something must be handled trough BIOS, no? Or i am wrong then ;) and must learn more (please dont find, what age i have... :D)
The BIOS doesn't have any functions to install interrupt handlers.

For real mode, your code shares the computer with the BIOS, so your code needs to keep the BIOS happy. This means that depending on which interrupt your installing, the new interrupt may need to "chain" the old interrupt handler so that the old interrupt handler is jumped to at the end of the new interrupt handler. This also means (for e.g.) that if you change the frequency of the PIT timer you'd still need to jump to the BIOS's interrupt handler at the old frequency (18.2 Hz) if you want the BIOS to keep track of time correctly.

Also, you can still remap the PIC chips so that they don't conflict with the CPUs exceptions. this isn't that hard. For an example, if you remap the PIC chips to generate interrupts 0x68 to 0x77, then you'd need interrupt handlers for 0x68 to 0x6F that jump to the old/BIOS's interrupt handlers (at interrupts 0x08 to 0x0F). In this case if you can install exception handlers without worrying about things like IRQ5 (which uses interrupt 15, the same as the general protection fault handler).

For some interrupts, the BIOS either doesn't use them or doesn't do anything you want to keep with them. These you can simply replace without chaining the old interrupt handler.
inflater wrote:Dex (or other dude) has helped me with procedures GetIntVec/SetIntVec:

Code: Select all

Procedure SetIntVec(Vec:integer;VAddr:pointer);
begin
pointer(meml[0:vec*4]) := vaddr;
end;
Does the compiler set the new interrupt vector atomically (i.e. as a single 32-bit write), or is it possible for an interrupt to occur after the first half is set but before the second half is set?
inflater wrote:i am programming real mode (for now)
What do you mean by "for now"? If you're planning on using protected mode eventually, then I'd recommend skipping real mode completely. In general, the only thing good about real mode is that you can use BIOS functions, but there's nothing good about any of the BIOS functions so it's mostly pointless anyway.


Cheers,

Brendan

Posted: Tue Oct 24, 2006 9:42 am
by Brendan
Hi again,
inflater wrote:Sorry then; i think that is impossible to build an protected mode OS in BORLAND PASCAL 7.0 - it requires that DPMI - DOS protected blah blah.
If the only reason you're using real mode is your tools, then the answer would be to find suitable tools....

Have you considered GNU Pascal?


Cheers,

Brendan

Posted: Tue Oct 24, 2006 9:48 am
by inflater
Yep, but it is a long story:

I cant find the download link !

No seriously, i CANT find the DOWNLOAD LINK for ALREADY compiled executables & tools. I have found only EXECUTABLES for faster compiling or something and not a COMPLETE precompiled app pack.

I've downloaded DEV-PAS, and there was no gnu pascal, only some compiler (NOT a GP).

But, I dont want to download GP, because of... for example: CRT unit. There is nothing better than a patched unit from Pedt Scragg (RE 200) and not a other unit... The GP unit may not have functions like Sound, Window and so on. I will be on BP. I only need SOURCE CODE of FUNCTION add_irq. That is all. Thanx !

inflater