Hardware cursor

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
marcio.f

Hardware cursor

Post 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 ;)
pini

Re:Hardware cursor

Post 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).
AR

Re:Hardware cursor

Post 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))
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Hardware cursor

Post 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 ...
marcio.f

Re:Hardware cursor

Post 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));
}
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Hardware cursor

Post by Pype.Clicker »

difficult to tell just like this ... we'd need that ".s" file the assembler is working on to find out ...
marcio.f

Re:Hardware cursor

Post 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
AR

Re:Hardware cursor

Post 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).
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Hardware cursor

Post 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".
Every good solution is obvious once you've found it.
marcio.f

Re:Hardware cursor

Post 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.
AR

Re:Hardware cursor

Post by AR »

Sorry, I forgot a colon, it should be:

Code: Select all

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

Re:Hardware cursor

Post 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");
AR

Re:Hardware cursor

Post 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.
marcio.f

Re:Hardware cursor

Post 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?
AR

Re:Hardware cursor

Post 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.
Post Reply