diff --git a/.gitignore b/.gitignore index cc44d59..aa364a8 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ uimage *.hh gpio lcd +init +boot-programs/charset.data diff --git a/Makefile b/Makefile index 3ae8456..d4b33b5 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ PYPP = /usr/bin/pypp %.o:%.cc Makefile Makefile.arch $(headers) $(CC) $(CPPFLAGS) $(TARGET_FLAGS) $(CXXFLAGS) -c $< -o $@ -%: boot-programs/init.o boot-programs/%.o +%: boot-programs/crt0.o boot-programs/%.o $(LD) $(filter %.o,$^) -o $@ #$(OBJCOPY) -S $(OBJCOPYFLAGS) $@ diff --git a/boot-programs/charset b/boot-programs/charset new file mode 100755 index 0000000..2602743 --- /dev/null +++ b/boot-programs/charset @@ -0,0 +1,883 @@ +#!/usr/bin/env python +data = """ +...... +...... +...... +...... +...... +...... +...... +...... + +..#... +..#... +..#... +..#... +...... +..#... +...... +...... + +.#.#.. +.#.#.. +.#.#.. +...... +...... +...... +...... +...... + +...... +.#.#.. +#####. +.#.#.. +#####. +.#.#.. +...... +...... + +..#... +.####. +#.#... +.###.. +..#.#. +####.. +..#... +...... + +...... +#...#. +.#.... +..#... +...#.. +#...#. +...... +...... + +.#.... +#.#... +.#.... +#.#.#. +#..#.. +.##.#. +...... +...... + +...#.. +...#.. +..#... +...... +...... +...... +...... +...... + +....#. +...#.. +..#... +..#... +..#... +...#.. +....#. +...... + +#..... +.#.... +..#... +..#... +..#... +.#.... +#..... +...... + +...... +#...#. +.#.#.. +#####. +.#.#.. +#...#. +...... +...... + +...... +..#... +..#... +#####. +..#... +..#... +...... +...... + +...... +...... +...... +...... +..#... +..#... +.#.... +...... + +...... +...... +...... +...... +#####. +...... +...... +...... + +...... +...... +...... +...... +...... +..#... +...... +...... + +...... +....#. +...#.. +..#... +.#.... +#..... +...... +...... + +...... +.###.. +#...#. +#.#.#. +#...#. +.###.. +...... +...... + +...... +..#... +.##... +..#... +..#... +.###.. +...... +...... + +...... +.###.. +#...#. +..##.. +.#.... +#####. +...... +...... + +...... +.###.. +#...#. +..##.. +#...#. +.###.. +...... +...... + +...... +.#.#.. +#..#.. +#####. +...#.. +...#.. +...... +...... + +...... +#####. +#..... +####.. +....#. +####.. +...... +...... + +...#.. +..#... +.###.. +#...#. +#...#. +.###.. +...... +...... + +...... +#####. +....#. +...#.. +...#.. +..#... +..#... +...... + +...... +.###.. +#...#. +.###.. +#...#. +.###.. +...... +...... + +...... +.###.. +#...#. +#...#. +.###.. +..#... +.#.... +...... + +...... +...... +..#... +...... +...... +..#... +...... +...... + +...... +...... +..#... +...... +...... +..#... +.#.... +...... + +...... +....#. +..##.. +##.... +..##.. +....#. +...... +...... + +...... +...... +#####. +...... +#####. +...... +...... +...... + +...... +#..... +.##... +...##. +.##... +#..... +...... +...... + +.###.. +#...#. +#...#. +...#.. +..#... +...... +..#... +...... + +...... +####.. +....#. +.##.#. +#.#.#. +.###.. +...... +...... + +..#... +.#.#.. +#...#. +#####. +#...#. +#...#. +...... +...... + +###... +#..#.. +####.. +#...#. +#...#. +####.. +...... +...... + +.###.. +#...#. +#..... +#..... +#...#. +.###.. +...... +...... + +###... +#..#.. +#...#. +#...#. +#..#.. +###... +...... +...... + +#####. +#..... +###... +#..... +#..... +#####. +...... +...... + +#####. +#..... +#..... +###... +#..... +#..... +...... +...... + +.###.. +#..... +#..... +#..##. +#...#. +.###.. +...... +...... + +#...#. +#...#. +#####. +#...#. +#...#. +#...#. +...... +...... + +.###.. +..#... +..#... +..#... +..#... +.###.. +...... +...... + +..###. +...#.. +...#.. +...#.. +#..#.. +.##... +...... +...... + +#...#. +#..#.. +#.#... +###... +#..#.. +#...#. +...... +...... + +#..... +#..... +#..... +#..... +#..... +#####. +...... +...... + +#...#. +##.##. +#.#.#. +#...#. +#...#. +#...#. +...... +...... + +#...#. +##..#. +#.#.#. +#..##. +#...#. +#...#. +...... +...... + +.###.. +#...#. +#...#. +#...#. +#...#. +.###.. +...... +...... + +####.. +#...#. +#...#. +####.. +#..... +#..... +...... +...... + +.###.. +#...#. +#...#. +#.#.#. +#..#.. +.##.#. +...... +...... + +####.. +#...#. +#...#. +####.. +#..#.. +#...#. +...... +...... + +.####. +#..... +.###.. +....#. +....#. +####.. +...... +...... + +#####. +..#... +..#... +..#... +..#... +..#... +...... +...... + +#...#. +#...#. +#...#. +#...#. +#...#. +.###.. +...... +...... + +#...#. +#...#. +.#.#.. +.#.#.. +..#... +..#... +...... +...... + +#...#. +#...#. +#.#.#. +#.#.#. +.#.#.. +.#.#.. +...... +...... + +#...#. +#...#. +.###.. +.#.#.. +#...#. +#...#. +...... +...... + +#...#. +#...#. +.#.#.. +..#... +.#.... +#..... +...... +...... + +#####. +...#.. +..#... +.#.... +#..... +#####. +...... +...... + +..###. +..#... +..#... +..#... +..#... +..#... +..###. +...... + +...... +#..... +.#.... +..#... +...#.. +....#. +...... +...... + +###... +..#... +..#... +..#... +..#... +..#... +###... +...... + +..#... +.#.#.. +#...#. +...... +...... +...... +...... +...... + +...... +...... +...... +...... +...... +#####. +...... +...... + +..#... +..#... +...#.. +...... +...... +...... +...... +...... + +...... +.##.#. +#..##. +#...#. +#..##. +.##.#. +...... +...... + +#..... +#..... +####.. +#...#. +#...#. +####.. +...... +...... + +...... +.###.. +#...#. +#..... +#...#. +.###.. +...... +...... + +....#. +....#. +.####. +#...#. +#...#. +.####. +...... +...... + +...... +.###.. +#...#. +####.. +#..... +.####. +...... +...... + +...#.. +..#.#. +..#... +.###.. +..#... +..#... +...... +...... + +...... +.####. +#...#. +#...#. +.####. +....#. +.###.. +...... + +#..... +#..... +####.. +#...#. +#...#. +#...#. +...... +...... + +..#... +...... +..#... +..#... +..#... +..#... +...... +...... + +..#... +...... +..#... +..#... +..#... +#.#... +.#.... +...... + +#..... +#..#.. +#.#... +##.... +#.#... +#..#.. +...... +...... + +..#... +..#... +..#... +..#... +..#... +..#... +...... +...... + +...... +.#.#.. +#.#.#. +#.#.#. +#...#. +#...#. +...... +...... + +...... +#.##.. +##..#. +#...#. +#...#. +#...#. +...... +...... + +...... +.###.. +#...#. +#...#. +#...#. +.###.. +...... +...... + +...... +####.. +#...#. +#...#. +####.. +#..... +#..... +...... + +...... +.####. +#...#. +#...#. +.####. +....#. +....#. +...... + +...... +#.##.. +##..#. +#..... +#..... +#..... +...... +...... + +...... +.####. +#..... +.###.. +....#. +####.. +...... +...... + +...... +..#... +.###.. +..#... +..#.#. +...#.. +...... +...... + +...... +#...#. +#...#. +#...#. +#...#. +.###.. +...... +...... + +...... +#...#. +#...#. +.#.#.. +.#.#.. +..#... +...... +...... + +...... +#...#. +#...#. +#.#.#. +#.#.#. +.#.#.. +...... +...... + +...... +#...#. +.#.#.. +..#... +.#.#.. +#...#. +...... +...... + +...... +#...#. +.#.#.. +..#... +.#.... +#..... +...... +...... + +...... +#####. +...#.. +..#... +.#.... +#####. +...... +...... + +...##. +..#... +..#... +##.... +..#... +..#... +...##. +...... + +..#... +..#... +..#... +..#... +..#... +..#... +..#... +...... + +##.... +..#... +..#... +...##. +..#... +..#... +##.... +...... + +...... +...... +.#.... +#.#.#. +...#.. +...... +...... +...... + +#####. +#...#. +#.#.#. +#.#.#. +#.#.#. +#...#. +#####. +...... +""" +# """ # add quotes, because vim thinkt the qotes on the previous line start a string. + +import sys + +charsize = 7 * 8 + 1 +for c in range (128 - 32): + line = [] + for l in range (8): + offset = 1 + c * charsize + 7 * l + line += [int (data[offset:offset + 6].replace ('.', '0').replace ('#', '1'), 2)] + kols = [] + for k in range (5, -1, -1): + d = 0 + for l in range (8): + if line[l] & (1 << k): + d += 1 << l + sys.stdout.write (chr (d)) diff --git a/boot-programs/init.S b/boot-programs/crt0.S similarity index 94% rename from boot-programs/init.S rename to boot-programs/crt0.S index b5e0aaf..be5cfe8 100644 --- a/boot-programs/init.S +++ b/boot-programs/crt0.S @@ -20,6 +20,7 @@ .globl __my_thread .globl __my_memory .globl __my_call + .globl __my_parent .set noreorder __start: @@ -37,6 +38,8 @@ __hack_label: sw $a2, ($v0) la $v0, __my_call sw $a3, ($v0) + la $v0, __my_parent + sw $t0, ($v0) la $t9, main la $ra, 1f jr $t9 @@ -51,3 +54,4 @@ __hack_label: .comm __my_thread, 4 .comm __my_memory, 4 .comm __my_call, 4 + .comm __my_parent, 4 diff --git a/boot-programs/devices.hhp b/boot-programs/devices.hhp index 54970c7..ca40ef5 100644 --- a/boot-programs/devices.hhp +++ b/boot-programs/devices.hhp @@ -19,8 +19,9 @@ #ifndef __IRIS_DEVICES_HH #define __IRIS_DEVICES_HH -// lcd driver. -#define LCD_BACKLIGHT 1 -#define LCD_RESET 2 +enum init_requests: + INIT_SET_GPIO_0 + INIT_SET_GPIO_1 + INIT_SET_LCD #endif diff --git a/boot-programs/gpio.ccp b/boot-programs/gpio.ccp index a21a90c..a83142c 100644 --- a/boot-programs/gpio.ccp +++ b/boot-programs/gpio.ccp @@ -46,15 +46,56 @@ // Battery presence and charge detection: 3.29 (note that this is also a keyboard column.) // interrupts: no; it would be possible, but setting these to input makes it impossible to detect certain key presses as interrupts. +// interrupt summary +// Port 0: pin 0, 1, 2, 3, 4, 5, 6, 7: keyboard; 13, 16: touchpad +// Port 1: None. +// Port 2: None. +// Port 3: None. + +enum event_type: + KEYBOARD_EVENT + TOUCHPAD_EVENT + POWERBUTTON_EVENT + BATTERY_EVENT + NUM_EVENTS + +enum cap_type: + CAP_KEYBOARD = 32 + CAP_TOUCHPAD + CAP_POWEROFF + CAP_POWERBUTTON + CAP_BATTERY + CAP_LOCKLEDS + CAP_PWM + +static Capability cbs[NUM_EVENTS] + +static void event (event_type type, unsigned data): + if !cbs[type]: + return + invoke_01 (cbs[type], data) + +static void set_cb (event_type type, Capability cb): + if cbs[type]: + drop (cbs[type]) + cbs[type] = cb + +enum battery_type: + BATTERY_ABSENT + BATTERY_CHARGING + BATTERY_CHARGED + class Keyboard: enum { NUM_COLS = 17 } enum { COL_MASK = 0x2000ffff } enum { ROW_MASK = 0x000000ff } unsigned keys[NUM_COLS] - void event (bool release, unsigned row, unsigned col): + bool scanning public: + bool is_scanning (): + return scanning Keyboard (): // Set all columns to input and disable the pull-ups. GPIO_GPDIR (3) &= ~COL_MASK @@ -66,6 +107,7 @@ class Keyboard: // Enable interrupts on falling edge. GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & 0xffff) | (GPIO_IRQ_FALLEDG * 0xaaaa) GPIO_GPIER (0) |= 0xff + scanning = false for unsigned i = 0; i < NUM_COLS; ++i: keys[i] = 0xff @@ -81,31 +123,39 @@ class Keyboard: // Generate events. for unsigned row = 0; row < 8; ++row: if (data ^ keys[col]) & (1 << row): - event (data & (1 << row), row, col) + unsigned code = (row << 8) | col + if data & (1 << row): + code |= 0x10000 + event (KEYBOARD_EVENT, code) keys[col] = data if data != ROW_MASK: key_pressed = true if key_pressed: - // TODO: schedule keyboard scan. + scanning = true class Touchpad: - enum { LEFT = 1 << 16 } - enum { RIGHT = 1 << 13 } unsigned old_state - void event (): + public: + enum buttons: + LEFT = 1 << 16 + RIGHT = 1 << 13 + void check_events (): unsigned state = GPIO_GPDR (0) if (state ^ old_state) & LEFT: if state & LEFT: GPIO_GPIDUR (0) = (GPIO_GPIDUR (0) & (3 << (2 * 0))) | (GPIO_IRQ_FALLEDG << (2 * 0)) + event (TOUCHPAD_EVENT, 0) else: GPIO_GPIDUR (0) = (GPIO_GPIDUR (0) & (3 << (2 * 0))) | (GPIO_IRQ_RAISEDG << (2 * 0)) + event (TOUCHPAD_EVENT, 0x10000) if (state ^ old_state) & RIGHT: if state & RIGHT: GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & (3 << (2 * 13))) | (GPIO_IRQ_FALLEDG << (2 * 13)) + event (TOUCHPAD_EVENT, 1) else: GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & (3 << (2 * 13))) | (GPIO_IRQ_RAISEDG << (2 * 13)) + event (TOUCHPAD_EVENT, 0x10001) old_state = state - public: Touchpad (): // Set pins to input with pull-ups. GPIO_GPDIR (0) &= ~(LEFT | RIGHT) @@ -115,7 +165,7 @@ class Touchpad: GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & (3 << (2 * 13))) | (GPIO_IRQ_FALLEDG << (2 * 13)) old_state = 0 // See if they are already pressed. If so, the interrupt detection is changed. - event () + check_events () // Now enable the interrupts. GPIO_GPIER (0) |= LEFT | RIGHT @@ -130,16 +180,16 @@ class Lockleds: GPIO_GPDR (0) &= ~(SCROLL | CAPS) GPIO_GPDIR (2) |= NUM GPIO_GPDIR (0) |= CAPS | SCROLL - void set (bool num, bool caps, bool scroll): - if num: + void set (unsigned state): + if state & 4: GPIO_GPDR (2) &= ~NUM else: GPIO_GPDR (2) |= NUM - if caps: + if state & 2: GPIO_GPDR (0) &= ~CAPS else: GPIO_GPDR (0) |= CAPS - if scroll: + if state & 1: GPIO_GPDR (0) &= ~SCROLL else: GPIO_GPDR (0) |= SCROLL @@ -151,6 +201,7 @@ class Power: enum { BATTERY = 1 << 29 } unsigned old_state bool was_present + public: void poll (): // Switch off keyboard interrupts, because this may interfere with them. GPIO_GPIER (0) &= ~0xff @@ -159,25 +210,26 @@ class Power: udelay (100) unsigned state = GPIO_GPDR (3) if (state ^ old_state) & PWR_IN: - // TODO: event + event (POWERBUTTON_EVENT, state & PWR_IN ? 0 : 0x10000) if (state ^ old_state) & BATTERY: if !(state & BATTERY): GPIO_GPPUR (3) |= BATTERY udelay (100) if GPIO_GPDR (3) & BATTERY: if !was_present: - // TODO: event + event (BATTERY_EVENT, BATTERY_CHARGED) was_present = true else: if was_present: - // TODO: event + event (BATTERY_EVENT, BATTERY_ABSENT) was_present = false + else: + event (BATTERY_EVENT, BATTERY_CHARGING) old_state = state GPIO_GPPUR (3) &= ~BATTERY GPIO_GPDIR (3) &= ~(PWR_IN | BATTERY) udelay (100) GPIO_GPIER (3) |= 0xff - public: Power (): GPIO_GPDR (2) |= PWR_OUT GPIO_GPDIR (2) |= PWR_OUT @@ -186,23 +238,90 @@ class Power: poll () void poweroff (): GPIO_GPDR (2) &= ~PWR_OUT + GPIO_GPDIR (2) |= PWR_OUT while true: // Do nothing; wait until the device stops running. +// Not really a gpio device, but it's so small, and uses gpio, so I include it here to avoid ipc. +class Pwm: + // Pin definitions, all in port 2. + enum { PWM_ENABLE = 1 << 30 } + public: + Pwm (): + GPIO_GPDIR (2) |= PWM_ENABLE + PWM_PER (0) = 300 + void set_backlight (bool state): + if state: + PWM_DUT (0) = 300 + PWM_CTR (0) = 0xbf + GPIO_GPDR (2) |= PWM_ENABLE + else: + PWM_DUT (0) = 0 + PWM_CTR (0) = 0x3f + GPIO_GPDR (2) &= ~PWM_ENABLE + // TODO: make it really work as a pwm instead of a switch; check if pwm1 is connected to anything. + int main (): map_gpio () + map_pwm0 () Keyboard kbd Touchpad tp - Lockleds leds + //Lockleds leds Power power + Pwm pwm + register_interrupt (IRQ_GPIO0) + + Capability cap_kbd = receiver_create_capability (__my_receiver, CAP_KEYBOARD) + Capability cap_tp = receiver_create_capability (__my_receiver, CAP_TOUCHPAD) + Capability cap_poweroff = receiver_create_capability (__my_receiver, CAP_POWEROFF) + Capability cap_powerbutton = receiver_create_capability (__my_receiver, CAP_POWERBUTTON) + Capability cap_battery = receiver_create_capability (__my_receiver, CAP_BATTERY) + Capability cap_lockleds = receiver_create_capability (__my_receiver, CAP_LOCKLEDS) + Capability cap_pwm = receiver_create_capability (__my_receiver, CAP_PWM) + + invoke_41 (__my_parent, cap_copy (cap_kbd), cap_copy (cap_tp), cap_copy (cap_poweroff), cap_copy (cap_powerbutton), INIT_SET_GPIO_0) + invoke_31 (__my_parent, cap_copy (cap_battery), cap_copy (cap_lockleds), cap_copy (cap_pwm), INIT_SET_GPIO_1) + + receiver_set_alarm (__my_receiver, HZ / 5) while true: Message msg wait (&msg) switch msg.protected_data: + case ~0: + // Alarm. + if kbd.is_scanning (): + kbd.scan () + power.poll () + receiver_set_alarm (__my_receiver, HZ / 5) + break case IRQ_GPIO0: - case IRQ_GPIO1: - case IRQ_GPIO2: - case IRQ_GPIO3: - // TODO + unsigned irq = GPIO_GPFR (0) + // Ack all. This works because they are all edge triggered. + GPIO_GPFR (0) = irq + if irq & 0xff: + kbd.scan () + if irq & (Touchpad::LEFT | Touchpad::RIGHT): + tp.check_events () + case CAP_KEYBOARD: + set_cb (KEYBOARD_EVENT, msg.cap[0]) + break + case CAP_TOUCHPAD: + set_cb (TOUCHPAD_EVENT, msg.cap[0]) + break + case CAP_POWEROFF: + power.poweroff () + break + case CAP_POWERBUTTON: + set_cb (POWERBUTTON_EVENT, msg.cap[0]) + break + case CAP_BATTERY: + set_cb (BATTERY_EVENT, msg.cap[0]) + break + case CAP_LOCKLEDS: + //leds.set (msg.data[0]) + break + case CAP_PWM: + pwm.set_backlight (msg.data[0]) + break diff --git a/boot-programs/init.ccp b/boot-programs/init.ccp new file mode 100644 index 0000000..6e01958 --- /dev/null +++ b/boot-programs/init.ccp @@ -0,0 +1,84 @@ +#pypp 0 +// Iris: micro-kernel for a capability-based operating system. +// boot-programs/init.ccp: System boot manager. +// Copyright 2009 Bas Wijnen +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "devices.hh" +#include "iris.h" + +static Capability kbd, tp, poweroff, powerbutton, battery, lockleds, pwm, lcd + +enum type: + KBD = 0x10000 + TP + POWERBUTTON + BATTERY + +static void send (Capability c, unsigned d): + Capability n = receiver_create_capability (__my_receiver, d) + invoke_10 (c, cap_copy (n)) + drop (n) + +static void setup (): + unsigned state = 0 + while true: + Message msg + wait (&msg) + switch msg.data[0]: + case INIT_SET_GPIO_0: + kdebug (0, 2) + kbd = msg.cap[0] + tp = msg.cap[1] + poweroff = msg.cap[2] + powerbutton = msg.cap[3] + ++state + break + case INIT_SET_GPIO_1: + kdebug (1, 2) + battery = msg.cap[0] + lockleds = msg.cap[1] + pwm = msg.cap[2] + ++state + break + case INIT_SET_LCD: + kdebug (2, 2) + lcd = msg.cap[0] + ++state + break + if state == 3: + break + send (kbd, KBD) + send (tp, TP) + send (powerbutton, POWERBUTTON) + send (battery, BATTERY) + invoke_01 (pwm, 1) + +int main (): + setup () + kdebug (3, 2) + while true: + Message msg + wait (&msg) + switch msg.protected_data: + case KBD: + invoke_01 (lockleds, 0x4 | (msg.data[0] >> 16)) + break + case TP: + invoke_01 (lockleds, 0x2 | (msg.data[0] >> 16)) + break + case POWERBUTTON: + case BATTERY: + break diff --git a/boot-programs/lcd.ccp b/boot-programs/lcd.ccp index 6c5dcf8..760e927 100644 --- a/boot-programs/lcd.ccp +++ b/boot-programs/lcd.ccp @@ -20,30 +20,20 @@ #define ARCH #include "arch.hh" +__asm__ volatile (".globl charset\ncharset:\n.incbin \"boot-programs/charset.data\"") +// I'm too lazy to do this right. The address of charset is really the address of the array. +extern unsigned charset + #define assert(x) do { while (!(x)) kdebug (0, 0); } while (0) +enum types: + LCD_EOF_CB = 32 + // For now, support only 16 bpp. // Screen is 800x480 tft. unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2 #define frame_size (v * h * Bpp) -// Pin definitions, all in port 2. -#define PWM_ENABLE (1 << 30) -#define SPEN (1 << 0) //LCD_SPL -#define SPCK (1 << 1) //LCD_CLS -#define SPDA (1 << 2) //LCD_PS -#define LCD_RET (1 << 3) //LCD_REV //use for lcd reset - -static void set_backlight (bool state): - if state: - PWM_DUT (0) = 300 - PWM_CTR (0) = 0xbf - GPIO_GPDR (2) |= PWM_ENABLE - else: - PWM_DUT (0) = 0 - PWM_CTR (0) = 0x3f - GPIO_GPDR (2) &= ~PWM_ENABLE - struct Descriptor: unsigned next unsigned frame @@ -51,18 +41,6 @@ struct Descriptor: unsigned cmd static void reset (unsigned physical_descriptor): - PWM_PER (0) = 300 - set_backlight (true) - - // initialize things. - GPIO_GPIER (2) &= ~(PWM_ENABLE | LCD_RET | SPEN | SPCK | SPDA) - GPIO_GPDIR (2) |= PWM_ENABLE | LCD_RET - udelay (50) - GPIO_GPDR (2) &= ~LCD_RET - ddelay (2) - GPIO_GPDR (2) |= LCD_RET - ddelay (1) - LCD_CTRL = LCD_CTRL_BPP_16 | LCD_CTRL_BST_16 LCD_VSYNC = vs LCD_HSYNC = hs @@ -92,6 +70,88 @@ static void reset (unsigned physical_descriptor): lcd_set_ena () lcd_enable_eof_intr () +static void putchar (unsigned x, unsigned y, unsigned utf8, unsigned fg = 0xffff, unsigned bg = 0x0000): + if utf8 < 32 || utf8 > 126: + utf8 = 127 + unsigned idx = utf8 - 32 + unsigned char *c = &((unsigned char *)&charset)[idx * 6] + unsigned lookup[2] = { bg, fg } + for unsigned k = 0; k < 6; ++k: + for unsigned r = 0; r < 8; ++r: + LCD_FRAMEBUFFER_BASE[(y * 8 + r) * 800 + x * 6 + k] = lookup[c[k] & (1 << r) ? 1 : 0] + +static unsigned read_rest (unsigned num, char const *&utf8): + unsigned ret = 0 + while num--: + if (*utf8 & 0xc0) != 0x80: + return ~0 + ret <<= 6 + ret |= (*utf8++) & 0x3f + return ret + +static unsigned read_utf8 (char const *&utf8): + unsigned c = *utf8++ + if !(c & 0x80): + return c + if !(c & 0x40): + // Invalid character. + return 0 + if !(c & 0x20): + // 2-byte character. + c &= 0x1f + c <<= 6 + c |= read_rest (1, utf8) + else if !(c & 0x10): + // 3-byte character. + c &= 0xf + c <<= 12 + c |= read_rest (2, utf8) + else if !(c & 0x8): + // 4-byte character. + c &= 0x7 + c <<= 18 + c |= read_rest (3, utf8) + else if !(c & 0x4): + // 5-byte character. + c &= 0x3 + c <<= 24 + c |= read_rest (4, utf8) + else if !(c & 0x2): + // 6-byte character. + c &= 0x1 + c <<= 30 + c |= read_rest (5, utf8) + else + // Invalid character. + return 0 + if c == ~0: + return 0 + return c + +static void putstr (unsigned x, unsigned y, char const *utf8): + while *utf8: + putchar (x++, y, read_utf8 (utf8)) + +static unsigned log_x = 1, log_y = 1 +static void inc_logx (): + if ++log_x >= 800 / 6: + log_x = 1 + if ++log_y >= 480 / 8: + log_y = 1 + +static void log (char const *utf8): + while *utf8: + unsigned c = read_utf8 (utf8) + switch c: + case '\n': + while log_x < 800 / 6: + putchar (log_x++, log_y, ' ') + inc_logx () + break + default: + putchar (log_x, log_y, c) + inc_logx () + int main (): // TODO: The descriptor takes an entire uncached page, because I don't know how to force a cache write-back. It's much better to do that instead. map_gpio () @@ -119,12 +179,8 @@ int main (): alloc_physical (page, physical + (i + CAPPAGE_SIZE) * PAGE_SIZE, 0, 1) memory_map (__my_memory, page, (unsigned)LCD_FRAMEBUFFER_BASE + (i + CAPPAGE_SIZE) * PAGE_SIZE, 1) drop (page) - unsigned og = 0 for unsigned y = 0; y < 480; ++y: unsigned g = (y << 6) / 480 - if g != og: - og = g - g = 0x3f unsigned olr = 0, ob = ((25 * y * y) << 5) / (9 * 800 * 800 + 25 * 480 * 480) for unsigned x = 0; x < 800; ++x: unsigned r = (x << 5) / 800 @@ -139,6 +195,7 @@ int main (): ob = b b = 0x1f LCD_FRAMEBUFFER_BASE[y * 800 + x] = (r << 11) | (g << 5) | (b) + log ("testing!\nIs dit een werkende console?\nLinks, rechts?\n") Descriptor *descriptor = (Descriptor *)((unsigned)LCD_FRAMEBUFFER_BASE + frame_size) unsigned physical_descriptor = physical + frame_size descriptor->next = physical_descriptor @@ -147,7 +204,12 @@ int main (): descriptor->cmd = LCD_CMD_EOFINT | ((frame_size / 4) << LCD_CMD_LEN_BIT) reset (physical_descriptor) register_interrupt (IRQ_LCD) - set_backlight (true) + + Capability eof_cb = 0 + + Capability cap = receiver_create_capability (__my_receiver, LCD_EOF_CB) + invoke_11 (__my_parent, cap, INIT_SET_LCD) + drop (cap) while true: Message msg @@ -156,13 +218,11 @@ int main (): case IRQ_LCD: lcd_clr_eof () register_interrupt (IRQ_LCD) - // TODO: allow callback + if eof_cb: + invoke_00 (eof_cb) break - #if 0 - case LCD_BACKLIGHT: - set_backlight (msg.data[0]) + case LCD_EOF_CB: + if eof_cb: + drop (eof_cb) + eof_cb = msg.cap[0] break - case LCD_RESET: - //reset (physical_descriptor) - break - #endif diff --git a/invoke.ccp b/invoke.ccp index bcc4bd3..0d493c3 100644 --- a/invoke.ccp +++ b/invoke.ccp @@ -127,9 +127,6 @@ bool Receiver::send_message (unsigned protected_data, Capability::Context *c): address_space->free_capability (msg->capabilities[j]) address_space->free_message (this, msg) return false - if tried_direct: - Thread_arch_receive_fail (owner) - owner->unwait () return true static Capability *reply @@ -141,8 +138,6 @@ static void fill_cap (Capability *r, unsigned target, unsigned protected_data): ref = &((Receiver *)target)->capabilities else: ref = &((Object_base *)protected_data)->refs - // alloc_capability needs a Memory, but it isn't used if return storage is given. - ref = &((Object_base *)protected_data)->refs // alloc_capability needs a Memory, but it isn't used if return storage is given. top_memory.alloc_capability ((Receiver *)target, NULL, ref, protected_data, r) diff --git a/iris.h b/iris.h index e164211..fce1c45 100644 --- a/iris.h +++ b/iris.h @@ -29,6 +29,9 @@ extern "C" { #endif +// Number of clock interrupts per second. +#define HZ 10 + #define PAGE_BITS (12) #define PAGE_SIZE (1 << PAGE_BITS) #define PAGE_MASK (~(PAGE_SIZE - 1)) @@ -135,6 +138,7 @@ extern Capability __my_receiver; extern Capability __my_thread; extern Capability __my_memory; extern Capability __my_call; +extern Capability __my_parent; Capability cap_copy (Capability src) { @@ -169,23 +173,23 @@ static void invoke (Capability target, Message *msg) "\tsyscall" : : "m"(target), "m"(msg) - : "v0", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3"); + : "memory", "v0", "v1", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3"); } static void wait (Message *msg) { __asm__ volatile ("li $v0, 2\n" "\tsyscall\n" - "\tlw $v0, %0\n" - "\tsw $t0, 0($v0)\n" - "\tsw $t1, 4($v0)\n" - "\tsw $t2, 8($v0)\n" - "\tsw $t3, 12($v0)\n" - "\tsw $a0, 16($v0)\n" - "\tsw $a1, 20($v0)\n" - "\tsw $a2, 24($v0)\n" - "\tsw $a3, 28($v0)\n" - "\tsw $v1, 32($v0)" + "\tlw $v1, %0\n" + "\tsw $t0, 0($v1)\n" + "\tsw $t1, 4($v1)\n" + "\tsw $t2, 8($v1)\n" + "\tsw $t3, 12($v1)\n" + "\tsw $a0, 16($v1)\n" + "\tsw $a1, 20($v1)\n" + "\tsw $a2, 24($v1)\n" + "\tsw $a3, 28($v1)\n" + "\tsw $v0, 32($v1)" : : "m"(msg) : "memory", "v0", "v1", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3"); @@ -205,21 +209,35 @@ static void call (Capability target, Message *msg) "\tlw $a2, 24($v1)\n" "\tlw $a3, 28($v1)\n" "\tsyscall\n" - "\tlw $v0, %1\n" - "\tsw $t0, 0($v0)\n" - "\tsw $t1, 4($v0)\n" - "\tsw $t2, 8($v0)\n" - "\tsw $t3, 12($v0)\n" - "\tsw $a0, 16($v0)\n" - "\tsw $a1, 20($v0)\n" - "\tsw $a2, 24($v0)\n" - "\tsw $a3, 28($v0)\n" - "\tsw $v1, 32($v0)" + "\tlw $v1, %1\n" + "\tsw $t0, 0($v1)\n" + "\tsw $t1, 4($v1)\n" + "\tsw $t2, 8($v1)\n" + "\tsw $t3, 12($v1)\n" + "\tsw $a0, 16($v1)\n" + "\tsw $a1, 20($v1)\n" + "\tsw $a2, 24($v1)\n" + "\tsw $a3, 28($v1)\n" + "\tsw $v0, 32($v1)" : : "m"(t), "m"(msg) : "memory", "v0", "v1", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3"); } +static void invoke_00 (Capability t) +{ + Message msg; + msg.data[0] = 0; + msg.data[1] = 0; + msg.data[2] = 0; + msg.data[3] = 0; + msg.cap[0] = 0; + msg.cap[1] = 0; + msg.cap[2] = 0; + msg.cap[3] = 0; + invoke (t, &msg); +} + static void invoke_01 (Capability t, unsigned d) { Message msg; @@ -276,6 +294,20 @@ static void invoke_04 (Capability t, unsigned d0, unsigned d1, unsigned d2, unsi invoke (t, &msg); } +static void invoke_10 (Capability t, Capability c) +{ + Message msg; + msg.cap[0] = c; + msg.data[0] = 0; + msg.data[1] = 0; + msg.data[2] = 0; + msg.data[3] = 0; + msg.cap[1] = 0; + msg.cap[2] = 0; + msg.cap[3] = 0; + invoke (t, &msg); +} + static void invoke_11 (Capability t, Capability c, unsigned d) { Message msg; @@ -318,6 +350,62 @@ static void invoke_13 (Capability t, Capability c, unsigned d0, unsigned d1, uns invoke (t, &msg); } +static void invoke_20 (Capability t, Capability c0, Capability c1) +{ + Message msg; + msg.cap[0] = c0; + msg.cap[1] = c1; + msg.data[0] = 0; + msg.data[1] = 0; + msg.data[2] = 0; + msg.data[3] = 0; + msg.cap[2] = 0; + msg.cap[3] = 0; + invoke (t, &msg); +} + +static void invoke_21 (Capability t, Capability c0, Capability c1, unsigned d) +{ + Message msg; + msg.cap[0] = c0; + msg.cap[1] = c1; + msg.data[0] = d; + msg.data[1] = 0; + msg.data[2] = 0; + msg.data[3] = 0; + msg.cap[2] = 0; + msg.cap[3] = 0; + invoke (t, &msg); +} + +static void invoke_31 (Capability t, Capability c0, Capability c1, Capability c2, unsigned d) +{ + Message msg; + msg.cap[0] = c0; + msg.cap[1] = c1; + msg.cap[2] = c2; + msg.data[0] = d; + msg.data[1] = 0; + msg.data[2] = 0; + msg.data[3] = 0; + msg.cap[3] = 0; + invoke (t, &msg); +} + +static void invoke_41 (Capability t, Capability c0, Capability c1, Capability c2, Capability c3, unsigned d) +{ + Message msg; + msg.cap[0] = c0; + msg.cap[1] = c1; + msg.cap[2] = c2; + msg.cap[3] = c3; + msg.data[0] = d; + msg.data[1] = 0; + msg.data[2] = 0; + msg.data[3] = 0; + invoke (t, &msg); +} + static Capability call_c01 (Capability c, unsigned d) { Message msg; diff --git a/kernel.hhp b/kernel.hhp index 7316540..d36d612 100644 --- a/kernel.hhp +++ b/kernel.hhp @@ -19,9 +19,6 @@ #ifndef _KERNEL_HH #define _KERNEL_HH -// Number of clock interrupts per second. -#define HZ 10 - // Include definitions which are shared with user space. #define __KERNEL #include "iris.h" @@ -205,7 +202,6 @@ void phys_free (unsigned page, unsigned num) // Defined by architecture-specific files. void Thread_arch_init (Thread *thread) void Thread_arch_receive (Thread *thread, unsigned protected_data, Capability::Context *c) -void Thread_arch_receive_fail (Thread *thread) unsigned *Thread_arch_info (Thread *thread, unsigned num) void Memory_arch_init (Memory *mem) void Memory_arch_free (Memory *mem) diff --git a/mips/Makefile.arch b/mips/Makefile.arch index a23fb57..9dc43fc 100644 --- a/mips/Makefile.arch +++ b/mips/Makefile.arch @@ -17,7 +17,7 @@ load = 0x80000000 -ARCH_CXXFLAGS = -DNUM_THREADS=1 +ARCH_CXXFLAGS = -DNUM_THREADS=3 ARCH_CPPFLAGS = -Imips -Wa,-mips32 CROSS = mipsel-linux-gnu- OBJDUMP = $(CROSS)objdump @@ -26,9 +26,8 @@ OBJCOPYFLAGS = $(addprefix --remove-section=.,$(junk)) arch_kernel_sources = mips/interrupts.cc mips/test.cc mips/arch.cc boot_sources = mips/init.cc -BUILT_SOURCES = $(kernel_sources) $(boot_sources) arch_headers = mips/arch.hh mips/jz4730.hh -boot_threads = gpio lcd +boot_threads = init gpio lcd uimage: @@ -36,6 +35,10 @@ mips/entry.o: $(boot_threads) mips/init.o: TARGET_FLAGS = -I/usr/include $(boot_threads): TARGET_FLAGS = -I. $(boot_threads): boot-programs/devices.hh +lcd: boot-programs/charset.data + +boot-programs/charset.data: boot-programs/charset + $< > $@ # Transform ':' into ';' so vim doesn't think there are errors. uimage: kernel.raw.gz Makefile mips/Makefile.arch @@ -54,4 +57,4 @@ kernel: mips/entry.o $(subst .cc,.o,$(kernel_sources)) mips/boot.o $(subst .cc,. %.gz: % gzip < $< > $@ -ARCH_CLEAN_FILES = uimage kernel kernel.raw kernel.raw.gz $(boot_threads) mips/*.o +ARCH_CLEAN_FILES = uimage kernel kernel.raw kernel.raw.gz $(boot_threads) mips/*.o boot-programs/charset.data diff --git a/mips/arch.ccp b/mips/arch.ccp index fbee855..76c20e5 100644 --- a/mips/arch.ccp +++ b/mips/arch.ccp @@ -54,11 +54,7 @@ void Thread_arch_receive (Thread *thread, unsigned protected_data, Capability::C thread->arch.t1 = c->data[1] thread->arch.t2 = c->data[2] thread->arch.t3 = c->data[3] - thread->arch.v1 = protected_data - thread->arch.v0 = 1 - -void Thread_arch_receive_fail (Thread *thread): - thread->arch.v0 = 0 + thread->arch.v0 = protected_data unsigned *Thread_arch_info (Thread *thread, unsigned num): switch num: diff --git a/mips/boot.S b/mips/boot.S index e8aa049..4422431 100644 --- a/mips/boot.S +++ b/mips/boot.S @@ -38,7 +38,14 @@ start_hack_for_disassembler: la $sp, kernel_stack + KERNEL_STACK_SIZE - // TODO: flush cache and optionally refill it. + // Flush cache. + lui $v1, 0x8000 + ori $v0, $v1, 0x8000 +1: + cache 0, 0($v1) + cache 1, 0($v1) + bne $v1, $v0, 1b + addiu $v1, $v1, 32 // Set kseg0 cachable. li $k0, 0x3 @@ -67,3 +74,4 @@ thread_start: .word thread0 .word thread1 .word thread2 + .word thread3 diff --git a/mips/entry.S b/mips/entry.S index 009e1ed..c869de8 100644 --- a/mips/entry.S +++ b/mips/entry.S @@ -231,10 +231,14 @@ save_regs: .globl thread0 .globl thread1 .globl thread2 + .globl thread3 .balign 0x1000 thread0: - .incbin "lcd" + .incbin "init" .balign 0x1000 thread1: - .incbin "gpio" + .incbin "lcd" + .balign 0x1000 thread2: + .incbin "gpio" +thread3: diff --git a/mips/init.ccp b/mips/init.ccp index 9aec1b6..65d2e02 100644 --- a/mips/init.ccp +++ b/mips/init.ccp @@ -141,6 +141,8 @@ static void init_threads (): //bool executable = shdr->sh_flags & SHF_EXEC_INSTR if shdr->sh_type != SHT_NOBITS: unsigned file_offset = shdr->sh_offset >> PAGE_BITS + if ((file_offset + shdr->sh_size) >> PAGE_BITS) >= (PAGE_SIZE >> 2): + panic (0x87446809, "initial thread too large") for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE: unsigned section_offset = (p - (shdr->sh_addr & PAGE_MASK)) >> PAGE_BITS unsigned idx = file_offset + section_offset @@ -238,11 +240,9 @@ void init (unsigned mem): // Set up initial threads. init_threads () - // Disable all gpio pins initially. + // Disable all gpio interrupts and alternate functions initially. for unsigned i = 0; i < 4; ++i: GPIO_GPIER (i) = 0 - GPIO_GPDIR (i) = 0 - GPIO_GPPUR (i) = 0 GPIO_GPALR (i) = 0 GPIO_GPAUR (i) = 0 // Set up the rest of the hardware (copied from Linux). diff --git a/mips/interrupts.ccp b/mips/interrupts.ccp index e4904bc..7db2982 100644 --- a/mips/interrupts.ccp +++ b/mips/interrupts.ccp @@ -19,6 +19,11 @@ #define ARCH #include "../kernel.hh" +typedef unsigned cacheline[8] +void arch_flush_cache (): + for cacheline *line = (cacheline *)0x80000000; line < (cacheline *)0x80008000; ++line: + __asm__ volatile ("lw $k0, %0; cache 0, 0($k0); cache 1, 0($k0)" :: "m"(line)) + static void handle_exit (Thread *old_current): if !current || (current == &idle): schedule () @@ -26,6 +31,7 @@ static void handle_exit (Thread *old_current): current = &idle if old_current == current: return + arch_flush_cache () if current != &idle: if (Memory *)asids[current->address_space->arch.asid] != current->address_space: if asids[0]: @@ -146,40 +152,48 @@ Thread *exception (): switch (cause >> 2) & 0x1f: case 0: // Interrupt. This shouldn't happen, since CAUSE[IV] == 1. - panic (0x11223344, "Interrupt on exception vector.") + panic (0x01223344, "Interrupt on exception vector.") case 1: // TLB modification. - panic (0x21223344, "TLB modification.") + panic (0x11223344, "TLB modification.") case 2: // TLB load or instruction fetch. unsigned a cp0_get (CP0_EPC, a) dbg_send (a) - panic (0x31223344, "TLB load or instruction fetch.") + panic (0x21223344, "TLB load or instruction fetch.") case 3: // TLB store. unsigned a cp0_get (CP0_EPC, a) dbg_send (a) - panic (0x41223344, "TLB store.") + cp0_get (CP0_BAD_V_ADDR, a) + dbg_send (a) + panic (0x31223344, "TLB store.") case 4: // Address error load or instruction fetch. unsigned a cp0_get (CP0_EPC, a) dbg_send (a) - panic (0x51223344, "Address error load or instruction fetch.") + cp0_get (CP0_BAD_V_ADDR, a) + dbg_send (a) + panic (0x41223344, "Address error load or instruction fetch.") case 5: // Address error store. + dbg_send (current->arch.v1, 4) unsigned a + cp0_get (CP0_EPC, a) + dbg_send (*(unsigned *)(a & ~3), 32) + dbg_send (a, 32) cp0_get (CP0_BAD_V_ADDR, a) dbg_send (a, 32) - panic (0x61223344, "Address error store.") + panic (0x51223344, "Address error store.") case 6: // Bus error instruction fetch. - panic (0x71223344, "Bus error instruction fetch.") + panic (0x61223344, "Bus error instruction fetch.") case 7: // Bus error load or store. - panic (0x81223344, "Bus error load or store.") + panic (0x71223344, "Bus error load or store.") case 8: // Syscall. current->pc += 4 @@ -202,13 +216,13 @@ Thread *exception (): panic (0xc1223344, "Arithmetic overflow.") case 13: // Trap. - panic (0xe1223344, "Trap.") + panic (0xd1223344, "Trap.") case 15: // Floating point exception. - panic (0xf1223344, "Floating point exception.") + panic (0xe1223344, "Floating point exception.") case 23: // Reference to WatchHi/WatchLo address. - panic (0xf2223344, "Reference to WatchHi/WatchLo address.") + panic (0xf1223344, "Reference to WatchHi/WatchLo address.") case 24: // Machine check. panic (0xf3223344, "Machine check.") diff --git a/schedule.ccp b/schedule.ccp index af77853..f64d444 100644 --- a/schedule.ccp +++ b/schedule.ccp @@ -92,13 +92,8 @@ void schedule (): current = &idle void timer_interrupt (): - //panic (0x88877744, "Timer interrupt") Receiver *recv, *next for recv = first_alarm; recv; recv = next: next = recv->next alarm_tick (recv) - schedule () - //#ifndef NDEBUG - //static bool ledstate = false - //dbg_led (false, false, ledstate = !ledstate) - //#endif + //schedule ()