Blame

e09617 Bob Green 2026-10-28 17:13:32
1
# NetBSD Port
26eeaf Bob Green 2026-10-28 17:21:46
2
3
> [!WARNING]
4
> This page is very much a work in progress!
5
6
7
## Building
8
I've forked a copy of the NetBSD sources.
9
### Kernel
10
NetBSD contains a port called **hb68k** which is designed for any 680x0 sbc type of board and I used that to create a variant for my SBC, which I've called **SBC3**.
11
12
```
13
git clone https://github.com/znac049/netbsd-src.git
14
cd netbsd-src
a34307 Bob Green 2026-10-28 17:23:37
15
./build.sh -U -u -j4 -O ~/obj -m hb68k tools
26eeaf Bob Green 2026-10-28 17:21:46
16
./build.sh -U -u -j4 -O ~/obj -m hb68k kernel=SBC3
17
./build.sh -U -u -j4 -O ~/obj -m hb68k distribution
18
```
19
e0d053 Bob Green 2026-10-28 17:22:31
20
- The first step builds the tools (compiler etc) that will be used to build the kernel and userspace.
21
- The next step builds the kernel.
26eeaf Bob Green 2026-10-28 17:21:46
22
- The final step takes a Long Time(tm) and builds the userspace, which will need to be added to the root filesystem.
e0d053 Bob Green 2026-10-28 17:22:31
23
24
I've still got to document how to build the root filesystem.
865e89 Bob Green 2026-10-30 07:28:07
25
26
## Device Driver Templates
27
I asked Claude about templates for coding device drivers. Here's what it said:
28
29
### Uart
30
The template is myuart.c. It’s a complete single-channel UART driver for hb68k: it attaches through the device tree, can be the system console, and gives you a normal tty with interrupt-driven I/O.
31
32
What you change: the two CHIP-SPECIFIC sections near the top
33
34
- Register map: placeholder offsets and bit definitions for data, status, control, baud divisor and interrupt enable. The real byte offset is reg << reg-shift, so register spacing comes from the device tree rather than the code.
35
- Eight small hardware functions, the only code that touches the chip:
36
- `rx_ready` / `getc`
37
- `tx_ready` / `putc`
38
- `clear_errors`
39
- `set_intr`
40
- `intr_pending`
41
- `program`, which sets speed and frame format from termios flags. The example assumes a 16× divisor UART.
42
- The `compatible` string your device-tree node will use.
43
44
Everything below those sections is generic, and you shouldn’t need to touch it for a first version: console, autoconfiguration, interrupt handling, soft interrupt, and the tty and cdevsw entry points. Each part has a comment explaining its role and the locking.
45
46
#### How data moves:
47
48
- Receive: the hard interrupt copies bytes into a ring buffer. A soft interrupt later passes them to the tty layer, because the hard interrupt mustn’t call into it.
49
- Transmit: the tty layer hands over a chunk of output. The transmit interrupt feeds it to the chip, then switches itself off when the chunk is done.
50
- Console: the console uses polling and works from very early in boot. BREAK on the console drops into DDB.
51
52
Setup steps, all listed at the top of the file:
53
54
1. Add the device/attach/file lines to files.hb68k.
55
1. Add a major number to majors.hb68k. 14 is free in your tree.
56
1. Add a myuart* at fdt? pass 5 line to the kernel config.
57
1. Add a device-tree node.
58
1. On the target, make the device node by hand (mknod /dev/ttyM0 c 14 0), since MAKEDEV won’t know about the driver.
59
60
Deliberately left out:
61
62
- modem control (carrier is treated as always present)
63
- hardware flow control
64
- split input/output speeds
65
- sending BREAK
66
67
The ioctl function marks where the last of these goes. Your mc68681_duart.c is a worked example of the same structure extended to a two-channel chip, with an IVR, if you want to compare.
68
69
One constraint carries over from your board: the driver’s lock is a spin mutex at IPL_VM, so the chip’s interrupt level in the device tree must be 5 or lower.
70
71
Myuart
72
C
73
74
### Timer
75
76
Confirmed: a NULL argument makes the dispatcher pass the interrupt frame. Now a compile test:
77
78
The timer template is mytimer.c, built the same way as the UART one. I compiled it into an SBC3 kernel twice, once each way for the auto-reload setting, and both built cleanly. Then I took it back out of the tree.
79
80
What you change: the CHIP-SPECIFIC sections
81
82
- Registers: a placeholder register map for a simple down-counter (control, status, 24-bit reload).
83
- Limits and reload behaviour:
84
- MYTIMER_COUNT_MAX is the largest reload value.
85
- MYTIMER_PRESCALE is any fixed divider in front of the counter.
86
- MYTIMER_AUTO_RELOAD says whether the chip restarts itself at zero. If it doesn’t, the driver restarts it by hand on every tick. That loses a little time per tick, so the clock runs slightly slow.
87
- Three hardware functions:
88
- hw_stop() stops the counter and clears pending interrupts.
89
- hw_start(count) loads the count and starts periodic interrupts.
90
- hw_ack() clears the interrupt. Getting this wrong makes the machine appear to hang, because the CPU re-enters the handler immediately.
91
92
How it fits into hb68k: a timer driver provides only mechanism. The clock code in hb68k/clock.c owns the policy and calls the driver through four functions in a small table (struct clock_if):
93
94
Function When it’s called What it does
95
clk_init once, late in boot establishes the interrupt at IPL_SCHED
96
clk_arm(interval_us) once, right after init starts periodic interrupts, e.g. every 10 000 µs for 100 Hz
97
clk_intr at the start of every tick acknowledges the interrupt, and reloads if needed
98
clk_disarm shutdown or error stops the timer
99
100
The file header explains:
101
102
- How netbsd,hardclock / netbsd,statclock under /chosen pick each timer’s role, and what happens without them.
103
- Why the timer belongs at IPL 6.
104
- Which HZ values are allowed (they must divide 1 000 000).
105
- Why the interrupt handler’s argument must be NULL. I checked this in the dispatcher: with NULL, the clock code receives the interrupt frame, which it needs.
106
107
Setup is lighter than the UART’s:
108
109
- Add device/attach/file to files.hb68k.
110
- Add mytimer* at fdt? pass 3 to the config.
111
- Add a device-tree node with clocks or clock-frequency, plus an interrupts entry.
112
113
There’s no major number or /dev node, since nothing opens a timer.
114
115
Left out deliberately:
116
117
- A high-resolution timecounter. That needs a free-running counter, not a counter that resets every tick, so it depends on what your chip offers.
118
- Randomising the statclock interval. hb68k’s clock code doesn’t do this yet either.
119
120
Mytimer
121
C