I assume that your hobby OS is 32-bit targetted on x86 machines. The following outlines the steps.
- Program the 8259 controller to enable IRQ2, the cascade line. The PS/2 mouse IRQ is IRQ12 which is in the slave PIC. Normally the IRQ numbers are remapped in 32-bit OSes.
#define IRQ_TIMER 1 #define IRQ_CASCADE 4 #define IRQ_KEYBOARD 2 #define IRQ_FDC 64 #define IRQ_MOUSE 16 void program8259(unsigned char b){ unsigned char b1=0xFF; //remap the IRQs outportb(0x20,0x11); outportb(0xA0,0x11); outportb(0x21,0x20); //IRQ0-IRQ7 -> interrupts 0x20-0x27 outportb(0xA1,0x28); //IRQ8-IRQ15 -> interrupts 0x28-0x2F outportb(0x21,4); outportb(0xA1,2); outportb(0x21,1); outportb(0xA1,1); b1^=b; outportb(0x21,b1); outportb(0xA1, inportb(0xA1) & ~0x10); //enable IRQ12 }; //Here's the call to enable needed IRQ Lines called usually in the main() function program8259(IRQ_TIMER | IRQ_KEYBOARD | IRQ_FDC | IRQ_CASCADE);
- And here's the driver code courtesy of SANiK.
//Mouse.inc by SANiK //License: Use as you wish, except to cause damage unsigned char mouse_cycle=0; signed char mouse_byte[3]; signed char mouse_x=0; signed char mouse_y=0; /* The interrupt handler */ void mouse_irq(){ DWORD flags; switch(mouse_cycle){ case 0: mouse_byte[0]=inportb(0x60); mouse_cycle++; break; case 1: mouse_byte[1]=inportb(0x60); mouse_cycle++; break; case 2: mouse_byte[2]=inportb(0x60); mouse_x=mouse_byte[1]; mouse_y=mouse_byte[2]; mouse_cycle=0; break; } } inline void mouse_wait(unsigned char a_type){ unsigned int _time_out=100000; //unsigned int if(a_type==0){ while(_time_out--){ //Data if((inportb(0x64) & 1)==1){ return; } } return; }else{ while(_time_out--){ //Signal if((inportb(0x64) & 2)==0){ return; } } return; } } inline void mouse_write(unsigned char a_write){ //Wait to be able to send a command mouse_wait(1); //Tell the mouse we are sending a command outportb(0x64, 0xD4); //Wait for the final part mouse_wait(1); //Finally write outportb(0x60, a_write); } unsigned char mouse_read(){ //Get's response from mouse mouse_wait(0); return inportb(0x60); } void installmouse(){ /* This enables the mouse, called in main() */ unsigned char _status; //Enable the auxiliary mouse device mouse_wait(1); outportb(0x64, 0xA8); //Enable the 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); //Tell the mouse to use default settings mouse_write(0xF6); mouse_read(); //Acknowledge //Enable the mouse mouse_write(0xF4); mouse_read(); //Acknowledge //Depends on your OS! setinterruptvector(0x2C,idtbase,0x8E,mousewrapper,SYS_CODE_SEL); printf("Mouse successfully initialized.\n"); } void get_mouse_pos(signed char *x,signed char *y){ *x=mouse_x; *y=mouse_y; }
- The mousewrapper code is important for the IRET so it is written in assembly. It just actually calls mouse_irq defined in the driver above..
global mousewrapper mousewrapper: push ebp push gs push fs push es push ss push ds pusha call mouse_irq ;re-enable interrupts, this is IMPORTANT! mov al,0x20 out 0xA0,al out 0x20,al popa pop ds pop ss pop es pop fs pop gs pop ebp iret
HUGE BOON.
ReplyDeleteDos uses int33 and Linux uses hidden obscure code that cant be found.
HID references are nice, but I need to start with a base of operations as PS2 keyboard and mouse are on same controller. THANK YOU!!
--FPOS is at rjasmin.net and fpos.firmos.at/fpos for SVN, you need a client like tortoise.
Might be broken for a little while yet, but its taking off.