QEMU Port 0xE9 Output?
QEMU Port 0xE9 Output?
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.
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.
Re: QEMU Port 0xE9 Output?
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/
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.
Re: QEMU Port 0xE9 Output?
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.
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
Re: QEMU Port 0xE9 Output?
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.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
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?
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
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
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...rwosdev wrote:Code: Select all
.next: pop dx cmp edx, ecx jl .debugOutLoop
Hope this helps,
Ben
Re: QEMU Port 0xE9 Output?
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
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
Re: QEMU Port 0xE9 Output?
"-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.
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].
Re: QEMU Port 0xE9 Output?
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
Still keeping the parallel code and learned some new things as well so nothing's in vain.
Cheers guys
Re: QEMU Port 0xE9 Output?
Slightly off topic:
BenLunt wrote: In fact, the "cmp" is an "and" instruction, disregarding the results.
You're confusing cmp with test
cmp compares by subtracting (so, sub), while test does the bitwise and
Re: QEMU Port 0xE9 Output?
Oh ya, you're right. Sorry. I don't know why I thought that. Long day probably.Wukl wrote:You're confusing cmp with testBenLunt wrote: In fact, the "cmp" is an "and" instruction, disregarding the results.
cmp compares by subtracting (so, sub), while test does the bitwise and
Thanks,
Ben