| @@ -1,1845 +1,1763 @@ | | | @@ -1,1845 +1,1763 @@ |
1 | /* $NetBSD: p9100.c,v 1.44 2009/05/27 00:35:34 macallan Exp $ */ | | 1 | /* $NetBSD: p9100.c,v 1.45 2009/05/27 15:13:22 macallan Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1998, 2005, 2006 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1998, 2005, 2006 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Matt Thomas. | | 8 | * by Matt Thomas. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | /* | | 32 | /* |
33 | * color display (p9100) driver. | | 33 | * color display (p9100) driver. |
34 | * | | 34 | * |
35 | * Does not handle interrupts, even though they can occur. | | 35 | * Does not handle interrupts, even though they can occur. |
36 | * | | 36 | * |
37 | * XXX should defer colormap updates to vertical retrace interrupts | | 37 | * XXX should defer colormap updates to vertical retrace interrupts |
38 | */ | | 38 | */ |
39 | | | 39 | |
40 | #include <sys/cdefs.h> | | 40 | #include <sys/cdefs.h> |
41 | __KERNEL_RCSID(0, "$NetBSD: p9100.c,v 1.44 2009/05/27 00:35:34 macallan Exp $"); | | 41 | __KERNEL_RCSID(0, "$NetBSD: p9100.c,v 1.45 2009/05/27 15:13:22 macallan Exp $"); |
42 | | | 42 | |
43 | #include <sys/param.h> | | 43 | #include <sys/param.h> |
44 | #include <sys/systm.h> | | 44 | #include <sys/systm.h> |
45 | #include <sys/buf.h> | | 45 | #include <sys/buf.h> |
46 | #include <sys/device.h> | | 46 | #include <sys/device.h> |
47 | #include <sys/ioctl.h> | | 47 | #include <sys/ioctl.h> |
48 | #include <sys/malloc.h> | | 48 | #include <sys/malloc.h> |
49 | #include <sys/mman.h> | | 49 | #include <sys/mman.h> |
50 | #include <sys/tty.h> | | 50 | #include <sys/tty.h> |
51 | #include <sys/conf.h> | | 51 | #include <sys/conf.h> |
52 | | | 52 | |
53 | #include <sys/bus.h> | | 53 | #include <sys/bus.h> |
54 | #include <machine/autoconf.h> | | 54 | #include <machine/autoconf.h> |
55 | | | 55 | |
56 | #include <dev/sun/fbio.h> | | 56 | #include <dev/sun/fbio.h> |
57 | #include <dev/sun/fbvar.h> | | 57 | #include <dev/sun/fbvar.h> |
58 | #include <dev/sun/btreg.h> | | 58 | #include <dev/sun/btreg.h> |
59 | #include <dev/sun/btvar.h> | | 59 | #include <dev/sun/btvar.h> |
60 | | | 60 | |
61 | #include <dev/sbus/p9100reg.h> | | 61 | #include <dev/sbus/p9100reg.h> |
62 | | | 62 | |
63 | #include <dev/sbus/sbusvar.h> | | 63 | #include <dev/sbus/sbusvar.h> |
64 | | | 64 | |
65 | #include <dev/wscons/wsdisplayvar.h> | | 65 | #include <dev/wscons/wsdisplayvar.h> |
66 | #include <dev/wscons/wsconsio.h> | | 66 | #include <dev/wscons/wsconsio.h> |
67 | #include <dev/wsfont/wsfont.h> | | 67 | #include <dev/wsfont/wsfont.h> |
68 | #include <dev/rasops/rasops.h> | | 68 | #include <dev/rasops/rasops.h> |
69 | | | 69 | |
70 | #include <dev/wscons/wsdisplay_vconsvar.h> | | 70 | #include <dev/wscons/wsdisplay_vconsvar.h> |
71 | | | 71 | |
72 | #include "opt_wsemul.h" | | 72 | #include "opt_wsemul.h" |
73 | #include "rasops_glue.h" | | 73 | #include "rasops_glue.h" |
| | | 74 | #include "opt_pnozz.h" |
74 | | | 75 | |
75 | #include "tctrl.h" | | 76 | #include "tctrl.h" |
76 | #if NTCTRL > 0 | | 77 | #if NTCTRL > 0 |
77 | #include <machine/tctrl.h> | | 78 | #include <machine/tctrl.h> |
78 | #include <sparc/dev/tctrlvar.h>/*XXX*/ | | 79 | #include <sparc/dev/tctrlvar.h> /*XXX*/ |
79 | #endif | | 80 | #endif |
80 | | | 81 | |
81 | #ifdef PNOZZ_DEBUG | | 82 | #ifdef PNOZZ_DEBUG |
82 | #define DPRINTF aprint_normal | | 83 | #define DPRINTF aprint_normal |
83 | #else | | 84 | #else |
84 | #define DPRINTF while (0) aprint_normal | | 85 | #define DPRINTF while (0) aprint_normal |
85 | #endif | | 86 | #endif |
86 | | | 87 | |
87 | struct pnozz_cursor { | | 88 | struct pnozz_cursor { |
88 | short pc_enable; /* cursor is enabled */ | | 89 | short pc_enable; /* cursor is enabled */ |
89 | struct fbcurpos pc_pos; /* position */ | | 90 | struct fbcurpos pc_pos; /* position */ |
90 | struct fbcurpos pc_hot; /* hot-spot */ | | 91 | struct fbcurpos pc_hot; /* hot-spot */ |
91 | struct fbcurpos pc_size; /* size of mask & image fields */ | | 92 | struct fbcurpos pc_size; /* size of mask & image fields */ |
92 | uint32_t pc_bits[0x100]; /* space for mask & image bits */ | | 93 | uint32_t pc_bits[0x100]; /* space for mask & image bits */ |
93 | unsigned char red[3], green[3]; | | 94 | unsigned char red[3], green[3]; |
94 | unsigned char blue[3]; /* cursor palette */ | | 95 | unsigned char blue[3]; /* cursor palette */ |
95 | }; | | 96 | }; |
96 | | | 97 | |
97 | /* per-display variables */ | | 98 | /* per-display variables */ |
98 | struct p9100_softc { | | 99 | struct p9100_softc { |
99 | device_t sc_dev; /* base device */ | | 100 | device_t sc_dev; /* base device */ |
100 | struct sbusdev sc_sd; /* sbus device */ | | 101 | struct sbusdev sc_sd; /* sbus device */ |
101 | struct fbdevice sc_fb; /* frame buffer device */ | | 102 | struct fbdevice sc_fb; /* frame buffer device */ |
102 | | | 103 | |
103 | bus_space_tag_t sc_bustag; | | 104 | bus_space_tag_t sc_bustag; |
104 | | | 105 | |
105 | bus_addr_t sc_ctl_paddr; /* phys address description */ | | 106 | bus_addr_t sc_ctl_paddr; /* phys address description */ |
106 | bus_size_t sc_ctl_psize; /* for device mmap() */ | | 107 | bus_size_t sc_ctl_psize; /* for device mmap() */ |
107 | bus_space_handle_t sc_ctl_memh; /* bus space handle */ | | 108 | bus_space_handle_t sc_ctl_memh; /* bus space handle */ |
108 | | | 109 | |
109 | #if 0 | | | |
110 | bus_addr_t sc_cmd_paddr; /* phys address description */ | | | |
111 | bus_size_t sc_cmd_psize; /* for device mmap() */ | | | |
112 | bus_space_handle_t sc_cmd_memh; /* bus space handle */ | | | |
113 | #endif | | | |
114 | bus_addr_t sc_fb_paddr; /* phys address description */ | | 110 | bus_addr_t sc_fb_paddr; /* phys address description */ |
115 | bus_size_t sc_fb_psize; /* for device mmap() */ | | 111 | bus_size_t sc_fb_psize; /* for device mmap() */ |
116 | bus_space_handle_t sc_fb_memh; /* bus space handle */ | | 112 | bus_space_handle_t sc_fb_memh; /* bus space handle */ |
117 | | | 113 | |
118 | volatile uint32_t sc_junk; | | 114 | volatile uint32_t sc_junk; |
119 | uint32_t sc_mono_width; /* for setup_mono */ | | 115 | uint32_t sc_mono_width; /* for setup_mono */ |
120 | | | 116 | |
121 | uint32_t sc_width; | | 117 | uint32_t sc_width; |
122 | uint32_t sc_height; /* panel width / height */ | | 118 | uint32_t sc_height; /* panel width / height */ |
123 | uint32_t sc_stride; | | 119 | uint32_t sc_stride; |
124 | uint32_t sc_depth; | | 120 | uint32_t sc_depth; |
125 | int sc_depthshift; /* blitter works on bytes not pixels */ | | 121 | int sc_depthshift; /* blitter works on bytes not pixels */ |
126 | | | 122 | |
127 | union bt_cmap sc_cmap; /* Brooktree color map */ | | 123 | union bt_cmap sc_cmap; /* Brooktree color map */ |
128 | | | 124 | |
129 | struct pnozz_cursor sc_cursor; | | 125 | struct pnozz_cursor sc_cursor; |
130 | | | 126 | |
131 | int sc_mode; | | 127 | int sc_mode; |
132 | int sc_video, sc_powerstate; | | 128 | int sc_video, sc_powerstate; |
133 | uint32_t sc_bg; | | 129 | uint32_t sc_bg; |
134 | volatile uint32_t sc_last_offset; | | 130 | volatile uint32_t sc_last_offset; |
135 | struct vcons_data vd; | | 131 | struct vcons_data vd; |
| | | 132 | uint8_t sc_dac_power; |
136 | }; | | 133 | }; |
137 | | | 134 | |
138 | | | 135 | |
139 | static struct vcons_screen p9100_console_screen; | | 136 | static struct vcons_screen p9100_console_screen; |
140 | | | 137 | |
141 | extern const u_char rasops_cmap[768]; | | 138 | extern const u_char rasops_cmap[768]; |
142 | | | 139 | |
143 | struct wsscreen_descr p9100_defscreendesc = { | | 140 | struct wsscreen_descr p9100_defscreendesc = { |
144 | "default", | | 141 | "default", |
145 | 0, 0, | | 142 | 0, 0, |
146 | NULL, | | 143 | NULL, |
147 | 8, 16, | | 144 | 8, 16, |
148 | WSSCREEN_WSCOLORS, | | 145 | WSSCREEN_WSCOLORS, |
149 | }; | | 146 | }; |
150 | | | 147 | |
151 | const struct wsscreen_descr *_p9100_scrlist[] = { | | 148 | const struct wsscreen_descr *_p9100_scrlist[] = { |
152 | &p9100_defscreendesc, | | 149 | &p9100_defscreendesc, |
153 | /* XXX other formats, graphics screen? */ | | 150 | /* XXX other formats, graphics screen? */ |
154 | }; | | 151 | }; |
155 | | | 152 | |
156 | struct wsscreen_list p9100_screenlist = { | | 153 | struct wsscreen_list p9100_screenlist = { |
157 | sizeof(_p9100_scrlist) / sizeof(struct wsscreen_descr *), _p9100_scrlist | | 154 | sizeof(_p9100_scrlist) / sizeof(struct wsscreen_descr *), |
| | | 155 | _p9100_scrlist |
158 | }; | | 156 | }; |
159 | | | 157 | |
160 | /* autoconfiguration driver */ | | 158 | /* autoconfiguration driver */ |
161 | static int p9100_sbus_match(device_t, cfdata_t, void *); | | 159 | static int p9100_sbus_match(device_t, cfdata_t, void *); |
162 | static void p9100_sbus_attach(device_t, device_t, void *); | | 160 | static void p9100_sbus_attach(device_t, device_t, void *); |
163 | | | 161 | |
164 | static void p9100unblank(device_t); | | 162 | static void p9100unblank(device_t); |
165 | static void p9100_shutdown(void *); | | | |
166 | | | 163 | |
167 | CFATTACH_DECL_NEW(pnozz, sizeof(struct p9100_softc), | | 164 | CFATTACH_DECL_NEW(pnozz, sizeof(struct p9100_softc), |
168 | p9100_sbus_match, p9100_sbus_attach, NULL, NULL); | | 165 | p9100_sbus_match, p9100_sbus_attach, NULL, NULL); |
169 | | | 166 | |
170 | extern struct cfdriver pnozz_cd; | | 167 | extern struct cfdriver pnozz_cd; |
171 | | | 168 | |
172 | static dev_type_open(p9100open); | | 169 | static dev_type_open(p9100open); |
173 | static dev_type_ioctl(p9100ioctl); | | 170 | static dev_type_ioctl(p9100ioctl); |
174 | static dev_type_mmap(p9100mmap); | | 171 | static dev_type_mmap(p9100mmap); |
175 | | | 172 | |
176 | const struct cdevsw pnozz_cdevsw = { | | 173 | const struct cdevsw pnozz_cdevsw = { |
177 | p9100open, nullclose, noread, nowrite, p9100ioctl, | | 174 | p9100open, nullclose, noread, nowrite, p9100ioctl, |
178 | nostop, notty, nopoll, p9100mmap, nokqfilter, | | 175 | nostop, notty, nopoll, p9100mmap, nokqfilter, |
179 | }; | | 176 | }; |
180 | | | 177 | |
181 | /* frame buffer generic driver */ | | 178 | /* frame buffer generic driver */ |
182 | static struct fbdriver p9100fbdriver = { | | 179 | static struct fbdriver p9100fbdriver = { |
183 | p9100unblank, p9100open, nullclose, p9100ioctl, nopoll, | | 180 | p9100unblank, p9100open, nullclose, p9100ioctl, nopoll, |
184 | p9100mmap, nokqfilter | | 181 | p9100mmap, nokqfilter |
185 | }; | | 182 | }; |
186 | | | 183 | |
187 | static void p9100loadcmap(struct p9100_softc *, int, int); | | 184 | static void p9100loadcmap(struct p9100_softc *, int, int); |
188 | static void p9100_set_video(struct p9100_softc *, int); | | 185 | static void p9100_set_video(struct p9100_softc *, int); |
189 | static int p9100_get_video(struct p9100_softc *); | | 186 | static int p9100_get_video(struct p9100_softc *); |
190 | static uint32_t p9100_ctl_read_4(struct p9100_softc *, bus_size_t); | | 187 | static uint32_t p9100_ctl_read_4(struct p9100_softc *, bus_size_t); |
191 | static void p9100_ctl_write_4(struct p9100_softc *, bus_size_t, uint32_t); | | 188 | static void p9100_ctl_write_4(struct p9100_softc *, bus_size_t, uint32_t); |
192 | static uint8_t p9100_ramdac_read(struct p9100_softc *, bus_size_t); | | 189 | static uint8_t p9100_ramdac_read(struct p9100_softc *, bus_size_t); |
193 | static void p9100_ramdac_write(struct p9100_softc *, bus_size_t, uint8_t); | | 190 | static void p9100_ramdac_write(struct p9100_softc *, bus_size_t, uint8_t); |
194 | | | 191 | |
195 | static uint8_t p9100_ramdac_read_ctl(struct p9100_softc *, int); | | 192 | static uint8_t p9100_ramdac_read_ctl(struct p9100_softc *, int); |
196 | #if NTCTRL > 0 | | 193 | #if NTCTRL > 0 |
197 | static void p9100_ramdac_write_ctl(struct p9100_softc *, int, uint8_t); | | 194 | static void p9100_ramdac_write_ctl(struct p9100_softc *, int, uint8_t); |
198 | #endif | | 195 | #endif |
199 | | | 196 | |
200 | static void p9100_init_engine(struct p9100_softc *); | | 197 | static void p9100_init_engine(struct p9100_softc *); |
201 | static int p9100_set_depth(struct p9100_softc *, int); | | 198 | static int p9100_set_depth(struct p9100_softc *, int); |
202 | | | 199 | |
203 | #if NWSDISPLAY > 0 | | 200 | #if NWSDISPLAY > 0 |
204 | static void p9100_sync(struct p9100_softc *); | | 201 | static void p9100_sync(struct p9100_softc *); |
205 | static void p9100_bitblt(void *, int, int, int, int, int, int, uint32_t); | | 202 | static void p9100_bitblt(void *, int, int, int, int, int, int, uint32_t); |
206 | static void p9100_rectfill(void *, int, int, int, int, uint32_t); | | 203 | static void p9100_rectfill(void *, int, int, int, int, uint32_t); |
207 | static void p9100_clearscreen(struct p9100_softc *); | | 204 | static void p9100_clearscreen(struct p9100_softc *); |
208 | | | 205 | |
209 | static void p9100_setup_mono(struct p9100_softc *, int, int, int, int, | | 206 | static void p9100_setup_mono(struct p9100_softc *, int, int, int, int, |
210 | uint32_t, uint32_t); | | 207 | uint32_t, uint32_t); |
211 | static void p9100_feed_line(struct p9100_softc *, int, uint8_t *); | | 208 | static void p9100_feed_line(struct p9100_softc *, int, uint8_t *); |
212 | static void p9100_set_color_reg(struct p9100_softc *, int, int32_t); | | 209 | static void p9100_set_color_reg(struct p9100_softc *, int, int32_t); |
213 | | | 210 | |
214 | static void p9100_copycols(void *, int, int, int, int); | | 211 | static void p9100_copycols(void *, int, int, int, int); |
215 | static void p9100_erasecols(void *, int, int, int, long); | | 212 | static void p9100_erasecols(void *, int, int, int, long); |
216 | static void p9100_copyrows(void *, int, int, int); | | 213 | static void p9100_copyrows(void *, int, int, int); |
217 | static void p9100_eraserows(void *, int, int, long); | | 214 | static void p9100_eraserows(void *, int, int, long); |
218 | /*static int p9100_mapchar(void *, int, u_int *);*/ | | 215 | /*static int p9100_mapchar(void *, int, u_int *);*/ |
219 | static void p9100_putchar(void *, int, int, u_int, long); | | 216 | static void p9100_putchar(void *, int, int, u_int, long); |
220 | static void p9100_cursor(void *, int, int, int); | | 217 | static void p9100_cursor(void *, int, int, int); |
221 | static int p9100_allocattr(void *, int, int, int, long *); | | 218 | static int p9100_allocattr(void *, int, int, int, long *); |
222 | | | 219 | |
223 | /*static void p9100_scroll(void *, void *, int);*/ | | | |
224 | | | | |
225 | static int p9100_putcmap(struct p9100_softc *, struct wsdisplay_cmap *); | | 220 | static int p9100_putcmap(struct p9100_softc *, struct wsdisplay_cmap *); |
226 | static int p9100_getcmap(struct p9100_softc *, struct wsdisplay_cmap *); | | 221 | static int p9100_getcmap(struct p9100_softc *, struct wsdisplay_cmap *); |
227 | static int p9100_ioctl(void *, void *, u_long, void *, int, struct lwp *); | | 222 | static int p9100_ioctl(void *, void *, u_long, void *, int, struct lwp *); |
228 | static paddr_t p9100_mmap(void *, void *, off_t, int); | | 223 | static paddr_t p9100_mmap(void *, void *, off_t, int); |
229 | | | 224 | |
230 | /*static int p9100_load_font(void *, void *, struct wsdisplay_font *);*/ | | 225 | /*static int p9100_load_font(void *, void *, struct wsdisplay_font *);*/ |
231 | | | 226 | |
232 | static void p9100_init_screen(void *, struct vcons_screen *, int, | | 227 | static void p9100_init_screen(void *, struct vcons_screen *, int, |
233 | long *); | | 228 | long *); |
234 | #endif | | 229 | #endif |
235 | | | 230 | |
236 | static void p9100_init_cursor(struct p9100_softc *); | | 231 | static void p9100_init_cursor(struct p9100_softc *); |
237 | | | 232 | |
238 | static void p9100_set_fbcursor(struct p9100_softc *); | | 233 | static void p9100_set_fbcursor(struct p9100_softc *); |
239 | static void p9100_setcursorcmap(struct p9100_softc *); | | 234 | static void p9100_setcursorcmap(struct p9100_softc *); |
240 | static void p9100_loadcursor(struct p9100_softc *); | | 235 | static void p9100_loadcursor(struct p9100_softc *); |
241 | | | 236 | |
242 | #if 0 | | 237 | #if 0 |
243 | static int p9100_intr(void *); | | 238 | static int p9100_intr(void *); |
244 | #endif | | 239 | #endif |
245 | | | 240 | |
246 | /* power management stuff */ | | 241 | /* power management stuff */ |
247 | static void p9100_power_hook(int, void *); | | 242 | static bool p9100_suspend(device_t PMF_FN_PROTO); |
| | | 243 | static bool p9100_resume(device_t PMF_FN_PROTO); |
248 | | | 244 | |
249 | #if NTCTRL > 0 | | 245 | #if NTCTRL > 0 |
250 | static void p9100_set_extvga(void *, int); | | 246 | static void p9100_set_extvga(void *, int); |
251 | #endif | | 247 | #endif |
252 | | | 248 | |
253 | #if NWSDISPLAY > 0 | | 249 | #if NWSDISPLAY > 0 |
254 | struct wsdisplay_accessops p9100_accessops = { | | 250 | struct wsdisplay_accessops p9100_accessops = { |
255 | p9100_ioctl, | | 251 | p9100_ioctl, |
256 | p9100_mmap, | | 252 | p9100_mmap, |
257 | NULL, /* vcons_alloc_screen */ | | 253 | NULL, /* vcons_alloc_screen */ |
258 | NULL, /* vcons_free_screen */ | | 254 | NULL, /* vcons_free_screen */ |
259 | NULL, /* vcons_show_screen */ | | 255 | NULL, /* vcons_show_screen */ |
260 | NULL, /* load_font */ | | 256 | NULL, /* load_font */ |
261 | NULL, /* polls */ | | 257 | NULL, /* polls */ |
262 | NULL, /* scroll */ | | 258 | NULL, /* scroll */ |
263 | }; | | 259 | }; |
264 | #endif | | 260 | #endif |
265 | | | 261 | |
266 | #define PNOZZ_LATCH(sc, off) if(sc->sc_last_offset == (off & 0xffffff80)) { \ | | 262 | #define PNOZZ_LATCH(sc, off) if(sc->sc_last_offset == (off & 0xffffff80)) { \ |
267 | sc->sc_junk = bus_space_read_4(sc->sc_bustag, sc->sc_fb_memh, \ | | 263 | sc->sc_junk = bus_space_read_4(sc->sc_bustag, sc->sc_fb_memh, \ |
268 | off); \ | | 264 | off); \ |
269 | sc->sc_last_offset = off & 0xffffff80; } | | 265 | sc->sc_last_offset = off & 0xffffff80; } |
270 | | | 266 | |
271 | /* | | 267 | /* |
272 | * Match a p9100. | | 268 | * Match a p9100. |
273 | */ | | 269 | */ |
274 | static int | | 270 | static int |
275 | p9100_sbus_match(device_t parent, cfdata_t cf, void *aux) | | 271 | p9100_sbus_match(device_t parent, cfdata_t cf, void *aux) |
276 | { | | 272 | { |
277 | struct sbus_attach_args *sa = aux; | | 273 | struct sbus_attach_args *sa = aux; |
278 | | | 274 | |
279 | if (strcmp("p9100", sa->sa_name) == 0) | | 275 | if (strcmp("p9100", sa->sa_name) == 0) |
280 | return 100; | | 276 | return 100; |
281 | return 0; | | 277 | return 0; |
282 | } | | 278 | } |
283 | | | 279 | |
284 | | | 280 | |
285 | /* | | 281 | /* |
286 | * Attach a display. We need to notice if it is the console, too. | | 282 | * Attach a display. We need to notice if it is the console, too. |
287 | */ | | 283 | */ |
288 | static void | | 284 | static void |
289 | p9100_sbus_attach(device_t parent, device_t self, void *args) | | 285 | p9100_sbus_attach(device_t parent, device_t self, void *args) |
290 | { | | 286 | { |
291 | struct p9100_softc *sc = device_private(self); | | 287 | struct p9100_softc *sc = device_private(self); |
292 | struct sbus_attach_args *sa = args; | | 288 | struct sbus_attach_args *sa = args; |
293 | struct fbdevice *fb = &sc->sc_fb; | | 289 | struct fbdevice *fb = &sc->sc_fb; |
294 | int isconsole; | | 290 | int isconsole; |
295 | int node = sa->sa_node; | | 291 | int node = sa->sa_node; |
296 | int i, j; | | 292 | int i, j; |
297 | uint8_t ver; | | 293 | uint8_t ver; |
298 | | | 294 | |
299 | #if NWSDISPLAY > 0 | | 295 | #if NWSDISPLAY > 0 |
300 | struct wsemuldisplaydev_attach_args aa; | | 296 | struct wsemuldisplaydev_attach_args aa; |
301 | struct rasops_info *ri; | | 297 | struct rasops_info *ri; |
302 | unsigned long defattr; | | 298 | unsigned long defattr; |
303 | #endif | | 299 | #endif |
304 | | | 300 | |
305 | sc->sc_last_offset = 0xffffffff; | | 301 | sc->sc_last_offset = 0xffffffff; |
306 | sc->sc_dev = self; | | 302 | sc->sc_dev = self; |
307 | | | 303 | |
308 | /* | | 304 | /* |
309 | * When the ROM has mapped in a p9100 display, the address | | 305 | * When the ROM has mapped in a p9100 display, the address |
310 | * maps only the video RAM, so in any case we have to map the | | 306 | * maps only the video RAM, so in any case we have to map the |
311 | * registers ourselves. We only need the video RAM if we are | | 307 | * registers ourselves. |
312 | * going to print characters via rconsole. | | | |
313 | */ | | 308 | */ |
314 | | | 309 | |
315 | if (sa->sa_npromvaddrs != 0) | | 310 | if (sa->sa_npromvaddrs != 0) |
316 | fb->fb_pixels = (void *)sa->sa_promvaddrs[0]; | | 311 | fb->fb_pixels = (void *)sa->sa_promvaddrs[0]; |
317 | | | 312 | |
318 | /* Remember cookies for p9100_mmap() */ | | 313 | /* Remember cookies for p9100_mmap() */ |
319 | sc->sc_bustag = sa->sa_bustag; | | 314 | sc->sc_bustag = sa->sa_bustag; |
320 | | | 315 | |
321 | sc->sc_ctl_paddr = sbus_bus_addr(sa->sa_bustag, | | 316 | sc->sc_ctl_paddr = sbus_bus_addr(sa->sa_bustag, |
322 | sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base); | | 317 | sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base); |
323 | sc->sc_ctl_psize = 0x8000;/*(bus_size_t)sa->sa_reg[0].oa_size;*/ | | 318 | sc->sc_ctl_psize = 0x8000;/*(bus_size_t)sa->sa_reg[0].oa_size;*/ |
324 | | | 319 | |
325 | sc->sc_fb_paddr = sbus_bus_addr(sa->sa_bustag, | | 320 | sc->sc_fb_paddr = sbus_bus_addr(sa->sa_bustag, |
326 | sa->sa_reg[2].oa_space, sa->sa_reg[2].oa_base); | | 321 | sa->sa_reg[2].oa_space, sa->sa_reg[2].oa_base); |
327 | sc->sc_fb_psize = (bus_size_t)sa->sa_reg[2].oa_size; | | 322 | sc->sc_fb_psize = (bus_size_t)sa->sa_reg[2].oa_size; |
328 | | | 323 | |
329 | if (sbus_bus_map(sc->sc_bustag, | | 324 | if (sbus_bus_map(sc->sc_bustag, |
330 | sa->sa_reg[0].oa_space, | | 325 | sa->sa_reg[0].oa_space, |
331 | sa->sa_reg[0].oa_base, | | 326 | sa->sa_reg[0].oa_base, |
332 | /* | | 327 | /* |
333 | * XXX for some reason the SBus resources don't cover | | 328 | * XXX for some reason the SBus resources don't cover |
334 | * all registers, so we just map what we need | | 329 | * all registers, so we just map what we need |
335 | */ | | 330 | */ |
336 | 0x8000, | | 331 | 0x8000, |
337 | 0, &sc->sc_ctl_memh) != 0) { | | 332 | 0, &sc->sc_ctl_memh) != 0) { |
338 | printf("%s: cannot map control registers\n", | | 333 | printf("%s: cannot map control registers\n", |
339 | self->dv_xname); | | 334 | self->dv_xname); |
340 | return; | | 335 | return; |
341 | } | | 336 | } |
342 | | | 337 | |
| | | 338 | /* |
| | | 339 | * we need to map the framebuffer even though we never write to it, |
| | | 340 | * thanks to some weirdness in the SPARCbook's SBus glue for the |
| | | 341 | * P9100 - all register accesses need to be 'latched in' whenever we |
| | | 342 | * go to another 0x80 aligned 'page' by reading the framebuffer at the |
| | | 343 | * same offset |
| | | 344 | */ |
343 | if (fb->fb_pixels == NULL) { | | 345 | if (fb->fb_pixels == NULL) { |
344 | if (sbus_bus_map(sc->sc_bustag, | | 346 | if (sbus_bus_map(sc->sc_bustag, |
345 | sa->sa_reg[2].oa_space, | | 347 | sa->sa_reg[2].oa_space, |
346 | sa->sa_reg[2].oa_base, | | 348 | sa->sa_reg[2].oa_base, |
347 | sc->sc_fb_psize, | | 349 | sc->sc_fb_psize, |
348 | BUS_SPACE_MAP_LINEAR, &sc->sc_fb_memh) != 0) { | | 350 | BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE, |
| | | 351 | &sc->sc_fb_memh) != 0) { |
349 | printf("%s: cannot map framebuffer\n", | | 352 | printf("%s: cannot map framebuffer\n", |
350 | self->dv_xname); | | 353 | self->dv_xname); |
351 | return; | | 354 | return; |
352 | } | | 355 | } |
353 | fb->fb_pixels = (char *)sc->sc_fb_memh; | | 356 | fb->fb_pixels = (char *)sc->sc_fb_memh; |
354 | } else { | | 357 | } else { |
355 | sc->sc_fb_memh = (bus_space_handle_t) fb->fb_pixels; | | 358 | sc->sc_fb_memh = (bus_space_handle_t) fb->fb_pixels; |
356 | } | | 359 | } |
357 | sc->sc_width = prom_getpropint(node, "width", 800); | | 360 | sc->sc_width = prom_getpropint(node, "width", 800); |
358 | sc->sc_height = prom_getpropint(node, "height", 600); | | 361 | sc->sc_height = prom_getpropint(node, "height", 600); |
359 | sc->sc_depth = prom_getpropint(node, "depth", 8) >> 3; | | 362 | sc->sc_depth = prom_getpropint(node, "depth", 8) >> 3; |
360 | | | 363 | |
361 | sc->sc_stride = prom_getpropint(node, "linebytes", | | 364 | sc->sc_stride = prom_getpropint(node, "linebytes", |
362 | sc->sc_width * sc->sc_depth); | | 365 | sc->sc_width * sc->sc_depth); |
363 | | | 366 | |
364 | fb->fb_driver = &p9100fbdriver; | | 367 | fb->fb_driver = &p9100fbdriver; |
365 | fb->fb_device = sc->sc_dev; | | 368 | fb->fb_device = sc->sc_dev; |
366 | fb->fb_flags = device_cfdata(sc->sc_dev)->cf_flags & FB_USERMASK; | | 369 | fb->fb_flags = device_cfdata(sc->sc_dev)->cf_flags & FB_USERMASK; |
367 | #ifdef PNOZZ_EMUL_CG3 | | 370 | #ifdef PNOZZ_EMUL_CG3 |
368 | fb->fb_type.fb_type = FBTYPE_SUN3COLOR; | | 371 | fb->fb_type.fb_type = FBTYPE_SUN3COLOR; |
369 | #else | | 372 | #else |
370 | fb->fb_type.fb_type = FBTYPE_P9100; | | 373 | fb->fb_type.fb_type = FBTYPE_P9100; |
371 | #endif | | 374 | #endif |
372 | fb->fb_pixels = NULL; | | 375 | fb->fb_pixels = NULL; |
373 | | | 376 | |
374 | sc->sc_mode = WSDISPLAYIO_MODE_EMUL; | | 377 | sc->sc_mode = WSDISPLAYIO_MODE_EMUL; |
375 | | | 378 | |
376 | isconsole = fb_is_console(node); | | 379 | isconsole = fb_is_console(node); |
377 | #if 0 | | 380 | #if 0 |
378 | if (!isconsole) { | | 381 | if (!isconsole) { |
379 | aprint_normal("\n"); | | 382 | aprint_normal("\n"); |
380 | aprint_error_dev(self, "fatal error: PROM didn't configure device\n"); | | 383 | aprint_error_dev(self, "fatal error: PROM didn't configure device\n"); |
381 | return; | | 384 | return; |
382 | } | | 385 | } |
383 | #endif | | 386 | #endif |
384 | | | 387 | |
385 | /* | | | |
386 | * When the ROM has mapped in a p9100 display, the address | | | |
387 | * maps only the video RAM, so in any case we have to map the | | | |
388 | * registers ourselves. We only need the video RAM if we are | | | |
389 | * going to print characters via rconsole. | | | |
390 | */ | | | |
391 | if (sbus_bus_map(sc->sc_bustag, | | | |
392 | sa->sa_reg[0].oa_space, | | | |
393 | sa->sa_reg[0].oa_base, | | | |
394 | /* | | | |
395 | * XXX for some reason the SBus resources don't cover | | | |
396 | * all registers, so we just map what we need | | | |
397 | */ | | | |
398 | /*sc->sc_ctl_psize*/ 0x8000, | | | |
399 | /*BUS_SPACE_MAP_LINEAR*/0, &sc->sc_ctl_memh) != 0) { | | | |
400 | aprint_error_dev(self, "cannot map control registers\n"); | | | |
401 | return; | | | |
402 | } | | | |
403 | | | | |
404 | if (sa->sa_npromvaddrs != 0) | | | |
405 | fb->fb_pixels = (void *)sa->sa_promvaddrs[0]; | | | |
406 | | | | |
407 | if (fb->fb_pixels == NULL) { | | | |
408 | if (sbus_bus_map(sc->sc_bustag, | | | |
409 | sa->sa_reg[2].oa_space, | | | |
410 | sa->sa_reg[2].oa_base, | | | |
411 | sc->sc_fb_psize, | | | |
412 | BUS_SPACE_MAP_LINEAR, &sc->sc_fb_memh) != 0) { | | | |
413 | aprint_error_dev(self, "cannot map framebuffer\n"); | | | |
414 | return; | | | |
415 | } | | | |
416 | fb->fb_pixels = (char *)sc->sc_fb_memh; | | | |
417 | } else { | | | |
418 | sc->sc_fb_memh = (bus_space_handle_t) fb->fb_pixels; | | | |
419 | } | | | |
420 | | | | |
421 | #if 0 | | | |
422 | /* | | | |
423 | * we set our own depth and OBP won't hand us anything else than 8 bit | | | |
424 | * anyway | | | |
425 | */ | | | |
426 | i = p9100_ctl_read_4(sc, 0x0004); | | | |
427 | switch ((i >> 26) & 7) { | | | |
428 | case 5: | | | |
429 | fb->fb_type.fb_depth = 32; | | | |
430 | sc->sc_depth = 4; | | | |
431 | sc->sc_depthshift = 2; | | | |
432 | break; | | | |
433 | case 7: | | | |
434 | fb->fb_type.fb_depth = 24; | | | |
435 | /* bitch and moan */ | | | |
436 | break; | | | |
437 | case 3: | | | |
438 | fb->fb_type.fb_depth = 16; | | | |
439 | sc->sc_depth = 2; | | | |
440 | sc->sc_depthshift = 1; | | | |
441 | break; | | | |
442 | case 2: | | | |
443 | fb->fb_type.fb_depth = 8; | | | |
444 | sc->sc_depth = 1; | | | |
445 | sc->sc_depthshift = 0; | | | |
446 | break; | | | |
447 | default: { | | | |
448 | panic("pnozz: can't determine screen depth (0x%02x)", i); | | | |
449 | } | | | |
450 | } | | | |
451 | #else | | | |
452 | fb->fb_type.fb_depth = 8; | | 388 | fb->fb_type.fb_depth = 8; |
453 | sc->sc_depth = 1; | | 389 | sc->sc_depth = 1; |
454 | sc->sc_depthshift = 0; | | 390 | sc->sc_depthshift = 0; |
455 | #endif | | | |
456 | | | 391 | |
457 | /* check the RAMDAC */ | | 392 | /* check the RAMDAC */ |
458 | ver = p9100_ramdac_read_ctl(sc, DAC_VERSION); | | 393 | ver = p9100_ramdac_read_ctl(sc, DAC_VERSION); |
459 | | | 394 | |
460 | p9100_init_engine(sc); | | 395 | p9100_init_engine(sc); |
461 | p9100_set_depth(sc, 8); | | 396 | p9100_set_depth(sc, 8); |
462 | | | 397 | |
463 | fb_setsize_obp(fb, fb->fb_type.fb_depth, sc->sc_width, sc->sc_height, | | 398 | fb_setsize_obp(fb, fb->fb_type.fb_depth, sc->sc_width, sc->sc_height, |
464 | node); | | 399 | node); |
465 | | | 400 | |
466 | sbus_establish(&sc->sc_sd, sc->sc_dev); | | 401 | sbus_establish(&sc->sc_sd, sc->sc_dev); |
467 | #if 0 | | 402 | #if 0 |
468 | bus_intr_establish(sc->sc_bustag, sa->sa_pri, IPL_BIO, | | 403 | bus_intr_establish(sc->sc_bustag, sa->sa_pri, IPL_BIO, |
469 | p9100_intr, sc); | | 404 | p9100_intr, sc); |
470 | #endif | | 405 | #endif |
471 | | | 406 | |
472 | fb->fb_type.fb_cmsize = prom_getpropint(node, "cmsize", 256); | | 407 | fb->fb_type.fb_cmsize = prom_getpropint(node, "cmsize", 256); |
473 | if ((1 << fb->fb_type.fb_depth) != fb->fb_type.fb_cmsize) | | 408 | if ((1 << fb->fb_type.fb_depth) != fb->fb_type.fb_cmsize) |
474 | printf(", %d entry colormap", fb->fb_type.fb_cmsize); | | 409 | printf(", %d entry colormap", fb->fb_type.fb_cmsize); |
475 | | | 410 | |
476 | /* Initialize the default color map. */ | | 411 | /* Initialize the default color map. */ |
477 | j = 0; | | 412 | j = 0; |
478 | for (i = 0; i < 256; i++) { | | 413 | for (i = 0; i < 256; i++) { |
479 | sc->sc_cmap.cm_map[i][0] = rasops_cmap[j]; | | 414 | sc->sc_cmap.cm_map[i][0] = rasops_cmap[j]; |
480 | j++; | | 415 | j++; |
481 | sc->sc_cmap.cm_map[i][1] = rasops_cmap[j]; | | 416 | sc->sc_cmap.cm_map[i][1] = rasops_cmap[j]; |
482 | j++; | | 417 | j++; |
483 | sc->sc_cmap.cm_map[i][2] = rasops_cmap[j]; | | 418 | sc->sc_cmap.cm_map[i][2] = rasops_cmap[j]; |
484 | j++; | | 419 | j++; |
485 | } | | 420 | } |
486 | p9100loadcmap(sc, 0, 256); | | 421 | p9100loadcmap(sc, 0, 256); |
487 | | | 422 | |
488 | /* make sure we are not blanked */ | | 423 | /* make sure we are not blanked */ |
489 | if (isconsole) | | 424 | if (isconsole) |
490 | p9100_set_video(sc, 1); | | 425 | p9100_set_video(sc, 1); |
491 | | | 426 | |
492 | if (shutdownhook_establish(p9100_shutdown, sc) == NULL) { | | 427 | /* register with power management */ |
493 | panic("%s: could not establish shutdown hook", | | 428 | sc->sc_video = 1; |
| | | 429 | sc->sc_powerstate = PWR_RESUME; |
| | | 430 | if (!pmf_device_register(self, p9100_suspend, p9100_resume)) { |
| | | 431 | panic("%s: could not register with PMF", |
494 | device_xname(sc->sc_dev)); | | 432 | device_xname(sc->sc_dev)); |
495 | } | | 433 | } |
496 | | | 434 | |
497 | if (isconsole) { | | 435 | if (isconsole) { |
498 | printf(" (console)\n"); | | 436 | printf(" (console)\n"); |
499 | #ifdef RASTERCONSOLE | | 437 | #ifdef RASTERCONSOLE |
500 | /*p9100loadcmap(sc, 255, 1);*/ | | 438 | /*p9100loadcmap(sc, 255, 1);*/ |
501 | fbrcons_init(fb); | | 439 | fbrcons_init(fb); |
502 | #endif | | 440 | #endif |
503 | } else | | 441 | } else |
504 | printf("\n"); | | 442 | printf("\n"); |
505 | | | 443 | |
506 | #if NWSDISPLAY > 0 | | 444 | #if NWSDISPLAY > 0 |
507 | wsfont_init(); | | 445 | wsfont_init(); |
508 | | | 446 | |
509 | vcons_init(&sc->vd, sc, &p9100_defscreendesc, &p9100_accessops); | | 447 | vcons_init(&sc->vd, sc, &p9100_defscreendesc, &p9100_accessops); |
510 | sc->vd.init_screen = p9100_init_screen; | | 448 | sc->vd.init_screen = p9100_init_screen; |
511 | | | 449 | |
512 | vcons_init_screen(&sc->vd, &p9100_console_screen, 1, &defattr); | | 450 | vcons_init_screen(&sc->vd, &p9100_console_screen, 1, &defattr); |
513 | p9100_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; | | 451 | p9100_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; |
514 | | | 452 | |
515 | sc->sc_bg = (defattr >> 16) & 0xff; | | 453 | sc->sc_bg = (defattr >> 16) & 0xff; |
516 | p9100_clearscreen(sc); | | 454 | p9100_clearscreen(sc); |
517 | | | 455 | |
518 | ri = &p9100_console_screen.scr_ri; | | 456 | ri = &p9100_console_screen.scr_ri; |
519 | | | 457 | |
520 | p9100_defscreendesc.nrows = ri->ri_rows; | | 458 | p9100_defscreendesc.nrows = ri->ri_rows; |
521 | p9100_defscreendesc.ncols = ri->ri_cols; | | 459 | p9100_defscreendesc.ncols = ri->ri_cols; |
522 | p9100_defscreendesc.textops = &ri->ri_ops; | | 460 | p9100_defscreendesc.textops = &ri->ri_ops; |
523 | p9100_defscreendesc.capabilities = ri->ri_caps; | | 461 | p9100_defscreendesc.capabilities = ri->ri_caps; |
524 | | | 462 | |
525 | if(isconsole) { | | 463 | if(isconsole) { |
526 | wsdisplay_cnattach(&p9100_defscreendesc, ri, 0, 0, defattr); | | 464 | wsdisplay_cnattach(&p9100_defscreendesc, ri, 0, 0, defattr); |
527 | } | | 465 | } |
528 | | | 466 | |
529 | aa.console = isconsole; | | 467 | aa.console = isconsole; |
530 | aa.scrdata = &p9100_screenlist; | | 468 | aa.scrdata = &p9100_screenlist; |
531 | aa.accessops = &p9100_accessops; | | 469 | aa.accessops = &p9100_accessops; |
532 | aa.accesscookie = &sc->vd; | | 470 | aa.accesscookie = &sc->vd; |
533 | | | 471 | |
534 | config_found(self, &aa, wsemuldisplaydevprint); | | 472 | config_found(self, &aa, wsemuldisplaydevprint); |
535 | #endif | | 473 | #endif |
536 | fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes; | | 474 | fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes; |
537 | printf(": rev %d / %x, %dx%d, depth %d mem %x", | | 475 | printf("%s: rev %d / %x, %dx%d, depth %d mem %x\n", |
538 | (i & 7), ver, fb->fb_type.fb_width, fb->fb_type.fb_height, | | 476 | device_xname(self), |
539 | fb->fb_type.fb_depth, (unsigned int)sc->sc_fb_psize); | | 477 | (i & 7), ver, fb->fb_type.fb_width, fb->fb_type.fb_height, |
| | | 478 | fb->fb_type.fb_depth, (unsigned int)sc->sc_fb_psize); |
540 | /* cursor sprite handling */ | | 479 | /* cursor sprite handling */ |
541 | p9100_init_cursor(sc); | | 480 | p9100_init_cursor(sc); |
542 | | | 481 | |
543 | /* attach the fb */ | | 482 | /* attach the fb */ |
544 | fb_attach(fb, isconsole); | | 483 | fb_attach(fb, isconsole); |
545 | | | 484 | |
546 | /* register with power management */ | | | |
547 | sc->sc_video = 1; | | | |
548 | sc->sc_powerstate = PWR_RESUME; | | | |
549 | powerhook_establish(device_xname(sc->sc_dev), p9100_power_hook, sc); | | | |
550 | | | | |
551 | #if NTCTRL > 0 | | 485 | #if NTCTRL > 0 |
552 | /* register callback for external monitor status change */ | | 486 | /* register callback for external monitor status change */ |
553 | tadpole_register_callback(p9100_set_extvga, sc); | | 487 | tadpole_register_callback(p9100_set_extvga, sc); |
554 | #endif | | 488 | #endif |
555 | } | | 489 | } |
556 | | | 490 | |
557 | static void | | | |
558 | p9100_shutdown(void *arg) | | | |
559 | { | | | |
560 | struct p9100_softc *sc = arg; | | | |
561 | | | | |
562 | #ifdef RASTERCONSOLE | | | |
563 | sc->sc_cmap.cm_map[0][0] = 0xff; | | | |
564 | sc->sc_cmap.cm_map[0][1] = 0xff; | | | |
565 | sc->sc_cmap.cm_map[0][2] = 0xff; | | | |
566 | sc->sc_cmap.cm_map[1][0] = 0; | | | |
567 | sc->sc_cmap.cm_map[1][1] = 0; | | | |
568 | sc->sc_cmap.cm_map[1][2] = 0x00; | | | |
569 | p9100loadcmap(sc, 0, 2); | | | |
570 | sc->sc_cmap.cm_map[255][0] = 0; | | | |
571 | sc->sc_cmap.cm_map[255][1] = 0; | | | |
572 | sc->sc_cmap.cm_map[255][2] = 0; | | | |
573 | p9100loadcmap(sc, 255, 1); | | | |
574 | #endif | | | |
575 | p9100_set_video(sc, 1); | | | |
576 | } | | | |
577 | | | | |
578 | int | | 491 | int |
579 | p9100open(dev_t dev, int flags, int mode, struct lwp *l) | | 492 | p9100open(dev_t dev, int flags, int mode, struct lwp *l) |
580 | { | | 493 | { |
581 | int unit = minor(dev); | | 494 | int unit = minor(dev); |
582 | | | 495 | |
583 | if (device_lookup(&pnozz_cd, unit) == NULL) | | 496 | if (device_lookup(&pnozz_cd, unit) == NULL) |
584 | return (ENXIO); | | 497 | return (ENXIO); |
585 | return (0); | | 498 | return (0); |
586 | } | | 499 | } |
587 | | | 500 | |
588 | int | | 501 | int |
589 | p9100ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) | | 502 | p9100ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) |
590 | { | | 503 | { |
591 | struct p9100_softc *sc = device_lookup_private(&pnozz_cd, minor(dev)); | | 504 | struct p9100_softc *sc = device_lookup_private(&pnozz_cd, minor(dev)); |
592 | struct fbgattr *fba; | | 505 | struct fbgattr *fba; |
593 | int error, v; | | 506 | int error, v; |
594 | | | 507 | |
595 | switch (cmd) { | | 508 | switch (cmd) { |
596 | | | 509 | |
597 | case FBIOGTYPE: | | 510 | case FBIOGTYPE: |
598 | *(struct fbtype *)data = sc->sc_fb.fb_type; | | 511 | *(struct fbtype *)data = sc->sc_fb.fb_type; |
599 | break; | | 512 | break; |
600 | | | 513 | |
601 | case FBIOGATTR: | | 514 | case FBIOGATTR: |
602 | fba = (struct fbgattr *)data; | | 515 | fba = (struct fbgattr *)data; |
603 | fba->real_type = sc->sc_fb.fb_type.fb_type; | | 516 | fba->real_type = sc->sc_fb.fb_type.fb_type; |
604 | fba->owner = 0; /* XXX ??? */ | | 517 | fba->owner = 0; /* XXX ??? */ |
605 | fba->fbtype = sc->sc_fb.fb_type; | | 518 | fba->fbtype = sc->sc_fb.fb_type; |
606 | fba->sattr.flags = 0; | | 519 | fba->sattr.flags = 0; |
607 | fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; | | 520 | fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; |
608 | fba->sattr.dev_specific[0] = -1; | | 521 | fba->sattr.dev_specific[0] = -1; |
609 | fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; | | 522 | fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; |
610 | fba->emu_types[1] = -1; | | 523 | fba->emu_types[1] = -1; |
611 | break; | | 524 | break; |
612 | | | 525 | |
613 | case FBIOGETCMAP: | | 526 | case FBIOGETCMAP: |
614 | #define p ((struct fbcmap *)data) | | 527 | #define p ((struct fbcmap *)data) |
615 | return (bt_getcmap(p, &sc->sc_cmap, 256, 1)); | | 528 | return (bt_getcmap(p, &sc->sc_cmap, 256, 1)); |
616 | | | 529 | |
617 | case FBIOPUTCMAP: | | 530 | case FBIOPUTCMAP: |
618 | /* copy to software map */ | | 531 | /* copy to software map */ |
619 | error = bt_putcmap(p, &sc->sc_cmap, 256, 1); | | 532 | error = bt_putcmap(p, &sc->sc_cmap, 256, 1); |
620 | if (error) | | 533 | if (error) |
621 | return (error); | | 534 | return (error); |
622 | /* now blast them into the chip */ | | 535 | /* now blast them into the chip */ |
623 | /* XXX should use retrace interrupt */ | | 536 | /* XXX should use retrace interrupt */ |
624 | p9100loadcmap(sc, p->index, p->count); | | 537 | p9100loadcmap(sc, p->index, p->count); |
625 | #undef p | | 538 | #undef p |
626 | break; | | 539 | break; |
627 | | | 540 | |
628 | case FBIOGVIDEO: | | 541 | case FBIOGVIDEO: |
629 | *(int *)data = p9100_get_video(sc); | | 542 | *(int *)data = p9100_get_video(sc); |
630 | break; | | 543 | break; |
631 | | | 544 | |
632 | case FBIOSVIDEO: | | 545 | case FBIOSVIDEO: |
633 | p9100_set_video(sc, *(int *)data); | | 546 | p9100_set_video(sc, *(int *)data); |
634 | break; | | 547 | break; |
635 | | | 548 | |
636 | /* these are for both FBIOSCURSOR and FBIOGCURSOR */ | | 549 | /* these are for both FBIOSCURSOR and FBIOGCURSOR */ |
637 | #define p ((struct fbcursor *)data) | | 550 | #define p ((struct fbcursor *)data) |
638 | #define pc (&sc->sc_cursor) | | 551 | #define pc (&sc->sc_cursor) |
639 | | | 552 | |
640 | case FBIOGCURSOR: | | 553 | case FBIOGCURSOR: |
641 | p->set = FB_CUR_SETALL; /* close enough, anyway */ | | 554 | p->set = FB_CUR_SETALL; /* close enough, anyway */ |
642 | p->enable = pc->pc_enable; | | 555 | p->enable = pc->pc_enable; |
643 | p->pos = pc->pc_pos; | | 556 | p->pos = pc->pc_pos; |
644 | p->hot = pc->pc_hot; | | 557 | p->hot = pc->pc_hot; |
645 | p->size = pc->pc_size; | | 558 | p->size = pc->pc_size; |
646 | | | 559 | |
647 | if (p->image != NULL) { | | 560 | if (p->image != NULL) { |
648 | error = copyout(pc->pc_bits, p->image, 0x200); | | 561 | error = copyout(pc->pc_bits, p->image, 0x200); |
649 | if (error) | | 562 | if (error) |
650 | return error; | | 563 | return error; |
651 | error = copyout(&pc->pc_bits[0x80], p->mask, 0x200); | | 564 | error = copyout(&pc->pc_bits[0x80], p->mask, 0x200); |
652 | if (error) | | 565 | if (error) |
653 | return error; | | 566 | return error; |
654 | } | | 567 | } |
655 | | | 568 | |
656 | p->cmap.index = 0; | | 569 | p->cmap.index = 0; |
657 | p->cmap.count = 3; | | 570 | p->cmap.count = 3; |
658 | if (p->cmap.red != NULL) { | | 571 | if (p->cmap.red != NULL) { |
659 | copyout(pc->red, p->cmap.red, 3); | | 572 | copyout(pc->red, p->cmap.red, 3); |
660 | copyout(pc->green, p->cmap.green, 3); | | 573 | copyout(pc->green, p->cmap.green, 3); |
661 | copyout(pc->blue, p->cmap.blue, 3); | | 574 | copyout(pc->blue, p->cmap.blue, 3); |
662 | } | | 575 | } |
663 | break; | | 576 | break; |
664 | | | 577 | |
665 | case FBIOSCURSOR: | | 578 | case FBIOSCURSOR: |
666 | { | | 579 | { |
667 | int count; | | 580 | int count; |
668 | uint32_t image[0x80], mask[0x80]; | | 581 | uint32_t image[0x80], mask[0x80]; |
669 | uint8_t red[3], green[3], blue[3]; | | 582 | uint8_t red[3], green[3], blue[3]; |
670 | | | 583 | |
671 | v = p->set; | | 584 | v = p->set; |
672 | if (v & FB_CUR_SETCMAP) { | | 585 | if (v & FB_CUR_SETCMAP) { |
673 | error = copyin(p->cmap.red, red, 3); | | 586 | error = copyin(p->cmap.red, red, 3); |
674 | error |= copyin(p->cmap.green, green, 3); | | 587 | error |= copyin(p->cmap.green, green, 3); |
675 | error |= copyin(p->cmap.blue, blue, 3); | | 588 | error |= copyin(p->cmap.blue, blue, 3); |
676 | if (error) | | 589 | if (error) |
677 | return error; | | 590 | return error; |
678 | } | | 591 | } |
679 | if (v & FB_CUR_SETSHAPE) { | | 592 | if (v & FB_CUR_SETSHAPE) { |
680 | if (p->size.x > 64 || p->size.y > 64) | | 593 | if (p->size.x > 64 || p->size.y > 64) |
681 | return EINVAL; | | 594 | return EINVAL; |
682 | memset(&mask, 0, 0x200); | | 595 | memset(&mask, 0, 0x200); |
683 | memset(&image, 0, 0x200); | | 596 | memset(&image, 0, 0x200); |
684 | count = p->size.y * 8; | | 597 | count = p->size.y * 8; |
685 | error = copyin(p->image, image, count); | | 598 | error = copyin(p->image, image, count); |
686 | if (error) | | 599 | if (error) |
687 | return error; | | 600 | return error; |
688 | error = copyin(p->mask, mask, count); | | 601 | error = copyin(p->mask, mask, count); |
689 | if (error) | | 602 | if (error) |
690 | return error; | | 603 | return error; |
691 | } | | 604 | } |
692 | | | 605 | |
693 | /* parameters are OK; do it */ | | 606 | /* parameters are OK; do it */ |
694 | if (v & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)) { | | 607 | if (v & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)) { |
695 | if (v & FB_CUR_SETCUR) | | 608 | if (v & FB_CUR_SETCUR) |
696 | pc->pc_enable = p->enable; | | 609 | pc->pc_enable = p->enable; |
697 | if (v & FB_CUR_SETPOS) | | 610 | if (v & FB_CUR_SETPOS) |
698 | pc->pc_pos = p->pos; | | 611 | pc->pc_pos = p->pos; |
699 | if (v & FB_CUR_SETHOT) | | 612 | if (v & FB_CUR_SETHOT) |
700 | pc->pc_hot = p->hot; | | 613 | pc->pc_hot = p->hot; |
701 | p9100_set_fbcursor(sc); | | 614 | p9100_set_fbcursor(sc); |
702 | } | | 615 | } |
703 | | | 616 | |
704 | if (v & FB_CUR_SETCMAP) { | | 617 | if (v & FB_CUR_SETCMAP) { |
705 | memcpy(pc->red, red, 3); | | 618 | memcpy(pc->red, red, 3); |
706 | memcpy(pc->green, green, 3); | | 619 | memcpy(pc->green, green, 3); |
707 | memcpy(pc->blue, blue, 3); | | 620 | memcpy(pc->blue, blue, 3); |
708 | p9100_setcursorcmap(sc); | | 621 | p9100_setcursorcmap(sc); |
709 | } | | 622 | } |
710 | | | 623 | |
711 | if (v & FB_CUR_SETSHAPE) { | | 624 | if (v & FB_CUR_SETSHAPE) { |
712 | memcpy(pc->pc_bits, image, 0x200); | | 625 | memcpy(pc->pc_bits, image, 0x200); |
713 | memcpy(&pc->pc_bits[0x80], mask, 0x200); | | 626 | memcpy(&pc->pc_bits[0x80], mask, 0x200); |
714 | p9100_loadcursor(sc); | | 627 | p9100_loadcursor(sc); |
715 | } | | 628 | } |
716 | } | | 629 | } |
717 | break; | | 630 | break; |
718 | | | 631 | |
719 | #undef p | | 632 | #undef p |
720 | #undef cc | | 633 | #undef cc |
721 | | | 634 | |
722 | case FBIOGCURPOS: | | 635 | case FBIOGCURPOS: |
723 | *(struct fbcurpos *)data = sc->sc_cursor.pc_pos; | | 636 | *(struct fbcurpos *)data = sc->sc_cursor.pc_pos; |
724 | break; | | 637 | break; |
725 | | | 638 | |
726 | case FBIOSCURPOS: | | 639 | case FBIOSCURPOS: |
727 | sc->sc_cursor.pc_pos = *(struct fbcurpos *)data; | | 640 | sc->sc_cursor.pc_pos = *(struct fbcurpos *)data; |
728 | p9100_set_fbcursor(sc); | | 641 | p9100_set_fbcursor(sc); |
729 | break; | | 642 | break; |
730 | | | 643 | |
731 | case FBIOGCURMAX: | | 644 | case FBIOGCURMAX: |
732 | /* max cursor size is 64x64 */ | | 645 | /* max cursor size is 64x64 */ |
733 | ((struct fbcurpos *)data)->x = 64; | | 646 | ((struct fbcurpos *)data)->x = 64; |
734 | ((struct fbcurpos *)data)->y = 64; | | 647 | ((struct fbcurpos *)data)->y = 64; |
735 | break; | | 648 | break; |
736 | | | 649 | |
737 | default: | | 650 | default: |
738 | return (ENOTTY); | | 651 | return (ENOTTY); |
739 | } | | 652 | } |
740 | return (0); | | 653 | return (0); |
741 | } | | 654 | } |
742 | | | 655 | |
743 | static uint32_t | | 656 | static uint32_t |
744 | p9100_ctl_read_4(struct p9100_softc *sc, bus_size_t off) | | 657 | p9100_ctl_read_4(struct p9100_softc *sc, bus_size_t off) |
745 | { | | 658 | { |
746 | | | 659 | |
747 | PNOZZ_LATCH(sc, off); | | 660 | PNOZZ_LATCH(sc, off); |
748 | return bus_space_read_4(sc->sc_bustag, sc->sc_ctl_memh, off); | | 661 | return bus_space_read_4(sc->sc_bustag, sc->sc_ctl_memh, off); |
749 | } | | 662 | } |
750 | | | 663 | |
751 | static void | | 664 | static void |
752 | p9100_ctl_write_4(struct p9100_softc *sc, bus_size_t off, uint32_t v) | | 665 | p9100_ctl_write_4(struct p9100_softc *sc, bus_size_t off, uint32_t v) |
753 | { | | 666 | { |
754 | | | 667 | |
755 | PNOZZ_LATCH(sc, off); | | 668 | PNOZZ_LATCH(sc, off); |
756 | bus_space_write_4(sc->sc_bustag, sc->sc_ctl_memh, off, v); | | 669 | bus_space_write_4(sc->sc_bustag, sc->sc_ctl_memh, off, v); |
757 | } | | 670 | } |
758 | | | 671 | |
759 | /* initialize the drawing engine */ | | 672 | /* initialize the drawing engine */ |
760 | static void | | 673 | static void |
761 | p9100_init_engine(struct p9100_softc *sc) | | 674 | p9100_init_engine(struct p9100_softc *sc) |
762 | { | | 675 | { |
763 | /* reset clipping rectangles */ | | 676 | /* reset clipping rectangles */ |
764 | uint32_t rmax = ((sc->sc_width & 0x3fff) << 16) | | | 677 | uint32_t rmax = ((sc->sc_width & 0x3fff) << 16) | |
765 | (sc->sc_height & 0x3fff); | | 678 | (sc->sc_height & 0x3fff); |
766 | | | 679 | |
767 | sc->sc_last_offset = 0xffffffff; | | 680 | sc->sc_last_offset = 0xffffffff; |
768 | | | 681 | |
769 | p9100_ctl_write_4(sc, WINDOW_OFFSET, 0); | | 682 | p9100_ctl_write_4(sc, WINDOW_OFFSET, 0); |
770 | p9100_ctl_write_4(sc, WINDOW_MIN, 0); | | 683 | p9100_ctl_write_4(sc, WINDOW_MIN, 0); |
771 | p9100_ctl_write_4(sc, WINDOW_MAX, rmax); | | 684 | p9100_ctl_write_4(sc, WINDOW_MAX, rmax); |
772 | p9100_ctl_write_4(sc, BYTE_CLIP_MIN, 0); | | 685 | p9100_ctl_write_4(sc, BYTE_CLIP_MIN, 0); |
773 | p9100_ctl_write_4(sc, BYTE_CLIP_MAX, rmax); | | 686 | p9100_ctl_write_4(sc, BYTE_CLIP_MAX, rmax); |
774 | p9100_ctl_write_4(sc, DRAW_MODE, 0); | | 687 | p9100_ctl_write_4(sc, DRAW_MODE, 0); |
775 | p9100_ctl_write_4(sc, PLANE_MASK, 0xffffffff); | | 688 | p9100_ctl_write_4(sc, PLANE_MASK, 0xffffffff); |
776 | p9100_ctl_write_4(sc, PATTERN0, 0xffffffff); | | 689 | p9100_ctl_write_4(sc, PATTERN0, 0xffffffff); |
777 | p9100_ctl_write_4(sc, PATTERN1, 0xffffffff); | | 690 | p9100_ctl_write_4(sc, PATTERN1, 0xffffffff); |
778 | p9100_ctl_write_4(sc, PATTERN2, 0xffffffff); | | 691 | p9100_ctl_write_4(sc, PATTERN2, 0xffffffff); |
779 | p9100_ctl_write_4(sc, PATTERN3, 0xffffffff); | | 692 | p9100_ctl_write_4(sc, PATTERN3, 0xffffffff); |
780 | | | 693 | |
781 | } | | 694 | } |
782 | | | 695 | |
783 | /* we only need these in the wsdisplay case */ | | 696 | /* we only need these in the wsdisplay case */ |
784 | #if NWSDISPLAY > 0 | | 697 | #if NWSDISPLAY > 0 |
785 | | | 698 | |
786 | /* wait until the engine is idle */ | | 699 | /* wait until the engine is idle */ |
787 | static void | | 700 | static void |
788 | p9100_sync(struct p9100_softc *sc) | | 701 | p9100_sync(struct p9100_softc *sc) |
789 | { | | 702 | { |
790 | while((p9100_ctl_read_4(sc, ENGINE_STATUS) & | | 703 | while((p9100_ctl_read_4(sc, ENGINE_STATUS) & |
791 | (ENGINE_BUSY | BLITTER_BUSY)) != 0); | | 704 | (ENGINE_BUSY | BLITTER_BUSY)) != 0); |
792 | } | | 705 | } |
793 | | | 706 | |
794 | static void | | 707 | static void |
795 | p9100_set_color_reg(struct p9100_softc *sc, int reg, int32_t col) | | 708 | p9100_set_color_reg(struct p9100_softc *sc, int reg, int32_t col) |
796 | { | | 709 | { |
797 | uint32_t out; | | 710 | uint32_t out; |
798 | | | 711 | |
799 | switch(sc->sc_depth) | | 712 | switch(sc->sc_depth) |
800 | { | | 713 | { |
801 | case 1: /* 8 bit */ | | 714 | case 1: /* 8 bit */ |
802 | out = (col << 8) | col; | | 715 | out = (col << 8) | col; |
803 | out |= out << 16; | | 716 | out |= out << 16; |
804 | break; | | 717 | break; |
805 | case 2: /* 16 bit */ | | 718 | case 2: /* 16 bit */ |
806 | out = col | (col << 16); | | 719 | out = col | (col << 16); |
807 | break; | | 720 | break; |
808 | default: | | 721 | default: |
809 | out = col; | | 722 | out = col; |
810 | } | | 723 | } |
811 | p9100_ctl_write_4(sc, reg, out); | | 724 | p9100_ctl_write_4(sc, reg, out); |
812 | } | | 725 | } |
813 | | | 726 | |
814 | /* screen-to-screen blit */ | | 727 | /* screen-to-screen blit */ |
815 | static void | | 728 | static void |
816 | p9100_bitblt(void *cookie, int xs, int ys, int xd, int yd, int wi, | | 729 | p9100_bitblt(void *cookie, int xs, int ys, int xd, int yd, int wi, |
817 | int he, uint32_t rop) | | 730 | int he, uint32_t rop) |
818 | { | | 731 | { |
819 | struct p9100_softc *sc = cookie; | | 732 | struct p9100_softc *sc = cookie; |
820 | uint32_t src, dst, srcw, dstw; | | 733 | uint32_t src, dst, srcw, dstw; |
821 | | | 734 | |
822 | sc->sc_last_offset = 0xffffffff; | | 735 | sc->sc_last_offset = 0xffffffff; |
823 | | | 736 | |
824 | src = ((xs & 0x3fff) << 16) | (ys & 0x3fff); | | 737 | src = ((xs & 0x3fff) << 16) | (ys & 0x3fff); |
825 | dst = ((xd & 0x3fff) << 16) | (yd & 0x3fff); | | 738 | dst = ((xd & 0x3fff) << 16) | (yd & 0x3fff); |
826 | srcw = (((xs + wi - 1) & 0x3fff) << 16) | ((ys + he - 1) & 0x3fff); | | 739 | srcw = (((xs + wi - 1) & 0x3fff) << 16) | ((ys + he - 1) & 0x3fff); |
827 | dstw = (((xd + wi - 1) & 0x3fff) << 16) | ((yd + he - 1) & 0x3fff); | | 740 | dstw = (((xd + wi - 1) & 0x3fff) << 16) | ((yd + he - 1) & 0x3fff); |
828 | | | 741 | |
829 | p9100_sync(sc); | | 742 | p9100_sync(sc); |
830 | | | 743 | |
831 | p9100_ctl_write_4(sc, RASTER_OP, rop); | | 744 | p9100_ctl_write_4(sc, RASTER_OP, rop); |
832 | | | 745 | |
833 | p9100_ctl_write_4(sc, ABS_XY0, src << sc->sc_depthshift); | | 746 | p9100_ctl_write_4(sc, ABS_XY0, src << sc->sc_depthshift); |
834 | p9100_ctl_write_4(sc, ABS_XY1, srcw << sc->sc_depthshift); | | 747 | p9100_ctl_write_4(sc, ABS_XY1, srcw << sc->sc_depthshift); |
835 | p9100_ctl_write_4(sc, ABS_XY2, dst << sc->sc_depthshift); | | 748 | p9100_ctl_write_4(sc, ABS_XY2, dst << sc->sc_depthshift); |
836 | p9100_ctl_write_4(sc, ABS_XY3, dstw << sc->sc_depthshift); | | 749 | p9100_ctl_write_4(sc, ABS_XY3, dstw << sc->sc_depthshift); |
837 | | | 750 | |
838 | sc->sc_junk = p9100_ctl_read_4(sc, COMMAND_BLIT); | | 751 | sc->sc_junk = p9100_ctl_read_4(sc, COMMAND_BLIT); |
839 | } | | 752 | } |
840 | | | 753 | |
841 | /* solid rectangle fill */ | | 754 | /* solid rectangle fill */ |
842 | static void | | 755 | static void |
843 | p9100_rectfill(void *cookie, int xs, int ys, int wi, int he, uint32_t col) | | 756 | p9100_rectfill(void *cookie, int xs, int ys, int wi, int he, uint32_t col) |
844 | { | | 757 | { |
845 | struct p9100_softc *sc = cookie; | | 758 | struct p9100_softc *sc = cookie; |
846 | uint32_t src, srcw; | | 759 | uint32_t src, srcw; |
847 | | | 760 | |
848 | sc->sc_last_offset = 0xffffffff; | | 761 | sc->sc_last_offset = 0xffffffff; |
849 | | | 762 | |
850 | src = ((xs & 0x3fff) << 16) | (ys & 0x3fff); | | 763 | src = ((xs & 0x3fff) << 16) | (ys & 0x3fff); |
851 | srcw = (((xs + wi) & 0x3fff) << 16) | ((ys + he) & 0x3fff); | | 764 | srcw = (((xs + wi) & 0x3fff) << 16) | ((ys + he) & 0x3fff); |
852 | p9100_sync(sc); | | 765 | p9100_sync(sc); |
853 | p9100_set_color_reg(sc, FOREGROUND_COLOR, col); | | 766 | p9100_set_color_reg(sc, FOREGROUND_COLOR, col); |
854 | p9100_set_color_reg(sc, BACKGROUND_COLOR, col); | | 767 | p9100_set_color_reg(sc, BACKGROUND_COLOR, col); |
855 | p9100_ctl_write_4(sc, RASTER_OP, ROP_PAT); | | 768 | p9100_ctl_write_4(sc, RASTER_OP, ROP_PAT); |
856 | p9100_ctl_write_4(sc, COORD_INDEX, 0); | | 769 | p9100_ctl_write_4(sc, COORD_INDEX, 0); |
857 | p9100_ctl_write_4(sc, RECT_RTW_XY, src); | | 770 | p9100_ctl_write_4(sc, RECT_RTW_XY, src); |
858 | p9100_ctl_write_4(sc, RECT_RTW_XY, srcw); | | 771 | p9100_ctl_write_4(sc, RECT_RTW_XY, srcw); |
859 | sc->sc_junk = p9100_ctl_read_4(sc, COMMAND_QUAD); | | 772 | sc->sc_junk = p9100_ctl_read_4(sc, COMMAND_QUAD); |
860 | } | | 773 | } |
861 | | | 774 | |
862 | /* setup for mono->colour expansion */ | | 775 | /* setup for mono->colour expansion */ |
863 | static void | | 776 | static void |
864 | p9100_setup_mono(struct p9100_softc *sc, int x, int y, int wi, int he, | | 777 | p9100_setup_mono(struct p9100_softc *sc, int x, int y, int wi, int he, |
865 | uint32_t fg, uint32_t bg) | | 778 | uint32_t fg, uint32_t bg) |
866 | { | | 779 | { |
867 | | | 780 | |
868 | sc->sc_last_offset = 0xffffffff; | | 781 | sc->sc_last_offset = 0xffffffff; |
869 | | | 782 | |
870 | p9100_sync(sc); | | 783 | p9100_sync(sc); |
871 | /* | | 784 | /* |
872 | * this doesn't make any sense to me either, but for some reason the | | 785 | * this doesn't make any sense to me either, but for some reason the |
873 | * chip applies the foreground colour to 0 pixels | | 786 | * chip applies the foreground colour to 0 pixels |
874 | */ | | 787 | */ |
875 | | | 788 | |
876 | p9100_set_color_reg(sc,FOREGROUND_COLOR,bg); | | 789 | p9100_set_color_reg(sc,FOREGROUND_COLOR,bg); |
877 | p9100_set_color_reg(sc,BACKGROUND_COLOR,fg); | | 790 | p9100_set_color_reg(sc,BACKGROUND_COLOR,fg); |
878 | | | 791 | |
879 | p9100_ctl_write_4(sc, RASTER_OP, ROP_SRC); | | 792 | p9100_ctl_write_4(sc, RASTER_OP, ROP_SRC); |
880 | p9100_ctl_write_4(sc, ABS_X0, x); | | 793 | p9100_ctl_write_4(sc, ABS_X0, x); |
881 | p9100_ctl_write_4(sc, ABS_XY1, (x << 16) | (y & 0xFFFFL)); | | 794 | p9100_ctl_write_4(sc, ABS_XY1, (x << 16) | (y & 0xFFFFL)); |
882 | p9100_ctl_write_4(sc, ABS_X2, (x + wi)); | | 795 | p9100_ctl_write_4(sc, ABS_X2, (x + wi)); |
883 | p9100_ctl_write_4(sc, ABS_Y3, he); | | 796 | p9100_ctl_write_4(sc, ABS_Y3, he); |
884 | /* now feed the data into the chip */ | | 797 | /* now feed the data into the chip */ |
885 | sc->sc_mono_width = wi; | | 798 | sc->sc_mono_width = wi; |
886 | } | | 799 | } |
887 | | | 800 | |
888 | /* write monochrome data to the screen through the blitter */ | | 801 | /* write monochrome data to the screen through the blitter */ |
889 | static void | | 802 | static void |
890 | p9100_feed_line(struct p9100_softc *sc, int count, uint8_t *data) | | 803 | p9100_feed_line(struct p9100_softc *sc, int count, uint8_t *data) |
891 | { | | 804 | { |
892 | int i; | | 805 | int i; |
893 | uint32_t latch = 0, bork; | | 806 | uint32_t latch = 0, bork; |
894 | int shift = 24; | | 807 | int shift = 24; |
895 | int to_go = sc->sc_mono_width; | | 808 | int to_go = sc->sc_mono_width; |
896 | | | 809 | |
897 | PNOZZ_LATCH(sc, PIXEL_1); | | 810 | PNOZZ_LATCH(sc, PIXEL_1); |
898 | | | 811 | |
899 | for (i = 0; i < count; i++) { | | 812 | for (i = 0; i < count; i++) { |
900 | bork = data[i]; | | 813 | bork = data[i]; |
901 | latch |= (bork << shift); | | 814 | latch |= (bork << shift); |
902 | if (shift == 0) { | | 815 | if (shift == 0) { |
903 | /* check how many bits are significant */ | | 816 | /* check how many bits are significant */ |
904 | if (to_go > 31) { | | 817 | if (to_go > 31) { |
905 | bus_space_write_4(sc->sc_bustag, | | 818 | bus_space_write_4(sc->sc_bustag, |
906 | sc->sc_ctl_memh, | | 819 | sc->sc_ctl_memh, |
907 | (PIXEL_1 + (31 << 2)), latch); | | 820 | (PIXEL_1 + (31 << 2)), latch); |
908 | to_go -= 32; | | 821 | to_go -= 32; |
909 | } else | | 822 | } else |
910 | { | | 823 | { |
911 | bus_space_write_4(sc->sc_bustag, | | 824 | bus_space_write_4(sc->sc_bustag, |
912 | sc->sc_ctl_memh, | | 825 | sc->sc_ctl_memh, |
913 | (PIXEL_1 + ((to_go - 1) << 2)), latch); | | 826 | (PIXEL_1 + ((to_go - 1) << 2)), latch); |
914 | to_go = 0; | | 827 | to_go = 0; |
915 | } | | 828 | } |
916 | latch = 0; | | 829 | latch = 0; |
917 | shift = 24; | | 830 | shift = 24; |
918 | } else | | 831 | } else |
919 | shift -= 8; | | 832 | shift -= 8; |
920 | } | | 833 | } |
921 | if (shift != 24) | | 834 | if (shift != 24) |
922 | p9100_ctl_write_4(sc, (PIXEL_1 + ((to_go - 1) << 2)), latch); | | 835 | p9100_ctl_write_4(sc, (PIXEL_1 + ((to_go - 1) << 2)), latch); |
923 | } | | 836 | } |
924 | | | 837 | |
925 | static void | | 838 | static void |
926 | p9100_clearscreen(struct p9100_softc *sc) | | 839 | p9100_clearscreen(struct p9100_softc *sc) |
927 | { | | 840 | { |
928 | | | 841 | |
929 | p9100_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height, sc->sc_bg); | | 842 | p9100_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height, sc->sc_bg); |
930 | } | | 843 | } |
931 | #endif /* NWSDISPLAY > 0 */ | | 844 | #endif /* NWSDISPLAY > 0 */ |
932 | | | 845 | |
933 | static uint8_t | | 846 | static uint8_t |
934 | p9100_ramdac_read(struct p9100_softc *sc, bus_size_t off) | | 847 | p9100_ramdac_read(struct p9100_softc *sc, bus_size_t off) |
935 | { | | 848 | { |
936 | | | 849 | |
937 | sc->sc_junk = p9100_ctl_read_4(sc, PWRUP_CNFG); | | 850 | sc->sc_junk = p9100_ctl_read_4(sc, PWRUP_CNFG); |
938 | return ((bus_space_read_4(sc->sc_bustag, | | 851 | return ((bus_space_read_4(sc->sc_bustag, |
939 | sc->sc_ctl_memh, off) >> 16) & 0xff); | | 852 | sc->sc_ctl_memh, off) >> 16) & 0xff); |
940 | } | | 853 | } |
941 | | | 854 | |
942 | static void | | 855 | static void |
943 | p9100_ramdac_write(struct p9100_softc *sc, bus_size_t off, uint8_t v) | | 856 | p9100_ramdac_write(struct p9100_softc *sc, bus_size_t off, uint8_t v) |
944 | { | | 857 | { |
945 | | | 858 | |
946 | sc->sc_junk = p9100_ctl_read_4(sc, PWRUP_CNFG); | | 859 | sc->sc_junk = p9100_ctl_read_4(sc, PWRUP_CNFG); |
947 | bus_space_write_4(sc->sc_bustag, sc->sc_ctl_memh, off, | | 860 | bus_space_write_4(sc->sc_bustag, sc->sc_ctl_memh, off, |
948 | ((uint32_t)v) << 16); | | 861 | ((uint32_t)v) << 16); |
949 | } | | 862 | } |
950 | | | 863 | |
951 | static uint8_t | | 864 | static uint8_t |
952 | p9100_ramdac_read_ctl(struct p9100_softc *sc, int off) | | 865 | p9100_ramdac_read_ctl(struct p9100_softc *sc, int off) |
953 | { | | 866 | { |
954 | p9100_ramdac_write(sc, DAC_INDX_LO, off & 0xff); | | 867 | p9100_ramdac_write(sc, DAC_INDX_LO, off & 0xff); |
955 | p9100_ramdac_write(sc, DAC_INDX_HI, (off & 0xff00) >> 8); | | 868 | p9100_ramdac_write(sc, DAC_INDX_HI, (off & 0xff00) >> 8); |
956 | return p9100_ramdac_read(sc, DAC_INDX_DATA); | | 869 | return p9100_ramdac_read(sc, DAC_INDX_DATA); |
957 | } | | 870 | } |
958 | | | 871 | |
959 | #if NTCTRL > 0 | | 872 | #if NTCTRL > 0 |
960 | static void | | 873 | static void |
961 | p9100_ramdac_write_ctl(struct p9100_softc *sc, int off, uint8_t val) | | 874 | p9100_ramdac_write_ctl(struct p9100_softc *sc, int off, uint8_t val) |
962 | { | | 875 | { |
963 | p9100_ramdac_write(sc, DAC_INDX_LO, off & 0xff); | | 876 | p9100_ramdac_write(sc, DAC_INDX_LO, off & 0xff); |
964 | p9100_ramdac_write(sc, DAC_INDX_HI, (off & 0xff00) >> 8); | | 877 | p9100_ramdac_write(sc, DAC_INDX_HI, (off & 0xff00) >> 8); |
965 | p9100_ramdac_write(sc, DAC_INDX_DATA, val); | | 878 | p9100_ramdac_write(sc, DAC_INDX_DATA, val); |
966 | } | | 879 | } |
967 | #endif /* NTCTRL > 0 */ | | 880 | #endif /* NTCTRL > 0 */ |
968 | | | 881 | |
969 | /* | | 882 | /* |
970 | * Undo the effect of an FBIOSVIDEO that turns the video off. | | 883 | * Undo the effect of an FBIOSVIDEO that turns the video off. |
971 | */ | | 884 | */ |
972 | static void | | 885 | static void |
973 | p9100unblank(device_t dev) | | 886 | p9100unblank(device_t dev) |
974 | { | | 887 | { |
975 | struct p9100_softc *sc = device_private(dev); | | 888 | struct p9100_softc *sc = device_private(dev); |
976 | | | 889 | |
977 | p9100_set_video((struct p9100_softc *)dev, 1); | | 890 | p9100_set_video(sc, 1); |
978 | | | 891 | |
979 | /* | | 892 | /* |
980 | * Check if we're in terminal mode. If not force the console screen | | 893 | * Check if we're in terminal mode. If not force the console screen |
981 | * to front so we can see ddb, panic messages and so on | | 894 | * to front so we can see ddb, panic messages and so on |
982 | */ | | 895 | */ |
983 | if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) { | | 896 | if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) { |
984 | sc->sc_mode = WSDISPLAYIO_MODE_EMUL; | | 897 | sc->sc_mode = WSDISPLAYIO_MODE_EMUL; |
985 | if (sc->vd.active != &p9100_console_screen) { | | 898 | if (sc->vd.active != &p9100_console_screen) { |
986 | SCREEN_INVISIBLE(sc->vd.active); | | 899 | SCREEN_INVISIBLE(sc->vd.active); |
987 | sc->vd.active = &p9100_console_screen; | | 900 | sc->vd.active = &p9100_console_screen; |
988 | SCREEN_VISIBLE(&p9100_console_screen); | | 901 | SCREEN_VISIBLE(&p9100_console_screen); |
989 | } | | 902 | } |
990 | p9100_init_engine(sc); | | 903 | p9100_init_engine(sc); |
991 | p9100_set_depth(sc, 8); | | 904 | p9100_set_depth(sc, 8); |
992 | vcons_redraw_screen(&p9100_console_screen); | | 905 | vcons_redraw_screen(&p9100_console_screen); |
993 | } | | 906 | } |
994 | } | | 907 | } |
995 | | | 908 | |
996 | static void | | 909 | static void |
997 | p9100_set_video(struct p9100_softc *sc, int enable) | | 910 | p9100_set_video(struct p9100_softc *sc, int enable) |
998 | { | | 911 | { |
999 | u_int32_t v = p9100_ctl_read_4(sc, SCRN_RPNT_CTL_1); | | 912 | u_int32_t v = p9100_ctl_read_4(sc, SCRN_RPNT_CTL_1); |
1000 | | | 913 | |
1001 | if (enable) | | 914 | if (enable) |
1002 | v |= VIDEO_ENABLED; | | 915 | v |= VIDEO_ENABLED; |
1003 | else | | 916 | else |
1004 | v &= ~VIDEO_ENABLED; | | 917 | v &= ~VIDEO_ENABLED; |
1005 | p9100_ctl_write_4(sc, SCRN_RPNT_CTL_1, v); | | 918 | p9100_ctl_write_4(sc, SCRN_RPNT_CTL_1, v); |
1006 | #if NTCTRL > 0 | | 919 | #if NTCTRL > 0 |
1007 | /* Turn On/Off the TFT if we know how. | | 920 | /* Turn On/Off the TFT if we know how. |
1008 | */ | | 921 | */ |
1009 | tadpole_set_video(enable); | | 922 | tadpole_set_video(enable); |
1010 | #endif | | 923 | #endif |
1011 | } | | 924 | } |
1012 | | | 925 | |
1013 | static int | | 926 | static int |
1014 | p9100_get_video(struct p9100_softc *sc) | | 927 | p9100_get_video(struct p9100_softc *sc) |
1015 | { | | 928 | { |
1016 | return (p9100_ctl_read_4(sc, SCRN_RPNT_CTL_1) & VIDEO_ENABLED) != 0; | | 929 | return (p9100_ctl_read_4(sc, SCRN_RPNT_CTL_1) & VIDEO_ENABLED) != 0; |
1017 | } | | 930 | } |
1018 | | | 931 | |
1019 | static void | | 932 | static bool |
1020 | p9100_power_hook(int why, void *cookie) | | 933 | p9100_suspend(device_t dev PMF_FN_ARGS) |
1021 | { | | 934 | { |
1022 | struct p9100_softc *sc = cookie; | | 935 | struct p9100_softc *sc = device_private(dev); |
1023 | | | 936 | |
1024 | if (why == sc->sc_powerstate) | | 937 | if (sc->sc_powerstate == PWR_SUSPEND) |
1025 | return; | | 938 | return TRUE; |
1026 | | | 939 | |
1027 | switch(why) | | 940 | sc->sc_video = p9100_get_video(sc); |
1028 | { | | 941 | sc->sc_dac_power = p9100_ramdac_read_ctl(sc, DAC_POWER_MGT); |
1029 | case PWR_SUSPEND: | | 942 | p9100_ramdac_write_ctl(sc, DAC_POWER_MGT, |
1030 | case PWR_STANDBY: | | 943 | DAC_POWER_SCLK_DISABLE | |
1031 | sc->sc_video = p9100_get_video(sc); | | 944 | DAC_POWER_DDOT_DISABLE | |
1032 | p9100_set_video(sc, 0); | | 945 | DAC_POWER_SYNC_DISABLE | |
1033 | sc->sc_powerstate = why; | | 946 | DAC_POWER_ICLK_DISABLE | |
1034 | break; | | 947 | DAC_POWER_IPWR_DISABLE); |
1035 | case PWR_RESUME: | | 948 | p9100_set_video(sc, 0); |
1036 | p9100_set_video(sc, sc->sc_video); | | 949 | sc->sc_powerstate = PWR_SUSPEND; |
1037 | sc->sc_powerstate = why; | | 950 | return TRUE; |
1038 | break; | | 951 | } |
1039 | } | | 952 | |
| | | 953 | static bool |
| | | 954 | p9100_resume(device_t dev PMF_FN_ARGS) |
| | | 955 | { |
| | | 956 | struct p9100_softc *sc = device_private(dev); |
| | | 957 | |
| | | 958 | if (sc->sc_powerstate == PWR_RESUME) |
| | | 959 | return TRUE; |
| | | 960 | |
| | | 961 | p9100_ramdac_write_ctl(sc, DAC_POWER_MGT, sc->sc_dac_power); |
| | | 962 | p9100_set_video(sc, sc->sc_video); |
| | | 963 | |
| | | 964 | sc->sc_powerstate = PWR_RESUME; |
| | | 965 | return TRUE; |
1040 | } | | 966 | } |
1041 | | | 967 | |
1042 | /* | | 968 | /* |
1043 | * Load a subset of the current (new) colormap into the IBM RAMDAC. | | 969 | * Load a subset of the current (new) colormap into the IBM RAMDAC. |
1044 | */ | | 970 | */ |
1045 | static void | | 971 | static void |
1046 | p9100loadcmap(struct p9100_softc *sc, int start, int ncolors) | | 972 | p9100loadcmap(struct p9100_softc *sc, int start, int ncolors) |
1047 | { | | 973 | { |
1048 | int i; | | 974 | int i; |
1049 | sc->sc_last_offset = 0xffffffff; | | 975 | sc->sc_last_offset = 0xffffffff; |
1050 | | | 976 | |
1051 | p9100_ramdac_write(sc, DAC_CMAP_WRIDX, start); | | 977 | p9100_ramdac_write(sc, DAC_CMAP_WRIDX, start); |
1052 | | | 978 | |
1053 | for (i=0;i<ncolors;i++) { | | 979 | for (i=0;i<ncolors;i++) { |
1054 | p9100_ramdac_write(sc, DAC_CMAP_DATA, | | 980 | p9100_ramdac_write(sc, DAC_CMAP_DATA, |
1055 | sc->sc_cmap.cm_map[i + start][0]); | | 981 | sc->sc_cmap.cm_map[i + start][0]); |
1056 | p9100_ramdac_write(sc, DAC_CMAP_DATA, | | 982 | p9100_ramdac_write(sc, DAC_CMAP_DATA, |
1057 | sc->sc_cmap.cm_map[i + start][1]); | | 983 | sc->sc_cmap.cm_map[i + start][1]); |
1058 | p9100_ramdac_write(sc, DAC_CMAP_DATA, | | 984 | p9100_ramdac_write(sc, DAC_CMAP_DATA, |
1059 | sc->sc_cmap.cm_map[i + start][2]); | | 985 | sc->sc_cmap.cm_map[i + start][2]); |
1060 | } | | 986 | } |
1061 | } | | 987 | } |
1062 | | | 988 | |
1063 | /* | | 989 | /* |
1064 | * Return the address that would map the given device at the given | | 990 | * Return the address that would map the given device at the given |
1065 | * offset, allowing for the given protection, or return -1 for error. | | 991 | * offset, allowing for the given protection, or return -1 for error. |
1066 | */ | | 992 | */ |
1067 | static paddr_t | | 993 | static paddr_t |
1068 | p9100mmap(dev_t dev, off_t off, int prot) | | 994 | p9100mmap(dev_t dev, off_t off, int prot) |
1069 | { | | 995 | { |
1070 | struct p9100_softc *sc = device_lookup_private(&pnozz_cd, minor(dev)); | | 996 | struct p9100_softc *sc = device_lookup_private(&pnozz_cd, minor(dev)); |
1071 | | | 997 | |
1072 | if (off & PGOFSET) | | 998 | if (off & PGOFSET) |
1073 | panic("p9100mmap"); | | 999 | panic("p9100mmap"); |
1074 | if (off < 0) | | 1000 | if (off < 0) |
1075 | return (-1); | | 1001 | return (-1); |
1076 | | | 1002 | |
1077 | #ifdef PNOZZ_EMUL_CG3 | | 1003 | #ifdef PNOZZ_EMUL_CG3 |
1078 | #define CG3_MMAP_OFFSET 0x04000000 | | 1004 | #define CG3_MMAP_OFFSET 0x04000000 |
1079 | /* Make Xsun think we are a CG3 (SUN3COLOR) | | 1005 | /* Make Xsun think we are a CG3 (SUN3COLOR) |
1080 | */ | | 1006 | */ |
1081 | if (off >= CG3_MMAP_OFFSET && off < CG3_MMAP_OFFSET + sc->sc_fb_psize) { | | 1007 | if (off >= CG3_MMAP_OFFSET && off < CG3_MMAP_OFFSET + sc->sc_fb_psize) { |
1082 | off -= CG3_MMAP_OFFSET; | | 1008 | off -= CG3_MMAP_OFFSET; |
1083 | return (bus_space_mmap(sc->sc_bustag, | | 1009 | return (bus_space_mmap(sc->sc_bustag, |
1084 | sc->sc_fb_paddr, | | 1010 | sc->sc_fb_paddr, |
1085 | off, | | 1011 | off, |
1086 | prot, | | 1012 | prot, |
1087 | BUS_SPACE_MAP_LINEAR)); | | 1013 | BUS_SPACE_MAP_LINEAR)); |
1088 | } | | 1014 | } |
1089 | #endif | | 1015 | #endif |
1090 | | | 1016 | |
1091 | if (off >= sc->sc_fb_psize + sc->sc_ctl_psize/* + sc->sc_cmd_psize*/) | | 1017 | if (off >= sc->sc_fb_psize + sc->sc_ctl_psize/* + sc->sc_cmd_psize*/) |
1092 | return (-1); | | 1018 | return (-1); |
1093 | | | 1019 | |
1094 | if (off < sc->sc_fb_psize) { | | 1020 | if (off < sc->sc_fb_psize) { |
1095 | return (bus_space_mmap(sc->sc_bustag, | | 1021 | return (bus_space_mmap(sc->sc_bustag, |
1096 | sc->sc_fb_paddr, | | 1022 | sc->sc_fb_paddr, |
1097 | off, | | 1023 | off, |
1098 | prot, | | 1024 | prot, |
1099 | BUS_SPACE_MAP_LINEAR)); | | 1025 | BUS_SPACE_MAP_LINEAR)); |
1100 | } | | 1026 | } |
1101 | | | 1027 | |
1102 | off -= sc->sc_fb_psize; | | 1028 | off -= sc->sc_fb_psize; |
1103 | if (off < sc->sc_ctl_psize) { | | 1029 | if (off < sc->sc_ctl_psize) { |
1104 | return (bus_space_mmap(sc->sc_bustag, | | 1030 | return (bus_space_mmap(sc->sc_bustag, |
1105 | sc->sc_ctl_paddr, | | 1031 | sc->sc_ctl_paddr, |
1106 | off, | | 1032 | off, |
1107 | prot, | | 1033 | prot, |
1108 | BUS_SPACE_MAP_LINEAR)); | | 1034 | BUS_SPACE_MAP_LINEAR)); |
1109 | } | | 1035 | } |
1110 | #if 0 | | | |
1111 | off -= sc->sc_ctl_psize; | | | |
1112 | | | 1036 | |
1113 | return (bus_space_mmap(sc->sc_bustag, | | | |
1114 | sc->sc_cmd_paddr, | | | |
1115 | off, | | | |
1116 | prot, | | | |
1117 | BUS_SPACE_MAP_LINEAR)); | | | |
1118 | #endif | | | |
1119 | return EINVAL; | | 1037 | return EINVAL; |
1120 | } | | 1038 | } |
1121 | | | 1039 | |
1122 | /* wscons stuff */ | | 1040 | /* wscons stuff */ |
1123 | #if NWSDISPLAY > 0 | | 1041 | #if NWSDISPLAY > 0 |
1124 | | | 1042 | |
1125 | static void | | 1043 | static void |
1126 | p9100_cursor(void *cookie, int on, int row, int col) | | 1044 | p9100_cursor(void *cookie, int on, int row, int col) |
1127 | { | | 1045 | { |
1128 | struct rasops_info *ri = cookie; | | 1046 | struct rasops_info *ri = cookie; |
1129 | struct vcons_screen *scr = ri->ri_hw; | | 1047 | struct vcons_screen *scr = ri->ri_hw; |
1130 | struct p9100_softc *sc = scr->scr_cookie; | | 1048 | struct p9100_softc *sc = scr->scr_cookie; |
1131 | int x, y, wi,he; | | 1049 | int x, y, wi,he; |
1132 | | | 1050 | |
1133 | wi = ri->ri_font->fontwidth; | | 1051 | wi = ri->ri_font->fontwidth; |
1134 | he = ri->ri_font->fontheight; | | 1052 | he = ri->ri_font->fontheight; |
1135 | | | 1053 | |
1136 | if (ri->ri_flg & RI_CURSOR) { | | 1054 | if (ri->ri_flg & RI_CURSOR) { |
1137 | x = ri->ri_ccol * wi + ri->ri_xorigin; | | 1055 | x = ri->ri_ccol * wi + ri->ri_xorigin; |
1138 | y = ri->ri_crow * he + ri->ri_yorigin; | | 1056 | y = ri->ri_crow * he + ri->ri_yorigin; |
1139 | p9100_bitblt(sc, x, y, x, y, wi, he, ROP_SRC ^ 0xff); | | 1057 | p9100_bitblt(sc, x, y, x, y, wi, he, ROP_SRC ^ 0xff); |
1140 | ri->ri_flg &= ~RI_CURSOR; | | 1058 | ri->ri_flg &= ~RI_CURSOR; |
1141 | } | | 1059 | } |
1142 | | | 1060 | |
1143 | ri->ri_crow = row; | | 1061 | ri->ri_crow = row; |
1144 | ri->ri_ccol = col; | | 1062 | ri->ri_ccol = col; |
1145 | | | 1063 | |
1146 | if (on) | | 1064 | if (on) |
1147 | { | | 1065 | { |
1148 | x = ri->ri_ccol * wi + ri->ri_xorigin; | | 1066 | x = ri->ri_ccol * wi + ri->ri_xorigin; |
1149 | y = ri->ri_crow * he + ri->ri_yorigin; | | 1067 | y = ri->ri_crow * he + ri->ri_yorigin; |
1150 | p9100_bitblt(sc, x, y, x, y, wi, he, ROP_SRC ^ 0xff); | | 1068 | p9100_bitblt(sc, x, y, x, y, wi, he, ROP_SRC ^ 0xff); |
1151 | ri->ri_flg |= RI_CURSOR; | | 1069 | ri->ri_flg |= RI_CURSOR; |
1152 | } | | 1070 | } |
1153 | } | | 1071 | } |
1154 | | | 1072 | |
1155 | #if 0 | | 1073 | #if 0 |
1156 | static int | | 1074 | static int |
1157 | p9100_mapchar(void *cookie, int uni, u_int *index) | | 1075 | p9100_mapchar(void *cookie, int uni, u_int *index) |
1158 | { | | 1076 | { |
1159 | return 0; | | 1077 | return 0; |
1160 | } | | 1078 | } |
1161 | #endif | | 1079 | #endif |
1162 | | | 1080 | |
1163 | static void | | 1081 | static void |
1164 | p9100_putchar(void *cookie, int row, int col, u_int c, long attr) | | 1082 | p9100_putchar(void *cookie, int row, int col, u_int c, long attr) |
1165 | { | | 1083 | { |
1166 | struct rasops_info *ri = cookie; | | 1084 | struct rasops_info *ri = cookie; |
1167 | struct vcons_screen *scr = ri->ri_hw; | | 1085 | struct vcons_screen *scr = ri->ri_hw; |
1168 | struct p9100_softc *sc = scr->scr_cookie; | | 1086 | struct p9100_softc *sc = scr->scr_cookie; |
1169 | | | 1087 | |
1170 | int fg, bg, uc, i; | | 1088 | int fg, bg, uc, i; |
1171 | uint8_t *data; | | 1089 | uint8_t *data; |
1172 | int x, y, wi,he; | | 1090 | int x, y, wi,he; |
1173 | | | 1091 | |
1174 | wi = ri->ri_font->fontwidth; | | 1092 | wi = ri->ri_font->fontwidth; |
1175 | he = ri->ri_font->fontheight; | | 1093 | he = ri->ri_font->fontheight; |
1176 | | | 1094 | |
1177 | if (!CHAR_IN_FONT(c, ri->ri_font)) | | 1095 | if (!CHAR_IN_FONT(c, ri->ri_font)) |
1178 | return; | | 1096 | return; |
1179 | | | 1097 | |
1180 | bg = (u_char)ri->ri_devcmap[(attr >> 16) & 0xff]; | | 1098 | bg = (u_char)ri->ri_devcmap[(attr >> 16) & 0xff]; |
1181 | fg = (u_char)ri->ri_devcmap[(attr >> 24) & 0xff]; | | 1099 | fg = (u_char)ri->ri_devcmap[(attr >> 24) & 0xff]; |
1182 | x = ri->ri_xorigin + col * wi; | | 1100 | x = ri->ri_xorigin + col * wi; |
1183 | y = ri->ri_yorigin + row * he; | | 1101 | y = ri->ri_yorigin + row * he; |
1184 | | | 1102 | |
1185 | if (c == 0x20) { | | 1103 | if (c == 0x20) { |
1186 | p9100_rectfill(sc, x, y, wi, he, bg); | | 1104 | p9100_rectfill(sc, x, y, wi, he, bg); |
1187 | } else { | | 1105 | } else { |
1188 | uc = c-ri->ri_font->firstchar; | | 1106 | uc = c-ri->ri_font->firstchar; |
1189 | data = (uint8_t *)ri->ri_font->data + uc * | | 1107 | data = (uint8_t *)ri->ri_font->data + uc * |
1190 | ri->ri_fontscale; | | 1108 | ri->ri_fontscale; |
1191 | | | 1109 | |
1192 | p9100_setup_mono(sc, x, y, wi, 1, fg, bg); | | 1110 | p9100_setup_mono(sc, x, y, wi, 1, fg, bg); |
1193 | for (i = 0; i < he; i++) { | | 1111 | for (i = 0; i < he; i++) { |
1194 | p9100_feed_line(sc, ri->ri_font->stride, | | 1112 | p9100_feed_line(sc, ri->ri_font->stride, |
1195 | data); | | 1113 | data); |
1196 | data += ri->ri_font->stride; | | 1114 | data += ri->ri_font->stride; |
1197 | } | | 1115 | } |
1198 | } | | 1116 | } |
1199 | } | | 1117 | } |
1200 | | | 1118 | |
1201 | /* | | 1119 | /* |
1202 | * wsdisplay_accessops | | 1120 | * wsdisplay_accessops |
1203 | */ | | 1121 | */ |
1204 | | | 1122 | |
1205 | int | | 1123 | int |
1206 | p9100_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, | | 1124 | p9100_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, |
1207 | struct lwp *l) | | 1125 | struct lwp *l) |
1208 | { | | 1126 | { |
1209 | struct vcons_data *vd = v; | | 1127 | struct vcons_data *vd = v; |
1210 | struct p9100_softc *sc = vd->cookie; | | 1128 | struct p9100_softc *sc = vd->cookie; |
1211 | struct wsdisplay_fbinfo *wdf; | | 1129 | struct wsdisplay_fbinfo *wdf; |
1212 | struct vcons_screen *ms = vd->active; | | 1130 | struct vcons_screen *ms = vd->active; |
1213 | | | 1131 | |
1214 | switch (cmd) { | | 1132 | switch (cmd) { |
1215 | case WSDISPLAYIO_GTYPE: | | 1133 | case WSDISPLAYIO_GTYPE: |
1216 | *(u_int *)data = WSDISPLAY_TYPE_SB_P9100; | | 1134 | *(u_int *)data = WSDISPLAY_TYPE_SB_P9100; |
1217 | return 0; | | 1135 | return 0; |
1218 | | | 1136 | |
1219 | case FBIOGVIDEO: | | 1137 | case FBIOGVIDEO: |
1220 | case WSDISPLAYIO_GVIDEO: | | 1138 | case WSDISPLAYIO_GVIDEO: |
1221 | *(int *)data = p9100_get_video(sc); | | 1139 | *(int *)data = p9100_get_video(sc); |
1222 | return 0; | | 1140 | return 0; |
1223 | | | 1141 | |
1224 | case WSDISPLAYIO_SVIDEO: | | 1142 | case WSDISPLAYIO_SVIDEO: |
1225 | case FBIOSVIDEO: | | 1143 | case FBIOSVIDEO: |
1226 | p9100_set_video(sc, *(int *)data); | | 1144 | p9100_set_video(sc, *(int *)data); |
1227 | return 0; | | 1145 | return 0; |
1228 | | | 1146 | |
1229 | case WSDISPLAYIO_GINFO: | | 1147 | case WSDISPLAYIO_GINFO: |
1230 | wdf = (void *)data; | | 1148 | wdf = (void *)data; |
1231 | wdf->height = ms->scr_ri.ri_height; | | 1149 | wdf->height = ms->scr_ri.ri_height; |
1232 | wdf->width = ms->scr_ri.ri_width; | | 1150 | wdf->width = ms->scr_ri.ri_width; |
1233 | wdf->depth = ms->scr_ri.ri_depth; | | 1151 | wdf->depth = ms->scr_ri.ri_depth; |
1234 | wdf->cmsize = 256; | | 1152 | wdf->cmsize = 256; |
1235 | return 0; | | 1153 | return 0; |
1236 | | | 1154 | |
1237 | case WSDISPLAYIO_GETCMAP: | | 1155 | case WSDISPLAYIO_GETCMAP: |
1238 | return p9100_getcmap(sc, (struct wsdisplay_cmap *)data); | | 1156 | return p9100_getcmap(sc, (struct wsdisplay_cmap *)data); |
1239 | | | 1157 | |
1240 | case WSDISPLAYIO_PUTCMAP: | | 1158 | case WSDISPLAYIO_PUTCMAP: |
1241 | return p9100_putcmap(sc, (struct wsdisplay_cmap *)data); | | 1159 | return p9100_putcmap(sc, (struct wsdisplay_cmap *)data); |
1242 | | | 1160 | |
1243 | case WSDISPLAYIO_SMODE: | | 1161 | case WSDISPLAYIO_SMODE: |
1244 | { | | 1162 | { |
1245 | int new_mode = *(int*)data; | | 1163 | int new_mode = *(int*)data; |
1246 | if (new_mode != sc->sc_mode) | | 1164 | if (new_mode != sc->sc_mode) |
1247 | { | | 1165 | { |
1248 | sc->sc_mode = new_mode; | | 1166 | sc->sc_mode = new_mode; |
1249 | if (new_mode == WSDISPLAYIO_MODE_EMUL) | | 1167 | if (new_mode == WSDISPLAYIO_MODE_EMUL) |
1250 | { | | 1168 | { |
1251 | p9100_init_engine(sc); | | 1169 | p9100_init_engine(sc); |
1252 | p9100_set_depth(sc, 8); | | 1170 | p9100_set_depth(sc, 8); |
1253 | p9100loadcmap(sc, 0, 256); | | 1171 | p9100loadcmap(sc, 0, 256); |
1254 | p9100_clearscreen(sc); | | 1172 | p9100_clearscreen(sc); |
1255 | vcons_redraw_screen(ms); | | 1173 | vcons_redraw_screen(ms); |
1256 | } | | 1174 | } |
1257 | } | | 1175 | } |
1258 | } | | 1176 | } |
1259 | } | | 1177 | } |
1260 | return EPASSTHROUGH; | | 1178 | return EPASSTHROUGH; |
1261 | } | | 1179 | } |
1262 | | | 1180 | |
1263 | static paddr_t | | 1181 | static paddr_t |
1264 | p9100_mmap(void *v, void *vs, off_t offset, int prot) | | 1182 | p9100_mmap(void *v, void *vs, off_t offset, int prot) |
1265 | { | | 1183 | { |
1266 | struct vcons_data *vd = v; | | 1184 | struct vcons_data *vd = v; |
1267 | struct p9100_softc *sc = vd->cookie; | | 1185 | struct p9100_softc *sc = vd->cookie; |
1268 | paddr_t pa; | | 1186 | paddr_t pa; |
1269 | | | 1187 | |
1270 | /* 'regular' framebuffer mmap()ing */ | | 1188 | /* 'regular' framebuffer mmap()ing */ |
1271 | if (offset < sc->sc_fb_psize) { | | 1189 | if (offset < sc->sc_fb_psize) { |
1272 | pa = bus_space_mmap(sc->sc_bustag, sc->sc_fb_paddr + offset, 0, | | 1190 | pa = bus_space_mmap(sc->sc_bustag, sc->sc_fb_paddr + offset, 0, |
1273 | prot, BUS_SPACE_MAP_LINEAR); | | 1191 | prot, BUS_SPACE_MAP_LINEAR); |
1274 | return pa; | | 1192 | return pa; |
1275 | } | | 1193 | } |
1276 | | | 1194 | |
1277 | if ((offset >= sc->sc_fb_paddr) && (offset < (sc->sc_fb_paddr + | | 1195 | if ((offset >= sc->sc_fb_paddr) && (offset < (sc->sc_fb_paddr + |
1278 | sc->sc_fb_psize))) { | | 1196 | sc->sc_fb_psize))) { |
1279 | pa = bus_space_mmap(sc->sc_bustag, offset, 0, prot, | | 1197 | pa = bus_space_mmap(sc->sc_bustag, offset, 0, prot, |
1280 | BUS_SPACE_MAP_LINEAR); | | 1198 | BUS_SPACE_MAP_LINEAR); |
1281 | return pa; | | 1199 | return pa; |
1282 | } | | 1200 | } |
1283 | | | 1201 | |
1284 | if ((offset >= sc->sc_ctl_paddr) && (offset < (sc->sc_ctl_paddr + | | 1202 | if ((offset >= sc->sc_ctl_paddr) && (offset < (sc->sc_ctl_paddr + |
1285 | sc->sc_ctl_psize))) { | | 1203 | sc->sc_ctl_psize))) { |
1286 | pa = bus_space_mmap(sc->sc_bustag, offset, 0, prot, | | 1204 | pa = bus_space_mmap(sc->sc_bustag, offset, 0, prot, |
1287 | BUS_SPACE_MAP_LINEAR); | | 1205 | BUS_SPACE_MAP_LINEAR); |
1288 | return pa; | | 1206 | return pa; |
1289 | } | | 1207 | } |
1290 | | | 1208 | |
1291 | return -1; | | 1209 | return -1; |
1292 | } | | 1210 | } |
1293 | | | 1211 | |
1294 | static void | | 1212 | static void |
1295 | p9100_init_screen(void *cookie, struct vcons_screen *scr, | | 1213 | p9100_init_screen(void *cookie, struct vcons_screen *scr, |
1296 | int existing, long *defattr) | | 1214 | int existing, long *defattr) |
1297 | { | | 1215 | { |
1298 | struct p9100_softc *sc = cookie; | | 1216 | struct p9100_softc *sc = cookie; |
1299 | struct rasops_info *ri = &scr->scr_ri; | | 1217 | struct rasops_info *ri = &scr->scr_ri; |
1300 | | | 1218 | |
1301 | ri->ri_depth = sc->sc_depth << 3; | | 1219 | ri->ri_depth = sc->sc_depth << 3; |
1302 | ri->ri_width = sc->sc_width; | | 1220 | ri->ri_width = sc->sc_width; |
1303 | ri->ri_height = sc->sc_height; | | 1221 | ri->ri_height = sc->sc_height; |
1304 | ri->ri_stride = sc->sc_stride; | | 1222 | ri->ri_stride = sc->sc_stride; |
1305 | ri->ri_flg = RI_CENTER | RI_FULLCLEAR; | | 1223 | ri->ri_flg = RI_CENTER | RI_FULLCLEAR; |
1306 | | | 1224 | |
1307 | ri->ri_bits = bus_space_vaddr(sc->sc_bustag, sc->sc_fb_memh); | | 1225 | ri->ri_bits = bus_space_vaddr(sc->sc_bustag, sc->sc_fb_memh); |
1308 | | | 1226 | |
1309 | DPRINTF("addr: %08lx\n",(ulong)ri->ri_bits); | | 1227 | DPRINTF("addr: %08lx\n",(ulong)ri->ri_bits); |
1310 | | | 1228 | |
1311 | rasops_init(ri, sc->sc_height/8, sc->sc_width/8); | | 1229 | rasops_init(ri, sc->sc_height/8, sc->sc_width/8); |
1312 | ri->ri_caps = WSSCREEN_WSCOLORS; | | 1230 | ri->ri_caps = WSSCREEN_WSCOLORS; |
1313 | rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, | | 1231 | rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, |
1314 | sc->sc_width / ri->ri_font->fontwidth); | | 1232 | sc->sc_width / ri->ri_font->fontwidth); |
1315 | | | 1233 | |
1316 | /* enable acceleration */ | | 1234 | /* enable acceleration */ |
1317 | ri->ri_ops.cursor = p9100_cursor; | | 1235 | ri->ri_ops.cursor = p9100_cursor; |
1318 | ri->ri_ops.copyrows = p9100_copyrows; | | 1236 | ri->ri_ops.copyrows = p9100_copyrows; |
1319 | ri->ri_ops.eraserows = p9100_eraserows; | | 1237 | ri->ri_ops.eraserows = p9100_eraserows; |
1320 | ri->ri_ops.copycols = p9100_copycols; | | 1238 | ri->ri_ops.copycols = p9100_copycols; |
1321 | ri->ri_ops.erasecols = p9100_erasecols; | | 1239 | ri->ri_ops.erasecols = p9100_erasecols; |
1322 | ri->ri_ops.putchar = p9100_putchar; | | 1240 | ri->ri_ops.putchar = p9100_putchar; |
1323 | ri->ri_ops.allocattr = p9100_allocattr; | | 1241 | ri->ri_ops.allocattr = p9100_allocattr; |
1324 | } | | 1242 | } |
1325 | | | 1243 | |
1326 | static int | | 1244 | static int |
1327 | p9100_putcmap(struct p9100_softc *sc, struct wsdisplay_cmap *cm) | | 1245 | p9100_putcmap(struct p9100_softc *sc, struct wsdisplay_cmap *cm) |
1328 | { | | 1246 | { |
1329 | u_int index = cm->index; | | 1247 | u_int index = cm->index; |
1330 | u_int count = cm->count; | | 1248 | u_int count = cm->count; |
1331 | int i, error; | | 1249 | int i, error; |
1332 | u_char rbuf[256], gbuf[256], bbuf[256]; | | 1250 | u_char rbuf[256], gbuf[256], bbuf[256]; |
1333 | u_char *r, *g, *b; | | 1251 | u_char *r, *g, *b; |
1334 | | | 1252 | |
1335 | if (cm->index >= 256 || cm->count > 256 || | | 1253 | if (cm->index >= 256 || cm->count > 256 || |
1336 | (cm->index + cm->count) > 256) | | 1254 | (cm->index + cm->count) > 256) |
1337 | return EINVAL; | | 1255 | return EINVAL; |
1338 | error = copyin(cm->red, &rbuf[index], count); | | 1256 | error = copyin(cm->red, &rbuf[index], count); |
1339 | if (error) | | 1257 | if (error) |
1340 | return error; | | 1258 | return error; |
1341 | error = copyin(cm->green, &gbuf[index], count); | | 1259 | error = copyin(cm->green, &gbuf[index], count); |
1342 | if (error) | | 1260 | if (error) |
1343 | return error; | | 1261 | return error; |
1344 | error = copyin(cm->blue, &bbuf[index], count); | | 1262 | error = copyin(cm->blue, &bbuf[index], count); |
1345 | if (error) | | 1263 | if (error) |
1346 | return error; | | 1264 | return error; |
1347 | | | 1265 | |
1348 | r = &rbuf[index]; | | 1266 | r = &rbuf[index]; |
1349 | g = &gbuf[index]; | | 1267 | g = &gbuf[index]; |
1350 | b = &bbuf[index]; | | 1268 | b = &bbuf[index]; |
1351 | | | 1269 | |
1352 | for (i = 0; i < count; i++) { | | 1270 | for (i = 0; i < count; i++) { |
1353 | sc->sc_cmap.cm_map[index][0] = *r; | | 1271 | sc->sc_cmap.cm_map[index][0] = *r; |
1354 | sc->sc_cmap.cm_map[index][1] = *g; | | 1272 | sc->sc_cmap.cm_map[index][1] = *g; |
1355 | sc->sc_cmap.cm_map[index][2] = *b; | | 1273 | sc->sc_cmap.cm_map[index][2] = *b; |
1356 | index++; | | 1274 | index++; |
1357 | r++, g++, b++; | | 1275 | r++, g++, b++; |
1358 | } | | 1276 | } |
1359 | p9100loadcmap(sc, 0, 256); | | 1277 | p9100loadcmap(sc, 0, 256); |
1360 | return 0; | | 1278 | return 0; |
1361 | } | | 1279 | } |
1362 | | | 1280 | |
1363 | static int | | 1281 | static int |
1364 | p9100_getcmap(struct p9100_softc *sc, struct wsdisplay_cmap *cm) | | 1282 | p9100_getcmap(struct p9100_softc *sc, struct wsdisplay_cmap *cm) |
1365 | { | | 1283 | { |
1366 | u_int index = cm->index; | | 1284 | u_int index = cm->index; |
1367 | u_int count = cm->count; | | 1285 | u_int count = cm->count; |
1368 | int error, i; | | 1286 | int error, i; |
1369 | uint8_t red[256], green[256], blue[256]; | | 1287 | uint8_t red[256], green[256], blue[256]; |
1370 | | | 1288 | |
1371 | if (index >= 255 || count > 256 || index + count > 256) | | 1289 | if (index >= 255 || count > 256 || index + count > 256) |
1372 | return EINVAL; | | 1290 | return EINVAL; |
1373 | | | 1291 | |
1374 | i = index; | | 1292 | i = index; |
1375 | while (i < (index + count)) { | | 1293 | while (i < (index + count)) { |
1376 | red[i] = sc->sc_cmap.cm_map[i][0]; | | 1294 | red[i] = sc->sc_cmap.cm_map[i][0]; |
1377 | green[i] = sc->sc_cmap.cm_map[i][1]; | | 1295 | green[i] = sc->sc_cmap.cm_map[i][1]; |
1378 | blue[i] = sc->sc_cmap.cm_map[i][2]; | | 1296 | blue[i] = sc->sc_cmap.cm_map[i][2]; |
1379 | i++; | | 1297 | i++; |
1380 | } | | 1298 | } |
1381 | error = copyout(&red[index], cm->red, count); | | 1299 | error = copyout(&red[index], cm->red, count); |
1382 | if (error) | | 1300 | if (error) |
1383 | return error; | | 1301 | return error; |
1384 | error = copyout(&green[index], cm->green, count); | | 1302 | error = copyout(&green[index], cm->green, count); |
1385 | if (error) | | 1303 | if (error) |
1386 | return error; | | 1304 | return error; |
1387 | error = copyout(&blue[index], cm->blue, count); | | 1305 | error = copyout(&blue[index], cm->blue, count); |
1388 | if (error) | | 1306 | if (error) |
1389 | return error; | | 1307 | return error; |
1390 | | | 1308 | |
1391 | return 0; | | 1309 | return 0; |
1392 | } | | 1310 | } |
1393 | | | 1311 | |
1394 | static void | | 1312 | static void |
1395 | p9100_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) | | 1313 | p9100_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) |
1396 | { | | 1314 | { |
1397 | struct rasops_info *ri = cookie; | | 1315 | struct rasops_info *ri = cookie; |
1398 | struct vcons_screen *scr = ri->ri_hw; | | 1316 | struct vcons_screen *scr = ri->ri_hw; |
1399 | int32_t xs, xd, y, width, height; | | 1317 | int32_t xs, xd, y, width, height; |
1400 | | | 1318 | |
1401 | xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; | | 1319 | xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; |
1402 | xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; | | 1320 | xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; |
1403 | y = ri->ri_yorigin + ri->ri_font->fontheight * row; | | 1321 | y = ri->ri_yorigin + ri->ri_font->fontheight * row; |
1404 | width = ri->ri_font->fontwidth * ncols; | | 1322 | width = ri->ri_font->fontwidth * ncols; |
1405 | height = ri->ri_font->fontheight; | | 1323 | height = ri->ri_font->fontheight; |
1406 | p9100_bitblt(scr->scr_cookie, xs, y, xd, y, width, height, ROP_SRC); | | 1324 | p9100_bitblt(scr->scr_cookie, xs, y, xd, y, width, height, ROP_SRC); |
1407 | } | | 1325 | } |
1408 | | | 1326 | |
1409 | static void | | 1327 | static void |
1410 | p9100_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr) | | 1328 | p9100_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr) |
1411 | { | | 1329 | { |
1412 | struct rasops_info *ri = cookie; | | 1330 | struct rasops_info *ri = cookie; |
1413 | struct vcons_screen *scr = ri->ri_hw; | | 1331 | struct vcons_screen *scr = ri->ri_hw; |
1414 | int32_t x, y, width, height, bg; | | 1332 | int32_t x, y, width, height, bg; |
1415 | | | 1333 | |
1416 | x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; | | 1334 | x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; |
1417 | y = ri->ri_yorigin + ri->ri_font->fontheight * row; | | 1335 | y = ri->ri_yorigin + ri->ri_font->fontheight * row; |
1418 | width = ri->ri_font->fontwidth * ncols; | | 1336 | width = ri->ri_font->fontwidth * ncols; |
1419 | height = ri->ri_font->fontheight; | | 1337 | height = ri->ri_font->fontheight; |
1420 | bg = (uint32_t)ri->ri_devcmap[(fillattr >> 16) & 0xff]; | | 1338 | bg = (uint32_t)ri->ri_devcmap[(fillattr >> 16) & 0xff]; |
1421 | p9100_rectfill(scr->scr_cookie, x, y, width, height, bg); | | 1339 | p9100_rectfill(scr->scr_cookie, x, y, width, height, bg); |
1422 | } | | 1340 | } |
1423 | | | 1341 | |
1424 | static void | | 1342 | static void |
1425 | p9100_copyrows(void *cookie, int srcrow, int dstrow, int nrows) | | 1343 | p9100_copyrows(void *cookie, int srcrow, int dstrow, int nrows) |
1426 | { | | 1344 | { |
1427 | struct rasops_info *ri = cookie; | | 1345 | struct rasops_info *ri = cookie; |
1428 | struct vcons_screen *scr = ri->ri_hw; | | 1346 | struct vcons_screen *scr = ri->ri_hw; |
1429 | int32_t x, ys, yd, width, height; | | 1347 | int32_t x, ys, yd, width, height; |
1430 | | | 1348 | |
1431 | x = ri->ri_xorigin; | | 1349 | x = ri->ri_xorigin; |
1432 | ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; | | 1350 | ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; |
1433 | yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; | | 1351 | yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; |
1434 | width = ri->ri_emuwidth; | | 1352 | width = ri->ri_emuwidth; |
1435 | height = ri->ri_font->fontheight * nrows; | | 1353 | height = ri->ri_font->fontheight * nrows; |
1436 | p9100_bitblt(scr->scr_cookie, x, ys, x, yd, width, height, ROP_SRC); | | 1354 | p9100_bitblt(scr->scr_cookie, x, ys, x, yd, width, height, ROP_SRC); |
1437 | } | | 1355 | } |
1438 | | | 1356 | |
1439 | static void | | 1357 | static void |
1440 | p9100_eraserows(void *cookie, int row, int nrows, long fillattr) | | 1358 | p9100_eraserows(void *cookie, int row, int nrows, long fillattr) |
1441 | { | | 1359 | { |
1442 | struct rasops_info *ri = cookie; | | 1360 | struct rasops_info *ri = cookie; |
1443 | struct vcons_screen *scr = ri->ri_hw; | | 1361 | struct vcons_screen *scr = ri->ri_hw; |
1444 | int32_t x, y, width, height, bg; | | 1362 | int32_t x, y, width, height, bg; |
1445 | | | 1363 | |
1446 | if ((row == 0) && (nrows == ri->ri_rows)) { | | 1364 | if ((row == 0) && (nrows == ri->ri_rows)) { |
1447 | x = y = 0; | | 1365 | x = y = 0; |
1448 | width = ri->ri_width; | | 1366 | width = ri->ri_width; |
1449 | height = ri->ri_height; | | 1367 | height = ri->ri_height; |
1450 | } else { | | 1368 | } else { |
1451 | x = ri->ri_xorigin; | | 1369 | x = ri->ri_xorigin; |
1452 | y = ri->ri_yorigin + ri->ri_font->fontheight * row; | | 1370 | y = ri->ri_yorigin + ri->ri_font->fontheight * row; |
1453 | width = ri->ri_emuwidth; | | 1371 | width = ri->ri_emuwidth; |
1454 | height = ri->ri_font->fontheight * nrows; | | 1372 | height = ri->ri_font->fontheight * nrows; |
1455 | } | | 1373 | } |
1456 | bg = (uint32_t)ri->ri_devcmap[(fillattr >> 16) & 0xff]; | | 1374 | bg = (uint32_t)ri->ri_devcmap[(fillattr >> 16) & 0xff]; |
1457 | p9100_rectfill(scr->scr_cookie, x, y, width, height, bg); | | 1375 | p9100_rectfill(scr->scr_cookie, x, y, width, height, bg); |
1458 | } | | 1376 | } |
1459 | | | 1377 | |
1460 | | | 1378 | |
1461 | static int | | 1379 | static int |
1462 | p9100_allocattr(void *cookie, int fg, int bg, int flags, long *attrp) | | 1380 | p9100_allocattr(void *cookie, int fg, int bg, int flags, long *attrp) |
1463 | { | | 1381 | { |
1464 | if ((fg == 0) && (bg == 0)) | | 1382 | if ((fg == 0) && (bg == 0)) |
1465 | { | | 1383 | { |
1466 | fg = WS_DEFAULT_FG; | | 1384 | fg = WS_DEFAULT_FG; |
1467 | bg = WS_DEFAULT_BG; | | 1385 | bg = WS_DEFAULT_BG; |
1468 | } | | 1386 | } |
1469 | | | 1387 | |
1470 | *attrp = (fg & 0xff) << 24 | (bg & 0xff) << 16 | (flags & 0xff); | | 1388 | *attrp = (fg & 0xff) << 24 | (bg & 0xff) << 16 | (flags & 0xff); |
1471 | | | 1389 | |
1472 | if (flags & WSATTR_REVERSE) { | | 1390 | if (flags & WSATTR_REVERSE) { |
1473 | *attrp = (bg & 0xff) << 24 | (fg & 0xff) << 16 | | | 1391 | *attrp = (bg & 0xff) << 24 | (fg & 0xff) << 16 | |
1474 | (flags & 0xff) << 8; | | 1392 | (flags & 0xff) << 8; |
1475 | } else | | 1393 | } else |
1476 | *attrp = (fg & 0xff) << 24 | (bg & 0xff) << 16 | | | 1394 | *attrp = (fg & 0xff) << 24 | (bg & 0xff) << 16 | |
1477 | (flags & 0xff) << 8; | | 1395 | (flags & 0xff) << 8; |
1478 | | | 1396 | |
1479 | return 0; | | 1397 | return 0; |
1480 | } | | 1398 | } |
1481 | | | 1399 | |
1482 | #if 0 | | 1400 | #if 0 |
1483 | static int | | 1401 | static int |
1484 | p9100_load_font(void *v, void *cookie, struct wsdisplay_font *data) | | 1402 | p9100_load_font(void *v, void *cookie, struct wsdisplay_font *data) |
1485 | { | | 1403 | { |
1486 | | | 1404 | |
1487 | return 0; | | 1405 | return 0; |
1488 | } | | 1406 | } |
1489 | #endif | | 1407 | #endif |
1490 | | | 1408 | |
1491 | #endif /* NWSDISPLAY > 0 */ | | 1409 | #endif /* NWSDISPLAY > 0 */ |
1492 | | | 1410 | |
1493 | #if 0 | | 1411 | #if 0 |
1494 | static int | | 1412 | static int |
1495 | p9100_intr(void *arg) | | 1413 | p9100_intr(void *arg) |
1496 | { | | 1414 | { |
1497 | /*p9100_softc *sc=arg;*/ | | 1415 | /*p9100_softc *sc=arg;*/ |
1498 | DPRINTF("."); | | 1416 | DPRINTF("."); |
1499 | return 1; | | 1417 | return 1; |
1500 | } | | 1418 | } |
1501 | #endif | | 1419 | #endif |
1502 | | | 1420 | |
1503 | static void | | 1421 | static void |
1504 | p9100_init_cursor(struct p9100_softc *sc) | | 1422 | p9100_init_cursor(struct p9100_softc *sc) |
1505 | { | | 1423 | { |
1506 | | | 1424 | |
1507 | memset(&sc->sc_cursor, 0, sizeof(struct pnozz_cursor)); | | 1425 | memset(&sc->sc_cursor, 0, sizeof(struct pnozz_cursor)); |
1508 | sc->sc_cursor.pc_size.x = 64; | | 1426 | sc->sc_cursor.pc_size.x = 64; |
1509 | sc->sc_cursor.pc_size.y = 64; | | 1427 | sc->sc_cursor.pc_size.y = 64; |
1510 | | | 1428 | |
1511 | } | | 1429 | } |
1512 | | | 1430 | |
1513 | static void | | 1431 | static void |
1514 | p9100_set_fbcursor(struct p9100_softc *sc) | | 1432 | p9100_set_fbcursor(struct p9100_softc *sc) |
1515 | { | | 1433 | { |
1516 | #ifdef PNOZZ_PARANOID | | 1434 | #ifdef PNOZZ_PARANOID |
1517 | int s; | | 1435 | int s; |
1518 | | | 1436 | |
1519 | s = splhigh(); /* just in case... */ | | 1437 | s = splhigh(); /* just in case... */ |
1520 | #endif | | 1438 | #endif |
1521 | sc->sc_last_offset = 0xffffffff; | | 1439 | sc->sc_last_offset = 0xffffffff; |
1522 | | | 1440 | |
1523 | /* set position and hotspot */ | | 1441 | /* set position and hotspot */ |
1524 | p9100_ramdac_write(sc, DAC_INDX_CTL, DAC_INDX_AUTOINCR); | | 1442 | p9100_ramdac_write(sc, DAC_INDX_CTL, DAC_INDX_AUTOINCR); |
1525 | p9100_ramdac_write(sc, DAC_INDX_HI, 0); | | 1443 | p9100_ramdac_write(sc, DAC_INDX_HI, 0); |
1526 | p9100_ramdac_write(sc, DAC_INDX_LO, DAC_CURSOR_CTL); | | 1444 | p9100_ramdac_write(sc, DAC_INDX_LO, DAC_CURSOR_CTL); |
1527 | if (sc->sc_cursor.pc_enable) { | | 1445 | if (sc->sc_cursor.pc_enable) { |
1528 | p9100_ramdac_write(sc, DAC_INDX_DATA, DAC_CURSOR_X11 | | | 1446 | p9100_ramdac_write(sc, DAC_INDX_DATA, DAC_CURSOR_X11 | |
1529 | DAC_CURSOR_64); | | 1447 | DAC_CURSOR_64); |
1530 | } else | | 1448 | } else |
1531 | p9100_ramdac_write(sc, DAC_INDX_DATA, DAC_CURSOR_OFF); | | 1449 | p9100_ramdac_write(sc, DAC_INDX_DATA, DAC_CURSOR_OFF); |
1532 | /* next two registers - x low, high, y low, high */ | | 1450 | /* next two registers - x low, high, y low, high */ |
1533 | p9100_ramdac_write(sc, DAC_INDX_DATA, sc->sc_cursor.pc_pos.x & 0xff); | | 1451 | p9100_ramdac_write(sc, DAC_INDX_DATA, sc->sc_cursor.pc_pos.x & 0xff); |
1534 | p9100_ramdac_write(sc, DAC_INDX_DATA, (sc->sc_cursor.pc_pos.x >> 8) & | | 1452 | p9100_ramdac_write(sc, DAC_INDX_DATA, (sc->sc_cursor.pc_pos.x >> 8) & |
1535 | 0xff); | | 1453 | 0xff); |
1536 | p9100_ramdac_write(sc, DAC_INDX_DATA, sc->sc_cursor.pc_pos.y & 0xff); | | 1454 | p9100_ramdac_write(sc, DAC_INDX_DATA, sc->sc_cursor.pc_pos.y & 0xff); |
1537 | p9100_ramdac_write(sc, DAC_INDX_DATA, (sc->sc_cursor.pc_pos.y >> 8) & | | 1455 | p9100_ramdac_write(sc, DAC_INDX_DATA, (sc->sc_cursor.pc_pos.y >> 8) & |
1538 | 0xff); | | 1456 | 0xff); |
1539 | /* hotspot */ | | 1457 | /* hotspot */ |
1540 | p9100_ramdac_write(sc, DAC_INDX_DATA, sc->sc_cursor.pc_hot.x & 0xff); | | 1458 | p9100_ramdac_write(sc, DAC_INDX_DATA, sc->sc_cursor.pc_hot.x & 0xff); |
1541 | p9100_ramdac_write(sc, DAC_INDX_DATA, sc->sc_cursor.pc_hot.y & 0xff); | | 1459 | p9100_ramdac_write(sc, DAC_INDX_DATA, sc->sc_cursor.pc_hot.y & 0xff); |
1542 | | | 1460 | |
1543 | #ifdef PNOZZ_PARANOID | | 1461 | #ifdef PNOZZ_PARANOID |
1544 | splx(s); | | 1462 | splx(s); |
1545 | #endif | | 1463 | #endif |
1546 | | | 1464 | |
1547 | } | | 1465 | } |
1548 | | | 1466 | |
1549 | static void | | 1467 | static void |
1550 | p9100_setcursorcmap(struct p9100_softc *sc) | | 1468 | p9100_setcursorcmap(struct p9100_softc *sc) |
1551 | { | | 1469 | { |
1552 | int i; | | 1470 | int i; |
1553 | | | 1471 | |
1554 | #ifdef PNOZZ_PARANOID | | 1472 | #ifdef PNOZZ_PARANOID |
1555 | int s; | | 1473 | int s; |
1556 | s = splhigh(); /* just in case... */ | | 1474 | s = splhigh(); /* just in case... */ |
1557 | #endif | | 1475 | #endif |
1558 | sc->sc_last_offset = 0xffffffff; | | 1476 | sc->sc_last_offset = 0xffffffff; |
1559 | | | 1477 | |
1560 | /* set cursor colours */ | | 1478 | /* set cursor colours */ |
1561 | p9100_ramdac_write(sc, DAC_INDX_CTL, DAC_INDX_AUTOINCR); | | 1479 | p9100_ramdac_write(sc, DAC_INDX_CTL, DAC_INDX_AUTOINCR); |
1562 | p9100_ramdac_write(sc, DAC_INDX_HI, 0); | | 1480 | p9100_ramdac_write(sc, DAC_INDX_HI, 0); |
1563 | p9100_ramdac_write(sc, DAC_INDX_LO, DAC_CURSOR_COL_1); | | 1481 | p9100_ramdac_write(sc, DAC_INDX_LO, DAC_CURSOR_COL_1); |
1564 | | | 1482 | |
1565 | for (i = 0; i < 3; i++) { | | 1483 | for (i = 0; i < 3; i++) { |
1566 | p9100_ramdac_write(sc, DAC_INDX_DATA, sc->sc_cursor.red[i]); | | 1484 | p9100_ramdac_write(sc, DAC_INDX_DATA, sc->sc_cursor.red[i]); |
1567 | p9100_ramdac_write(sc, DAC_INDX_DATA, sc->sc_cursor.green[i]); | | 1485 | p9100_ramdac_write(sc, DAC_INDX_DATA, sc->sc_cursor.green[i]); |
1568 | p9100_ramdac_write(sc, DAC_INDX_DATA, sc->sc_cursor.blue[i]); | | 1486 | p9100_ramdac_write(sc, DAC_INDX_DATA, sc->sc_cursor.blue[i]); |
1569 | } | | 1487 | } |
1570 | | | 1488 | |
1571 | #ifdef PNOZZ_PARANOID | | 1489 | #ifdef PNOZZ_PARANOID |
1572 | splx(s); | | 1490 | splx(s); |
1573 | #endif | | 1491 | #endif |
1574 | } | | 1492 | } |
1575 | | | 1493 | |
1576 | static void | | 1494 | static void |
1577 | p9100_loadcursor(struct p9100_softc *sc) | | 1495 | p9100_loadcursor(struct p9100_softc *sc) |
1578 | { | | 1496 | { |
1579 | uint32_t *image, *mask; | | 1497 | uint32_t *image, *mask; |
1580 | uint32_t bit, bbit, im, ma; | | 1498 | uint32_t bit, bbit, im, ma; |
1581 | int i, j, k; | | 1499 | int i, j, k; |
1582 | uint8_t latch1, latch2; | | 1500 | uint8_t latch1, latch2; |
1583 | | | 1501 | |
1584 | #ifdef PNOZZ_PARANOID | | 1502 | #ifdef PNOZZ_PARANOID |
1585 | int s; | | 1503 | int s; |
1586 | s = splhigh(); /* just in case... */ | | 1504 | s = splhigh(); /* just in case... */ |
1587 | #endif | | 1505 | #endif |
1588 | sc->sc_last_offset = 0xffffffff; | | 1506 | sc->sc_last_offset = 0xffffffff; |
1589 | | | 1507 | |
1590 | /* set cursor shape */ | | 1508 | /* set cursor shape */ |
1591 | p9100_ramdac_write(sc, DAC_INDX_CTL, DAC_INDX_AUTOINCR); | | 1509 | p9100_ramdac_write(sc, DAC_INDX_CTL, DAC_INDX_AUTOINCR); |
1592 | p9100_ramdac_write(sc, DAC_INDX_HI, 1); | | 1510 | p9100_ramdac_write(sc, DAC_INDX_HI, 1); |
1593 | p9100_ramdac_write(sc, DAC_INDX_LO, 0); | | 1511 | p9100_ramdac_write(sc, DAC_INDX_LO, 0); |
1594 | | | 1512 | |
1595 | image = sc->sc_cursor.pc_bits; | | 1513 | image = sc->sc_cursor.pc_bits; |
1596 | mask = &sc->sc_cursor.pc_bits[0x80]; | | 1514 | mask = &sc->sc_cursor.pc_bits[0x80]; |
1597 | | | 1515 | |
1598 | for (i = 0; i < 0x80; i++) { | | 1516 | for (i = 0; i < 0x80; i++) { |
1599 | bit = 0x80000000; | | 1517 | bit = 0x80000000; |
1600 | im = image[i]; | | 1518 | im = image[i]; |
1601 | ma = mask[i]; | | 1519 | ma = mask[i]; |
1602 | for (k = 0; k < 4; k++) { | | 1520 | for (k = 0; k < 4; k++) { |
1603 | bbit = 0x1; | | 1521 | bbit = 0x1; |
1604 | latch1 = 0; | | 1522 | latch1 = 0; |
1605 | for (j = 0; j < 4; j++) { | | 1523 | for (j = 0; j < 4; j++) { |
1606 | if (im & bit) | | 1524 | if (im & bit) |
1607 | latch1 |= bbit; | | 1525 | latch1 |= bbit; |
1608 | bbit <<= 1; | | 1526 | bbit <<= 1; |
1609 | if (ma & bit) | | 1527 | if (ma & bit) |
1610 | latch1 |= bbit; | | 1528 | latch1 |= bbit; |
1611 | bbit <<= 1; | | 1529 | bbit <<= 1; |
1612 | bit >>= 1; | | 1530 | bit >>= 1; |
1613 | } | | 1531 | } |
1614 | bbit = 0x1; | | 1532 | bbit = 0x1; |
1615 | latch2 = 0; | | 1533 | latch2 = 0; |
1616 | for (j = 0; j < 4; j++) { | | 1534 | for (j = 0; j < 4; j++) { |
1617 | if (im & bit) | | 1535 | if (im & bit) |
1618 | latch2 |= bbit; | | 1536 | latch2 |= bbit; |
1619 | bbit <<= 1; | | 1537 | bbit <<= 1; |
1620 | if (ma & bit) | | 1538 | if (ma & bit) |
1621 | latch2 |= bbit; | | 1539 | latch2 |= bbit; |
1622 | bbit <<= 1; | | 1540 | bbit <<= 1; |
1623 | bit >>= 1; | | 1541 | bit >>= 1; |
1624 | } | | 1542 | } |
1625 | p9100_ramdac_write(sc, DAC_INDX_DATA, latch1); | | 1543 | p9100_ramdac_write(sc, DAC_INDX_DATA, latch1); |
1626 | p9100_ramdac_write(sc, DAC_INDX_DATA, latch2); | | 1544 | p9100_ramdac_write(sc, DAC_INDX_DATA, latch2); |
1627 | } | | 1545 | } |
1628 | } | | 1546 | } |
1629 | #ifdef PNOZZ_DEBUG_CURSOR | | 1547 | #ifdef PNOZZ_DEBUG_CURSOR |
1630 | printf("image:\n"); | | 1548 | printf("image:\n"); |
1631 | for (i=0;i<0x80;i+=2) | | 1549 | for (i=0;i<0x80;i+=2) |
1632 | printf("%08x %08x\n", image[i], image[i+1]); | | 1550 | printf("%08x %08x\n", image[i], image[i+1]); |
1633 | printf("mask:\n"); | | 1551 | printf("mask:\n"); |
1634 | for (i=0;i<0x80;i+=2) | | 1552 | for (i=0;i<0x80;i+=2) |
1635 | printf("%08x %08x\n", mask[i], mask[i+1]); | | 1553 | printf("%08x %08x\n", mask[i], mask[i+1]); |
1636 | #endif | | 1554 | #endif |
1637 | #ifdef PNOZZ_PARANOID | | 1555 | #ifdef PNOZZ_PARANOID |
1638 | splx(s); | | 1556 | splx(s); |
1639 | #endif | | 1557 | #endif |
1640 | } | | 1558 | } |
1641 | | | 1559 | |
1642 | #if NTCTRL > 0 | | 1560 | #if NTCTRL > 0 |
1643 | static void | | 1561 | static void |
1644 | p9100_set_extvga(void *cookie, int status) | | 1562 | p9100_set_extvga(void *cookie, int status) |
1645 | { | | 1563 | { |
1646 | struct p9100_softc *sc = cookie; | | 1564 | struct p9100_softc *sc = cookie; |
1647 | #ifdef PNOZZ_PARANOID | | 1565 | #ifdef PNOZZ_PARANOID |
1648 | int s; | | 1566 | int s; |
1649 | | | 1567 | |
1650 | s = splhigh(); | | 1568 | s = splhigh(); |
1651 | #endif | | 1569 | #endif |
1652 | | | 1570 | |
1653 | #ifdef PNOZZ_DEBUG | | 1571 | #ifdef PNOZZ_DEBUG |
1654 | printf("%s: external VGA %s\n", device_xname(sc->sc_dev), | | 1572 | printf("%s: external VGA %s\n", device_xname(sc->sc_dev), |
1655 | status ? "on" : "off"); | | 1573 | status ? "on" : "off"); |
1656 | #endif | | 1574 | #endif |
1657 | | | 1575 | |
1658 | sc->sc_last_offset = 0xffffffff; | | 1576 | sc->sc_last_offset = 0xffffffff; |
1659 | | | 1577 | |
1660 | if (status) { | | 1578 | if (status) { |
1661 | p9100_ramdac_write_ctl(sc, DAC_POWER_MGT, | | 1579 | p9100_ramdac_write_ctl(sc, DAC_POWER_MGT, |
1662 | p9100_ramdac_read_ctl(sc, DAC_POWER_MGT) & | | 1580 | p9100_ramdac_read_ctl(sc, DAC_POWER_MGT) & |
1663 | ~DAC_POWER_IPWR_DISABLE); | | 1581 | ~DAC_POWER_IPWR_DISABLE); |
1664 | } else { | | 1582 | } else { |
1665 | p9100_ramdac_write_ctl(sc, DAC_POWER_MGT, | | 1583 | p9100_ramdac_write_ctl(sc, DAC_POWER_MGT, |
1666 | p9100_ramdac_read_ctl(sc, DAC_POWER_MGT) | | | 1584 | p9100_ramdac_read_ctl(sc, DAC_POWER_MGT) | |
1667 | DAC_POWER_IPWR_DISABLE); | | 1585 | DAC_POWER_IPWR_DISABLE); |
1668 | } | | 1586 | } |
1669 | #ifdef PNOZZ_PARANOID | | 1587 | #ifdef PNOZZ_PARANOID |
1670 | splx(s); | | 1588 | splx(s); |
1671 | #endif | | 1589 | #endif |
1672 | } | | 1590 | } |
1673 | #endif /* NTCTRL > 0 */ | | 1591 | #endif /* NTCTRL > 0 */ |
1674 | | | 1592 | |
1675 | static int | | 1593 | static int |
1676 | upper_bit(uint32_t b) | | 1594 | upper_bit(uint32_t b) |
1677 | { | | 1595 | { |
1678 | uint32_t mask=0x80000000; | | 1596 | uint32_t mask=0x80000000; |
1679 | int cnt = 31; | | 1597 | int cnt = 31; |
1680 | if (b == 0) | | 1598 | if (b == 0) |
1681 | return -1; | | 1599 | return -1; |
1682 | while ((mask != 0) && ((b & mask) == 0)) { | | 1600 | while ((mask != 0) && ((b & mask) == 0)) { |
1683 | mask = mask >> 1; | | 1601 | mask = mask >> 1; |
1684 | cnt--; | | 1602 | cnt--; |
1685 | } | | 1603 | } |
1686 | return cnt; | | 1604 | return cnt; |
1687 | } | | 1605 | } |
1688 | | | 1606 | |
1689 | static int | | 1607 | static int |
1690 | p9100_set_depth(struct p9100_softc *sc, int depth) | | 1608 | p9100_set_depth(struct p9100_softc *sc, int depth) |
1691 | { | | 1609 | { |
1692 | int new_sls; | | 1610 | int new_sls; |
1693 | uint32_t bits, scr, memctl, mem; | | 1611 | uint32_t bits, scr, memctl, mem; |
1694 | int s0, s1, s2, s3, ps, crtcline; | | 1612 | int s0, s1, s2, s3, ps, crtcline; |
1695 | uint8_t pf, mc3, es; | | 1613 | uint8_t pf, mc3, es; |
1696 | | | 1614 | |
1697 | switch (depth) { | | 1615 | switch (depth) { |
1698 | case 8: | | 1616 | case 8: |
1699 | sc->sc_depthshift = 0; | | 1617 | sc->sc_depthshift = 0; |
1700 | ps = 2; | | 1618 | ps = 2; |
1701 | pf = 3; | | 1619 | pf = 3; |
1702 | mc3 = 0; | | 1620 | mc3 = 0; |
1703 | es = 0; /* no swapping */ | | 1621 | es = 0; /* no swapping */ |
1704 | memctl = 3; | | 1622 | memctl = 3; |
1705 | break; | | 1623 | break; |
1706 | case 16: | | 1624 | case 16: |
1707 | sc->sc_depthshift = 1; | | 1625 | sc->sc_depthshift = 1; |
1708 | ps = 3; | | 1626 | ps = 3; |
1709 | pf = 4; | | 1627 | pf = 4; |
1710 | mc3 = 0; | | 1628 | mc3 = 0; |
1711 | es = 2; /* swap bytes in 16bit words */ | | 1629 | es = 2; /* swap bytes in 16bit words */ |
1712 | memctl = 2; | | 1630 | memctl = 2; |
1713 | break; | | 1631 | break; |
1714 | case 24: | | 1632 | case 24: |
1715 | /* boo */ | | 1633 | /* boo */ |
1716 | printf("We don't DO 24bit pixels dammit!\n"); | | 1634 | printf("We don't DO 24bit pixels dammit!\n"); |
1717 | return 0; | | 1635 | return 0; |
1718 | case 32: | | 1636 | case 32: |
1719 | sc->sc_depthshift = 2; | | 1637 | sc->sc_depthshift = 2; |
1720 | ps = 5; | | 1638 | ps = 5; |
1721 | pf = 6; | | 1639 | pf = 6; |
1722 | mc3 = 0; | | 1640 | mc3 = 0; |
1723 | es = 6; /* swap both half-words and bytes */ | | 1641 | es = 6; /* swap both half-words and bytes */ |
1724 | memctl = 1; /* 0 */ | | 1642 | memctl = 1; /* 0 */ |
1725 | break; | | 1643 | break; |
1726 | default: | | 1644 | default: |
1727 | aprint_error("%s: bogus colour depth (%d)\n", | | 1645 | aprint_error("%s: bogus colour depth (%d)\n", |
1728 | __func__, depth); | | 1646 | __func__, depth); |
1729 | return FALSE; | | 1647 | return FALSE; |
1730 | } | | 1648 | } |
1731 | /* | | 1649 | /* |
1732 | * this could be done a lot shorter and faster but then nobody would | | 1650 | * this could be done a lot shorter and faster but then nobody would |
1733 | * understand what the hell we're doing here without getting a major | | 1651 | * understand what the hell we're doing here without getting a major |
1734 | * headache. Scanline size is encoded as 4 shift values, 3 of them 3 bits | | 1652 | * headache. Scanline size is encoded as 4 shift values, 3 of them 3 bits |
1735 | * wide, 16 << n for n>0, one 2 bits, 512 << n for n>0. n==0 means 0 | | 1653 | * wide, 16 << n for n>0, one 2 bits, 512 << n for n>0. n==0 means 0 |
1736 | */ | | 1654 | */ |
1737 | new_sls = sc->sc_width << sc->sc_depthshift; | | 1655 | new_sls = sc->sc_width << sc->sc_depthshift; |
1738 | sc->sc_stride = new_sls; | | 1656 | sc->sc_stride = new_sls; |
1739 | bits = new_sls; | | 1657 | bits = new_sls; |
1740 | s3 = upper_bit(bits); | | 1658 | s3 = upper_bit(bits); |
1741 | if (s3 > 9) { | | 1659 | if (s3 > 9) { |
1742 | bits &= ~(1 << s3); | | 1660 | bits &= ~(1 << s3); |
1743 | s3 -= 9; | | 1661 | s3 -= 9; |
1744 | } else | | 1662 | } else |
1745 | s3 = 0; | | 1663 | s3 = 0; |
1746 | s2 = upper_bit(bits); | | 1664 | s2 = upper_bit(bits); |
1747 | if (s2 > 0) { | | 1665 | if (s2 > 0) { |
1748 | bits &= ~(1 << s2); | | 1666 | bits &= ~(1 << s2); |
1749 | s2 -= 4; | | 1667 | s2 -= 4; |
1750 | } else | | 1668 | } else |
1751 | s2 = 0; | | 1669 | s2 = 0; |
1752 | s1 = upper_bit(bits); | | 1670 | s1 = upper_bit(bits); |
1753 | if (s1 > 0) { | | 1671 | if (s1 > 0) { |
1754 | bits &= ~(1 << s1); | | 1672 | bits &= ~(1 << s1); |
1755 | s1 -= 4; | | 1673 | s1 -= 4; |
1756 | } else | | 1674 | } else |
1757 | s1 = 0; | | 1675 | s1 = 0; |
1758 | s0 = upper_bit(bits); | | 1676 | s0 = upper_bit(bits); |
1759 | if (s0 > 0) { | | 1677 | if (s0 > 0) { |
1760 | bits &= ~(1 << s0); | | 1678 | bits &= ~(1 << s0); |
1761 | s0 -= 4; | | 1679 | s0 -= 4; |
1762 | } else | | 1680 | } else |
1763 | s0 = 0; | | 1681 | s0 = 0; |
1764 | | | 1682 | |
1765 | | | 1683 | |
1766 | DPRINTF("sls: %x sh: %d %d %d %d leftover: %x\n", new_sls, s0, s1, | | 1684 | DPRINTF("sls: %x sh: %d %d %d %d leftover: %x\n", new_sls, s0, s1, |
1767 | s2, s3, bits); | | 1685 | s2, s3, bits); |
1768 | | | 1686 | |
1769 | /* | | 1687 | /* |
1770 | * now let's put these values into the System Config Register. No need to | | 1688 | * now let's put these values into the System Config Register. No need to |
1771 | * read it here since we (hopefully) just saved the content | | 1689 | * read it here since we (hopefully) just saved the content |
1772 | */ | | 1690 | */ |
1773 | scr = p9100_ctl_read_4(sc, SYS_CONF); | | 1691 | scr = p9100_ctl_read_4(sc, SYS_CONF); |
1774 | scr = (s0 << SHIFT_0) | (s1 << SHIFT_1) | (s2 << SHIFT_2) | | | 1692 | scr = (s0 << SHIFT_0) | (s1 << SHIFT_1) | (s2 << SHIFT_2) | |
1775 | (s3 << SHIFT_3) | (ps << PIXEL_SHIFT) | (es << SWAP_SHIFT); | | 1693 | (s3 << SHIFT_3) | (ps << PIXEL_SHIFT) | (es << SWAP_SHIFT); |
1776 | | | 1694 | |
1777 | DPRINTF("new scr: %x DAC %x %x\n", scr, pf, mc3); | | 1695 | DPRINTF("new scr: %x DAC %x %x\n", scr, pf, mc3); |
1778 | | | 1696 | |
1779 | mem = p9100_ctl_read_4(sc, VID_MEM_CONFIG); | | 1697 | mem = p9100_ctl_read_4(sc, VID_MEM_CONFIG); |
1780 | | | 1698 | |
1781 | DPRINTF("old memctl: %08x\n", mem); | | 1699 | DPRINTF("old memctl: %08x\n", mem); |
1782 | | | 1700 | |
1783 | /* set shift and crtc clock */ | | 1701 | /* set shift and crtc clock */ |
1784 | mem &= ~(0x0000fc00); | | 1702 | mem &= ~(0x0000fc00); |
1785 | mem |= (memctl << 10) | (memctl << 13); | | 1703 | mem |= (memctl << 10) | (memctl << 13); |
1786 | p9100_ctl_write_4(sc, VID_MEM_CONFIG, mem); | | 1704 | p9100_ctl_write_4(sc, VID_MEM_CONFIG, mem); |
1787 | | | 1705 | |
1788 | DPRINTF("new memctl: %08x\n", mem); | | 1706 | DPRINTF("new memctl: %08x\n", mem); |
1789 | | | 1707 | |
1790 | /* whack the engine... */ | | 1708 | /* whack the engine... */ |
1791 | p9100_ctl_write_4(sc, SYS_CONF, scr); | | 1709 | p9100_ctl_write_4(sc, SYS_CONF, scr); |
1792 | | | 1710 | |
1793 | /* ok, whack the DAC */ | | 1711 | /* ok, whack the DAC */ |
1794 | p9100_ramdac_write_ctl(sc, DAC_MISC_1, 0x11); | | 1712 | p9100_ramdac_write_ctl(sc, DAC_MISC_1, 0x11); |
1795 | p9100_ramdac_write_ctl(sc, DAC_MISC_2, 0x45); | | 1713 | p9100_ramdac_write_ctl(sc, DAC_MISC_2, 0x45); |
1796 | p9100_ramdac_write_ctl(sc, DAC_MISC_3, mc3); | | 1714 | p9100_ramdac_write_ctl(sc, DAC_MISC_3, mc3); |
1797 | /* | | 1715 | /* |
1798 | * despite the 3GX manual saying otherwise we don't need to mess with | | 1716 | * despite the 3GX manual saying otherwise we don't need to mess with |
1799 | * any clock dividers here | | 1717 | * any clock dividers here |
1800 | */ | | 1718 | */ |
1801 | p9100_ramdac_write_ctl(sc, DAC_MISC_CLK, 1); | | 1719 | p9100_ramdac_write_ctl(sc, DAC_MISC_CLK, 1); |
1802 | p9100_ramdac_write_ctl(sc, 3, 0); | | 1720 | p9100_ramdac_write_ctl(sc, 3, 0); |
1803 | p9100_ramdac_write_ctl(sc, 4, 0); | | 1721 | p9100_ramdac_write_ctl(sc, 4, 0); |
1804 | | | 1722 | |
1805 | p9100_ramdac_write_ctl(sc, DAC_POWER_MGT, 0); | | 1723 | p9100_ramdac_write_ctl(sc, DAC_POWER_MGT, 0); |
1806 | p9100_ramdac_write_ctl(sc, DAC_OPERATION, 0); | | 1724 | p9100_ramdac_write_ctl(sc, DAC_OPERATION, 0); |
1807 | p9100_ramdac_write_ctl(sc, DAC_PALETTE_CTRL, 0); | | 1725 | p9100_ramdac_write_ctl(sc, DAC_PALETTE_CTRL, 0); |
1808 | | | 1726 | |
1809 | p9100_ramdac_write_ctl(sc, DAC_PIXEL_FMT, pf); | | 1727 | p9100_ramdac_write_ctl(sc, DAC_PIXEL_FMT, pf); |
1810 | | | 1728 | |
1811 | /* TODO: distinguish between 15 and 16 bit */ | | 1729 | /* TODO: distinguish between 15 and 16 bit */ |
1812 | p9100_ramdac_write_ctl(sc, DAC_8BIT_CTRL, 0); | | 1730 | p9100_ramdac_write_ctl(sc, DAC_8BIT_CTRL, 0); |
1813 | /* direct colour, linear, 565 */ | | 1731 | /* direct colour, linear, 565 */ |
1814 | p9100_ramdac_write_ctl(sc, DAC_16BIT_CTRL, 0xc6); | | 1732 | p9100_ramdac_write_ctl(sc, DAC_16BIT_CTRL, 0xc6); |
1815 | /* direct colour */ | | 1733 | /* direct colour */ |
1816 | p9100_ramdac_write_ctl(sc, DAC_32BIT_CTRL, 3); | | 1734 | p9100_ramdac_write_ctl(sc, DAC_32BIT_CTRL, 3); |
1817 | | | 1735 | |
1818 | /* From the 3GX manual. Needs magic number reduction */ | | 1736 | /* From the 3GX manual. Needs magic number reduction */ |
1819 | p9100_ramdac_write_ctl(sc, 0x10, 2); | | 1737 | p9100_ramdac_write_ctl(sc, 0x10, 2); |
1820 | p9100_ramdac_write_ctl(sc, 0x11, 0); | | 1738 | p9100_ramdac_write_ctl(sc, 0x11, 0); |
1821 | p9100_ramdac_write_ctl(sc, 0x14, 5); | | 1739 | p9100_ramdac_write_ctl(sc, 0x14, 5); |
1822 | p9100_ramdac_write_ctl(sc, 0x08, 1); | | 1740 | p9100_ramdac_write_ctl(sc, 0x08, 1); |
1823 | p9100_ramdac_write_ctl(sc, 0x15, 5); | | 1741 | p9100_ramdac_write_ctl(sc, 0x15, 5); |
1824 | p9100_ramdac_write_ctl(sc, 0x16, 0x63); | | 1742 | p9100_ramdac_write_ctl(sc, 0x16, 0x63); |
1825 | | | 1743 | |
1826 | /* whack the CRTC */ | | 1744 | /* whack the CRTC */ |
1827 | /* we always transfer 64bit in one go */ | | 1745 | /* we always transfer 64bit in one go */ |
1828 | crtcline = sc->sc_stride >> 3; | | 1746 | crtcline = sc->sc_stride >> 3; |
1829 | | | 1747 | |
1830 | DPRINTF("crtcline: %d\n", crtcline); | | 1748 | DPRINTF("crtcline: %d\n", crtcline); |
1831 | | | 1749 | |
1832 | p9100_ctl_write_4(sc, VID_HTOTAL, (24 << sc->sc_depthshift) + crtcline); | | 1750 | p9100_ctl_write_4(sc, VID_HTOTAL, (24 << sc->sc_depthshift) + crtcline); |
1833 | p9100_ctl_write_4(sc, VID_HSRE, 8 << sc->sc_depthshift); | | 1751 | p9100_ctl_write_4(sc, VID_HSRE, 8 << sc->sc_depthshift); |
1834 | p9100_ctl_write_4(sc, VID_HBRE, 18 << sc->sc_depthshift); | | 1752 | p9100_ctl_write_4(sc, VID_HBRE, 18 << sc->sc_depthshift); |
1835 | p9100_ctl_write_4(sc, VID_HBFE, (18 << sc->sc_depthshift) + crtcline); | | 1753 | p9100_ctl_write_4(sc, VID_HBFE, (18 << sc->sc_depthshift) + crtcline); |
1836 | | | 1754 | |
1837 | #ifdef PNOZZ_DEBUG | | 1755 | #ifdef PNOZZ_DEBUG |
1838 | { | | 1756 | { |
1839 | uint32_t sscr; | | 1757 | uint32_t sscr; |
1840 | sscr = p9100_ctl_read_4(sc, SYS_CONF); | | 1758 | sscr = p9100_ctl_read_4(sc, SYS_CONF); |
1841 | printf("scr: %x\n", sscr); | | 1759 | printf("scr: %x\n", sscr); |
1842 | } | | 1760 | } |
1843 | #endif | | 1761 | #endif |
1844 | return TRUE; | | 1762 | return TRUE; |
1845 | } | | 1763 | } |