]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/powerpc/ofw/ofw_syscons.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / powerpc / ofw / ofw_syscons.c
1 /*-
2  * Copyright (c) 2003 Peter Grehan
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/module.h>
33 #include <sys/bus.h>
34 #include <sys/kernel.h>
35 #include <sys/sysctl.h>
36 #include <sys/limits.h>
37 #include <sys/conf.h>
38 #include <sys/cons.h>
39 #include <sys/proc.h>
40 #include <sys/fcntl.h>
41 #include <sys/malloc.h>
42 #include <sys/fbio.h>
43 #include <sys/consio.h>
44
45 #include <machine/bus.h>
46 #include <machine/sc_machdep.h>
47
48 #include <sys/rman.h>
49
50 #include <dev/fb/fbreg.h>
51 #include <dev/syscons/syscons.h>
52
53 #include <dev/ofw/openfirm.h>
54 #include <dev/ofw/ofw_pci.h>
55 #include <powerpc/ofw/ofw_syscons.h>
56 #include <machine/nexusvar.h>
57
58 static int ofwfb_ignore_mmap_checks;
59 SYSCTL_NODE(_hw, OID_AUTO, ofwfb, CTLFLAG_RD, 0, "ofwfb");
60 SYSCTL_INT(_hw_ofwfb, OID_AUTO, relax_mmap, CTLFLAG_RW,
61     &ofwfb_ignore_mmap_checks, 0, "relax mmap bounds checking");
62
63 extern u_char dflt_font_16[];
64 extern u_char dflt_font_14[];
65 extern u_char dflt_font_8[];
66
67 static int ofwfb_configure(int flags);
68
69 static vi_probe_t ofwfb_probe;
70 static vi_init_t ofwfb_init;
71 static vi_get_info_t ofwfb_get_info;
72 static vi_query_mode_t ofwfb_query_mode;
73 static vi_set_mode_t ofwfb_set_mode;
74 static vi_save_font_t ofwfb_save_font;
75 static vi_load_font_t ofwfb_load_font;
76 static vi_show_font_t ofwfb_show_font;
77 static vi_save_palette_t ofwfb_save_palette;
78 static vi_load_palette_t ofwfb_load_palette;
79 static vi_set_border_t ofwfb_set_border;
80 static vi_save_state_t ofwfb_save_state;
81 static vi_load_state_t ofwfb_load_state;
82 static vi_set_win_org_t ofwfb_set_win_org;
83 static vi_read_hw_cursor_t ofwfb_read_hw_cursor;
84 static vi_set_hw_cursor_t ofwfb_set_hw_cursor;
85 static vi_set_hw_cursor_shape_t ofwfb_set_hw_cursor_shape;
86 static vi_blank_display_t ofwfb_blank_display;
87 static vi_mmap_t ofwfb_mmap;
88 static vi_ioctl_t ofwfb_ioctl;
89 static vi_clear_t ofwfb_clear;
90 static vi_fill_rect_t ofwfb_fill_rect;
91 static vi_bitblt_t ofwfb_bitblt;
92 static vi_diag_t ofwfb_diag;
93 static vi_save_cursor_palette_t ofwfb_save_cursor_palette;
94 static vi_load_cursor_palette_t ofwfb_load_cursor_palette;
95 static vi_copy_t ofwfb_copy;
96 static vi_putp_t ofwfb_putp;
97 static vi_putc_t ofwfb_putc;
98 static vi_puts_t ofwfb_puts;
99 static vi_putm_t ofwfb_putm;
100
101 static video_switch_t ofwfbvidsw = {
102         .probe                  = ofwfb_probe,
103         .init                   = ofwfb_init,
104         .get_info               = ofwfb_get_info,
105         .query_mode             = ofwfb_query_mode,
106         .set_mode               = ofwfb_set_mode,
107         .save_font              = ofwfb_save_font,
108         .load_font              = ofwfb_load_font,
109         .show_font              = ofwfb_show_font,
110         .save_palette           = ofwfb_save_palette,
111         .load_palette           = ofwfb_load_palette,
112         .set_border             = ofwfb_set_border,
113         .save_state             = ofwfb_save_state,
114         .load_state             = ofwfb_load_state,
115         .set_win_org            = ofwfb_set_win_org,
116         .read_hw_cursor         = ofwfb_read_hw_cursor,
117         .set_hw_cursor          = ofwfb_set_hw_cursor,
118         .set_hw_cursor_shape    = ofwfb_set_hw_cursor_shape,
119         .blank_display          = ofwfb_blank_display,
120         .mmap                   = ofwfb_mmap,
121         .ioctl                  = ofwfb_ioctl,
122         .clear                  = ofwfb_clear,
123         .fill_rect              = ofwfb_fill_rect,
124         .bitblt                 = ofwfb_bitblt,
125         .diag                   = ofwfb_diag,
126         .save_cursor_palette    = ofwfb_save_cursor_palette,
127         .load_cursor_palette    = ofwfb_load_cursor_palette,
128         .copy                   = ofwfb_copy,
129         .putp                   = ofwfb_putp,
130         .putc                   = ofwfb_putc,
131         .puts                   = ofwfb_puts,
132         .putm                   = ofwfb_putm,
133 };
134
135 /*
136  * bitmap depth-specific routines
137  */
138 static vi_blank_display_t ofwfb_blank_display8;
139 static vi_putc_t ofwfb_putc8;
140 static vi_set_border_t ofwfb_set_border8;
141
142 static vi_blank_display_t ofwfb_blank_display32;
143 static vi_putc_t ofwfb_putc32;
144 static vi_set_border_t ofwfb_set_border32;
145
146 VIDEO_DRIVER(ofwfb, ofwfbvidsw, ofwfb_configure);
147
148 extern sc_rndr_sw_t txtrndrsw;
149 RENDERER(ofwfb, 0, txtrndrsw, gfb_set);
150
151 RENDERER_MODULE(ofwfb, gfb_set);
152
153 /*
154  * Define the iso6429-1983 colormap
155  */
156 static struct {
157         uint8_t red;
158         uint8_t green;
159         uint8_t blue;
160 } ofwfb_cmap[16] = {            /*  #     R    G    B   Color */
161                                 /*  -     -    -    -   ----- */
162         { 0x00, 0x00, 0x00 },   /*  0     0    0    0   Black */
163         { 0x00, 0x00, 0xaa },   /*  1     0    0  2/3   Blue  */
164         { 0x00, 0xaa, 0x00 },   /*  2     0  2/3    0   Green */
165         { 0x00, 0xaa, 0xaa },   /*  3     0  2/3  2/3   Cyan  */
166         { 0xaa, 0x00, 0x00 },   /*  4   2/3    0    0   Red   */
167         { 0xaa, 0x00, 0xaa },   /*  5   2/3    0  2/3   Magenta */
168         { 0xaa, 0x55, 0x00 },   /*  6   2/3  1/3    0   Brown */
169         { 0xaa, 0xaa, 0xaa },   /*  7   2/3  2/3  2/3   White */
170         { 0x55, 0x55, 0x55 },   /*  8   1/3  1/3  1/3   Gray  */
171         { 0x55, 0x55, 0xff },   /*  9   1/3  1/3    1   Bright Blue  */
172         { 0x55, 0xff, 0x55 },   /* 10   1/3    1  1/3   Bright Green */
173         { 0x55, 0xff, 0xff },   /* 11   1/3    1    1   Bright Cyan  */
174         { 0xff, 0x55, 0x55 },   /* 12     1  1/3  1/3   Bright Red   */
175         { 0xff, 0x55, 0xff },   /* 13     1  1/3    1   Bright Magenta */
176         { 0xff, 0xff, 0x80 },   /* 14     1    1  1/3   Bright Yellow */
177         { 0xff, 0xff, 0xff }    /* 15     1    1    1   Bright White */
178 };
179
180 #define TODO    printf("%s: unimplemented\n", __func__)
181
182 static u_int16_t ofwfb_static_window[ROW*COL];
183
184 static struct ofwfb_softc ofwfb_softc;
185
186 static __inline int
187 ofwfb_background(uint8_t attr)
188 {
189         return (attr >> 4);
190 }
191
192 static __inline int
193 ofwfb_foreground(uint8_t attr)
194 {
195         return (attr & 0x0f);
196 }
197
198 static u_int
199 ofwfb_pix32(int attr)
200 {
201         u_int retval;
202
203         retval = (ofwfb_cmap[attr].blue  << 16) |
204                 (ofwfb_cmap[attr].green << 8) |
205                 ofwfb_cmap[attr].red;
206
207         return (retval);
208 }
209
210 static int
211 ofwfb_configure(int flags)
212 {
213         struct ofwfb_softc *sc;
214         phandle_t chosen;
215         ihandle_t stdout;
216         phandle_t node;
217         int depth;
218         int disable;
219         int len;
220         char type[16];
221         static int done = 0;
222
223         disable = 0;
224         TUNABLE_INT_FETCH("hw.syscons.disable", &disable);
225         if (disable != 0)
226                 return (0);
227
228         if (done != 0)
229                 return (0);
230         done = 1;
231
232         sc = &ofwfb_softc;
233
234         chosen = OF_finddevice("/chosen");
235         OF_getprop(chosen, "stdout", &stdout, sizeof(stdout));
236         node = OF_instance_to_package(stdout);
237         OF_getprop(node, "device_type", type, sizeof(type));
238         if (strcmp(type, "display") != 0)
239                 return (0);
240
241         /* Only support 8 and 32-bit framebuffers */
242         OF_getprop(node, "depth", &depth, sizeof(depth));
243         if (depth == 8) {
244                 sc->sc_blank = ofwfb_blank_display8;
245                 sc->sc_putc = ofwfb_putc8;
246                 sc->sc_set_border = ofwfb_set_border8;
247         } else if (depth == 32) {
248                 sc->sc_blank = ofwfb_blank_display32;
249                 sc->sc_putc = ofwfb_putc32;
250                 sc->sc_set_border = ofwfb_set_border32;
251         } else
252                 return (0);
253
254         sc->sc_depth = depth;
255         sc->sc_node = node;
256         sc->sc_console = 1;
257         OF_getprop(node, "height", &sc->sc_height, sizeof(sc->sc_height));
258         OF_getprop(node, "width", &sc->sc_width, sizeof(sc->sc_width));
259         OF_getprop(node, "linebytes", &sc->sc_stride, sizeof(sc->sc_stride));
260
261         /*
262          * XXX the physical address of the frame buffer is assumed to be
263          * BAT-mapped so it can be accessed directly
264          */
265         OF_getprop(node, "address", &sc->sc_addr, sizeof(sc->sc_addr));
266
267         /*
268          * Get the PCI addresses of the adapter. The node may be the
269          * child of the PCI device: in that case, try the parent for
270          * the assigned-addresses property.
271          */
272         len = OF_getprop(node, "assigned-addresses", sc->sc_pciaddrs,
273                   sizeof(sc->sc_pciaddrs));
274         if (len == -1) {
275                 len = OF_getprop(OF_parent(node), "assigned-addresses", sc->sc_pciaddrs,
276                           sizeof(sc->sc_pciaddrs));
277         }
278
279         if (len != -1) {
280                 sc->sc_num_pciaddrs = len / sizeof(struct ofw_pci_register);
281         }
282
283         ofwfb_init(0, &sc->sc_va, 0);
284
285         return (0);
286 }
287
288 static int
289 ofwfb_probe(int unit, video_adapter_t **adp, void *arg, int flags)
290 {
291         TODO;
292         return (0);
293 }
294
295 static int
296 ofwfb_init(int unit, video_adapter_t *adp, int flags)
297 {
298         struct ofwfb_softc *sc;
299         video_info_t *vi;
300         char name[64];
301         ihandle_t ih;
302         int i;
303         int cborder;
304         int font_height;
305         int retval;
306
307         sc = (struct ofwfb_softc *)adp;
308         vi = &adp->va_info;
309
310         vid_init_struct(adp, "ofwfb", -1, unit);
311
312         if (sc->sc_depth == 8) {
313                 /*
314                  * Install the ISO6429 colormap - older OFW systems
315                  * don't do this by default
316                  */
317                 memset(name, 0, sizeof(name));
318                 OF_package_to_path(sc->sc_node, name, sizeof(name));
319                 ih = OF_open(name);
320                 for (i = 0; i < 16; i++) {
321                         OF_call_method("color!", ih, 4, 1,
322                                        ofwfb_cmap[i].red,
323                                        ofwfb_cmap[i].green,
324                                        ofwfb_cmap[i].blue,
325                                        i,
326                                        &retval);
327                 }
328         }
329
330         /* The default font size can be overridden by loader */
331         font_height = 16;
332         TUNABLE_INT_FETCH("hw.syscons.fsize", &font_height);
333         if (font_height == 8) {
334                 sc->sc_font = dflt_font_8;
335                 sc->sc_font_height = 8;
336         } else if (font_height == 14) {
337                 sc->sc_font = dflt_font_14;
338                 sc->sc_font_height = 14;
339         } else {
340                 /* default is 8x16 */
341                 sc->sc_font = dflt_font_16;
342                 sc->sc_font_height = 16;
343         }
344
345         /* The user can set a border in chars - default is 1 char width */
346         cborder = 1;
347         TUNABLE_INT_FETCH("hw.syscons.border", &cborder);
348
349         vi->vi_cheight = sc->sc_font_height;
350         vi->vi_width = sc->sc_width/8 - 2*cborder;
351         vi->vi_height = sc->sc_height/sc->sc_font_height - 2*cborder;
352         vi->vi_cwidth = 8;
353
354         /*
355          * Clamp width/height to syscons maximums
356          */
357         if (vi->vi_width > COL)
358                 vi->vi_width = COL;
359         if (vi->vi_height > ROW)
360                 vi->vi_height = ROW;
361
362         sc->sc_xmargin = (sc->sc_width - (vi->vi_width * vi->vi_cwidth)) / 2;
363         sc->sc_ymargin = (sc->sc_height - (vi->vi_height * vi->vi_cheight))/2;
364
365         /*
366          * Avoid huge amounts of conditional code in syscons by
367          * defining a dummy h/w text display buffer.
368          */
369         adp->va_window = (vm_offset_t) ofwfb_static_window;
370
371         /* Enable future font-loading and flag color support */
372         adp->va_flags |= V_ADP_FONT | V_ADP_COLOR;
373
374         ofwfb_blank_display(&sc->sc_va, V_DISPLAY_ON);
375
376         ofwfb_set_mode(&sc->sc_va, 0);
377
378         vid_register(&sc->sc_va);
379
380         return (0);
381 }
382
383 static int
384 ofwfb_get_info(video_adapter_t *adp, int mode, video_info_t *info)
385 {
386         bcopy(&adp->va_info, info, sizeof(*info));
387         return (0);
388 }
389
390 static int
391 ofwfb_query_mode(video_adapter_t *adp, video_info_t *info)
392 {
393         TODO;
394         return (0);
395 }
396
397 static int
398 ofwfb_set_mode(video_adapter_t *adp, int mode)
399 {
400
401         return (0);
402 }
403
404 static int
405 ofwfb_save_font(video_adapter_t *adp, int page, int size, int width,
406     u_char *data, int c, int count)
407 {
408         TODO;
409         return (0);
410 }
411
412 static int
413 ofwfb_load_font(video_adapter_t *adp, int page, int size, int width,
414     u_char *data, int c, int count)
415 {
416         struct ofwfb_softc *sc;
417
418         sc = (struct ofwfb_softc *)adp;
419
420         /*
421          * syscons code has already determined that current width/height
422          * are unchanged for this new font
423          */
424         sc->sc_font = data;
425         return (0);
426 }
427
428 static int
429 ofwfb_show_font(video_adapter_t *adp, int page)
430 {
431
432         return (0);
433 }
434
435 static int
436 ofwfb_save_palette(video_adapter_t *adp, u_char *palette)
437 {
438         /* TODO; */
439         return (0);
440 }
441
442 static int
443 ofwfb_load_palette(video_adapter_t *adp, u_char *palette)
444 {
445         /* TODO; */
446         return (0);
447 }
448
449 static int
450 ofwfb_set_border8(video_adapter_t *adp, int border)
451 {
452         struct ofwfb_softc *sc;
453         int i, j;
454         uint8_t *addr;
455         uint8_t bground;
456
457         sc = (struct ofwfb_softc *)adp;
458
459         bground = ofwfb_background(border);
460
461         /* Set top margin */
462         addr = (uint8_t *) sc->sc_addr;
463         for (i = 0; i < sc->sc_ymargin; i++) {
464                 for (j = 0; j < sc->sc_width; j++) {
465                         *(addr + j) = bground;
466                 }
467                 addr += sc->sc_stride;
468         }
469
470         /* bottom margin */
471         addr = (uint8_t *) sc->sc_addr + (sc->sc_height - sc->sc_ymargin)*sc->sc_stride;
472         for (i = 0; i < sc->sc_ymargin; i++) {
473                 for (j = 0; j < sc->sc_width; j++) {
474                         *(addr + j) = bground;
475                 }
476                 addr += sc->sc_stride;
477         }
478
479         /* remaining left and right borders */
480         addr = (uint8_t *) sc->sc_addr + sc->sc_ymargin*sc->sc_stride;
481         for (i = 0; i < sc->sc_height - 2*sc->sc_xmargin; i++) {
482                 for (j = 0; j < sc->sc_xmargin; j++) {
483                         *(addr + j) = bground;
484                         *(addr + j + sc->sc_width - sc->sc_xmargin) = bground;
485                 }
486                 addr += sc->sc_stride;
487         }
488
489         return (0);
490 }
491
492 static int
493 ofwfb_set_border32(video_adapter_t *adp, int border)
494 {
495         /* XXX Be lazy for now and blank entire screen */
496         return (ofwfb_blank_display32(adp, border));
497 }
498
499 static int
500 ofwfb_set_border(video_adapter_t *adp, int border)
501 {
502         struct ofwfb_softc *sc;
503
504         sc = (struct ofwfb_softc *)adp;
505
506         return ((*sc->sc_set_border)(adp, border));
507 }
508
509 static int
510 ofwfb_save_state(video_adapter_t *adp, void *p, size_t size)
511 {
512         TODO;
513         return (0);
514 }
515
516 static int
517 ofwfb_load_state(video_adapter_t *adp, void *p)
518 {
519         TODO;
520         return (0);
521 }
522
523 static int
524 ofwfb_set_win_org(video_adapter_t *adp, off_t offset)
525 {
526         TODO;
527         return (0);
528 }
529
530 static int
531 ofwfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
532 {
533         *col = 0;
534         *row = 0;
535
536         return (0);
537 }
538
539 static int
540 ofwfb_set_hw_cursor(video_adapter_t *adp, int col, int row)
541 {
542
543         return (0);
544 }
545
546 static int
547 ofwfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
548     int celsize, int blink)
549 {
550         return (0);
551 }
552
553 static int
554 ofwfb_blank_display8(video_adapter_t *adp, int mode)
555 {
556         struct ofwfb_softc *sc;
557         int i;
558         uint8_t *addr;
559
560         sc = (struct ofwfb_softc *)adp;
561         addr = (uint8_t *) sc->sc_addr;
562
563         /* Could be done a lot faster e.g. 32-bits, or Altivec'd */
564         for (i = 0; i < sc->sc_stride*sc->sc_height; i++)
565                 *(addr + i) = ofwfb_background(SC_NORM_ATTR);
566
567         return (0);
568 }
569
570 static int
571 ofwfb_blank_display32(video_adapter_t *adp, int mode)
572 {
573         struct ofwfb_softc *sc;
574         int i;
575         uint32_t *addr;
576
577         sc = (struct ofwfb_softc *)adp;
578         addr = (uint32_t *) sc->sc_addr;
579
580         for (i = 0; i < (sc->sc_stride/4)*sc->sc_height; i++)
581                 *(addr + i) = ofwfb_pix32(ofwfb_background(SC_NORM_ATTR));
582
583         return (0);
584 }
585
586 static int
587 ofwfb_blank_display(video_adapter_t *adp, int mode)
588 {
589         struct ofwfb_softc *sc;
590
591         sc = (struct ofwfb_softc *)adp;
592
593         return ((*sc->sc_blank)(adp, mode));
594 }
595
596 static int
597 ofwfb_mmap(video_adapter_t *adp, vm_offset_t offset, vm_paddr_t *paddr,
598     int prot)
599 {
600         struct ofwfb_softc *sc;
601         int i;
602
603         sc = (struct ofwfb_softc *)adp;
604
605         if (sc->sc_num_pciaddrs == 0)
606                 return (ENOMEM);
607
608         /*
609          * Hack for Radeon...
610          */
611         if (ofwfb_ignore_mmap_checks) {
612                 *paddr = offset;
613                 return (0);
614         }
615
616         /*
617          * Make sure the requested address lies within the PCI device's assigned addrs
618          */
619         for (i = 0; i < sc->sc_num_pciaddrs; i++)
620                 if (offset >= sc->sc_pciaddrs[i].phys_lo &&
621                     offset < (sc->sc_pciaddrs[i].phys_lo + sc->sc_pciaddrs[i].size_lo)) {
622                         *paddr = offset;
623                         return (0);
624                 }
625
626         /*
627          * This might be a legacy VGA mem request: if so, just point it at the
628          * framebuffer, since it shouldn't be touched
629          */
630         if (offset < sc->sc_stride*sc->sc_height) {
631                 *paddr = sc->sc_addr + offset;
632                 return (0);
633         }
634
635         return (EINVAL);
636 }
637
638 static int
639 ofwfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
640 {
641
642         return (0);
643 }
644
645 static int
646 ofwfb_clear(video_adapter_t *adp)
647 {
648         TODO;
649         return (0);
650 }
651
652 static int
653 ofwfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
654 {
655         TODO;
656         return (0);
657 }
658
659 static int
660 ofwfb_bitblt(video_adapter_t *adp, ...)
661 {
662         TODO;
663         return (0);
664 }
665
666 static int
667 ofwfb_diag(video_adapter_t *adp, int level)
668 {
669         TODO;
670         return (0);
671 }
672
673 static int
674 ofwfb_save_cursor_palette(video_adapter_t *adp, u_char *palette)
675 {
676         TODO;
677         return (0);
678 }
679
680 static int
681 ofwfb_load_cursor_palette(video_adapter_t *adp, u_char *palette)
682 {
683         TODO;
684         return (0);
685 }
686
687 static int
688 ofwfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n)
689 {
690         TODO;
691         return (0);
692 }
693
694 static int
695 ofwfb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a,
696     int size, int bpp, int bit_ltor, int byte_ltor)
697 {
698         TODO;
699         return (0);
700 }
701
702 static int
703 ofwfb_putc8(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
704 {
705         struct ofwfb_softc *sc;
706         int row;
707         int col;
708         int i;
709         uint32_t *addr;
710         u_char *p, fg, bg;
711         union {
712                 uint32_t l;
713                 uint8_t  c[4];
714         } ch1, ch2;
715
716
717         sc = (struct ofwfb_softc *)adp;
718         row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
719         col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth;
720         p = sc->sc_font + c*sc->sc_font_height;
721         addr = (u_int32_t *)((int)sc->sc_addr
722                 + (row + sc->sc_ymargin)*sc->sc_stride
723                 + col + sc->sc_xmargin);
724
725         fg = ofwfb_foreground(a);
726         bg = ofwfb_background(a);
727
728         for (i = 0; i < sc->sc_font_height; i++) {
729                 u_char fline = p[i];
730
731                 /*
732                  * Assume that there is more background than foreground
733                  * in characters and init accordingly
734                  */
735                 ch1.l = ch2.l = (bg << 24) | (bg << 16) | (bg << 8) | bg;
736
737                 /*
738                  * Calculate 2 x 4-chars at a time, and then
739                  * write these out.
740                  */
741                 if (fline & 0x80) ch1.c[0] = fg;
742                 if (fline & 0x40) ch1.c[1] = fg;
743                 if (fline & 0x20) ch1.c[2] = fg;
744                 if (fline & 0x10) ch1.c[3] = fg;
745
746                 if (fline & 0x08) ch2.c[0] = fg;
747                 if (fline & 0x04) ch2.c[1] = fg;
748                 if (fline & 0x02) ch2.c[2] = fg;
749                 if (fline & 0x01) ch2.c[3] = fg;
750
751                 addr[0] = ch1.l;
752                 addr[1] = ch2.l;
753                 addr += (sc->sc_stride / sizeof(u_int32_t));
754         }
755
756         return (0);
757 }
758
759 static int
760 ofwfb_putc32(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
761 {
762         struct ofwfb_softc *sc;
763         int row;
764         int col;
765         int i, j, k;
766         uint32_t *addr;
767         u_char *p;
768
769         sc = (struct ofwfb_softc *)adp;
770         row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
771         col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth;
772         p = sc->sc_font + c*sc->sc_font_height;
773         addr = (uint32_t *)sc->sc_addr
774                 + (row + sc->sc_ymargin)*(sc->sc_stride/4)
775                 + col + sc->sc_xmargin;
776
777         for (i = 0; i < sc->sc_font_height; i++) {
778                 for (j = 0, k = 7; j < 8; j++, k--) {
779                         if ((p[i] & (1 << k)) == 0)
780                                 *(addr + j) = ofwfb_pix32(ofwfb_background(a));
781                         else
782                                 *(addr + j) = ofwfb_pix32(ofwfb_foreground(a));
783                 }
784                 addr += (sc->sc_stride/4);
785         }
786
787         return (0);
788 }
789
790 static int
791 ofwfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
792 {
793         struct ofwfb_softc *sc;
794
795         sc = (struct ofwfb_softc *)adp;
796
797         return ((*sc->sc_putc)(adp, off, c, a));
798 }
799
800 static int
801 ofwfb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
802 {
803         int i;
804
805         for (i = 0; i < len; i++) {
806                 ofwfb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8);
807         }
808         return (0);
809 }
810
811 static int
812 ofwfb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
813     uint32_t pixel_mask, int size, int width)
814 {
815         struct ofwfb_softc *sc;
816
817         sc = (struct ofwfb_softc *)adp;
818
819         /* put mouse */
820
821         return (0);
822 }
823
824 /*
825  * Define the syscons nexus device attachment
826  */
827 static void
828 ofwfb_scidentify(driver_t *driver, device_t parent)
829 {
830         device_t child;
831
832         /*
833          * Add with a priority guaranteed to make it last on
834          * the device list
835          */
836         child = BUS_ADD_CHILD(parent, INT_MAX, SC_DRIVER_NAME, 0);
837         if (child != NULL)
838                 nexus_set_device_type(child, "syscons");
839 }
840
841 static int
842 ofwfb_scprobe(device_t dev)
843 {
844         char *name;
845
846         name = nexus_get_name(dev);
847         if (strcmp(SC_DRIVER_NAME, name) != 0)
848                 return (ENXIO);
849
850         device_set_desc(dev, "System console");
851         return (sc_probe_unit(device_get_unit(dev), 
852             device_get_flags(dev) | SC_AUTODETECT_KBD));
853 }
854
855 static int
856 ofwfb_scattach(device_t dev)
857 {
858         return (sc_attach_unit(device_get_unit(dev),
859             device_get_flags(dev) | SC_AUTODETECT_KBD));
860 }
861
862 static device_method_t ofwfb_sc_methods[] = {
863         DEVMETHOD(device_identify,      ofwfb_scidentify),
864         DEVMETHOD(device_probe,         ofwfb_scprobe),
865         DEVMETHOD(device_attach,        ofwfb_scattach),
866         { 0, 0 }
867 };
868
869 static driver_t ofwfb_sc_driver = {
870         SC_DRIVER_NAME,
871         ofwfb_sc_methods,
872         sizeof(sc_softc_t),
873 };
874
875 static devclass_t       sc_devclass;
876
877 DRIVER_MODULE(sc, nexus, ofwfb_sc_driver, sc_devclass, 0, 0);
878
879 /*
880  * Define a stub keyboard driver in case one hasn't been
881  * compiled into the kernel
882  */
883 #include <sys/kbio.h>
884 #include <dev/kbd/kbdreg.h>
885
886 static int dummy_kbd_configure(int flags);
887
888 keyboard_switch_t dummysw;
889
890 static int
891 dummy_kbd_configure(int flags)
892 {
893
894         return (0);
895 }
896 KEYBOARD_DRIVER(dummy, dummysw, dummy_kbd_configure);
897
898 /*
899  * Utility routines from <dev/fb/fbreg.h>
900  */
901 void
902 ofwfb_bcopy(const void *s, void *d, size_t c)
903 {
904         bcopy(s, d, c);
905 }
906
907 void
908 ofwfb_bzero(void *d, size_t c)
909 {
910         bzero(d, c);
911 }
912
913 void
914 ofwfb_fillw(int pat, void *base, size_t cnt)
915 {
916         u_int16_t *bptr = base;
917
918         while (cnt--)
919                 *bptr++ = pat;
920 }
921
922 u_int16_t
923 ofwfb_readw(u_int16_t *addr)
924 {
925         return (*addr);
926 }
927
928 void
929 ofwfb_writew(u_int16_t *addr, u_int16_t val)
930 {
931         *addr = val;
932 }