can't get COM1 working

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.
Post Reply
000Zer000
Posts: 5
Joined: Wed Jun 30, 2021 2:34 pm

can't get COM1 working

Post by 000Zer000 »

Hi, I'm new to this forum, so if I'm doing anything wrong, just tell me.

I can't get a proper logging to COM1, The problem (I think) is that it is virtualized, I used the code in https://wiki.osdev.org/Serial_Ports
After the code exits, There is nothing sent to the other side (or the other side doesn't receive it), So I went around and found other people having some problems, (i mean viewtopic.php?f=1&t=29086, viewtopic.php?f=1&t=30753 and viewtopic.php?t=31374&p=271838)

And one other topic, which i wasn't able to find the link to it, But NONE of them work, Whenever i try to initialize that serial port, it breaks and nothing is sent to the other side, if i don't initialize it, it receive data but its 0x18 (surely not my logs!), What am i missing?
indigo256
Posts: 7
Joined: Wed Jun 30, 2021 9:29 am

Re: can't get COM1 working

Post by indigo256 »

000Zer000 wrote:I can't get a proper logging to COM1, The problem (I think) is that it is virtualized, I used the code in https://wiki.osdev.org/Serial_Ports
Just to be sure, could you post the code you use for your COM port?

Also, I assume you mean you're using a virtual machine. What are you using? I only have experience with qemu, so if you're running on that, I might be able to help if you send over the command you use to launch it.
If not, I'm sure someone else more experienced in what you're using can help if you post a config.
000Zer000
Posts: 5
Joined: Wed Jun 30, 2021 2:34 pm

Re: can't get COM1 working

Post by 000Zer000 »

Well, I take the COM port from the bios (using the same code in osdev about its BDA), On qemu, COM1 port is 0 (even when i use -serial file:com1.log), so on qemu, nothing should work (assuming that really old qemu on ubuntu repository (4.1)), my most concern is why it doesn't work even in a virtual machine (using vmware), On vmware, When I go to the details section of virtual machine, it says there is a virtual serial port

The command for qemu is:

qemu-system-i386 -kernel bin/kernel -serial file:com1.log

And I use grub-mkrescue to supply a bootloader for my "kernel"

I think for the code, You gotta wait a little bit more (sorry), I worked with compiler definitions a lot in my currently-non-working driver, So i gotta assemble everything to each other and post it
Last edited by 000Zer000 on Wed Jun 30, 2021 10:29 pm, edited 1 time in total.
000Zer000
Posts: 5
Joined: Wed Jun 30, 2021 2:34 pm

Re: can't get COM1 working

Post by 000Zer000 »

Code: Select all

int init_com1(int rate)
{
    short *_coms = ((short *)0x400);
    short _com1 = _coms[0];
    if(_com1 == 0)
    {
        // There is no COM1 for us, Report this
        return 2;
    }
    uint8_t LOW_RATE = (uint8_t)((115200 / rate) & 0xFF);
    uint8_t HIGH_RATE = (uint8_t)((115200 / rate) >> 8);

    outb(_com1 + 1, 0x00);
    outb(_com1 + 2, 0x04);
    outb(_com1 + 3, 0x80);
    outb(_com1 + 0, LOW_RATE);
    outb(_com1 + 0, HIGH_RATE);
    outb(_com1 + 3, 0x08 | 0x00 | 0x00); // Which is ineffective (the result is still 8), compiler will optimize it
    outb(_com1 + 2, 1 | 4 | 0);
    outb(_com1 + 4, (1 | 2 | 4));
    outb(_com1 + 1, 0xF);
    inb(_com1 + 9); // Taken from the Linux kernel
    return 0;
}
This is the way i call it:

Code: Select all

(void)init_com1(1);
I haven't done anything fancy for inb and outb, the "usual" implementation of them.

I tried passing other rates to it, (i tried 2 and 3), When the above code runs, Nothing is received on the other side, But if I just don't call it, 534 of 0x18 is received (I checked, That's exactly the same count of my "logs"),
On qemu, It returns 2 (as it finds _com1 is 0, which tells us there is no COM1), But in vmware, it initializes but again, the problem i told above^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
000Zer000
Posts: 5
Joined: Wed Jun 30, 2021 2:34 pm

Re: can't get COM1 working

Post by 000Zer000 »

btw, I check viewtopic.php?f=1&t=37400, The strings are there in .rodata (i dumped the .rodata section using objcopy --dump-section .rodata=rodata.elf), And the strings are there, It's two days that I'm on this #-o
klange
Member
Member
Posts: 679
Joined: Wed Mar 30, 2011 12:31 am
Libera.chat IRC: klange
Discord: klange

Re: can't get COM1 working

Post by klange »

000Zer000 wrote:On qemu, It returns 2 (as it finds _com1 is 0, which tells us there is no COM1), But in vmware, it initializes but again, the problem i told above^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Instead of trying to use the BIOS Data Area, which may not exist - and is even less likely to exist when you booted from GRUB via Multiboot as maintaining it is not in the spec - have you considered hardcoding the well-known fixed port addresses for the serial controller?
000Zer000
Posts: 5
Joined: Wed Jun 30, 2021 2:34 pm

Re: can't get COM1 working

Post by 000Zer000 »

Wait BDA isn't guaranteed to exist? Where else should we get those info from? (assuming we are booting from BIOS, as there is currently no support for UEFI, my kernel is pretty much basic), anyway, i tried hard coding it (to 0x3F8), that didn't work either, It had the same results as getting the address from BDA.
Is everything fine with the code?
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: can't get COM1 working

Post by nexos »

The standard method of getting the COM1 base is using ACPI, but that is very complicated. For now, just hardcode 0x3F8 as the COM1 base. On most hardware I've seen (and QEMU), that works.
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
Octocontrabass
Member
Member
Posts: 5567
Joined: Mon Mar 25, 2013 7:01 pm

Re: can't get COM1 working

Post by Octocontrabass »

Code: Select all

    outb(_com1 + 0, HIGH_RATE);
You're writing the divisor high byte to the port for the divisor low byte.

Code: Select all

    outb(_com1 + 3, 0x08 | 0x00 | 0x00); // Which is ineffective (the result is still 8), compiler will optimize it
Why are you selecting 5O1 instead of the much more common 8N1? You'll have a hard time fitting ASCII into 5 bits.

Code: Select all

    inb(_com1 + 9); // Taken from the Linux kernel
Where in the Linux kernel?

Code: Select all

(void)init_com1(1);
You can't program a high enough divisor to set the baud rate to 1, and I can't imagine such a low baud rate being useful anyway. Try something like 9600 instead.
000Zer000 wrote:I haven't done anything fancy for inb and outb, the "usual" implementation of them.
Can't hurt to post them anyway.
Post Reply