QEMU Port 0xE9 Output?

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
rwosdev
Member
Member
Posts: 49
Joined: Thu Apr 26, 2018 11:21 pm

QEMU Port 0xE9 Output?

Post by rwosdev »

How do you get port 0xE9 output in QEMU as in Bochs? I've written a function to enable redirecting all kernel output to 0xE9 (or elsewhere) which works fine in Bochs.

Would be extremely helpful if I could have the same in QEMU for graphics debugging.

The command-line option "-debugcon stdio" produces no output in the command line when QEMU is launched in it.
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: QEMU Port 0xE9 Output?

Post by BenLunt »

Write to the parallel port.

Doing this is almost as easy as writing to port 0xE9 and as long as the emulator supports a parallel port, you can direct any text to a specific file.

0) Read port 0x379, polling bit 7.
1) Write the char to port 0x378
2) "toggle" bit 0 in port 0x37A
3) Read port 0x379, polling bit 6.

You might want to "catch" CRLF's if your guest uses CRLF instead of LF. The text file may not look quite right with CRLF's or LF alone depending on the platform you are using.

Ben
- http://www.fysnet.net/osdesign_book_series.htm

Update: Since the OP has had a chance to write up his/her own code (as it should be), here is an example: http://www.fysnet.net/blog/2018/06/
Last edited by BenLunt on Sat Jun 02, 2018 12:26 pm, edited 1 time in total.
rwosdev
Member
Member
Posts: 49
Joined: Thu Apr 26, 2018 11:21 pm

Re: QEMU Port 0xE9 Output?

Post by rwosdev »

Hey, thanks for the suggestion.

I tried it but polling for BUSY results in an infinite loop and ignoring it causes only one character to be written on the parallel output.

Code: Select all

PollParallelBusy:
	push ax
	push dx
	
	mov dx, 0x379
.loop:
	in al, dx
	and al, 10000000b
	cmp al, 0
	jnz .loop
	
	pop dx
	pop ax
	ret

StringOut:
...
.debugOutLoop:
	lodsb
	inc edx
	
	; For Bochs
	out 0xE9, al
	
	; For QEMU:
	push dx
	
	;call PollParallelBusy

	; Write character
	mov dx, 0x378
	out dx, al
	
	; Toggle bit 0 (STROBE) of 0x37A to say data is ready
	mov dx, 0x37A
	in al, dx
	or al, 00000001b
	out dx, al
	
	; ... Left out polling 0x379 acknowledge for now
	
.next:
	pop dx
	
	cmp edx, ecx
	jl .debugOutLoop
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: QEMU Port 0xE9 Output?

Post by BenLunt »

rwosdev wrote:Hey, thanks for the suggestion.

I tried it but polling for BUSY results in an infinite loop and ignoring it causes only one character to be written on the parallel output.

Code: Select all

PollParallelBusy:
	push ax
	push dx
	
	mov dx, 0x379
.loop:
	in al, dx
	and al, 10000000b
	cmp al, 0
	jnz .loop
No need for the "cmp al,0" instruction. The "and" sets the flags identical to the "cmp". In fact, the "cmp" is an "and" instruction, disregarding the results.

In my first reply, I tried to point you in the right direction, which it seems I did, though I tried not to do it for you.

Please search a little more and find out what value to watch for in bit 7. A lot of places say that it is the busy bit, which is correct, but is it set or clear to indicate busy?
rwosdev wrote:

Code: Select all

	pop dx
	pop ax
	ret

StringOut:
...
.debugOutLoop:
	lodsb
	inc edx
	
	; For Bochs
	out 0xE9, al
	
	; For QEMU:
	push dx
	
	;call PollParallelBusy

	; Write character
	mov dx, 0x378
	out dx, al
	
	; Toggle bit 0 (STROBE) of 0x37A to say data is ready
	mov dx, 0x37A
	in al, dx
	or al, 00000001b
	out dx, al
	
	; ... Left out polling 0x379 acknowledge for now
The reason it only outputs one char, is that you never turn off the strobe to be able to turn it back on, indicating another character. An on bit only indicates to the other side to read the parallel lines for the char. Only when the bit goes low (drops the power on that line), does the hardware indicate that it needs to be ready for the next char. This is where timing comes into play. How fast can I toggle (strobe) the strobe line and the "other side" will receive all my characters intact? For a simple thing as outputting to a file using an emulator, the fact that the line goes high, then low is enough. No need for timing. However, my code pauses for a slight bit, while the line is high, before dropping the strobe, just to be sure.
rwosdev wrote:

Code: Select all

.next:
	pop dx
	
	cmp edx, ecx
	jl .debugOutLoop
Side note: The Parallel Port hardware, in the standard form, has little or no circuitry. It simply is a bit representation of the status of each of the pins. If a pin is high (has power), the bit will be set (or clear), period. Writing a value to the data port, simply sets high all lines (pins) that have a bit set, dropping the power (setting to low) all the pins that have a zero bit. It is the closest you can come to actually physically manipulating the hardware without any firmware getting in the way. Long live the Parall....oh, ya, its dead...

Hope this helps,
Ben
rwosdev
Member
Member
Posts: 49
Joined: Thu Apr 26, 2018 11:21 pm

Re: QEMU Port 0xE9 Output?

Post by rwosdev »

Took everything you said into consideration, here's the new code which seems to work nicely.

I've never used the parallel port before so if there's something not quite right here please let me know.

In my OS, I only send newlines in strings ('\n') so this code catches them as you said and sends an additional carriage return byte to the parallel port so each string starts on a new line when requested.

Screenshot of result attached, showing correct text sent from two different drivers being routed through the parallel port.

Many thanks

Code: Select all

ParallelPollStatus:
; bl = mask
	push ax
	push dx
	
	mov dx, 0x379
.loop:
	in al, dx
	and al, bl
	jz .loop ; Function is only used for BUSY and ACK, and them being 0 means they're set.
	; https://wiki.osdev.org/Parallel_port says: The ERROR, ACK and BUSY signals are active low when reading from the IO port.
	
	pop dx
	pop ax
	ret
	
ParallelWriteByte:
; al = character
	push ax
	push bx
	push dx
	
	mov bl, 10000000b ; Wait until not busy
	call ParallelPollStatus

	mov dx, 0x378
	out dx, al	; Write character
	
	mov dx, 0x37A
	in al, dx
	or al, 00000001b
	out dx, al ; Set STROBE to say 'data is ready'
	
	mov bl, 01000000b ; Wait until acknowledgement
	call ParallelPollStatus
	
	and al, 11111110b  ; Clear STROBE so device is ready for next character
	out dx, al
	
	mov bl, 01000000b ; Wait until acknowledgement
	call ParallelPollStatus
		
	pop dx
	pop bx
	pop ax
	
	ret

StringOut:
...
.debugOutLoop:
	lodsb
	mov ah, al
	inc edx
	
	; For Bochs
	out 0xE9, al
	
	; For QEMU:
	call ParallelWriteByte
	
	cmp al, 10 ; Catch newline
	jne .next
	
.addCR:		; If newline, add carriage return
	mov al, 13
	call ParallelWriteByte
	
.next:
	cmp edx, ecx
	jl .debugOutLoop

.done:
	...
	ret
Attachments
parallel.jpg
Korona
Member
Member
Posts: 1000
Joined: Thu May 17, 2007 1:27 pm
Contact:

Re: QEMU Port 0xE9 Output?

Post by Korona »

"-debugcon stdio" certainly works. If it does not, maybe it was deactivated during configure-time (?). Of course, this also only works if you run qemu from a terminal.

If you want to write to a real device, I would suggest serial over parallel ports as modern PCs actually have serial ports but no parallel ports.

Use "-serial stdio" or the equivalent option for the parallel port to redirect output to the terminal qemu is running in.
managarm: Microkernel-based OS capable of running a Wayland desktop (Discord: https://discord.gg/7WB6Ur3). My OS-dev projects: [mlibc: Portable C library for managarm, qword, Linux, Sigma, ...] [LAI: AML interpreter] [xbstrap: Build system for OS distributions].
rwosdev
Member
Member
Posts: 49
Joined: Thu Apr 26, 2018 11:21 pm

Re: QEMU Port 0xE9 Output?

Post by rwosdev »

I just discovered I was using qemu-system-i386w.exe - I switched to qemu-system-i386.exe and port 0xE9 output in the command line (with -debugcon stdio) worked, as did parallel output using -parallel stdio

Still keeping the parallel code and learned some new things as well so nothing's in vain.

Cheers guys
User avatar
Wukl
Posts: 8
Joined: Tue Jul 05, 2011 5:17 am
Location: Delft, Netherlands
Contact:

Re: QEMU Port 0xE9 Output?

Post by Wukl »


Slightly off topic:

BenLunt wrote: In fact, the "cmp" is an "and" instruction, disregarding the results.


You're confusing cmp with test :wink:

cmp compares by subtracting (so, sub), while test does the bitwise and
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: QEMU Port 0xE9 Output?

Post by BenLunt »

Wukl wrote:
BenLunt wrote: In fact, the "cmp" is an "and" instruction, disregarding the results.
You're confusing cmp with test :wink:

cmp compares by subtracting (so, sub), while test does the bitwise and
Oh ya, you're right. Sorry. I don't know why I thought that. Long day probably.

Thanks,
Ben
Post Reply