Page 1 of 2

Serial port outputs random data

Posted: Sun Aug 28, 2016 2:39 pm
by Ycep
Hi, I was recently writing my Serial Port Driver, and it seems to output random data.
When I try to send character 'X', I get 0x18.
This is my SendSerial function. ex. SendSerial(0,'X');

Code: Select all

void SendSerial(uint8 COM, uint8 data)
{
	if(COM>SerialComAmount-1)
	{
		if(SerialComAmount==0)cerror("No Serial Hardware in System.");
		else cerror("Can't use unregistered serial port!");
		return;
	}
	uint16 SerAddr=SerialPort[COM];
	while(!(inb(SerAddr+5)&0x20));
	outb(SerAddr,data);
}
Bochs and VMWare just output 0x18 rather than 0x58 on serial port.
InitSerial():

Code: Select all

bool InitSerial()
{
	for(uint8 i=0;i<4;i++)
	{
		uint16 val=*((uint16*)(0x0400+i*2));
		if(!val)continue;
		SerialPort[i]=val;
		SerialComAmount++;
		InitPort(val);
	}
	printf("\nSerial Ports:%d\n",SerialComAmount);
	if(SerialComAmount)return true;
	else return false;
}
SetBaud (Function for setting baud) and InitPort:

Code: Select all

void SetBaud(uint16 portaddr,uint8 divisor)
{
	outb(portaddr+3,0x80);
	outb(portaddr,divisor);
	outb(portaddr+1,0);//I will not use divisors bigger than 255
}
void InitPort(uint8 portaddr)
{
	outb(portaddr+1,0x00);
	SetBaud(portaddr,3);
	outb(portaddr,0x03);//0000 0011
	outb(portaddr+2,0xC7);
	outb(portaddr+4,0x0B);
}

Re: Serial port outputs random data

Posted: Sun Aug 28, 2016 3:01 pm
by Octacone
Your code seems overly complex. (I use something much simpler, personal preference)
Try this:

Code: Select all

outportb(COM1, 'o');
//com1 is 0x3F8
and tell me the output.

Re: Serial port outputs random data

Posted: Sun Aug 28, 2016 3:11 pm
by Ycep
octacone wrote:Your code seems overly complex.
Try this:

Code: Select all

outportb(COM1, 'o');
//com1 is 0x3F8
and tell me the output.
0x0F. Again random.
It isn't complex. It only has support for multiple serial ports, serial port address detection, etc. Nothing complex, I'll rather refer it simple.
Thanks for suggestion.

Re: Serial port outputs random data

Posted: Sun Aug 28, 2016 3:15 pm
by Octacone
Lukand wrote:
octacone wrote:Your code seems overly complex.
Try this:

Code: Select all

outportb(COM1, 'o');
//com1 is 0x3F8
and tell me the output.
0x0F. Again random.
It isn't complex. It only has support for multiple serial ports, serial port address detection, etc. Nothing complex, I'll rather refer it simple.
Thanks for suggestion.
What!? That is not what I expected. Give me a moment.

Re: Serial port outputs random data

Posted: Sun Aug 28, 2016 3:16 pm
by phredreeck
Hmm, your code seems OK. Could you show your outb() function?

Re: Serial port outputs random data

Posted: Sun Aug 28, 2016 3:18 pm
by Octacone
@f2

This is the one I use:

Code: Select all

void outportb(uint16 _port, uint8 _data)
{
	__asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
}
Works perfectly fine, he can try it out.

Re: Serial port outputs random data

Posted: Sun Aug 28, 2016 3:19 pm
by Ycep
f2 wrote:Hmm, your code seems OK. Could you show your outb() function?
No problem. Why is it needen? It's working flawlessly for everything else:

Code: Select all

void outb(uint16 prt, uint8 val)
{
	_asm
	{
		mov     al, byte ptr[val]
		mov     dx, word ptr[prt]
		out     dx, al
	}
}
octacone wrote:@f2

This is the one I use:

Code: Select all

void outportb(uint16 _port, uint8 _data)
{
	__asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
}
Works perfectly fine, he can try it out.
Eh... =P~. I don't want to, since that is GCC compilant. Please do not make fool from me. Do you really think that my outb() code isn't working?

Re: Serial port outputs random data

Posted: Sun Aug 28, 2016 3:24 pm
by Octacone
So did it work?
Edit: what emulator do you use?

Re: Serial port outputs random data

Posted: Sun Aug 28, 2016 3:26 pm
by Ycep
octacone wrote:So did it work?
Edit: what emulator do you use?
I said I tried it on VMWare and Bochs.

Re: Serial port outputs random data

Posted: Sun Aug 28, 2016 3:27 pm
by Octacone
Lukand wrote:
octacone wrote:So did it work?
Edit: what emulator do you use?
I said I tried it on VMWare and Bochs.
Try Qemu with and don't forget std -serial stdio

Re: Serial port outputs random data

Posted: Sun Aug 28, 2016 3:31 pm
by Ycep
octacone wrote:
Lukand wrote:
octacone wrote:So did it work?
Edit: what emulator do you use?
I said I tried it on VMWare and Bochs.
Try Qemu with and don't forget std -serial stdio
I am using MS Windows. QEMU is Linux emulator. And if it won't work on VMWare and Bochs what is the purpose then?

Re: Serial port outputs random data

Posted: Sun Aug 28, 2016 3:37 pm
by phredreeck
OK, so your outb() seems correct.

I just found something in your InitPort() function I haven't seen before.
Look at this code from OSDev Wiki ( http://wiki.osdev.org/Serial_Ports#Example_Code ):

Code: Select all

#define PORT 0x3f8   /* COM1 */
void init_serial() {
   outb(PORT + 1, 0x00);    // Disable all interrupts
   outb(PORT + 3, 0x80);    // Enable DLAB (set baud rate divisor)
   outb(PORT + 0, 0x03);    // Set divisor to 3 (lo byte) 38400 baud
   outb(PORT + 1, 0x00);    //                  (hi byte)
   outb(PORT + 3, 0x03);    // 8 bits, no parity, one stop bit
   outb(PORT + 2, 0xC7);    // Enable FIFO, clear them, with 14-byte threshold
   outb(PORT + 4, 0x0B);    // IRQs enabled, RTS/DSR set
}
If I compare it with your code:

Code: Select all

outb(portaddr+1,0x00);
   SetBaud(portaddr,3);
   outb(portaddr,0x03);//0000 0011
   outb(portaddr+2,0xC7);
   outb(portaddr+4,0x0B);
I see on the third line that you are sending the value 0x03 to portaddr and not to portaddr + 3, as you can see in the init_serial() function.
Can you change the line outb(portaddr,0x03) to outb(portaddr+3,0x03) and see if that fixes your problem?

EDIT: removed a comma, thanks octacone :)

Re: Serial port outputs random data

Posted: Sun Aug 28, 2016 3:39 pm
by Octacone
f2 wrote: Can you change the line outb(portaddr,0x03) to outb(portaddr,+3,0x03) and see if that fixes your problem?
outb(portaddr,+3,0x03) -> outb(portaddr+3,0x03)
Edit: @f2 ;)

Re: Serial port outputs random data

Posted: Sun Aug 28, 2016 3:42 pm
by BrightLight
Lukand wrote:I am using MS Windows. QEMU is Linux emulator.
QEMU is by no means tied to Linux. A quick Google search "QEMU on Windows" will get you good results.
The code snippets on the serial port Wiki page are enough to properly initialize the serial port.

Code: Select all

void com1_init()
{
	short* com1_bda = (short*)0x400;
	com1_base = com1_bda[0];
	if(com1_base == 0) return;	// if there is no serial port, there's nothing to do

	outb(com1_base+1, 1);
	iowait();
	outb(com1_base+3, 0x80);
	iowait();
	outb(com1_base+0, 2);
	iowait();
	outb(com1_base+1, 0);
	iowait();
	outb(com1_base+3, 3);
	iowait();
	outb(com1_base+2, 0xC7);
	iowait();

	dprintf(KERNEL_STRING);
	dprintf("\n");
	dprintf("com1: initialized serial port, base IO port is at 0x%x.\n", com1_base);
}

void com1_send_byte(char byte)
{
	if(com1_base == 0) return;
	while(!(inb(com1_base+5) & 0x20));

	if(byte == '\n')
	{
		while(!(inb(com1_base+5) & 0x20));
		outb(com1_base, 13);	// carriage
		while(!(inb(com1_base+5) & 0x20));
		outb(com1_base, 10);	// newline
		while(!(inb(com1_base+5) & 0x20));
		return;
	}

	outb(com1_base, byte);
	while(!(inb(com1_base+5) & 0x20));
}

Re: Serial port outputs random data

Posted: Sun Aug 28, 2016 3:45 pm
by iansjack
'X' = 0x58, you get 0x18
'o' = 0x6F, you get 0x0F

Do you spot the pattern? You haven't set the number of data bits, so it looks like it has defaulted to 5 bits rather than 7 or 8.