1 /* $NetBSD: amidisplaycc.c,v 1.21 2008/12/19 18:49:38 cegger Exp $ */
4 * Copyright (c) 2000 Jukka Andberg.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: amidisplaycc.c,v 1.21 2008/12/19 18:49:38 cegger Exp $");
34 * wscons interface to amiga custom chips. Contains the necessary functions
35 * to render text on bitmapped screens. Uses the functions defined in
36 * grfabs_reg.h for display creation/destruction and low level setup.
38 * For each virtual terminal a new screen ('view') is allocated.
39 * Also one more is allocated for the mapped screen on demand.
42 #include "amidisplaycc.h"
45 #include "opt_amigaccgrf.h"
50 #include <sys/param.h>
51 #include <sys/types.h>
52 #include <sys/device.h>
53 #include <sys/malloc.h>
54 #include <sys/systm.h>
58 #include <amiga/dev/grfabs_reg.h>
59 #include <amiga/dev/kbdvar.h>
60 #include <amiga/dev/viewioctl.h>
61 #include <amiga/amiga/device.h>
62 #include <dev/wscons/wsconsio.h>
63 #include <dev/rcons/raster.h>
64 #include <dev/wscons/wscons_raster.h>
65 #include <dev/wscons/wsdisplayvar.h>
67 #include <dev/wsfont/wsfont.h>
69 #include <machine/stdarg.h>
71 /* These can be lowered if you are sure you dont need that much colors. */
77 #define MAXCOLORS (1<<MAXDEPTH)
79 struct amidisplaycc_screen
;
80 struct amidisplaycc_softc
84 struct amidisplaycc_screen
* currentscreen
;
86 /* display turned on? */
89 /* stuff relating to the mapped screen */
99 * Configuration stuff.
102 static int amidisplaycc_match(struct device
*, struct cfdata
*, void *);
103 static void amidisplaycc_attach(struct device
*, struct device
*, void *);
105 CFATTACH_DECL(amidisplaycc
, sizeof(struct amidisplaycc_softc
),
106 amidisplaycc_match
, amidisplaycc_attach
, NULL
, NULL
);
108 static int amidisplaycc_attached
;
110 cons_decl(amidisplaycc_
);
112 /* end of configuration stuff */
114 /* private utility functions */
116 static int amidisplaycc_setvideo(struct amidisplaycc_softc
*, int);
118 static int amidisplaycc_setemulcmap(struct amidisplaycc_screen
*,
119 struct wsdisplay_cmap
*);
121 static int amidisplaycc_cmapioctl(view_t
*, u_long
, struct wsdisplay_cmap
*);
122 static int amidisplaycc_setcmap(view_t
*, struct wsdisplay_cmap
*);
123 static int amidisplaycc_getcmap(view_t
*, struct wsdisplay_cmap
*);
124 static int amidisplaycc_gfxscreen(struct amidisplaycc_softc
*, int);
126 static int amidisplaycc_setfont(struct amidisplaycc_screen
*, const char *);
127 static const struct wsdisplay_font
* amidisplaycc_getbuiltinfont(void);
129 static void dprintf(const char *fmt
, ...);
131 /* end of private utility functions */
133 /* emulops for wscons */
134 void amidisplaycc_cursor(void *, int, int, int);
135 int amidisplaycc_mapchar(void *, int, unsigned int *);
136 void amidisplaycc_putchar(void *, int, int, u_int
, long);
137 void amidisplaycc_copycols(void *, int, int, int, int);
138 void amidisplaycc_erasecols(void *, int, int, int, long);
139 void amidisplaycc_copyrows(void *, int, int, int);
140 void amidisplaycc_eraserows(void *, int, int, long);
141 int amidisplaycc_allocattr(void *, int, int, int, long *);
142 /* end of emulops for wscons */
145 /* accessops for wscons */
146 int amidisplaycc_ioctl(void *, void *, u_long
, void *, int, struct lwp
*);
147 paddr_t
amidisplaycc_mmap(void *, void *, off_t
, int);
148 int amidisplaycc_alloc_screen(void *, const struct wsscreen_descr
*, void **,
149 int *, int *, long *);
150 void amidisplaycc_free_screen( void *, void *);
151 int amidisplaycc_show_screen(void *, void *, int, void (*)(void *, int, int),
153 int amidisplaycc_load_font(void *, void *, struct wsdisplay_font
*);
154 void amidisplaycc_pollc(void *, int);
155 /* end of accessops for wscons */
158 * These structures are passed to wscons, and they contain the
159 * display-specific callback functions.
162 const struct wsdisplay_accessops amidisplaycc_accessops
= {
165 amidisplaycc_alloc_screen
,
166 amidisplaycc_free_screen
,
167 amidisplaycc_show_screen
,
168 amidisplaycc_load_font
,
172 const struct wsdisplay_emulops amidisplaycc_emulops
= {
174 amidisplaycc_mapchar
,
175 amidisplaycc_putchar
,
176 amidisplaycc_copycols
,
177 amidisplaycc_erasecols
,
178 amidisplaycc_copyrows
,
179 amidisplaycc_eraserows
,
180 amidisplaycc_allocattr
183 /* add some of our own data to the wsscreen_descr */
184 struct amidisplaycc_screen_descr
{
185 struct wsscreen_descr wsdescr
;
190 * List of supported screenmodes. Almost anything can be given here.
193 #define ADCC_SCREEN(name, width, height, depth, fontwidth, fontheight) \
198 height / fontheight, \
199 &amidisplaycc_emulops, fontwidth, fontheight, \
200 (depth > 1 ? WSSCREEN_WSCOLORS : 0) | WSSCREEN_REVERSE | \
201 WSSCREEN_HILIT | WSSCREEN_UNDERLINE }, \
207 * The first in list is used for the console screen.
208 * A suitable screen mode is guessed for it by looking
209 * at the GRF_* options.
211 struct amidisplaycc_screen_descr amidisplaycc_screentab
[] = {
212 /* name, width, height, depth, fontwidth==8, fontheight */
214 #if defined(GRF_PAL) && !defined(GRF_NTSC)
215 ADCC_SCREEN("default", 640, 512, 3, 8, 8),
217 ADCC_SCREEN("default", 640, 400, 3, 8, 8),
219 ADCC_SCREEN("80x50", 640, 400, 3, 8, 8),
220 ADCC_SCREEN("80x40", 640, 400, 3, 8, 10),
221 ADCC_SCREEN("80x25", 640, 400, 3, 8, 16),
222 ADCC_SCREEN("80x24", 640, 192, 3, 8, 8),
224 ADCC_SCREEN("80x64", 640, 512, 3, 8, 8),
225 ADCC_SCREEN("80x51", 640, 510, 3, 8, 10),
226 ADCC_SCREEN("80x32", 640, 512, 3, 8, 16),
227 ADCC_SCREEN("80x31", 640, 248, 3, 8, 8),
229 ADCC_SCREEN("640x400x1", 640, 400, 1, 8, 8),
230 ADCC_SCREEN("640x400x2", 640, 400, 2, 8, 8),
231 ADCC_SCREEN("640x400x3", 640, 400, 3, 8, 8),
233 ADCC_SCREEN("640x200x1", 640, 200, 1, 8, 8),
234 ADCC_SCREEN("640x200x2", 640, 200, 2, 8, 8),
235 ADCC_SCREEN("640x200x3", 640, 200, 3, 8, 8),
238 #define ADCC_SCREENPTR(index) &amidisplaycc_screentab[index].wsdescr
239 const struct wsscreen_descr
*amidisplaycc_screens
[] = {
257 #define NELEMS(arr) (sizeof(arr)/sizeof((arr)[0]))
260 * This structure also is passed to wscons. It contains pointers
261 * to the available display modes.
264 const struct wsscreen_list amidisplaycc_screenlist
= {
265 sizeof(amidisplaycc_screens
)/sizeof(amidisplaycc_screens
[0]),
270 * Our own screen structure. One will be created for each screen.
273 struct amidisplaycc_screen
275 struct amidisplaycc_softc
*device
;
287 /* Active bitplanes for each character row. */
288 int rowmasks
[MAXROWS
];
290 /* Mapping of colors to screen colors. */
291 int colormap
[MAXCOLORS
];
293 /* Copies of display parameters for convenience */
298 int widthbytes
; /* bytes_per_row */
299 int linebytes
; /* widthbytes + row_mod */
300 int rowbytes
; /* linebytes * fontheight */
302 u_char
* planes
[MAXDEPTH
];
304 const struct wsdisplay_font
* wsfont
;
305 int wsfontcookie
; /* if -1, builtin font */
310 typedef struct amidisplaycc_screen adccscr_t
;
313 * Need one statically allocated screen for early init.
314 * The rest are mallocated when needed.
316 adccscr_t amidisplaycc_consolescreen
;
319 * Default palettes for 2, 4 and 8 color emulation displays.
323 static u_char pal2red
[] = { 0x00, 0xaa };
324 static u_char pal2grn
[] = { 0x00, 0xaa };
325 static u_char pal2blu
[] = { 0x00, 0xaa };
327 /* black, red, green, grey */
328 static u_char pal4red
[] = { 0x00, 0xaa, 0x00, 0xaa };
329 static u_char pal4grn
[] = { 0x00, 0x00, 0xaa, 0xaa };
330 static u_char pal4blu
[] = { 0x00, 0x00, 0x00, 0xaa };
332 /* black, red, green, brown, blue, magenta, cyan, grey */
333 static u_char pal8red
[] = { 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa};
334 static u_char pal8grn
[] = { 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0xaa, 0xaa};
335 static u_char pal8blu
[] = { 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa};
337 static struct wsdisplay_cmap pal2
= { 0, 2, pal2red
, pal2grn
, pal2blu
};
338 static struct wsdisplay_cmap pal4
= { 0, 4, pal4red
, pal4grn
, pal4blu
};
339 static struct wsdisplay_cmap pal8
= { 0, 8, pal8red
, pal8grn
, pal8blu
};
342 extern int aga_enable
;
344 static int aga_enable
= 0;
348 * This gets called at console init to determine the priority of
349 * this console device.
351 * Of course pointers to this and other functions must present
352 * in constab[] in conf.c for this to work.
355 amidisplaycc_cnprobe(struct consdev
*cd
)
357 cd
->cn_pri
= CN_INTERNAL
;
360 * Yeah, real nice. But if we win the console then the wscons system
361 * does the proper initialization.
367 * This gets called if this device is used as the console.
370 amidisplaycc_cninit(struct consdev
* cd
)
377 /* Yeah, we got the console! */
380 * This will do the basic stuff we also need.
391 * Set up wscons to handle the details.
392 * It will then call us back when it needs something
393 * display-specific. It will also set up cn_tab properly,
394 * something which we failed to do at amidisplaycc_cnprobe().
398 * The alloc_screen knows to allocate the first screen statically.
400 amidisplaycc_alloc_screen(NULL
, &amidisplaycc_screentab
[0].wsdescr
,
401 &cookie
, &x
, &y
, &attr
);
402 wsdisplay_cnattach(&amidisplaycc_screentab
[0].wsdescr
,
406 /* tell kbd device it is used as console keyboard */
412 amidisplaycc_match(struct device
*pdp
, struct cfdata
*cfp
, void *auxp
)
416 if (matchname("amidisplaycc", name
) == 0)
419 /* Allow only one of us now. Not sure about that. */
420 if (amidisplaycc_attached
)
428 amidisplaycc_attach(struct device
*pdp
, struct device
*dp
, void *auxp
)
430 struct wsemuldisplaydev_attach_args waa
;
431 struct amidisplaycc_softc
* adp
;
433 amidisplaycc_attached
= 1;
435 adp
= (struct amidisplaycc_softc
*)dp
;
444 * Attach only at real configuration time. Console init is done at
445 * the amidisplaycc_cninit function above.
448 printf(": Amiga custom chip graphics %s",
449 aga_enable
? "(AGA)" : "");
451 if (amidisplaycc_consolescreen
.isconsole
) {
452 adp
->currentscreen
= &amidisplaycc_consolescreen
;
453 printf(" (console)");
455 adp
->currentscreen
= NULL
;
462 * Mapped screen properties.
463 * Would need a way to configure.
467 adp
->gfxwidth
= amidisplaycc_screentab
[0].wsdescr
.ncols
*
468 amidisplaycc_screentab
[0].wsdescr
.fontwidth
;
469 adp
->gfxheight
= amidisplaycc_screentab
[0].wsdescr
.nrows
*
470 amidisplaycc_screentab
[0].wsdescr
.fontheight
;
477 if (NELEMS(amidisplaycc_screentab
) !=
478 NELEMS(amidisplaycc_screens
))
479 panic("invalid screen definitions");
481 waa
.scrdata
= &amidisplaycc_screenlist
;
482 waa
.console
= amidisplaycc_consolescreen
.isconsole
;
483 waa
.accessops
= &amidisplaycc_accessops
;
484 waa
.accesscookie
= dp
;
485 config_found(dp
, &waa
, wsemuldisplaydevprint
);
493 * Color, bgcolor and style are packed into one long attribute.
494 * These macros are used to create/split the attribute
497 #define MAKEATTR(fg, bg, mode) (((fg)<<16) | ((bg)<<8) | (mode))
498 #define ATTRFG(attr) (((attr)>>16) & 255)
499 #define ATTRBG(attr) (((attr)>>8) & 255)
500 #define ATTRMO(attr) ((attr) & 255)
503 * Called by wscons to draw/clear the cursor.
504 * We do this by xorring the block to the screen.
506 * This simple implementation will break if the screen is modified
507 * under the cursor before clearing it.
510 amidisplaycc_cursor(void *screen
, int on
, int row
, int col
)
518 if (row
< 0 || col
< 0 || row
>= scr
->nrows
|| col
>= scr
->ncols
)
521 /* was off, turning off again? */
522 if (!on
&& scr
->cursorrow
== -1 && scr
->cursorcol
== -1)
525 /* was on, and turning on again? */
526 if (on
&& scr
->cursorrow
>= 0 && scr
->cursorcol
>= 0)
528 /* clear from old location first */
529 amidisplaycc_cursor (screen
, 0, scr
->cursorrow
, scr
->cursorcol
);
532 dst
= scr
->planes
[0];
533 dst
+= row
* scr
->rowbytes
;
537 scr
->cursorrow
= row
;
538 scr
->cursorcol
= col
;
544 for (i
= scr
->fontheight
; i
> 0 ; i
--) {
546 dst
+= scr
->linebytes
;
552 * This obviously does something important, don't ask me what.
555 amidisplaycc_mapchar(void *screen
, int ch
, unsigned int *chp
)
557 if (ch
> 0 && ch
< 256) {
566 * Write a character to screen with color / bgcolor / hilite(bold) /
567 * underline / reverse.
568 * Surely could be made faster but I'm not sure if its worth the
569 * effort as scrolling is at least a magnitude slower.
572 amidisplaycc_putchar(void *screen
, int row
, int col
, u_int ch
, long attr
)
597 if (row
< 0 || col
< 0 || row
>= scr
->nrows
|| col
>= scr
->ncols
)
600 /* Extract the colors from the attribute */
601 fgcolor
= ATTRFG(attr
);
602 bgcolor
= ATTRBG(attr
);
605 /* Translate to screen colors */
606 fgcolor
= scr
->colormap
[fgcolor
];
607 bgcolor
= scr
->colormap
[bgcolor
];
609 if (mode
& WSATTR_REVERSE
) {
615 bold
= (mode
& WSATTR_HILIT
) > 0;
616 underline
= (mode
& WSATTR_UNDERLINE
) > 0;
618 fontreal
= scr
->wsfont
->data
;
619 fontlow
= scr
->wsfont
->firstchar
;
620 fonthigh
= fontlow
+ scr
->wsfont
->numchars
- 1;
622 fontheight
= min(scr
->fontheight
, scr
->wsfont
->fontheight
);
624 linebytes
= scr
->linebytes
;
626 if (ch
< fontlow
|| ch
> fonthigh
)
629 /* Find the location where the wanted char is in the font data */
630 fontreal
+= scr
->wsfont
->fontheight
* (ch
- fontlow
);
632 bmapoffset
= row
* scr
->rowbytes
+ col
;
634 scr
->rowmasks
[row
] |= fgcolor
| bgcolor
;
636 for (plane
= 0 ; plane
< depth
; plane
++) {
637 dst
= scr
->planes
[plane
] + bmapoffset
;
641 /* fg=on bg=on (fill) */
643 for (j
= 0 ; j
< fontheight
; j
++) {
648 /* fg=on bg=off (normal) */
651 for (j
= 0 ; j
< fontheight
; j
++) {
659 *(dst
- linebytes
) = 255;
663 /* fg=off bg=on (inverted) */
666 for (j
= 0 ; j
< fontheight
; j
++) {
674 *(dst
- linebytes
) = 0;
676 /* fg=off bg=off (clear) */
678 for (j
= 0 ; j
< fontheight
; j
++) {
690 * Copy characters on a row to another position on the same row.
694 amidisplaycc_copycols(void *screen
, int row
, int srccol
, int dstcol
, int ncols
)
709 if (srccol
< 0 || srccol
+ ncols
> scr
->ncols
||
710 dstcol
< 0 || dstcol
+ ncols
> scr
->ncols
||
711 row
< 0 || row
>= scr
->nrows
)
715 linebytes
= scr
->linebytes
;
716 bmapoffset
= row
* scr
->rowbytes
;
718 for (plane
= 0 ; plane
< depth
; plane
++) {
719 src
= scr
->planes
[plane
] + bmapoffset
;
721 for (j
= 0 ; j
< scr
->fontheight
; j
++) {
724 if (srccol
< dstcol
) {
726 for (i
= ncols
- 1 ; i
>= 0 ; i
--)
727 dst
[dstcol
+ i
] = src
[srccol
+ i
];
731 for (i
= 0 ; i
< ncols
; i
++)
732 dst
[dstcol
+ i
] = src
[srccol
+ i
];
741 * Erase part of a row.
745 amidisplaycc_erasecols(void *screen
, int row
, int startcol
, int ncols
,
761 if (row
< 0 || row
>= scr
->nrows
||
762 startcol
< 0 || startcol
+ ncols
> scr
->ncols
)
766 linebytes
= scr
->linebytes
;
767 bmapoffset
= row
* scr
->rowbytes
+ startcol
;
769 /* Erase will be done using the set background color. */
770 bgcolor
= ATTRBG(attr
);
771 bgcolor
= scr
->colormap
[bgcolor
];
773 for(plane
= 0 ; plane
< depth
; plane
++) {
775 fill
= (bgcolor
& 1) ? 255 : 0;
777 dst
= scr
->planes
[plane
] + bmapoffset
;
779 for (j
= 0 ; j
< scr
->fontheight
; j
++) {
780 memset(dst
, fill
, ncols
);
787 * Copy a number of rows to another location on the screen.
788 * Combined with eraserows it can be used to perform operation
789 * also known as 'scrolling'.
793 amidisplaycc_copyrows(void *screen
, int srcrow
, int dstrow
, int nrows
)
817 if (srcrow
< 0 || srcrow
+ nrows
> scr
->nrows
||
818 dstrow
< 0 || dstrow
+ nrows
> scr
->nrows
)
823 widthbytes
= scr
->widthbytes
;
824 rowbytes
= scr
->rowbytes
;
825 linebytes
= scr
->linebytes
;
826 fontheight
= scr
->fontheight
;
828 srcbmapoffset
= rowbytes
* srcrow
;
829 dstbmapoffset
= rowbytes
* dstrow
;
831 if (srcrow
< dstrow
) {
832 /* Move data downwards, need to copy from down to up */
836 srcbmapoffset
+= rowbytes
* (nrows
- 1);
839 dstbmapoffset
+= rowbytes
* (nrows
- 1);
842 /* Move data upwards, copy up to down */
847 if (widthbytes
== linebytes
)
852 for (j
= 0 ; j
< nrows
; j
++) {
853 /* Need to copy only planes that have data on src or dst */
854 srcmask
= scr
->rowmasks
[srcrow
];
855 dstmask
= scr
->rowmasks
[dstrow
];
856 scr
->rowmasks
[dstrow
] = srcmask
;
858 for (plane
= 0 ; plane
< depth
; plane
++) {
862 * Source row has data on this
866 src
= scr
->planes
[plane
] + srcbmapoffset
;
867 dst
= scr
->planes
[plane
] + dstbmapoffset
;
871 memcpy(dst
, src
, copysize
);
876 * Data not continuous,
879 for (i
=0 ; i
< fontheight
; i
++) {
880 memcpy(dst
, src
, widthbytes
);
886 } else if (dstmask
& 1) {
888 * Source plane is empty, but dest is not.
889 * so all we need to is clear it.
892 dst
= scr
->planes
[plane
] + dstbmapoffset
;
896 memset(dst
, 0, copysize
);
898 for (i
= 0 ; i
< fontheight
; i
++) {
899 memset(dst
, 0, widthbytes
);
908 srcbmapoffset
+= bmdelta
;
909 dstbmapoffset
+= bmdelta
;
921 amidisplaycc_eraserows(void *screen
, int row
, int nrows
, long attr
)
941 if (row
< 0 || row
+ nrows
> scr
->nrows
)
945 widthbytes
= scr
->widthbytes
;
946 linebytes
= scr
->linebytes
;
947 rowbytes
= scr
->rowbytes
;
949 bmapoffset
= row
* rowbytes
;
951 if (widthbytes
== linebytes
)
952 fillsize
= rowbytes
* nrows
;
956 bgcolor
= ATTRBG(attr
);
957 bgcolor
= scr
->colormap
[bgcolor
];
959 for (j
= 0 ; j
< nrows
; j
++)
960 scr
->rowmasks
[row
+j
] = bgcolor
;
962 for (plane
= 0 ; plane
< depth
; plane
++) {
963 dst
= scr
->planes
[plane
] + bmapoffset
;
964 fill
= (bgcolor
& 1) ? 255 : 0;
967 /* If the rows are continuous, write them all. */
968 memset(dst
, fill
, fillsize
);
970 for (j
= 0 ; j
< scr
->fontheight
* nrows
; j
++) {
971 memset(dst
, fill
, widthbytes
);
981 * Compose an attribute value from foreground color,
982 * background color, and flags.
985 amidisplaycc_allocattr(void *screen
, int fg
, int bg
, int flags
, long *attrp
)
993 maxcolor
= (1 << scr
->view
->bitmap
->depth
) - 1;
995 /* Ensure the colors are displayable. */
996 newfg
= fg
& maxcolor
;
997 newbg
= bg
& maxcolor
;
1001 * Hack for low-color screens, if background color is nonzero
1002 * but would be displayed as one, adjust it.
1004 if (bg
> 0 && newbg
== 0)
1008 * If foreground and background colors are different but would
1009 * display the same fix them by modifying the foreground.
1011 if (fg
!= bg
&& newfg
== newbg
) {
1018 *attrp
= MAKEATTR(newfg
, newbg
, flags
);
1024 amidisplaycc_ioctl(void *dp
, void *vs
, u_long cmd
, void *data
, int flag
,
1027 struct amidisplaycc_softc
*adp
;
1032 printf("amidisplaycc_ioctl: adp==NULL\n");
1036 #define UINTDATA (*(u_int*)data)
1037 #define INTDATA (*(int*)data)
1038 #define FBINFO (*(struct wsdisplay_fbinfo*)data)
1042 case WSDISPLAYIO_GTYPE
:
1043 UINTDATA
= WSDISPLAY_TYPE_AMIGACC
;
1046 case WSDISPLAYIO_SVIDEO
:
1047 dprintf("amidisplaycc: WSDISPLAYIO_SVIDEO %s\n",
1048 UINTDATA
? "On" : "Off");
1050 return (amidisplaycc_setvideo(adp
, UINTDATA
));
1052 case WSDISPLAYIO_GVIDEO
:
1053 dprintf("amidisplaycc: WSDISPLAYIO_GVIDEO\n");
1054 UINTDATA
= adp
->ison
?
1055 WSDISPLAYIO_VIDEO_ON
: WSDISPLAYIO_VIDEO_OFF
;
1059 case WSDISPLAYIO_SMODE
:
1060 if (INTDATA
== WSDISPLAYIO_MODE_EMUL
)
1061 return amidisplaycc_gfxscreen(adp
, 0);
1062 if (INTDATA
== WSDISPLAYIO_MODE_MAPPED
)
1063 return amidisplaycc_gfxscreen(adp
, 1);
1066 case WSDISPLAYIO_GINFO
:
1067 FBINFO
.width
= adp
->gfxwidth
;
1068 FBINFO
.height
= adp
->gfxheight
;
1069 FBINFO
.depth
= adp
->gfxdepth
;
1070 FBINFO
.cmsize
= 1 << FBINFO
.depth
;
1073 case WSDISPLAYIO_PUTCMAP
:
1074 case WSDISPLAYIO_GETCMAP
:
1075 return (amidisplaycc_cmapioctl(adp
->gfxview
,
1077 (struct wsdisplay_cmap
*)data
));
1080 dprintf("amidisplaycc: unknown ioctl %lx (grp:'%c' num:%d)\n",
1082 (char)((cmd
&0xff00)>>8),
1085 return (EPASSTHROUGH
);
1094 * Switch to either emulation (text) or mapped (graphics) mode
1095 * We keep an extra screen for mapped mode so it does not
1096 * interfere with emulation screens.
1098 * Once the extra screen is created, it never goes away.
1102 amidisplaycc_gfxscreen(struct amidisplaycc_softc
*adp
, int on
)
1106 dprintf("amidisplaycc: switching to %s mode.\n",
1107 on
? "mapped" : "emul");
1109 /* Current mode same as requested mode? */
1110 if ( (on
> 0) == (adp
->gfxon
> 0) )
1115 * Switch away from mapped mode. If there is
1116 * a emulation screen, switch to it, otherwise
1117 * just try to hide the mapped screen.
1120 if (adp
->currentscreen
)
1121 grf_display_view(adp
->currentscreen
->view
);
1122 else if (adp
->gfxview
)
1123 grf_remove_view(adp
->gfxview
);
1128 /* switch to mapped mode then */
1130 if (adp
->gfxview
== NULL
) {
1131 /* First time here, create the screen */
1133 dimension
.width
= adp
->gfxwidth
;
1134 dimension
.height
= adp
->gfxheight
;
1136 dprintf("amidisplaycc: preparing mapped screen %dx%dx%d\n",
1141 adp
->gfxview
= grf_alloc_view(NULL
,
1149 grf_display_view(adp
->gfxview
);
1151 printf("amidisplaycc: failed to make mapped screen\n");
1158 * Map the graphics screen. It must have been created before
1159 * by switching to mapped mode by using an ioctl.
1162 amidisplaycc_mmap(void *dp
, void *vs
, off_t off
, int prot
)
1164 struct amidisplaycc_softc
* adp
;
1168 adp
= (struct amidisplaycc_softc
*)dp
;
1170 /* Check we are in mapped mode */
1171 if (adp
->gfxon
== 0 || adp
->gfxview
== NULL
) {
1172 dprintf("amidisplaycc_mmap: Not in mapped mode\n");
1173 return (paddr_t
)(-1);
1177 * As we all know by now, we are mapping our special
1178 * screen here so our pretty text consoles are left
1182 bm
= adp
->gfxview
->bitmap
;
1184 /* Check that the offset is valid */
1185 if (off
< 0 || off
>= bm
->depth
* bm
->bytes_per_row
* bm
->rows
) {
1186 dprintf("amidisplaycc_mmap: Offset out of range\n");
1187 return (paddr_t
)(-1);
1190 rv
= (paddr_t
)bm
->hardware_address
;
1193 return (rv
>> PGSHIFT
);
1198 * Create a new screen.
1199 * NULL dp signifies console and then memory is allocated statically
1200 * and the screen is automatically displayed.
1202 * A font with suitable size is searched and if not found
1203 * the builtin 8x8 font is used.
1205 * There are separate default palettes for 2, 4 and 8+ color
1210 amidisplaycc_alloc_screen(void *dp
, const struct wsscreen_descr
*screenp
,
1211 void **cookiep
, int *curxp
, int *curyp
,
1214 const struct amidisplaycc_screen_descr
* adccscreenp
;
1215 struct amidisplaycc_screen
* scr
;
1216 struct amidisplaycc_softc
* adp
;
1227 adccscreenp
= (const struct amidisplaycc_screen_descr
*)screenp
;
1228 depth
= adccscreenp
->depth
;
1232 maxcolor
= (1 << depth
) - 1;
1234 /* Sanity checks because of fixed buffers */
1235 if (depth
> MAXDEPTH
|| maxcolor
>= MAXCOLORS
)
1237 if (screenp
->nrows
> MAXROWS
)
1240 fontwidth
= screenp
->fontwidth
;
1241 fontheight
= screenp
->fontheight
;
1244 * The screen size is defined in characters.
1245 * Calculate the pixel size using the font size.
1248 dimension
.width
= screenp
->ncols
* fontwidth
;
1249 dimension
.height
= screenp
->nrows
* fontheight
;
1251 view
= grf_alloc_view(NULL
, &dimension
, depth
);
1256 * First screen gets the statically allocated console screen.
1257 * Others are allocated dynamically.
1260 scr
= &amidisplaycc_consolescreen
;
1262 panic("more than one console?");
1266 scr
= malloc(sizeof(adccscr_t
), M_DEVBUF
, M_WAITOK
|M_ZERO
);
1271 scr
->ncols
= screenp
->ncols
;
1272 scr
->nrows
= screenp
->nrows
;
1274 /* Copies of most used values */
1275 scr
->width
= dimension
.width
;
1276 scr
->height
= dimension
.height
;
1278 scr
->widthbytes
= view
->bitmap
->bytes_per_row
;
1279 scr
->linebytes
= scr
->widthbytes
+ view
->bitmap
->row_mod
;
1280 scr
->rowbytes
= scr
->linebytes
* fontheight
;
1286 * Try to find a suitable font.
1287 * Avoid everything but the builtin font for console screen.
1288 * Builtin font is used if no other is found, even if it
1289 * has the wrong size.
1292 KASSERT(fontwidth
== 8);
1295 scr
->wsfontcookie
= -1;
1296 scr
->fontwidth
= fontwidth
;
1297 scr
->fontheight
= fontheight
;
1300 amidisplaycc_setfont(scr
, NULL
);
1302 if (scr
->wsfont
== NULL
)
1304 scr
->wsfont
= amidisplaycc_getbuiltinfont();
1305 scr
->wsfontcookie
= -1;
1308 KASSERT(scr
->wsfont
);
1309 KASSERT(scr
->wsfont
->stride
== 1);
1311 for (i
= 0 ; i
< depth
; i
++) {
1312 scr
->planes
[i
] = view
->bitmap
->plane
[i
];
1315 for (i
= 0 ; i
< MAXROWS
; i
++)
1316 scr
->rowmasks
[i
] = 0;
1318 /* Simple one-to-one mapping for most colors */
1319 for (i
= 0 ; i
< MAXCOLORS
; i
++)
1320 scr
->colormap
[i
] = i
;
1323 * Arrange the most used pens to quickest colors.
1324 * The default color for given depth is (1<<depth)-1.
1325 * It is assumed it is used most and it is mapped to
1326 * color that can be drawn by writing data to one bitplane
1328 * So map colors 3->2, 7->4, 15->8 and so on.
1330 for (i
= 2 ; i
< MAXCOLORS
; i
*= 2) {
1333 if (j
< MAXCOLORS
) {
1334 scr
->colormap
[i
] = j
;
1335 scr
->colormap
[j
] = i
;
1340 * Set the default colormap.
1343 amidisplaycc_setemulcmap(scr
, &pal2
);
1344 else if (depth
== 2)
1345 amidisplaycc_setemulcmap(scr
, &pal4
);
1347 amidisplaycc_setemulcmap(scr
, &pal8
);
1351 /* cursor initially at top left */
1352 scr
->cursorrow
= -1;
1353 scr
->cursorcol
= -1;
1356 amidisplaycc_cursor(scr
, 1, *curxp
, *curyp
);
1358 *defattrp
= MAKEATTR(maxcolor
, 0, 0);
1360 /* Show the console automatically */
1362 grf_display_view(scr
->view
);
1365 dprintf("amidisplaycc: allocated screen; %dx%dx%d; font=%s\n",
1381 amidisplaycc_free_screen(void *dp
, void *screen
)
1383 struct amidisplaycc_screen
* scr
;
1384 struct amidisplaycc_softc
* adp
;
1387 adp
= (struct amidisplaycc_softc
*)dp
;
1392 /* Free the used font */
1393 if (scr
->wsfont
&& scr
->wsfontcookie
!= -1)
1394 wsfont_unlock(scr
->wsfontcookie
);
1396 scr
->wsfontcookie
= -1;
1398 if (adp
->currentscreen
== scr
)
1399 adp
->currentscreen
= NULL
;
1402 grf_free_view(scr
->view
);
1405 /* Take care not to free the statically allocated console screen */
1406 if (scr
!= &amidisplaycc_consolescreen
) {
1407 free(scr
, M_DEVBUF
);
1412 * Switch to another vt. Switch is always made immediately.
1417 amidisplaycc_show_screen(void *dp
, void *screen
, int waitok
,
1418 void (*cb
) (void *, int, int), void *cbarg
)
1421 struct amidisplaycc_softc
*adp
;
1423 adp
= (struct amidisplaycc_softc
*)dp
;
1427 dprintf("amidisplaycc_show_screen: adp==NULL\n");
1431 dprintf("amidisplaycc_show_screen: scr==NULL\n");
1436 dprintf("amidisplaycc: Screen shift while in gfx mode?");
1440 adp
->currentscreen
= scr
;
1443 grf_display_view(scr
->view
);
1451 * Only setting is supported, as the wsfont pseudo-device can
1452 * handle the loading of fonts for us.
1455 amidisplaycc_load_font(void *dp
, void *cookie
, struct wsdisplay_font
*font
)
1457 struct amidisplaycc_softc
* adp
;
1458 struct amidisplaycc_screen
* scr
;
1466 KASSERT(font
->name
);
1470 /* request to load the font, not supported */
1475 /* request to use the given font on this screen */
1476 return amidisplaycc_setfont(scr
, font
->name
);
1481 * Set display on/off.
1484 amidisplaycc_setvideo(struct amidisplaycc_softc
*adp
, int mode
)
1489 dprintf("amidisplaycc_setvideo: adp==NULL\n");
1492 if (adp
->currentscreen
== NULL
) {
1493 dprintf("amidisplaycc_setvideo: adp->currentscreen==NULL\n");
1497 /* select graphics or emulation screen */
1498 if (adp
->gfxon
&& adp
->gfxview
)
1499 view
= adp
->gfxview
;
1501 view
= adp
->currentscreen
->view
;
1506 grf_display_view(view
);
1507 dprintf("amidisplaycc: video is now on\n");
1513 grf_remove_view(view
);
1514 dprintf("amidisplaycc: video is now off\n");
1522 * Handle the WSDISPLAY_[PUT/GET]CMAP ioctls.
1523 * Just handle the copying of data to/from userspace and
1524 * let the functions amidisplaycc_setcmap and amidisplaycc_putcmap
1529 amidisplaycc_cmapioctl(view_t
*view
, u_long cmd
, struct wsdisplay_cmap
*cmap
)
1531 struct wsdisplay_cmap tmpcmap
;
1532 u_char cmred
[MAXCOLORS
];
1533 u_char cmgrn
[MAXCOLORS
];
1534 u_char cmblu
[MAXCOLORS
];
1538 if (cmap
->index
>= MAXCOLORS
||
1539 cmap
->count
> MAXCOLORS
||
1540 cmap
->index
+ cmap
->count
> MAXCOLORS
)
1543 if (cmap
->count
== 0)
1546 tmpcmap
.index
= cmap
->index
;
1547 tmpcmap
.count
= cmap
->count
;
1548 tmpcmap
.red
= cmred
;
1549 tmpcmap
.green
= cmgrn
;
1550 tmpcmap
.blue
= cmblu
;
1552 if (cmd
== WSDISPLAYIO_PUTCMAP
) {
1553 /* copy the color data to kernel space */
1555 err
= copyin(cmap
->red
, cmred
, cmap
->count
);
1559 err
= copyin(cmap
->green
, cmgrn
, cmap
->count
);
1563 err
= copyin(cmap
->blue
, cmblu
, cmap
->count
);
1567 return amidisplaycc_setcmap(view
, &tmpcmap
);
1569 } else if (cmd
== WSDISPLAYIO_GETCMAP
) {
1571 err
= amidisplaycc_getcmap(view
, &tmpcmap
);
1575 /* copy data to user space */
1577 err
= copyout(cmred
, cmap
->red
, cmap
->count
);
1581 err
= copyout(cmgrn
, cmap
->green
, cmap
->count
);
1585 err
= copyout(cmblu
, cmap
->blue
, cmap
->count
);
1592 return (EPASSTHROUGH
);
1596 * Set the palette of a emulation screen.
1597 * Here we do only color remapping and then call
1598 * amidisplaycc_setcmap to do the work.
1602 amidisplaycc_setemulcmap(struct amidisplaycc_screen
*scr
,
1603 struct wsdisplay_cmap
*cmap
)
1605 struct wsdisplay_cmap tmpcmap
;
1607 u_char red
[MAXCOLORS
];
1608 u_char grn
[MAXCOLORS
];
1609 u_char blu
[MAXCOLORS
];
1615 * Get old palette first.
1616 * Because of the color mapping going on in the emulation
1617 * screen the color range may not be contiguous in the real
1619 * So get the whole palette, insert the new colors
1620 * at the appropriate places and then set the whole
1625 tmpcmap
.count
= 1 << scr
->depth
;
1627 tmpcmap
.green
= grn
;
1630 rc
= amidisplaycc_getcmap(scr
->view
, &tmpcmap
);
1634 for (i
= cmap
->index
; i
< cmap
->index
+ cmap
->count
; i
++) {
1636 tmpcmap
.red
[ scr
->colormap
[ i
] ] = cmap
->red
[ i
];
1637 tmpcmap
.green
[ scr
->colormap
[ i
] ] = cmap
->green
[ i
];
1638 tmpcmap
.blue
[ scr
->colormap
[ i
] ] = cmap
->blue
[ i
];
1641 rc
= amidisplaycc_setcmap(scr
->view
, &tmpcmap
);
1650 * Set the colormap for the given screen.
1654 amidisplaycc_setcmap(view_t
*view
, struct wsdisplay_cmap
*cmap
)
1656 u_long cmentries
[MAXCOLORS
];
1667 if (!cmap
|| !cmap
->red
|| !cmap
->green
|| !cmap
->blue
) {
1668 dprintf("amidisplaycc_setcmap: other==NULL\n");
1672 index
= cmap
->index
;
1673 count
= cmap
->count
;
1674 colors
= (1 << view
->bitmap
->depth
);
1676 if (count
> colors
|| index
>= colors
|| index
+ count
> colors
)
1682 cm
.entry
= cmentries
;
1687 * Get the old colormap. We need to do this at least to know
1688 * how many bits to use with the color values.
1691 err
= grf_get_colormap(view
, &cm
);
1696 * The palette entries from wscons contain 8 bits per gun.
1697 * We need to convert them to the number of bits the view
1698 * expects. That is typically 4 or 8. Here we calculate the
1699 * conversion constants with which we divide the color values.
1702 if (cm
.type
== CM_COLOR
) {
1703 int c
, green_div
, blue_div
, red_div
;
1705 red_div
= 256 / (cm
.red_mask
+ 1);
1706 green_div
= 256 / (cm
.green_mask
+ 1);
1707 blue_div
= 256 / (cm
.blue_mask
+ 1);
1709 for (c
= 0 ; c
< count
; c
++)
1710 cm
.entry
[c
+ index
] = MAKE_COLOR_ENTRY(
1711 cmap
->red
[c
] / red_div
,
1712 cmap
->green
[c
] / green_div
,
1713 cmap
->blue
[c
] / blue_div
);
1715 } else if (cm
.type
== CM_GREYSCALE
) {
1718 grey_div
= 256 / (cm
.grey_mask
+ 1);
1720 /* Generate grey from average of r-g-b (?) */
1721 for (c
= 0 ; c
< count
; c
++)
1722 cm
.entry
[c
+ index
] = MAKE_COLOR_ENTRY(
1727 cmap
->blue
[c
]) / 3 / grey_div
);
1729 return (EINVAL
); /* Hmhh */
1732 * Now we have a new colormap that contains all the entries. Set
1736 err
= grf_use_colormap(view
, &cm
);
1744 * Return the colormap of the given screen.
1748 amidisplaycc_getcmap(view_t
*view
, struct wsdisplay_cmap
*cmap
)
1750 u_long cmentries
[MAXCOLORS
];
1761 if (!cmap
|| !cmap
->red
|| !cmap
->green
|| !cmap
->blue
)
1764 index
= cmap
->index
;
1765 count
= cmap
->count
;
1766 colors
= (1 << view
->bitmap
->depth
);
1768 if (count
> colors
|| index
>= colors
|| index
+ count
> colors
)
1774 cm
.entry
= cmentries
;
1778 err
= grf_get_colormap(view
, &cm
);
1783 * Copy color data to wscons-style structure. Translate to
1784 * 8 bits/gun from whatever resolution the color natively is.
1786 if (cm
.type
== CM_COLOR
) {
1787 int c
, red_mul
, green_mul
, blue_mul
;
1789 red_mul
= 256 / (cm
.red_mask
+ 1);
1790 green_mul
= 256 / (cm
.green_mask
+ 1);
1791 blue_mul
= 256 / (cm
.blue_mask
+ 1);
1793 for (c
= 0 ; c
< count
; c
++) {
1794 cmap
->red
[c
] = red_mul
*
1795 CM_GET_RED(cm
.entry
[index
+c
]);
1796 cmap
->green
[c
] = green_mul
*
1797 CM_GET_GREEN(cm
.entry
[index
+c
]);
1798 cmap
->blue
[c
] = blue_mul
*
1799 CM_GET_BLUE(cm
.entry
[index
+c
]);
1801 } else if (cm
.type
== CM_GREYSCALE
) {
1804 grey_mul
= 256 / (cm
.grey_mask
+ 1);
1806 for (c
= 0 ; c
< count
; c
++) {
1807 cmap
->red
[c
] = grey_mul
*
1808 CM_GET_GREY(cm
.entry
[index
+c
]);
1809 cmap
->green
[c
] = grey_mul
*
1810 CM_GET_GREY(cm
.entry
[index
+c
]);
1811 cmap
->blue
[c
] = grey_mul
*
1812 CM_GET_GREY(cm
.entry
[index
+c
]);
1821 * Find and set a font for the given screen.
1823 * If fontname is given, a font with that name and suitable
1824 * size (determined by the screen) is searched for.
1825 * If fontname is NULL, a font with suitable size is searched.
1827 * On success, the found font is assigned to the screen and possible
1828 * old font is freed.
1831 amidisplaycc_setfont(struct amidisplaycc_screen
*scr
, const char *fontname
)
1833 struct wsdisplay_font
*wsfont
;
1838 wsfontcookie
= wsfont_find(fontname
,
1842 WSDISPLAY_FONTORDER_L2R
,
1843 WSDISPLAY_FONTORDER_L2R
);
1845 if (wsfontcookie
== -1)
1848 /* Suitable font found. Now lock it. */
1849 if (wsfont_lock(wsfontcookie
, &wsfont
))
1854 if (scr
->wsfont
&& scr
->wsfontcookie
!= -1)
1855 wsfont_unlock(scr
->wsfontcookie
);
1857 scr
->wsfont
= wsfont
;
1858 scr
->wsfontcookie
= wsfontcookie
;
1864 * Return a font that is guaranteed to exist.
1866 static const struct wsdisplay_font
*
1867 amidisplaycc_getbuiltinfont(void)
1869 static struct wsdisplay_font font
;
1871 extern unsigned char kernel_font_width_8x8
;
1872 extern unsigned char kernel_font_height_8x8
;
1873 extern unsigned char kernel_font_lo_8x8
;
1874 extern unsigned char kernel_font_hi_8x8
;
1875 extern unsigned char kernel_font_8x8
[];
1877 font
.name
= "kf8x8";
1878 font
.firstchar
= kernel_font_lo_8x8
;
1879 font
.numchars
= kernel_font_hi_8x8
- kernel_font_lo_8x8
+ 1;
1880 font
.fontwidth
= kernel_font_width_8x8
;
1882 font
.fontheight
= kernel_font_height_8x8
;
1883 font
.data
= kernel_font_8x8
;
1885 /* these values aren't really used for anything */
1886 font
.encoding
= WSDISPLAY_FONTENC_ISO
;
1887 font
.bitorder
= WSDISPLAY_FONTORDER_KNOWN
;
1888 font
.byteorder
= WSDISPLAY_FONTORDER_KNOWN
;
1895 amidisplaycc_pollc(void *cookie
, int on
)
1900 * These dummy functions are here just so that we can compete of
1901 * the console at init.
1902 * If we win the console then the wscons system will provide the
1903 * real ones which in turn will call the apropriate wskbd device.
1904 * These should never be called.
1909 amidisplaycc_cnputc(dev_t cd
, int ch
)
1915 amidisplaycc_cngetc(dev_t cd
)
1922 amidisplaycc_cnpollc(dev_t cd
, int on
)
1928 * Prints stuff if DEBUG is turned on.
1933 dprintf(const char *fmt
, ...)
1944 #endif /* AMIDISPLAYCC */