Newsgroup: it.comp.os.linux.development
Titolo: leggere un carattere dalla porta keyboard con SYSCALL ioperm

ciao a tutti,
premetto che posto questo msg dopo aver cercato ovunque sulla rete.
Linguaggio ASSEMBLER
Utilizzo la sintassi AT&T e Gas come assemblatore: kernel 2.4.20
il mio obbiettivo e il seguente:
1-digitare un tasto numerico
2-il programma lo prende lo converte in un long e lo mette in un buffer
3-aspetta un'altro tasto
4-con enter interrompo la sequenza
N.b. l'imissione non deve avvenire con enter. io premo e lui(il 
programma) lo tratta
Dando uno sguardo a UNISTD.H ho visto che il kernel implementa un 
syscall la 101 (65h) con la quale è possibile interagire con le porte 
hardware.
Di seguito ho cercato l'indirizzo di I/O della mia keyboard 
(/proc/ioports) che risulta essere 0x060-0x06f
Il programma qui sotto e quello che dovrebbe funzionare ma il loop 
wait_char esce subito poichè la porta contiene un carattere
precisamente FS (28 dec; 1C hex) e non so perchè.
La chiamata alla syscal funziona perfettamente in quanto in eax non 
ottengo valori diversi da 0 e ovviamente il programma non salta a fine.
Vorrei capire poiché il loop wait_char termina subito nonostante io non 
prema nulla e che comunque azzeri il registro eax
chi scrive 1c nella porta???
gradite altre soluzioni per arrivare allo stesso obbiettivo senza il 
supporto del C
#PROGRAM:	getcharfromport
#SCOPO: legge un carattere numerico direttamenta dalla porta della tastiera
#	lo converte in long
#	utilizza interrupt 101 ioperm(PORT ADDRESS, SIZE PORTS, BOOL 
enable/disable)
#	documentato in UNISTD.h di linux
#REGISTER:	%eax numero interruzione
#		%ebx:Port Numerber
#		%ecx:enabled/disabled port
.section	.data
	.equ	EXIT,		0X01
	.equ	PORT_ADDR,	0X60
	.equ	PORT_SIZE,	0X05
	.equ	ENABLED,	0X01
	.equ	LINUX_SYSCALL, 	0X80
	.equ	SYS_IOPERM,	0X65
 
	buf:		.byte	0
 
.SECTION	.text
.globl _start
_start:
	push	$buf
	movl	$SYS_IOPERM,	%eax
	movl	$PORT_ADDR,	%ebx
	movl	$PORT_SIZE,	%ecx
	movl	$ENABLED,	%edx
----->	int	$LINUX_SYSCALL		
	cmpl	$0,%eax		QUI E' OK $EAX=0
	jne	fine
	jmp 	wait_char
wait_char:
	movl	$0, %eax
	in	$0x60,%al  ???????????????????????????????''
	cmp $0,%al
	je wait_char
	jne leggi
leggi:
	movl	(%esp),%edx
	movb	%al,(%edx)
	jmp	fine
fine:
	movl 	$EXIT,%eax
	int	$LINUX_SYSCALL



 hardware.
qui mi blocco e ti posto una soluzione alternativa, cuttando il resto del
post perchè secondo me hai scelto una strada, se non sbagliata, inutilmente
complicata. Puoi benissimo leggere i caratteri non appena premuti con la
syscall read, basta disabilitare il buffering sullo standard input.
Ti scrivo una soluzione in C e una in assembly (sintassi nasm):
#include <stdio.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
int main(){
char blah;
set_raw_mode();
while(1) {
        read(0,&blah,1);
        write(1,&blah,1);
}
}
int set_raw_mode(void)
{
struct termios t;
tcgetattr(0, &t);
t.c_lflag &= ~ICANON;
tcsetattr(0, TCSANOW, &t);
return 0;
}
ora la soluzione in assembly, che include alla fine il codice per
ripristinare il terminale alle impostazioni originali
%define IOCTL 54
%define TCGETS 5401h
%define TCSETS 5402h
%define ICANON 2o
%define sizeof_termios 60
%define offset_c_lflag 12
global _start
_start:
        enter sizeof_termios,0
        mov eax,IOCTL
        mov ebx,0
        mov ecx,TCGETS
        lea edx,[ebp-sizeof_termios]
        int 80h
        and dword [ebp-sizeof_termios+offset_c_lflag],~ICANON
        mov eax,IOCTL
        mov ecx,TCSETS
        int 80h
[resto del programma]
[ora ripristiniamo il terminale]
        or dword [ebp-sizeof_termios+offset_c_lflag],ICANON
        mov eax,IOCTL
        mov ebx,0
        mov ecx,TCSETS
        lea edx,[ebp-sizeof_termios]
        int 80h
        mov eax,1
        xor ebx,ebx
        int 80h
Ciao
-- 
none

 hardware.
Sei sicuro di poter accedere a quei registri in user-mode?
L'indirizzo a cui cerchi di accedere e` sicuramente un indirizzo fisico, 
se tu accedi a 0x65 da un programma invece accedi all'indirizzo 0x65 
dello spazio di memoria virtuale allocato per la tua applicazione. 
Quello che vuoi fare tu lo potresti fare all'interno di un modulo del 
kernel ed anche li' dovresti usare probabilmente alcune delle macro di 
accesso alla memoria.
Bye,
  Gabry