Last active
January 1, 2018 13:07
-
-
Save nelsoncole/92f843b0ef4fc6161cdbe4a5eced2657 to your computer and use it in GitHub Desktop.
Teste de PS/2 mouse (Borland C++ 3.1 - MS-DOS)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* C¢digo para o Borland C++ 3.1. | |
coloquei delays de 1us entre escritas/leituras para o KBDC. | |
coloquei verificação de acknowledge depois de mouse_writes. | |
Ainda travando | |
OK! Tio Fred estamos lidando com dispositivos seriais, na verade dois dispositivos partilhando o mesmo Chip, | |
sabes o aquão trasçueiros eles são. | |
Ao que parce o código merecer uma reescrita completa, tentei altera-lo no mínimo | |
*/ | |
#include <stddef.h> | |
#include <dos.h> | |
#include <conio.h> | |
char buttons = 0; | |
char mouse_x = 0; | |
char mouse_y = 0; | |
// Tio Fred estas variaves também devem ser globais senão zeramos a cada irq12 | |
char mouse_data[3]; | |
int pos = 0; | |
enum kbdc_reg { | |
KBDC_OUTPUT, | |
KBDC_INPUT | |
}; | |
// Ponteiro para o antigo vetor 0x74 (irq12). | |
static void interrupt (far *oldvect)(void) = NULL; | |
// handler que vai ser chamado pela ISR da IRQ 12. | |
// Note que o handler é chamado para cada byte disponibilizado | |
// pelo auxiliary device (mouse)... Isso está certo? | |
static void interrupt far mouse_handler(void) | |
{ | |
mouse_data[pos++] = inportb(0x60); | |
if (pos == 3) | |
{ | |
// Tio Fred ! Eu nao sei o porquê mas em meu VM (Qemu), nalguma das vezes os dados vêm nesta ordem. | |
// Inco somente acontece quando o cusor do mouse está por fora do VM, no meio de sua configuração | |
// penso que seja a falta da confirmação do KBDC_OK (0xAA) | |
buttons = mouse_data[0]; | |
mouse_x = mouse_data[1]; | |
mouse_y = mouse_data[2]; | |
pos = 0; | |
} | |
outportb(0xa0, 0x20); // EOI. | |
// Tio Fred o PIC 1 Também deve enviar um EOI, devido o modo cascata IRQ2 | |
outportb(0x20,0x20); | |
// enable(); // STI (é necessário aqui?). Não, não é necessário | |
} | |
#define io_delay() asm { out 0x80,al } | |
static void mouse_wait(enum kbdc_reg buff) | |
{ | |
int time_out =0; // E o zero? | |
// Ok... vamos fazer isso, no m ximo 65536 vezes. | |
if (buff == KBDC_OUTPUT) | |
{ | |
while (--time_out) | |
// Se temos dados no output buffer, sai... | |
if (inportb(0x64) & 1) | |
break; | |
} | |
else | |
while (--time_out) | |
// Se o input buffer est limpo, sai... | |
if (!(inportb(0x64) & 2)) | |
break; | |
} | |
static void mouse_write(unsigned char data) | |
{ | |
mouse_wait(KBDC_INPUT); | |
outportb(0x64, 0xD4); | |
io_delay(); | |
mouse_wait(KBDC_INPUT); | |
outportb(0x60, data); | |
io_delay(); | |
} | |
static unsigned char mouse_read(void) | |
{ | |
unsigned char b; | |
mouse_wait(KBDC_OUTPUT); | |
b = inportb(0x60); | |
io_delay(); | |
return b; | |
} | |
void mouse_install(void) | |
{ | |
unsigned char ram0; | |
// mascara IRQ1 e IRQ12. (Dica do Nelson Cole). | |
disable(); | |
outportb(0x21, inport(0x21) | (1 << 1)); | |
outportb(0xa1, inport(0xa1) | (1 << 4)); | |
mouse_wait(KBDC_INPUT); | |
outportb(0x64,0xAD); // Desativar a primeira porta PS/2 | |
mouse_wait(KBDC_INPUT); | |
outportb(0x64,0xA7); /* Desativar a segunda porta PS/2, hahaha por default ela já vem desativada, só pra constar */ | |
// Habilita IRQ 12 no KBDC. | |
mouse_wait(KBDC_INPUT); | |
outportb(0x64, 0x20); | |
io_delay(); | |
mouse_wait(KBDC_OUTPUT); | |
ram0 = (inportb(0x60) | 2); | |
io_delay(); | |
mouse_wait(KBDC_INPUT); | |
outportb(0x64, 0x60); | |
io_delay(); | |
mouse_wait(KBDC_INPUT); | |
outportb(0x60, ram0); | |
io_delay(); | |
// Habilita a primeira porta PS/2 | |
mouse_wait(KBDC_INPUT); | |
outportb(0x64,0xAE); | |
io_delay(); | |
// Habilita o auxiliary device. | |
mouse_wait(KBDC_INPUT); | |
outportb(0x64, 0xa8); | |
io_delay(); | |
// Espera terminar | |
mouse_wait(KBDC_INPUT); | |
// Reseta mouse. | |
mouse_write(0xff); | |
while (mouse_read() == 0xfA); // Espera os dados descer (ACK) | |
// while (mouse_read() != 0xaa); // Reset Ack! | |
// FIXME: Trava logo que tenta mouse_read(), acima... | |
// Restaura defaults do PS/2 mouse. | |
mouse_write(0xf6); | |
// while (mouse_read() != 0xfA) // Ack | |
// Habilita o mouse streaming | |
mouse_write(0xf4); | |
while (mouse_read() == 0xfA); // Espera os dados descer (ACK) | |
mouse_wait(KBDC_INPUT); // Espera nossa controladora terminar | |
// Instala o novo ISR, mantendo o velho. | |
oldvect = getvect(0x74); | |
setvect(0x74, mouse_handler); | |
// desmascara a IRQ12 e IRQ1 no PIC. | |
outportb(0xa1, inportb(0xa1) & ~(1 << 4)); | |
outportb(0x21, inportb(0x21) & ~(1 << 1)); | |
enable(); | |
} | |
void mouse_uninstall(void) | |
{ | |
unsigned char ram0; | |
// Mascara IRQ1 e IRQ12 no PIC. | |
disable(); | |
outportb(0x21, inport(0x21) | (1 << 1)); | |
outportb(0xa1, inport(0xa1) | (1 << 4)); | |
mouse_wait(KBDC_INPUT); | |
outportb(0x64,0xAD); // Desativar a primeira porta PS/2 | |
mouse_wait(KBDC_INPUT); | |
outportb(0x64,0xA7); // Desativar a segunda porta PS/2 | |
// Desabilita IRQ 12 no KBDC. | |
mouse_wait(KBDC_INPUT); | |
outportb(0x64, 0x20); | |
io_delay(); | |
mouse_wait(KBDC_OUTPUT); | |
ram0 = (inportb(0x60) & ~2); | |
mouse_wait(KBDC_INPUT); | |
outportb(0x64, 0x60); | |
io_delay(); | |
mouse_wait(KBDC_INPUT); | |
outportb(0x60, ram0); | |
io_delay(); | |
// Desabilita o auxiliary device. | |
mouse_wait(KBDC_INPUT); | |
outportb(0x64, 0xa7); | |
io_delay(); | |
mouse_wait(KBDC_INPUT); | |
// Retorna com a velha ISR para a IRQ 12. | |
setvect(0x74, oldvect); | |
// Habilita a primeira porta PS/2 | |
mouse_wait(KBDC_INPUT); | |
outportb(0x64,0xAE); | |
io_delay(); | |
mouse_wait(KBDC_INPUT); | |
// desmascara aIRQ1 no PIC. | |
outportb(0x21, inportb(0x21) & ~(1 << 1)); | |
enable(); | |
} | |
void main(void) | |
{ | |
mouse_install(); | |
// Enquanto não clicou no botão esquerdo... | |
while(!(buttons & 1)) | |
// Imprime as coordenadas. | |
cprintf("(%d, %d)\r", mouse_x, mouse_y); | |
cprintf("\nFeliz ano novo!"); | |
mouse_uninstall(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment