Since the last post I have added functionality necessary to make it possible to use the computer from a directly connected keyboard and screen.
This required two things:
- Making the already written PS/2 controller VHDL implementation available to the Linux kernel by adding a PS/2 driver.
- Modifying the existing, and somewhat hacky, VGA controller for my video card and writing a wrapper to Linux’s framebuffer infrastructure to make use if it.
Both tasks turned out to be fairly straightforward.
Linux has an infrastructure for supporting PS/2 devices attached to ports presented via platform-specific hardware. The driver I’ve created shunts bytes, read by the hardware at the serio subsystem, which then interprets these bytes, eventually generating keyboard and mouse events. It likewise is used to forward on bytes to the PS/2 devices to do things like manipulate the LEDs found on keyboards. In terms of getting the keyboard working, this went fairly easily.
The framebuffer driver was remarkably easy to get going, but before looking at the Linux side I first I had to modify my exiting VHDL to implement the required screen mode: in this case 640×480 at 60Hz, but in 256 colours. One interesting angle to this is the palette: it was held in dual ported memory, with one side read by the video generator, and the other side read and written by the processor, so it could change the palette, the default palette being the standard 256 colour VGA one. This was a little involved, and even once “finished” it wasn’t perfect: I had to introduce wait states in the MAXI030 FPGA since the wait signal generated by the card didn’t appear to be generated properly, despite my best efforts. In any case, eventually I had some decent images:
This image, which started out as a JPG, was scaled and colour reduced into a BMP file, which was transferred across the ethernet link, described in the previous post.
The MAXI030 framebuffer driver is very simple, and simply configures where in the memory space the buffer is, along with its resolution and colour depth.
Getting Linux to make use of the framebuffer and PS/2 was done next, using the drivers previously added to the kernel:
I was very pleased to get to this point, though if you look closely at the bottom of Tux you will spot a line of red pixels which should not be there. This indicates a subtle timing issue with the 68030 asserting a colour onto the video card palette memory. I had a further issue at this point: the Linux kernel exposed a problem with the PS/2 controller I hadn’t up to that point seen. This was undoubtedly caused by not having a simulation harness for the controller.
Looking closely at the above screenshot shows a further addition: the obtaining of the time form the DS1307 I2C Real Time Clock.
drivers/i2c/busses/i2c-maxi030core.c
This driver is a little similar to the PS/2 driver just described: it operates as a go-between between the platform specific hardware, in this case the I2C controller implemented in the MAXI030 FPGA, to the I2C infrastructure in the Linux kernel. Linux terms these drivers “busses”.
The really interesting thing is that once a bus has been created, peripherals can be easily attached to those busses. For MAXI030 I have attached two:
- The aforementioned DS1307.
- The LM75A (PDF) temperature sensor
The stock driver source for these two parts were used; no MAXI030-specific changes were needed. Peripheral ICs can either be added in code, which is what I’ve done via the config.c module, or it can be done at runtime.
Because the Debian userland I’m running is somewhat old, and designed to run on older kernels, some hacks were necessary to make this work with the up-to-date kernel I’m running. For instance the hwclock program requires a /dev/rtc symlink to /dev/rtc0, since on new kernels multiple RTCs can be present, whereas the hwclock program expects only one, at /dev/rtc.
As well as having a working RTC, it was pretty nice seeing the temperature sensor working inside Linux.
At this point I have not discussed any negatives. Unfortunately there was one quite large one: the text console was pretty slow, especially with scrolling. Certainly not unusable, but not great either. This could be improved with two changes:
- Reducing the colours presented to, say, 16.
- Adding hardware acceleration to the VHDL implementation, and then leveraging this in the framebuffer driver.
The latter is probably the most interesting. Without any acceleration, all pixel drawing must be accomplished with processor code. This is obviously quite expensive, especially if one considers something like scrolling the screen. The framebuffer implementation in Linux supports acceleration for key drawing functions, such as copying one area of the screen to another. By exploiting these hooks and calling into the hardware via registers to satisfy them, it should be possibly to greatly speed up drawing, especially scrolling text in the console. This could be achieved in a similar way to how I previously implemented hardware accelerated drawing for my video card.
At the present time I’ve not implemented either of these ideas, for a simple reason: neither can be utilised by the X server framebuffer driver.
After playing about with the framebuffer console, the logical next step was to see if it was possible to run the X server on MAXI030 using it. This would end up being a major milestone for the project: a working, if rather slow, GUI.
I was pleased to see someone had written an X server display driver module for the framebuffer, called fbdev. Even with the limitations mentioned (it supports only 8, 15, 16 and 24 bit colour and does not support any acceleration) I thought it would be great to see X running on MAXI030:
For anyone curious, the window manager used here is twm. The photograph also shows, xlogo, xload and xeyes. All three are part of the core X distribution.
Unfortunately this nice picture hides a secret: the X server was very slow to use. Just starting it took perhaps 3 minutes. And dragging windows around is fairly painful. But I was still pleased.
Yet another problem then appeared: the PS/2 implementation detected the mouse I’d attached via a Y-splitter, but mouse movements were erratic, with the kernel reporting a loss of sync in the PS/2 byte stream. This was particularly likely to happen under disk load. I later noticed the same problem, only very occasionally, with the keyboard. Since the PS/2 interrupts were the highest priority used, it appeared that the only reasonable explanation was that something, probably in the IDE driver, was disabling interrupts and causing PS/2 bytes to be lost.
The solution to this was to introduce a FIFO in the PS/2 controller implementation. This FIFO would queue up bytes so a byte could be received on the port before the previous byte was read back by the processor, without that previous byte being discarded.
This was actually surprisingly easy to do. Using the Quartus MegaWizard an 8 byte deep FIFO was created. The read end was attached to the external databus of the FPGA using the existing hardware address, and the write end was attached to the PS/2 controller’s data output. In addition, I extended the PS/2 status registers to supply the number of bytes currently waiting to be read in the FIFO, since I had a few bits free in the 8 bit status register.
After playing around with this new functionality inside my machine-code monitor, I straight away noticed some weird problems with erratic behaviour. Sometimes MAXI030 would even refuse to reset cleanly. The problems looked precisely like those I saw with MIDI020 previously. Making changes to the VHDL coding in trivial parts of the design, such as wether the user controlled LED was linked to its controlling register, would result in a non functional board.
As a fairly desperate means to have a functioning board again, I have switched the clock oscillator back to a 20MHz part and this has resulted in a useable board, including working PS/2 FIFOs, albeit a board that now runs at half the speed.
I have explored various approaches to getting the board working at its maximum speed. All, so far, without success. I thought I was onto a promising approach when I, at last, figured out how to replace the sequential address decoder with a combinational one. This did not result in any improvement. I am determined to come back here, as this board has many more projects to offer. But for now, I think, I must move on to something else.
And that something else is a new softcore processor…
May be for Acceleration you can look at TCX card/driver for old Sun machines, it has accelerated X driver in NetBSD working emulation in qemu
http://cvsweb.netbsd.org/bsdweb.cgi/xsrc/external/mit/xf86-video-suntcx/dist/src/?only_with_tag=MAIN
(Uses new EXA acceleration architecture, it might be not included in Debian 3.1’s X server)
https://git.qemu.org/?p=qemu.git;a=blob;f=hw/display/tcx.c;h=1b27b64f6d14e1a878e25ef75c8e2f48a9bfa419;hb=HEAD
You can also poke EmuTOS it was ported to some 68ķ machines, so not completely tied to Atari HW itself
The tricky part would be replicating the video card acceleration hardware in my own FPGA-based card. If the register API was documented, I suspect it could be done though, and then the job would be to port/write X server….
In terms of EmuTOS, I’ve actually had it running on MAXI030 already. Unfortunately I get “random” exceptions after a few minutes of use. Strangely this is exactly the same problem I had running EmuTOS on my 68000 board (https://www.aslak.net/index.php/2020/08/13/more-maxi000-construction-and-progress-towards-an-emutos-port/). I thought it might be the MAXI030 board’s FPGA design, or some other timing problem, but I have had Linux running under heavy load (compiling, network tests, disk thrashing all running together) for 6 hours without a single problem. It’s very strange why it is just EmuTOS which gives trouble.
Thanks for your interest in my projects! 🙂
Lawrence
While this pdf about different framebuffer it discuss some of old X interactions with hardware and provides some desing notes:
http://bitsavers.trailing-edge.com/pdf/dec/tech_reports/WRL-93-1.pdf
That PDF is extremely interesting. Did you read about my graphics card?
https://www.aslak.net/index.php/2021/07/08/the-design-of-a-video-and-sound-card-for-midi020/
Briefly: EP2C8 (Cyclone II), 1M x 16 10nS SRAM, 16 bit data paths. I got as far as implementing hardware box drawing. CAD files are here: https://github.com/aslak3/MAXI030/tree/main/ExpansionCards/Video%2BSound – though I have yet to uploaded the VHDL because it’s in a terrible state.
How’s your VHDL? Or Verilog for that matter (you could teach me). I would love someone to collaborate with.
You might also find – https://www.ddraig68k.com – interesting. The graphics setup in that 68000 is similar to mine, but using Xilinx parts.
Lawrence
Unfortunately I do not know any of those hardware description languages. I wonder if there are some software emulator fir fpga workflow?
https://github.com/Grabulosaure/ss/blob/main/src/ts/ts_tcx.vhd
This probably contain TCX as implemented in TME
Also, some fun at m68k forums
https://68kmla.org/bb/index.php?forums/hacks-development.32/
I see someone played with microcontroller-based ps2 interface. may be you can add such additional board to your design so main fpga will not bother itself with keyboard interactions ..
I’ll dig though that VHDL project and see if there’s something useful there. Thanks!
Sure it would be easy to move the PS/2 port off onto another device. Instead of an AVR I could use a VT82C42. I could just use a card I guess. I hadn’t thought of that. I may well do a new board and move some functionality out of the FPGA, or maybe add a second one for peripherals. It’s an interesting idea to speed the system up again.
Good to see you still about. Was looking up some bits to get my two 68k dev boards up and running. I shall follow with interest. R aka rtech lab on YT