Page 1 of 2

Hardware cursor

Posted: Fri Jul 22, 2005 2:23 pm
by marcio.f
Hi,

The following code:

Code: Select all

void _main(void* mbd, unsigned int magic)
{
   char *port = (char *)0x3D4;
   
   port[0] = 0x0F;
   port[1] = (char)0;
   
   port[0] = 0x0E;
   port[1] = (char )0;
   
   while (1);
}
should place the hardware cursor on line and column 0, right? But I couldn't do it with the Bare Bones example from the wiki. Am I doing something wrong?

Thanks in advance ;)

Re:Hardware cursor

Posted: Fri Jul 22, 2005 2:46 pm
by pini
Actually, writing to port XX doesn't mean writing to memory location XX.
The only way to read/write to ports is to use processor specific instructions. If you intend to use C, you'll have to use either asm stubs or inline asm.

Ports are mapped somewhere in the memory (is it real physical one ? i'm not sure this is necessary), but it's not a 1:1 mapping. This means that you simply can't access a port by accessing to a memory cell (like you tried in the code above).

Re:Hardware cursor

Posted: Fri Jul 22, 2005 4:37 pm
by AR
Ports exist in the IO Address Space and can only be accessed by in and out. Some things do use memory mapped registers like the APIC for example, but things like the PS/2 chip and PIT use ports, I'm not sure what the tendency is in new hardware.

Code: Select all

#define INB(Port, Data)  __asm__ ("inb %1, %0" : "=a"(Data) : "Nd"(Port))
#define INW(Port, Data)  __asm__ ("inw %1, %0" : "=a"(Data) : "Nd"(Port))
#define INL(Port, Data)  __asm__ ("inl %1, %0" : "=a"(Data) : "Nd"(Port))
#define OUTB(Port, Data) __asm__ ("outb %0, %1" : : "a"(Data), "Nd"(Port))
#define OUTW(Port, Data) __asm__ ("outw %0, %1" : : "a"(Data), "Nd"(Port))
#define OUTL(Port, Data) __asm__ ("outl %0, %1" : : "a"(Data), "Nd"(Port))

Re:Hardware cursor

Posted: Sat Jul 23, 2005 2:26 am
by Pype.Clicker
you have such functions (and more) available in the FAQ (check "http://www.osdev.org/osfaq2/index.php/SampleInlineFunctions")

The "tendency" nowadays is still a matter of implementor preference: my audio chip use ports, my nvidia card uses only memory and my RTL network card uses both ...

Re:Hardware cursor

Posted: Sat Jul 23, 2005 4:47 pm
by marcio.f
@AR:
I couldn't use your OUTB:

Code: Select all

/usr/cross/bin/i586-elf-as -o loader.o init/loader.s
/usr/cross/bin/i586-elf-gcc -Wall -Werror -nostdlib -nostartfiles -nodefaultlibs -o kernel.o -c kernel.c
/cygdrive/c/DOCUME~1/marciof/DEFINI~1/Temp/cclyNKF0.s: Assembler messages:
/cygdrive/c/DOCUME~1/marciof/DEFINI~1/Temp/cclyNKF0.s:23: Error: suffix or operands invalid for `out'
/cygdrive/c/DOCUME~1/marciof/DEFINI~1/Temp/cclyNKF0.s:28: Error: suffix or operands invalid for `out'
/cygdrive/c/DOCUME~1/marciof/DEFINI~1/Temp/cclyNKF0.s:33: Error: suffix or operands invalid for `out'
/cygdrive/c/DOCUME~1/marciof/DEFINI~1/Temp/cclyNKF0.s:39: Error: suffix or operands invalid for `out'
make: *** [kernel.o] Error 1
in the following code:

Code: Select all

#define OUTB(Port, Data) __asm__ ("outb %0, %1" : : "a"(Data), "Nd"(Port))

void _main(void* mbd, unsigned int magic)
{
   int row = 0, col = 0;
   unsigned short position = (row*80) + col;
   
   /* cursor LOW port to vga INDEX register */
   OUTB(0x3D4, 0x0F);
   OUTB(0x3D5, (unsigned char)(position&0xFF));
   /* cursor HIGH port to vga INDEX register */
   OUTB(0x3D4, 0x0E);
   OUTB(0x3D5, (unsigned char )((position>>8)&0xFF));
   
   while (1);
}
@all:
Thanks for your help. Sorry for such a ?stupid? question :)
Now I'm using the functions (outb, etc) written in the wiki.

Btw, what's the difference between i.e.:

Code: Select all

static __inline__ void outb(unsigned short port, unsigned char val)
{
   asm volatile("outb %0,%1"::"a"(val), "Nd" (port));
}
and

Code: Select all

void outb(unsigned short port, unsigned char val)
{
   __asm__ __volatile__ ("outb %0,%1"::"a"(val), "Nd" (port));
}

Re:Hardware cursor

Posted: Mon Jul 25, 2005 4:05 am
by Pype.Clicker
difficult to tell just like this ... we'd need that ".s" file the assembler is working on to find out ...

Re:Hardware cursor

Posted: Mon Jul 25, 2005 4:15 am
by marcio.f
Pype.Clicker wrote: difficult to tell just like this ... we'd need that ".s" file the assembler is working on to find out ...
I can't even ?see? that file because it's temporary, as soon as the assembler stops, the file is deleted :-\
Anyway, no worries about it, because I'm already using the code written in the wiki for outb, etc.

And what about the difference between the two outb functions? Can you explain me?

I have another question :)
I can't compile this code:

Code: Select all

void io_wait(void)
{
   __asm__ __volatile__ ("outb %%al,$0x80");
}

Code: Select all

/usr/cross/bin/i586-elf-as -o loader.oo init/loader.s
/usr/cross/bin/i586-elf-gcc -o kernel.oo -c kernel.c -ffreestanding -g -Wall -ansi -pedantic -Werror -nostdlib -nostartfiles -nodefaultlibs -Iinclude
/cygdrive/c/DOCUME~1/marciof/DEFINI~1/Temp/ccEV8BYh.s: Assembler messages:
/cygdrive/c/DOCUME~1/marciof/DEFINI~1/Temp/ccEV8BYh.s:56: Error: bad register name `%%al'
make: *** [kernel.oo] Error 1

Re:Hardware cursor

Posted: Mon Jul 25, 2005 5:11 am
by AR
gcc -S kernel.c -o kernel.s
The error generated by that is caused by the double percent signs since you aren't actually using the input/output/clobber fields. I would suggest being less specific about what you're writing as well to let the compiler optimize the code better:

Code: Select all

__asm__ __volatile__ ("outb %0, $0x80" : "r"(0));
For the macros, try changing the "a"s to "r"s. The difference between the macros and the functions is that the macro is inserted into the code at that point (The macro is just a placeholder which is replaced by whatever the macro actually is during the build process).

Re:Hardware cursor

Posted: Mon Jul 25, 2005 5:24 am
by Solar
The __ prefixed versions won't make a fuzz if the code is compiled in -pedantic mode.

Just adding a keyword (like "asm") is not "legal" according to the standard, as it violates the namespace reserved to the user. But anything starting with __ or _ and a capital letter is reserved for the implementation (i.e., compiler and / or library), and thus can remain in there "legally".

Re:Hardware cursor

Posted: Mon Jul 25, 2005 5:44 am
by marcio.f
@AR, Pype.Clicker
I'm having trouble at using the code for io_wait() from the wiki (http://www.osdev.org/osfaq2/index.php/SampleInlineFunctions)

@AR
Even with your code:

Code: Select all

void _main(void* mbd, unsigned int magic)
{
   __asm__ __volatile__ ("outb %0, $0x80" : "r"(0));
}
gcc won't compile:

Code: Select all

/usr/cross/bin/i586-elf-as -o loader.o init/loader.s
/usr/cross/bin/i586-elf-gcc -Wall -Werror -nostdlib -nostartfiles -nodefaultlibs -pedantic -o kernel.o -c kernel.c
kernel.c: In function `_main':
kernel.c:10: error: invalid lvalue in asm statement
kernel.c:10: error: output operand constraint lacks `='
make: *** [kernel.o] Error 1
For the macros, tried your idea but it still doesn't assemble. Don't worry as I'm already using the one (outb) supplied in the faq :)

@Solar
Didn't know it, thanks for the info.

Re:Hardware cursor

Posted: Mon Jul 25, 2005 6:04 am
by AR
Sorry, I forgot a colon, it should be:

Code: Select all

__asm__ __volatile__ ("outb %0, $0x80" : : "r"(0));

Re:Hardware cursor

Posted: Mon Jul 25, 2005 6:16 am
by marcio.f
Thanks!
Just a minor thing, the assembler gives a warning:

Code: Select all

/cygdrive/c/DOCUME~1/marciof/DEFINI~1/Temp/ccIS0T3r.s: Assembler messages:
/cygdrive/c/DOCUME~1/marciof/DEFINI~1/Temp/ccIS0T3r.s:55: Warning: using `%al' instead of `%eax' due to `b' suffix
is it relevant?

Because with your code now it works, does this means the one in the wiki is wrong?

Code: Select all

asm volatile ("outb %%al,$0x80");

Re:Hardware cursor

Posted: Mon Jul 25, 2005 6:22 am
by AR
That's just a warning that the compiler doesn't know that it's an 8bit instruction so is trying to use a 32bit register with it (Which GAS is smart enough to automatically change to %AL), there should be probably some way to tell GCC about it but I'll have to look it up.

That code may have been valid in an earlier version of GCC but it would appear to be wrong in the newer releases.

Re:Hardware cursor

Posted: Mon Jul 25, 2005 6:27 am
by marcio.f
AR wrote: (...) there should be probably some way to tell GCC about it but I'll have to look it up.
When you find it, please let me know. :)
AR wrote: (...)That code may have been valid in an earlier version of GCC but it would appear to be wrong in the newer releases.
So... that section in the faq should be fixed to prevent future problems, right?

Re:Hardware cursor

Posted: Mon Jul 25, 2005 7:05 am
by AR
There doesn't seem to be any way to constrain the register sizes unfortunately, basically you'll need something like:

Code: Select all

__asm__ ("outb %%al, $0x80" : : "a"(0)); /* Load zero in EAX then use AL in the instruction */
I've fixed the Wiki entry.