Loongson support finally works, thanks to Manuel Bouyer's work on porting OpenBSD's code, with this I finally managed to get my Gdium to boot multiuser.
Since some of the device support already existed I didn't port any of OpenBSD's Gdium-specific drivers and instead used NetBSD's existing ones and code I wrote for our initial effort on getting NetBSD to work. The hardware includes:
- a Silicon Motion SM502 'Multimedia Companion Controller' - for graphics, audio, timers. Also contains a USB controller which non-prototype Gdiums don't seem to use. I wrote a driver for the graphics portion in 2009, added support for stuff like i2c and a base device for other drivers to attach to.
- a M41T8x real time clock. Already supported by the strtc driver.
- an LM75 temperature sensor. Already supported by the lmtemp driver.
- a generic ehci/ohci USB2 controller
- a Realtek 8139 fast ethernet controller
- a Realtek RT2561C wlan controller
- an ST7 microcontroller to manage things like power buttons and battery charge. This thing is strange - we talk to it over i2c and it doesn't seem to have any way to directly alert the CPU on anything, we actually have to poll the thing in order to figure out if the battery is low or someone pressed the power button. Wrote my own driver since OpenBSD's doesn't really do much at all.
Another problem with these machines is the braindead firmware. It's PMON2000, which is intended for embedded controllers and evaluation boards, and that shows. It can boot over network, contains all sorts of debugging facilities but there is no way to get information like the current video mode, vram location and geometry out of it. Or any information at all that's not basic configuration variable stuff. This means there is no way to have a machine independent, simple early console - drivers either need early attachment hooks, which is ugly, or we need hacks to retrieve or guess the necessary parameters. On Gdium we can safely assume that the display is 1024x600 in 16 bit and finding the framebuffer is just one BAR read, but on other machines it's not that easy. There is no device tree either so devices that can't be probed ( like i2c devices for example ) need to be guessed based on the model.
Finally, there is only one high resolution timer in the entire system and that's the CPU's cycle counter. The problem with that is, the counter's frequency changes with the CPU's clock frequency so we need to compensate for that if we ever want to support frequency scaling ( and since Gdium is a little laptop which gets fairly warm we most definitely do ). My current plan is to use one of the SM502's pulse width modulation units to generate a periodic interrupt at 100Hz, only modify the CPU clock rate in the timer interrupt handler, save the adjusted cycle counter on each interrupt and when querying the counter use the cycles passed since the last timer interrupt, adjust for frequency scaling, add the count saves in the last interrupt and return that. With this the counter's frequency should appear uniform no matter what clock the CPU actually runs on, we can guarantee it's uniform between timer interrupts and we only lose resolution when lowering the clock rate.
Why oh why didn't they put a cycle counter in the SM502? Just something that increments on every PWM cycle? Or add a counter to the CPU that works like PowerPC's time base, with its own clock, independent from the main CPU clock. Guess it shows which CPUs were designed with laptops in mind and which weren't.
Finally, since the kernel runs in 64bit while the userland is N32 I keep running into ioctl()s that need to be translated by the compat/netbsd32 code. The problem occurs only with ioctl()s which pass pointers between userland and the kernel - obviously they're different sizes which changes the data structures passed, which needs to be compensated for. On NetBSD, instead of having separate ioctl() handlers for 32bit and 64bit calls in every driver, we have code which translates based on the ioctl() number and the data structures passed, that way for example everything that uses for example a struct plistref can use the same translator.
As it is now, Gdium goes multiuser, ethernet, graphics, USB, real time clock etc. all work. X works with the wsfb driver only so far ( there's a problem loading modules which depend on other modules, like Xorg drivers that use XAA, EXA etc. - not sure if it's a bug in the runtime linker or binutils or whatever. Wsfb works because it doesn't depend on anything. ) There is no audio support yet and wlan support doesn't work right ( It manages to associate with my router but stops doing anything after answering a few pings. Not sure if it's the ral driver or something else. )
There is basic powerd and envsys support - pushing the power button initiates a shutdown, closing the lid turns the backlight off, envstat gives temperatures and power status.