-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathversatilepb-graphics.nothing
352 lines (311 loc) · 11.7 KB
/
versatilepb-graphics.nothing
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
;; -*- mode: scheme -*-
;; Copyright (C) 2012-2015 Tony Garnock-Jones <[email protected]>
;;
;; This file is part of pi-nothing.
;;
;; pi-nothing 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.
;;
;; pi-nothing 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 pi-nothing. If not, see <http://www.gnu.org/licenses/>.
(struct uart ((dr word)
(rsr-ecr word)
(reserved1 byte 16)
(fr word)
(reserved2 byte 4)
(lpr word)
(ibrd word)
(fbrd word)
(lcr-h word)
(cr word)
(ifls word)
(imsc word)
(ris word)
(mis word)
(icr word)
(dmacr word)))
(const uart0 #x101f1000)
(const uart-flag-rx-fifo-empty #x10)
(const uart-flag-tx-fifo-full #x20)
(define (division-by-zero a b)
(puts (data #"Division by zero\0"))
(while (= 0 0)))
(define (putc ch)
(while (<> (binand (? (+ uart0 uart-fr)) uart-flag-tx-fifo-full) 0))
(! (+ uart0 uart-dr) ch))
(define (poll-for-char)
(if (<> (binand (? (+ uart0 uart-fr)) uart-flag-rx-fifo-empty) 0)
-1
(? (+ uart0 uart-dr))))
(define (getc)
(let ((mutable ch -1))
(while (= ch -1)
(set! ch (poll-for-char)))
ch))
(define (puts p)
(let ((ch (?byte p)))
(when (<> ch 0)
(putc ch)
(puts (+ p 1)))))
(define (putn* i)
(if (<> i 0)
(begin (putn* (/ i 10))
(putc (+ (% i 10) 48)))
0))
(define (putn i)
(if (<> i 0)
(putn* i)
(putc 48)))
(define (putx n)
(let ((mutable shift 28))
(while (>=s shift 0)
(let ((digit (binand 15 (>>u n shift))))
(putc (+ digit (if (>=u digit 10)
55 ;; 65 - 10
48)))
(set! shift (- shift 4))))))
(define (newline)
(putc 13)
(putc 10))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(const N_PCI_BASE_ADDRESS_REGISTERS 6)
(const PCI_HEADER_TYPE_GENERAL #x00)
(const PCI_HEADER_TYPE_BRIDGE #x01)
(const PCI_HEADER_TYPE_CARDBUS #x02)
(const PCI_HEADER_TYPE_MULTI_FUNCTION_MASK #x80)
(const PCI_HEADER_TYPE_MASK #x7f)
(const PCI_CLASS_LEGACY #x00) ;; Device was built prior definition of the class code field
(const PCI_CLASS_STORAGE #x01) ;; Mass Storage Controller
(const PCI_CLASS_NETWORK #x02) ;; Network Controller
(const PCI_CLASS_DISPLAY #x03) ;; Display Controller
(const PCI_CLASS_MULTIMEDIA #x04) ;; Multimedia Controller
(const PCI_CLASS_MEMORY #x05) ;; Memory Controller
(const PCI_CLASS_BRIDGE #x06) ;; Bridge Device
(const PCI_CLASS_SIMPLE_COMM #x07) ;; Simple Communication Controllers
(const PCI_CLASS_BASE_SYSTEM_PERIPHERAL #x08) ;; Base System Peripherals
(const PCI_CLASS_INPUT #x09) ;; Input Devices
(const PCI_CLASS_DOCK #x0A) ;; Docking Stations
(const PCI_CLASS_PROCESSOR #x0B) ;; Processors
(const PCI_CLASS_SERIAL_BUS #x0C) ;; Serial Bus Controllers
(const PCI_CLASS_WIRELESS #x0D) ;; Wireless Controllers
(const PCI_CLASS_INTELLIGENT_IO #x0E) ;; Intelligent I/O Controllers
(const PCI_CLASS_SATELLITE_COMM #x0F) ;; Satellite Communication Controllers
(const PCI_CLASS_CRYPTO #x10) ;; Encryption/Decryption Controllers
(const PCI_CLASS_DASP #x11) ;; Data Acquisition and Signal Processing Controllers
;; others reserved
(const PCI_CLASS_MISC #xFF) ;; Device does not fit any defined class.
;; N.B.: This lines up with struct pci-device below!
(const PCI_REGISTER_VENDOR_ID 0)
(const PCI_REGISTER_DEVICE_ID 2)
(const PCI_REGISTER_COMMAND 4)
(const PCI_REGISTER_STATUS 6)
(const PCI_REGISTER_REVISION_ID 8)
(const PCI_REGISTER_PROG_IF 9)
(const PCI_REGISTER_SUBCLASS 10)
(const PCI_REGISTER_CLASS_CODE 11)
(const PCI_REGISTER_CACHE_LINE_SIZE 12)
(const PCI_REGISTER_LATENCY_TIMER 13)
(const PCI_REGISTER_HEADER_TYPE 14)
(const PCI_REGISTER_BIST 15)
(const PCI_REGISTER_BAR0 16)
(const PCI_REGISTER_BAR1 20)
(const PCI_REGISTER_BAR2 24)
(const PCI_REGISTER_BAR3 28)
(const PCI_REGISTER_BAR4 32)
(const PCI_REGISTER_BAR5 36)
(const PCI_REGISTER_CARDBUS_CIS_POINTER 40)
(const PCI_REGISTER_SUBSYSTEM_VENDOR_ID 44)
(const PCI_REGISTER_SUBSYSTEM_ID 46)
(const PCI_REGISTER_EXPANSION_ROM_BASE_ADDRESS 48)
(const PCI_REGISTER_CAPABILITIES_POINTER 52)
(const PCI_REGISTER_INTERRUPT_LINE 60)
(const PCI_REGISTER_INTERRUPT_PIN 61)
(const PCI_REGISTER_MIN_GRANT 62)
(const PCI_REGISTER_MAX_LATENCY 63)
(const PCI_COMMAND_IO_SPACE #x0001)
(const PCI_COMMAND_MEMORY_SPACE #x0002)
(const PCI_COMMAND_BUS_MASTER #x0004)
(const PCI_COMMAND_SPECIAL_CYCLES #x0008)
(const PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE_ENABLE #x0010)
(const PCI_COMMAND_VGA_PALETTE_SNOOP #x0020)
(const PCI_COMMAND_PARITY_ERROR_RESPONSE #x0040)
(const PCI_COMMAND_SERR_ENABLE #x0100)
(const PCI_COMMAND_FAST_BACKTOBACK_ENABLE #x0200)
(const PCI_COMMAND_INTERRUPT_DISABLE #x0400)
(const PCI_STATUS_INTERRUPT #x0008)
(const PCI_STATUS_CAPABILITIES_LIST #x0010)
(const PCI_STATUS_66_MHZ_CAPABLE #x0020)
(const PCI_STATUS_FAST_BACKTOBACK_CAPABLE #x0080)
(const PCI_STATUS_MASTER_DATA_PARITY_ERROR #x0100)
(const PCI_STATUS_DEVSEL_MASK #x0600)
(const PCI_STATUS_DEVSEL_FAST #x0000)
(const PCI_STATUS_DEVSEL_MEDIUM #x0200)
(const PCI_STATUS_DEVSEL_SLOW #x0400)
(const PCI_STATUS_SIGNALED_TARGET_ABORT #x0800)
(const PCI_STATUS_RECEIVED_TARGET_ABORT #x1000)
(const PCI_STATUS_RECEIVED_MASTER_ABORT #x2000)
(const PCI_STATUS_SIGNALED_SYSTEM_ERROR #x4000)
(const PCI_STATUS_DETECTED_PARITY_ERROR #x8000)
(struct pci-device ((vendor-id word) ;; vendor ID in low 16 bits, device ID in high 16 bits
(status-command word)
(class-code-rev-id word)
(bist word)
(bars word 6) ;; TODO: would be nice to reuse N_PCI_BASE_ADDRESS_REGISTERS here
(cardbus-cis-pointer word)
(subsystem-id word) ;; vendor ID in low 16 bits, subsystem ID proper in high
(expansion-rom-base word)
(unused word)
(reserved word)
(max-lat-min-gnt-interrupt-pin-interrupt-line word)))
(define (?pci slot offset)
(? (+ #x42000000 (<< slot 11) offset)))
(define (!pci slot offset value)
(! (+ #x42000000 (<< slot 11) offset) value))
;; TODO: ARM emitter can't cope with such a large constant right now,
;; which is why this is a subroutine. Gross!
(define (self-id) #x030010ee) ;; Vendor/device for PB926EJ-S
(define (find-self-slot)
;; http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0224i/Cacdijji.html
(let ((mutable i 11))
(while (<u i 32)
(when (= (? (+ #x41000000 (<< i 11))) (self-id))
(return i))
(set! i (+ i 1)))))
(define (configure-pci-slot slot)
(let ((vendor-id (?pci slot pci-device-vendor-id)))
(when (<> vendor-id -1)
(puts (data #"Slot number \0")) (putn slot) (putc 32) (putx vendor-id) (newline)
(puts (data #"Class/Rev \0")) (putx (?pci slot pci-device-class-code-rev-id)) (newline)
(let ((mutable bar-num 0))
(while (<u bar-num N_PCI_BASE_ADDRESS_REGISTERS)
(puts (data #"BAR \0")) (putn bar-num) (putc 32)
(putx (?pci slot (+ pci-device-bars (<< bar-num 4))))
(newline)
(set! bar-num (+ bar-num 1))))
)))
(define (configure-pci)
;; http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0224i/Cacdijji.html
(if (<> (binand 1 (? #x10000044)) 0)
(let ((self-slot (find-self-slot)))
(puts (data #"PCI configuration\n\n\0"))
(puts (data #"Self-slot: \0")) (putn self-slot) (newline)
(! #x1000100c self-slot) ;; set PCI_SELFID register
;; TODO: should the following bus master config happen at
;; #x41000000 instead of #x42000000?
(!pci self-slot pci-device-status-command
(binor (?pci self-slot pci-device-status-command)
PCI_COMMAND_BUS_MASTER)) ;; "set bit 2"
;; Now scan the bus
(let ((mutable i 11))
(while (<u i 32)
(configure-pci-slot i)
(set! i (+ i 1)))))
(puts (data #"PCI not present on board\n\0"))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; CLCDC, "Color LCD Controller"
;; http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0224i/Cachedgd.html
;; http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0225d/CACCIDGI.html
;; http://infocenter.arm.com/help/topic/com.arm.doc.ddi0161e/DDI0161.pdf
(const sys-oscclk4 #x1000001c)
(const clcdc-base #x10120000)
(struct clcdc ((timing0 word)
(timing1 word)
(timing2 word)
(timing3 word) ;; N.B. only the low 17 bits are used
(upbase word)
(lpbase word)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; WARNING: A real PL110 has imsc BEFORE control.
;;
;; qemu's versatilepb variation on PL110 has them in
;; the following order, which is NOT the order as
;; specified by ARM.
;;
(control word) ;; 5 bits used
(imsc word) ;; 16 bits used
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(ris word) ;; 5 bits used
(mis word) ;; 5 bits used
(icr word) ;; 5 bits used
(upcurr word)
(lpcurr word)
))
(define (framebuffer)
#x100000) ;; !!! yuck
(define (set-clcdc-control-bits! n)
(! (+ clcdc-base clcdc-control)
(binor (? (+ clcdc-base clcdc-control))
n)))
(define (set-resolution-800x600!)
;; Set up screen timings for 800x600.
;; See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0224i/Cachedgd.html
(! sys-oscclk4 #x2cac)
(! (+ clcdc-base clcdc-timing0) #x1313a4c4)
(! (+ clcdc-base clcdc-timing1) #x0505f657)
(! (+ clcdc-base clcdc-timing2) #x071f1800))
(define (set-resolution-640x480!)
;; Set up screen timings for 640x480.
;; See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0224i/Cachedgd.html
(! sys-oscclk4 #x2c77)
(! (+ clcdc-base clcdc-timing0) #x3f1f3f9c)
(! (+ clcdc-base clcdc-timing1) #x090b61df)
(! (+ clcdc-base clcdc-timing2) #x067f1800))
(define (configure-display)
(puts (data #"CLCDC Setup\n\0"))
(putx (? (+ clcdc-base #xfe0))) (newline)
(putx (? (+ clcdc-base #xfe4))) (newline)
(putx (? (+ clcdc-base #xfe8))) (newline)
(putx (? (+ clcdc-base #xfec))) (newline)
(putx (? (+ clcdc-base #xff0))) (newline)
(putx (? (+ clcdc-base #xff4))) (newline)
(putx (? (+ clcdc-base #xff8))) (newline)
(putx (? (+ clcdc-base #xffc))) (newline)
(set-resolution-800x600!)
;; (set-resolution-640x480!)
(let ((mutable n 0)
(limit (* (* 800 600) 4)))
(while (<u n limit)
(! (+ (framebuffer) n) n)
(set! n (+ n 4))))
;; Must set base address before turning on the display.
(! (+ clcdc-base clcdc-upbase) (framebuffer))
;; Control word:
;; #x82b = 0000100000101011
;;
;; fedcba9876543210
;;
;; | power
;; | lcd is tft
;; ||| bits-per-pixel: 5 = 24bpp
;; | enable
(set-clcdc-control-bits! (<< 5 1))
(set-clcdc-control-bits! (<< 1 5))
;; Power-up routine (from page 1-5 of DDI0161):
;; - set LcdEn bit (low bit, bit 0) in the control register
;; - wait a display specific (!) number of milliseconds for things to stabilise
;; - set LcdPwr (bit 11) in the control register
(set-clcdc-control-bits! (<< 1 0))
;; Linux waits for 20ms here.
(set-clcdc-control-bits! (<< 1 11))
(puts (data #"CLCDC control reg: \0"))
(putx (? (+ clcdc-base clcdc-control)))
(newline)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (main)
(configure-pci)
(configure-display)
(newline)
(puts (data #"Hello, world!\n\0"))
(while (= 0 0)
(let ((ch (getc)))
(puts (data #"You typed: \0"))
(putc ch)
(newline))))