Fix warnings from GCC 4.6.0
[openbios.git] / drivers / sbus.c
blobcba1050975eeee683ecccc75a59e9d7fa1ab9ff4
1 /*
2 * OpenBIOS SBus driver
4 * (C) 2004 Stefan Reinauer <stepan@openbios.org>
5 * (C) 2005 Ed Schouten <ed@fxq.nl>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2
13 #include "config.h"
14 #include "libopenbios/bindings.h"
15 #include "kernel/kernel.h"
16 #include "libc/byteorder.h"
17 #include "libc/vsprintf.h"
18 #include "drivers/drivers.h"
19 #include "libopenbios/ofmem.h"
21 #define SBUS_REGS 0x28
22 #define SBUS_SLOTS 16
23 #define APC_REGS 0x10
24 #define APC_OFFSET 0x0a000000ULL
25 #define CS4231_REGS 0x40
26 #define CS4231_OFFSET 0x0c000000ULL
27 #define MACIO_ESPDMA 0x00400000ULL /* ESP DMA controller */
28 #define MACIO_ESP 0x00800000ULL /* ESP SCSI */
29 #define SS600MP_ESPDMA 0x00081000ULL
30 #define SS600MP_ESP 0x00080000ULL
31 #define SS600MP_LEBUFFER (SS600MP_ESPDMA + 0x10) // XXX should be 0x40000
33 static void
34 ob_sbus_node_init(uint64_t base)
36 void *regs;
38 push_str("/iommu/sbus");
39 fword("find-device");
41 PUSH(base >> 32);
42 fword("encode-int");
43 PUSH(base & 0xffffffff);
44 fword("encode-int");
45 fword("encode+");
46 PUSH(SBUS_REGS);
47 fword("encode-int");
48 fword("encode+");
49 push_str("reg");
50 fword("property");
52 regs = map_io(base, SBUS_REGS);
53 PUSH((unsigned long)regs);
54 fword("encode-int");
55 push_str("address");
56 fword("property");
59 static void
60 ob_le_init(unsigned int slot, unsigned long leoffset, unsigned long dmaoffset)
62 push_str("/iommu/sbus/ledma");
63 fword("find-device");
64 PUSH(slot);
65 fword("encode-int");
66 PUSH(dmaoffset);
67 fword("encode-int");
68 fword("encode+");
69 PUSH(0x00000020);
70 fword("encode-int");
71 fword("encode+");
72 push_str("reg");
73 fword("property");
75 push_str("/iommu/sbus/ledma/le");
76 fword("find-device");
77 PUSH(slot);
78 fword("encode-int");
79 PUSH(leoffset);
80 fword("encode-int");
81 fword("encode+");
82 PUSH(0x00000004);
83 fword("encode-int");
84 fword("encode+");
85 push_str("reg");
86 fword("property");
89 uint16_t graphic_depth;
91 static void
92 ob_tcx_init(unsigned int slot, const char *path)
94 phandle_t chosen, aliases;
96 push_str(path);
97 fword("find-device");
99 PUSH(slot);
100 fword("encode-int");
101 PUSH(0x00800000);
102 fword("encode-int");
103 fword("encode+");
104 PUSH(0x00100000);
105 fword("encode-int");
106 fword("encode+");
108 PUSH(slot);
109 fword("encode-int");
110 fword("encode+");
111 PUSH(0x02000000);
112 fword("encode-int");
113 fword("encode+");
114 if (graphic_depth == 24) {
115 PUSH(0x00400000);
116 } else {
117 PUSH(0x00000001);
119 fword("encode-int");
120 fword("encode+");
122 PUSH(slot);
123 fword("encode-int");
124 fword("encode+");
125 PUSH(0x04000000);
126 fword("encode-int");
127 fword("encode+");
128 if (graphic_depth == 24) {
129 PUSH(0x00400000);
130 } else {
131 PUSH(0x00000001);
133 fword("encode-int");
134 fword("encode+");
136 PUSH(slot);
137 fword("encode-int");
138 fword("encode+");
139 PUSH(0x06000000);
140 fword("encode-int");
141 fword("encode+");
142 PUSH(0x00800000);
143 fword("encode-int");
144 fword("encode+");
146 PUSH(slot);
147 fword("encode-int");
148 fword("encode+");
149 PUSH(0x0a000000);
150 fword("encode-int");
151 fword("encode+");
152 if (graphic_depth == 24) {
153 PUSH(0x00400000);
154 } else {
155 PUSH(0x00000001);
157 fword("encode-int");
158 fword("encode+");
160 PUSH(slot);
161 fword("encode-int");
162 fword("encode+");
163 PUSH(0x0c000000);
164 fword("encode-int");
165 fword("encode+");
166 if (graphic_depth == 24) {
167 PUSH(0x00800000);
168 } else {
169 PUSH(0x00000001);
171 fword("encode-int");
172 fword("encode+");
174 PUSH(slot);
175 fword("encode-int");
176 fword("encode+");
177 PUSH(0x0e000000);
178 fword("encode-int");
179 fword("encode+");
180 if (graphic_depth == 24) {
181 PUSH(0x00800000);
182 } else {
183 PUSH(0x00000001);
185 fword("encode-int");
186 fword("encode+");
188 PUSH(slot);
189 fword("encode-int");
190 fword("encode+");
191 PUSH(0x00700000);
192 fword("encode-int");
193 fword("encode+");
194 PUSH(0x00001000);
195 fword("encode-int");
196 fword("encode+");
198 PUSH(slot);
199 fword("encode-int");
200 fword("encode+");
201 PUSH(0x00200000);
202 fword("encode-int");
203 fword("encode+");
204 if (graphic_depth == 24) {
205 PUSH(0x00004000);
206 } else {
207 PUSH(0x00000004);
209 fword("encode-int");
210 fword("encode+");
212 PUSH(slot);
213 fword("encode-int");
214 fword("encode+");
215 if (graphic_depth == 24) {
216 PUSH(0x00301000);
217 } else {
218 PUSH(0x00300000);
220 fword("encode-int");
221 fword("encode+");
222 if (graphic_depth == 24) {
223 PUSH(0x00001000);
224 } else {
225 PUSH(0x0000081c);
227 fword("encode-int");
228 fword("encode+");
230 PUSH(slot);
231 fword("encode-int");
232 fword("encode+");
233 PUSH(0x00000000);
234 fword("encode-int");
235 fword("encode+");
236 PUSH(0x00010000);
237 fword("encode-int");
238 fword("encode+");
240 PUSH(slot);
241 fword("encode-int");
242 fword("encode+");
243 PUSH(0x00240000);
244 fword("encode-int");
245 fword("encode+");
246 if (graphic_depth == 24) {
247 PUSH(0x00004000);
248 } else {
249 PUSH(0x00000004);
251 fword("encode-int");
252 fword("encode+");
254 PUSH(slot);
255 fword("encode-int");
256 fword("encode+");
257 PUSH(0x00280000);
258 fword("encode-int");
259 fword("encode+");
260 if (graphic_depth == 24) {
261 PUSH(0x00008000);
262 } else {
263 PUSH(0x00000001);
265 fword("encode-int");
266 fword("encode+");
268 push_str("reg");
269 fword("property");
271 PUSH((int)graphic_depth);
272 fword("encode-int");
273 push_str("depth");
274 fword("property");
276 if (graphic_depth == 8) {
277 push_str("true");
278 fword("encode-string");
279 push_str("tcx-8-bit");
280 fword("property");
283 chosen = find_dev("/chosen");
284 push_str(path);
285 fword("open-dev");
286 set_int_property(chosen, "screen", POP());
288 aliases = find_dev("/aliases");
289 set_property(aliases, "screen", path, strlen(path) + 1);
292 static void
293 ob_apc_init(unsigned int slot, unsigned long base)
295 push_str("/iommu/sbus");
296 fword("find-device");
297 fword("new-device");
299 push_str("power-management");
300 fword("device-name");
302 PUSH(slot);
303 fword("encode-int");
304 PUSH(base);
305 fword("encode-int");
306 fword("encode+");
307 PUSH(APC_REGS);
308 fword("encode-int");
309 fword("encode+");
310 push_str("reg");
311 fword("property");
313 fword("finish-device");
316 static void
317 ob_cs4231_init(unsigned int slot)
319 push_str("/iommu/sbus");
320 fword("find-device");
321 fword("new-device");
323 push_str("SUNW,CS4231");
324 fword("device-name");
326 push_str("serial");
327 fword("device-type");
329 PUSH(slot);
330 fword("encode-int");
331 PUSH(CS4231_OFFSET);
332 fword("encode-int");
333 fword("encode+");
334 PUSH(CS4231_REGS);
335 fword("encode-int");
336 fword("encode+");
337 push_str("reg");
338 fword("property");
340 PUSH(5);
341 fword("encode-int");
342 PUSH(0);
343 fword("encode-int");
344 fword("encode+");
345 push_str("intr");
346 fword("property");
348 PUSH(5);
349 fword("encode-int");
350 push_str("interrupts");
351 fword("property");
353 push_str("audio");
354 fword("encode-string");
355 push_str("alias");
356 fword("property");
358 fword("finish-device");
361 static void
362 ob_macio_init(unsigned int slot, uint64_t base, unsigned long offset)
364 // All devices were integrated to NCR89C100, see
365 // http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
367 // NCR 53c9x, aka ESP. See
368 // http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
369 #ifdef CONFIG_DRIVER_ESP
370 ob_esp_init(slot, base, offset + MACIO_ESP, offset + MACIO_ESPDMA);
371 #endif
373 // NCR 92C990, Am7990, Lance. See http://www.amd.com
374 ob_le_init(slot, offset + 0x00c00000, offset + 0x00400010);
376 // Parallel port
377 //ob_bpp_init(base);
380 static void
381 sbus_probe_slot_ss5(unsigned int slot, uint64_t base)
383 // OpenBIOS and Qemu don't know how to do Sbus probing
384 switch(slot) {
385 case 3: // SUNW,tcx
386 ob_tcx_init(slot, "/iommu/sbus/SUNW,tcx");
387 break;
388 case 4:
389 // SUNW,CS4231
390 ob_cs4231_init(slot);
391 // Power management (APC)
392 ob_apc_init(slot, APC_OFFSET);
393 break;
394 case 5: // MACIO: le, esp, bpp
395 ob_macio_init(slot, base, 0x08000000);
396 break;
397 default:
398 break;
402 static void
403 sbus_probe_slot_ss10(unsigned int slot, uint64_t base)
405 // OpenBIOS and Qemu don't know how to do Sbus probing
406 switch(slot) {
407 case 2: // SUNW,tcx
408 ob_tcx_init(slot, "/iommu/sbus/SUNW,tcx");
409 break;
410 case 0xf: // le, esp, bpp, power-management
411 ob_macio_init(slot, base, 0);
412 // Power management (APC) XXX should not exist
413 ob_apc_init(slot, APC_OFFSET);
414 break;
415 default:
416 break;
420 static void
421 sbus_probe_slot_ss600mp(unsigned int slot, uint64_t base)
423 // OpenBIOS and Qemu don't know how to do Sbus probing
424 switch(slot) {
425 case 2: // SUNW,tcx
426 ob_tcx_init(slot, "/iommu/sbus/SUNW,tcx");
427 break;
428 case 0xf: // le, esp, bpp, power-management
429 #ifdef CONFIG_DRIVER_ESP
430 ob_esp_init(slot, base, SS600MP_ESP, SS600MP_ESPDMA);
431 #endif
432 // NCR 92C990, Am7990, Lance. See http://www.amd.com
433 ob_le_init(slot, 0x00060000, SS600MP_LEBUFFER);
434 // Power management (APC) XXX should not exist
435 ob_apc_init(slot, APC_OFFSET);
436 break;
437 default:
438 break;
442 static void
443 ob_sbus_open(void)
445 int ret=1;
446 RET ( -ret );
449 static void
450 ob_sbus_close(void)
452 selfword("close-deblocker");
455 static void
456 ob_sbus_initialize(void)
461 NODE_METHODS(ob_sbus_node) = {
462 { NULL, ob_sbus_initialize },
463 { "open", ob_sbus_open },
464 { "close", ob_sbus_close },
467 struct sbus_offset {
468 int slot, type;
469 uint64_t base;
470 unsigned long size;
473 static const struct sbus_offset sbus_offsets_ss5[SBUS_SLOTS] = {
474 { 0, 0, 0x20000000, 0x10000000,},
475 { 1, 0, 0x30000000, 0x10000000,},
476 { 2, 0, 0x40000000, 0x10000000,},
477 { 3, 0, 0x50000000, 0x10000000,},
478 { 4, 0, 0x60000000, 0x10000000,},
479 { 5, 0, 0x70000000, 0x10000000,},
482 /* Shared with ss600mp */
483 static const struct sbus_offset sbus_offsets_ss10[SBUS_SLOTS] = {
484 { 0, 0, 0xe00000000ULL, 0x10000000,},
485 { 1, 0, 0xe10000000ULL, 0x10000000,},
486 { 2, 0, 0xe20000000ULL, 0x10000000,},
487 { 3, 0, 0xe30000000ULL, 0x10000000,},
488 [0xf] = { 0xf, 0, 0xef0000000ULL, 0x10000000,},
491 static void
492 ob_add_sbus_range(const struct sbus_offset *range, int notfirst)
494 if (!notfirst) {
495 push_str("/iommu/sbus");
496 fword("find-device");
498 PUSH(range->slot);
499 fword("encode-int");
500 if (notfirst)
501 fword("encode+");
502 PUSH(range->type);
503 fword("encode-int");
504 fword("encode+");
505 PUSH(range->base >> 32);
506 fword("encode-int");
507 fword("encode+");
508 PUSH(range->base & 0xffffffff);
509 fword("encode-int");
510 fword("encode+");
511 PUSH(range->size);
512 fword("encode-int");
513 fword("encode+");
516 static int
517 ob_sbus_init_ss5(void)
519 unsigned int slot;
520 int notfirst = 0;
522 for (slot = 0; slot < SBUS_SLOTS; slot++) {
523 if (sbus_offsets_ss5[slot].size > 0)
524 ob_add_sbus_range(&sbus_offsets_ss5[slot], notfirst++);
526 push_str("ranges");
527 fword("property");
529 for (slot = 0; slot < SBUS_SLOTS; slot++) {
530 if (sbus_offsets_ss5[slot].size > 0)
531 sbus_probe_slot_ss5(slot, sbus_offsets_ss5[slot].base);
534 return 0;
537 static int
538 ob_sbus_init_ss10(void)
540 unsigned int slot;
541 int notfirst = 0;
543 for (slot = 0; slot < SBUS_SLOTS; slot++) {
544 if (sbus_offsets_ss10[slot].size > 0)
545 ob_add_sbus_range(&sbus_offsets_ss10[slot], notfirst++);
547 push_str("ranges");
548 fword("property");
550 for (slot = 0; slot < SBUS_SLOTS; slot++) {
551 if (sbus_offsets_ss10[slot].size > 0)
552 sbus_probe_slot_ss10(slot, sbus_offsets_ss10[slot].base);
555 return 0;
558 static int
559 ob_sbus_init_ss600mp(void)
561 unsigned int slot;
562 int notfirst = 0;
564 for (slot = 0; slot < SBUS_SLOTS; slot++) {
565 if (sbus_offsets_ss10[slot].size > 0)
566 ob_add_sbus_range(&sbus_offsets_ss10[slot], notfirst++);
568 push_str("ranges");
569 fword("property");
571 for (slot = 0; slot < SBUS_SLOTS; slot++) {
572 if (sbus_offsets_ss10[slot].size > 0)
573 sbus_probe_slot_ss600mp(slot, sbus_offsets_ss10[slot].base);
576 return 0;
579 int ob_sbus_init(uint64_t base, int machine_id)
581 ob_sbus_node_init(base);
583 switch (machine_id) {
584 case 66:
585 return ob_sbus_init_ss600mp();
586 case 64 ... 65:
587 return ob_sbus_init_ss10();
588 case 32 ... 63:
589 return ob_sbus_init_ss5();
590 default:
591 return -1;