machfb.c revision 1.19 1 /* $NetBSD: machfb.c,v 1.19 2005/01/09 16:29:20 martin Exp $ */
2
3 /*
4 * Copyright (c) 2002 Bang Jun-Young
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /*
31 * Some code is derived from ATI Rage Pro and Derivatives Programmer's Guide.
32 */
33
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: machfb.c,v 1.19 2005/01/09 16:29:20 martin Exp $");
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/device.h>
41 #include <sys/malloc.h>
42 #include <sys/callout.h>
43
44 #ifdef __sparc__
45 #include <machine/promlib.h>
46 #endif
47
48 #include <dev/ic/videomode.h>
49
50 #include <dev/pci/pcivar.h>
51 #include <dev/pci/pcireg.h>
52 #include <dev/pci/pcidevs.h>
53 #include <dev/pci/pciio.h>
54 #include <dev/pci/machfbreg.h>
55
56 #include <dev/wscons/wsdisplayvar.h>
57 #include <dev/wscons/wsconsio.h>
58 #include <dev/wsfont/wsfont.h>
59 #include <dev/rasops/rasops.h>
60
61 #include "opt_wsemul.h"
62
63 #define MACH64_REG_SIZE 1024
64 #define MACH64_REG_OFF 0x7ffc00
65
66 #define NBARS 3 /* number of Mach64 PCI BARs */
67
68 struct vga_bar {
69 bus_addr_t vb_base;
70 bus_size_t vb_size;
71 pcireg_t vb_type;
72 int vb_flags;
73 };
74
75 struct mach64_softc {
76 struct device sc_dev;
77 pci_chipset_tag_t sc_pc;
78 pcitag_t sc_pcitag;
79
80 struct vga_bar sc_bars[NBARS];
81 struct vga_bar sc_rom;
82
83 #define sc_aperbase sc_bars[0].vb_base
84 #define sc_apersize sc_bars[0].vb_size
85
86 #define sc_iobase sc_bars[1].vb_base
87 #define sc_iosize sc_bars[1].vb_size
88
89 #define sc_regbase sc_bars[2].vb_base
90 #define sc_regsize sc_bars[2].vb_size
91
92 bus_space_tag_t sc_regt;
93 bus_space_tag_t sc_memt;
94 bus_space_handle_t sc_regh;
95 bus_space_handle_t sc_memh;
96
97 size_t memsize;
98 int memtype;
99
100 int has_dsp;
101 int bits_per_pixel;
102 int max_x, max_y;
103 int virt_x, virt_y;
104 int color_depth;
105
106 int mem_freq;
107 int ramdac_freq;
108 int ref_freq;
109
110 int ref_div;
111 int log2_vclk_post_div;
112 int vclk_post_div;
113 int vclk_fb_div;
114 int mclk_post_div;
115 int mclk_fb_div;
116
117 struct mach64screen *wanted;
118 struct mach64screen *active;
119 void (*switchcb)(void *, int, int);
120 void *switchcbarg;
121 struct callout switch_callout;
122 LIST_HEAD(, mach64screen) screens;
123 const struct wsscreen_descr *currenttype;
124 u_char sc_cmap_red[256];
125 u_char sc_cmap_green[256];
126 u_char sc_cmap_blue[256];
127 int sc_dacw;
128 };
129
130 struct mach64screen {
131 struct rasops_info ri;
132 LIST_ENTRY(mach64screen) next;
133 struct mach64_softc *sc;
134 const struct wsscreen_descr *type;
135 int active;
136 u_int16_t *mem;
137 int dispoffset;
138 int mindispoffset;
139 int maxdispoffset;
140
141 int cursoron;
142 int cursorcol;
143 int cursorrow;
144 u_int16_t cursortmp;
145 };
146
147 struct mach64_crtcregs {
148 u_int32_t h_total_disp;
149 u_int32_t h_sync_strt_wid;
150 u_int32_t v_total_disp;
151 u_int32_t v_sync_strt_wid;
152 u_int32_t gen_cntl;
153 u_int32_t clock_cntl;
154 u_int32_t color_depth;
155 u_int32_t dot_clock;
156 };
157
158 struct {
159 u_int16_t chip_id;
160 u_int32_t ramdac_freq;
161 } mach64_info[] = {
162 { PCI_PRODUCT_ATI_MACH64_CT, 135000 },
163 { PCI_PRODUCT_ATI_RAGE_PRO_AGP, 230000 },
164 { PCI_PRODUCT_ATI_RAGE_PRO_AGP1X, 230000 },
165 { PCI_PRODUCT_ATI_RAGE_PRO_PCI_B, 230000 },
166 { PCI_PRODUCT_ATI_RAGE_XL_AGP, 230000 },
167 { PCI_PRODUCT_ATI_RAGE_PRO_PCI_P, 230000 },
168 { PCI_PRODUCT_ATI_RAGE_PRO_PCI_L, 230000 },
169 { PCI_PRODUCT_ATI_RAGE_XL_PCI, 230000 },
170 { PCI_PRODUCT_ATI_RAGE_II, 135000 },
171 { PCI_PRODUCT_ATI_RAGE_IIP, 200000 },
172 { PCI_PRODUCT_ATI_RAGE_IIC_PCI, 230000 },
173 { PCI_PRODUCT_ATI_RAGE_IIC_AGP_B, 230000 },
174 { PCI_PRODUCT_ATI_RAGE_IIC_AGP_P, 230000 },
175 { PCI_PRODUCT_ATI_RAGE_LT_PRO_AGP, 230000 },
176 { PCI_PRODUCT_ATI_RAGE_MOB_M3_PCI, 230000 },
177 { PCI_PRODUCT_ATI_RAGE_MOB_M3_AGP, 230000 },
178 { PCI_PRODUCT_ATI_RAGE_LT, 230000 },
179 { PCI_PRODUCT_ATI_RAGE_LT_PRO_PCI, 230000 },
180 { PCI_PRODUCT_ATI_RAGE_MOBILITY, 230000 },
181 { PCI_PRODUCT_ATI_RAGE_LT_PRO, 230000 },
182 { PCI_PRODUCT_ATI_MACH64_VT, 170000 },
183 { PCI_PRODUCT_ATI_MACH64_VTB, 200000 },
184 { PCI_PRODUCT_ATI_MACH64_VT4, 230000 }
185 };
186
187 static int mach64_chip_id, mach64_chip_rev;
188 static struct videomode default_mode;
189 static struct mach64screen mach64_console_screen;
190
191 static char *mach64_memtype_names[] = {
192 "(N/A)", "DRAM", "EDO DRAM", "EDO DRAM", "SDRAM", "SGRAM", "WRAM",
193 "(unknown type)"
194 };
195
196 struct videomode mach64_modes[] = {
197 /* 640x400 @ 70 Hz, 31.5 kHz */
198 { 25175, 640, 664, 760, 800, 400, 409, 411, 450, 0 },
199 /* 640x480 @ 72 Hz, 36.5 kHz */
200 { 25175, 640, 664, 760, 800, 480, 491, 493, 525, 0 },
201 /* 800x600 @ 72 Hz, 48.0 kHz */
202 { 50000, 800, 856, 976, 1040, 600, 637, 643, 666,
203 VID_PHSYNC | VID_PVSYNC },
204 /* 1024x768 @ 70 Hz, 56.5 kHz */
205 { 75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806,
206 VID_NHSYNC | VID_NVSYNC },
207 /* 1152x864 @ 70 Hz, 62.4 kHz */
208 { 92000, 1152, 1208, 1368, 1474, 864, 865, 875, 895, 0 },
209 /* 1280x1024 @ 70 Hz, 74.59 kHz */
210 { 126500, 1280, 1312, 1472, 1696, 1024, 1032, 1040, 1068,
211 VID_NHSYNC | VID_NVSYNC }
212 };
213
214 /* Macallan: let the terminal emulator program the palette, it should be in the softc anyway */
215 #if 1
216 /* FIXME values are wrong! */
217 const u_char mach64_cmap[16 * 3] = {
218 0x00, 0x00, 0x00, /* black */
219 0x7f, 0x00, 0x00, /* red */
220 0x00, 0x7f, 0x00, /* green */
221 0x7f, 0x7f, 0x00, /* brown */
222 0x00, 0x00, 0x7f, /* blue */
223 0x7f, 0x00, 0x7f, /* magenta */
224 0x00, 0x7f, 0x7f, /* cyan */
225 0xc8, 0xc8, 0xc8, /* white */
226
227 0x7f, 0x7f, 0x7f, /* black */
228 0xff, 0x00, 0x00, /* red */
229 0x00, 0xff, 0x00, /* green */
230 0xff, 0xff, 0x00, /* brown */
231 0x00, 0x00, 0xff, /* blue */
232 0xff, 0x00, 0xff, /* magenta */
233 0x00, 0xff, 0xff, /* cyan */
234 0xff, 0xff, 0xff, /* white */
235 };
236 #endif
237
238 #ifdef WSEMUL_VT100
239 extern const u_char rasops_cmap[768];
240 #endif
241
242 int mach64_match(struct device *, struct cfdata *, void *);
243 void mach64_attach(struct device *, struct device *, void *);
244
245 CFATTACH_DECL(machfb, sizeof(struct mach64_softc), mach64_match, mach64_attach,
246 NULL, NULL);
247
248 void mach64_init(struct mach64_softc *);
249 int mach64_get_memsize(struct mach64_softc *);
250 int mach64_get_max_ramdac(struct mach64_softc *);
251 void mach64_get_mode(struct mach64_softc *, struct videomode *);
252 int mach64_calc_crtcregs(struct mach64_softc *, struct mach64_crtcregs *,
253 struct videomode *);
254 void mach64_set_crtcregs(struct mach64_softc *, struct mach64_crtcregs *);
255 int mach64_modeswitch(struct mach64_softc *, struct videomode *);
256 void mach64_set_dsp(struct mach64_softc *);
257 void mach64_set_pll(struct mach64_softc *, int);
258 void mach64_reset_engine(struct mach64_softc *);
259 void mach64_init_engine(struct mach64_softc *);
260 void mach64_adjust_frame(struct mach64_softc *, int, int);
261 void mach64_init_lut(struct mach64_softc *);
262 void mach64_switch_screen(struct mach64_softc *);
263 void mach64_init_screen(struct mach64_softc *, struct mach64screen *,
264 const struct wsscreen_descr *, int, long *, int);
265 void mach64_restore_screen(struct mach64screen *,
266 const struct wsscreen_descr *, u_int16_t *);
267 int mach64_set_screentype(struct mach64_softc *,
268 const struct wsscreen_descr *);
269 int mach64_is_console(struct pci_attach_args *);
270
271 void mach64_cursor(void *, int, int, int);
272 int mach64_mapchar(void *, int, u_int *);
273 void mach64_putchar(void *, int, int, u_int, long);
274 void mach64_copycols(void *, int, int, int, int);
275 void mach64_erasecols(void *, int, int, int, long);
276 void mach64_copyrows(void *, int, int, int);
277 void mach64_eraserows(void *, int, int, long);
278 int mach64_allocattr(void *, int, int, int, long *);
279
280 void mach64_scroll(void *, void *, int);
281
282 int mach64_putcmap(struct mach64_softc *, struct wsdisplay_cmap *);
283 int mach64_getcmap(struct mach64_softc *, struct wsdisplay_cmap *);
284 int mach64_putpalreg(struct mach64_softc *, uint8_t, uint8_t, uint8_t, uint8_t);
285 void mach64_bitblt(struct mach64_softc *, int, int, int, int, int, int, int, int) ;
286 void mach64_rectfill(struct mach64_softc *, int, int, int, int, int);
287 void mach64_showpal(struct mach64_softc *);
288
289 #if 0
290 const struct wsdisplay_emulops mach64_emulops = {
291 mach64_cursor,
292 mach64_mapchar,
293 mach64_putchar,
294 mach64_copycols,
295 mach64_erasecols,
296 mach64_copyrows,
297 mach64_eraserows,
298 mach64_allocattr,
299 };
300 #endif
301
302 struct wsscreen_descr mach64_defaultscreen = {
303 "default",
304 0, 0,
305 &mach64_console_screen.ri.ri_ops,
306 8, 16,
307 WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
308 &default_mode
309 }, mach64_80x25_screen = {
310 "80x25", 80, 25,
311 &mach64_console_screen.ri.ri_ops,
312 8, 16,
313 WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
314 &mach64_modes[0]
315 }, mach64_80x30_screen = {
316 "80x30", 80, 30,
317 &mach64_console_screen.ri.ri_ops,
318 8, 16,
319 WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
320 &mach64_modes[1]
321 }, mach64_80x40_screen = {
322 "80x40", 80, 40,
323 &mach64_console_screen.ri.ri_ops,
324 8, 10,
325 WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
326 &mach64_modes[0]
327 }, mach64_80x50_screen = {
328 "80x50", 80, 50,
329 &mach64_console_screen.ri.ri_ops,
330 8, 8,
331 WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
332 &mach64_modes[0]
333 }, mach64_100x37_screen = {
334 "100x37", 100, 37,
335 &mach64_console_screen.ri.ri_ops,
336 8, 16,
337 WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
338 &mach64_modes[2]
339 }, mach64_128x48_screen = {
340 "128x48", 128, 48,
341 &mach64_console_screen.ri.ri_ops,
342 8, 16,
343 WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
344 &mach64_modes[3]
345 }, mach64_144x54_screen = {
346 "144x54", 144, 54,
347 &mach64_console_screen.ri.ri_ops,
348 8, 16,
349 WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
350 &mach64_modes[4]
351 }, mach64_160x64_screen = {
352 "160x54", 160, 64,
353 &mach64_console_screen.ri.ri_ops,
354 8, 16,
355 WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
356 &mach64_modes[5]
357 };
358
359 const struct wsscreen_descr *_mach64_scrlist[] = {
360 &mach64_defaultscreen,
361 &mach64_80x25_screen,
362 &mach64_80x30_screen,
363 &mach64_80x40_screen,
364 &mach64_80x50_screen,
365 &mach64_100x37_screen,
366 &mach64_128x48_screen,
367 &mach64_144x54_screen,
368 &mach64_160x64_screen
369 };
370
371 struct wsscreen_list mach64_screenlist = {
372 sizeof(_mach64_scrlist) / sizeof(struct wsscreen_descr *),
373 _mach64_scrlist
374 };
375
376 int mach64_ioctl(void *, u_long, caddr_t, int, struct proc *);
377 paddr_t mach64_mmap(void *, off_t, int);
378 int mach64_alloc_screen(void *, const struct wsscreen_descr *, void **,
379 int *, int *, long *);
380 void mach64_free_screen(void *, void *);
381 int mach64_show_screen(void *, void *, int, void (*)(void *, int, int),
382 void *);
383 int mach64_load_font(void *, void *, struct wsdisplay_font *);
384
385 struct wsdisplay_accessops mach64_accessops = {
386 mach64_ioctl,
387 mach64_mmap,
388 mach64_alloc_screen,
389 mach64_free_screen,
390 mach64_show_screen,
391 NULL, /* load_font */
392 NULL, /* polls */
393 NULL, /* getwschar */
394 NULL, /* putwschar */
395 NULL, /* scroll */
396 NULL, /* getborder */
397 NULL /* setborder */
398 };
399
400 /*
401 * Inline functions for getting access to register aperture.
402 */
403 static inline u_int32_t regr(struct mach64_softc *, u_int32_t);
404 static inline u_int8_t regrb(struct mach64_softc *, u_int32_t);
405 static inline void regw(struct mach64_softc *, u_int32_t, u_int32_t);
406 static inline void regwb(struct mach64_softc *, u_int32_t, u_int8_t);
407 static inline void regwb_pll(struct mach64_softc *, u_int32_t, u_int8_t);
408
409 static inline u_int32_t
410 regr(struct mach64_softc *sc, u_int32_t index)
411 {
412
413 return bus_space_read_4(sc->sc_regt, sc->sc_regh, index);
414 }
415
416 static inline u_int8_t
417 regrb(struct mach64_softc *sc, u_int32_t index)
418 {
419
420 return bus_space_read_1(sc->sc_regt, sc->sc_regh, index);
421 }
422
423 static inline void
424 regw(struct mach64_softc *sc, u_int32_t index, u_int32_t data)
425 {
426
427 bus_space_write_4(sc->sc_regt, sc->sc_regh, index, data);
428 bus_space_barrier(sc->sc_regt, sc->sc_regh, index, 4, BUS_SPACE_BARRIER_WRITE);
429 }
430
431 static inline void
432 regwb(struct mach64_softc *sc, u_int32_t index, u_int8_t data)
433 {
434
435 bus_space_write_1(sc->sc_regt, sc->sc_regh, index, data);
436 bus_space_barrier(sc->sc_regt, sc->sc_regh, index, 1, BUS_SPACE_BARRIER_WRITE);
437 }
438
439 static inline void
440 regwb_pll(struct mach64_softc *sc, u_int32_t index, u_int8_t data)
441 {
442
443 regwb(sc, CLOCK_CNTL + 1, (index << 2) | PLL_WR_EN);
444 regwb(sc, CLOCK_CNTL + 2, data);
445 regwb(sc, CLOCK_CNTL + 1, (index << 2) & ~PLL_WR_EN);
446 }
447
448 static inline void
449 wait_for_fifo(struct mach64_softc *sc, u_int8_t v)
450 {
451
452 while ((regr(sc, FIFO_STAT) & 0xffff) > (0x8000 >> v))
453 ;
454 }
455
456 static inline void
457 wait_for_idle(struct mach64_softc *sc)
458 {
459
460 wait_for_fifo(sc, 16);
461 while ((regr(sc, GUI_STAT) & 1) != 0)
462 ;
463 }
464
465 int
466 mach64_match(struct device *parent, struct cfdata *match, void *aux)
467 {
468 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
469 int i;
470
471 if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY ||
472 PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA)
473 return 0;
474
475 for (i = 0; i < sizeof(mach64_info) / sizeof(mach64_info[0]); i++)
476 if (PCI_PRODUCT(pa->pa_id) == mach64_info[i].chip_id) {
477 mach64_chip_id = PCI_PRODUCT(pa->pa_id);
478 mach64_chip_rev = PCI_REVISION(pa->pa_class);
479 return 1;
480 }
481
482 return 0;
483 }
484
485 void
486 mach64_attach(struct device *parent, struct device *self, void *aux)
487 {
488 struct mach64_softc *sc = (void *)self;
489 struct pci_attach_args *pa = aux;
490 char devinfo[256];
491 int bar, reg, id;
492 struct wsemuldisplaydev_attach_args aa;
493 long defattr;
494 int setmode, console;
495
496 sc->sc_pc = pa->pa_pc;
497 sc->sc_pcitag = pa->pa_tag;
498 sc->sc_dacw=-1;
499 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
500 printf(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(pa->pa_class));
501
502 for (bar = 0; bar < NBARS; bar++) {
503 reg = PCI_MAPREG_START + (bar * 4);
504 sc->sc_bars[bar].vb_type = pci_mapreg_type(sc->sc_pc,
505 sc->sc_pcitag, reg);
506 (void)pci_mapreg_info(sc->sc_pc, sc->sc_pcitag, reg,
507 sc->sc_bars[bar].vb_type, &sc->sc_bars[bar].vb_base,
508 &sc->sc_bars[bar].vb_size, &sc->sc_bars[bar].vb_flags);
509 }
510 sc->sc_memt = pa->pa_memt;
511
512 mach64_init(sc);
513
514 printf("%s: %d MB aperture at 0x%08x, %d KB registers at 0x%08x\n",
515 sc->sc_dev.dv_xname, (u_int)(sc->sc_apersize / (1024 * 1024)),
516 (u_int)sc->sc_aperbase, (u_int)(sc->sc_regsize / 1024),
517 (u_int)sc->sc_regbase);
518
519 if (mach64_chip_id == PCI_PRODUCT_ATI_MACH64_CT ||
520 ((mach64_chip_id == PCI_PRODUCT_ATI_MACH64_VT ||
521 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_II) &&
522 (mach64_chip_rev & 0x07) == 0))
523 sc->has_dsp = 0;
524 else
525 sc->has_dsp = 1;
526
527 sc->memsize = mach64_get_memsize(sc);
528 if (sc->memsize == 8192)
529 /* The last page is used as register aperture. */
530 sc->memsize -= 4;
531 sc->memtype = regr(sc, CONFIG_STAT0) & 0x07;
532
533 /* XXX is there any way to calculate reference frequency from
534 known values? */
535 if (mach64_chip_id == PCI_PRODUCT_ATI_RAGE_XL_PCI)
536 sc->ref_freq = 29498;
537 else
538 sc->ref_freq = 14318;
539
540 regwb(sc, CLOCK_CNTL + 1, PLL_REF_DIV << 2);
541 sc->ref_div = regrb(sc, CLOCK_CNTL + 2);
542 regwb(sc, CLOCK_CNTL + 1, MCLK_FB_DIV << 2);
543 sc->mclk_fb_div = regrb(sc, CLOCK_CNTL + 2);
544 sc->mem_freq = (2 * sc->ref_freq * sc->mclk_fb_div) /
545 (sc->ref_div * 2);
546 sc->mclk_post_div = (sc->mclk_fb_div * 2 * sc->ref_freq) /
547 (sc->mem_freq * sc->ref_div);
548 sc->ramdac_freq = mach64_get_max_ramdac(sc);
549 printf("%s: %ld KB %s %d.%d MHz, maximum RAMDAC clock %d MHz\n",
550 sc->sc_dev.dv_xname, (u_long)sc->memsize,
551 mach64_memtype_names[sc->memtype],
552 sc->mem_freq / 1000, sc->mem_freq % 1000,
553 sc->ramdac_freq / 1000);
554
555 id = regr(sc, CONFIG_CHIP_ID) & 0xffff;
556 if (id != mach64_chip_id) {
557 printf("%s: chip ID mismatch, 0x%x != 0x%x\n",
558 sc->sc_dev.dv_xname, id, mach64_chip_id);
559 return;
560 }
561
562 console = mach64_is_console(pa);
563
564 #ifdef __sparc__
565 if (console) {
566 mach64_get_mode(sc, &default_mode);
567 setmode = 0;
568 } else {
569 memcpy(&default_mode, &mach64_modes[4], sizeof(struct videomode));
570 setmode = 1;
571 }
572 #else
573 memcpy(&default_mode, &mach64_modes[0], sizeof(struct videomode));
574 setmode = 1;
575 #endif
576
577 sc->bits_per_pixel = 8;
578 sc->virt_x = default_mode.hdisplay;
579 sc->virt_y = default_mode.vdisplay;
580 sc->max_x = sc->virt_x - 1;
581 sc->max_y = (sc->memsize * 1024) /
582 (sc->virt_x * (sc->bits_per_pixel / 8)) - 1;
583
584 sc->color_depth = CRTC_PIX_WIDTH_8BPP;
585
586 mach64_init_engine(sc);
587 #if 0
588 mach64_adjust_frame(0, 0);
589 if (sc->bits_per_pixel == 8)
590 mach64_init_lut(sc);
591 #endif
592
593 printf("%s: initial resolution %dx%d at %d bpp\n", sc->sc_dev.dv_xname,
594 default_mode.hdisplay, default_mode.vdisplay,
595 sc->bits_per_pixel);
596
597 mach64_console_screen.ri.ri_hw = sc;
598 mach64_console_screen.ri.ri_depth = sc->bits_per_pixel;
599 mach64_console_screen.ri.ri_bits = (void*)(u_long)sc->sc_aperbase;
600 mach64_console_screen.ri.ri_width = default_mode.hdisplay;
601 mach64_console_screen.ri.ri_height = default_mode.vdisplay;
602 mach64_console_screen.ri.ri_stride = mach64_console_screen.ri.ri_width;
603
604 mach64_console_screen.ri.ri_flg = RI_CLEAR|RI_CENTER;
605
606 #ifdef WSEMUL_SUN
607 mach64_console_screen.ri.ri_flg = RI_CLEAR|RI_CENTER|RI_FORCEMONO;
608 #endif
609
610 rasops_init(&mach64_console_screen.ri, mach64_console_screen.ri.ri_height / 16,
611 mach64_console_screen.ri.ri_width / 8); /* XXX width/height are nonsense */
612
613 /* enable acceleration */
614 mach64_console_screen.ri.ri_ops.copyrows=mach64_copyrows;
615 mach64_console_screen.ri.ri_ops.eraserows=mach64_eraserows;
616 mach64_console_screen.ri.ri_ops.copycols=mach64_copycols;
617 mach64_console_screen.ri.ri_ops.erasecols=mach64_erasecols;
618
619 mach64_defaultscreen.nrows = mach64_console_screen.ri.ri_rows;
620 mach64_defaultscreen.ncols = mach64_console_screen.ri.ri_cols;
621
622 mach64_console_screen.ri.ri_ops.allocattr(&mach64_console_screen.ri, 0, 0, 0,
623 &defattr);
624
625 /* really necessary? */
626 mach64_defaultscreen.capabilities=mach64_console_screen.ri.ri_caps;
627 mach64_defaultscreen.textops=&mach64_console_screen.ri.ri_ops;
628
629 /* Initialize fonts */
630 /* XXX Macallan: shouldn't that happen /before/ we call rasops_init()? */
631 wsfont_init();
632
633 if (console) {
634 mach64_init_screen(sc, &mach64_console_screen,
635 &mach64_defaultscreen, 1, &defattr, setmode);
636 wsdisplay_cnattach(&mach64_defaultscreen, &mach64_console_screen.ri,
637 0, 0, defattr);
638 }
639
640 mach64_init_lut(sc);
641
642 #ifdef DEBUG
643 mach64_showpal(sc);
644 delay(4000000);
645 #endif
646 aa.console = console;
647 aa.scrdata = &mach64_screenlist;
648 aa.accessops = &mach64_accessops;
649 aa.accesscookie = sc;
650
651 config_found(self, &aa, wsemuldisplaydevprint);
652 }
653
654 void
655 mach64_init_screen(struct mach64_softc *sc, struct mach64screen *scr,
656 const struct wsscreen_descr *type, int existing, long *attrp, int setmode)
657 {
658
659 scr->sc = sc;
660 scr->type = type;
661 scr->mindispoffset = 0;
662 scr->maxdispoffset = sc->memsize * 1024;
663 scr->dispoffset = 0;
664 scr->cursorcol = 0;
665 scr->cursorrow = 0;
666
667 scr->mem = (u_int16_t *)malloc(type->nrows * type->ncols * 2,
668 M_DEVBUF, M_WAITOK);
669 if (existing) {
670 scr->active = 1;
671
672 if (setmode && mach64_set_screentype(sc, type)) {
673 panic("%s: failed to switch video mode",
674 sc->sc_dev.dv_xname);
675 }
676 } else {
677 scr->active = 0;
678 }
679
680 LIST_INSERT_HEAD(&sc->screens, scr, next);
681 }
682
683 void
684 mach64_init(struct mach64_softc *sc)
685 {
686 u_int32_t *p32, saved_value;
687 u_int8_t *p;
688 int need_swap;
689
690 if (bus_space_map(sc->sc_memt, sc->sc_aperbase, sc->sc_apersize,
691 BUS_SPACE_MAP_LINEAR, &sc->sc_memh)) {
692 panic("%s: failed to map aperture", sc->sc_dev.dv_xname);
693 }
694 sc->sc_aperbase = (vaddr_t)bus_space_vaddr(sc->sc_memt, sc->sc_memh);
695
696 sc->sc_regt = sc->sc_memt;
697 bus_space_subregion(sc->sc_regt, sc->sc_memh, MACH64_REG_OFF,
698 sc->sc_regsize, &sc->sc_regh);
699 sc->sc_regbase = sc->sc_aperbase + 0x7ffc00;
700
701 /*
702 * Test wether the aperture is byte swapped or not
703 */
704 p32 = (u_int32_t*)(u_long)sc->sc_aperbase;
705 saved_value = *p32;
706 p = (u_int8_t*)(u_long)sc->sc_aperbase;
707 *p32 = 0x12345678;
708 if (p[0] == 0x12 && p[1] == 0x34 && p[2] == 0x56 && p[3] == 0x78)
709 need_swap = 0;
710 else
711 need_swap = 1;
712 if (need_swap) {
713 sc->sc_aperbase += 0x800000;
714 sc->sc_apersize -= 0x800000;
715 }
716 *p32 = saved_value;
717
718 LIST_INIT(&sc->screens);
719 sc->active = NULL;
720 sc->currenttype = &mach64_defaultscreen;
721 callout_init(&sc->switch_callout);
722 }
723
724 int
725 mach64_get_memsize(struct mach64_softc *sc)
726 {
727 int tmp, memsize;
728 int mem_tab[] = {
729 512, 1024, 2048, 4096, 6144, 8192, 12288, 16384
730 };
731
732 tmp = regr(sc, MEM_CNTL);
733 if (sc->has_dsp) {
734 tmp &= 0x0000000f;
735 if (tmp < 8)
736 memsize = (tmp + 1) * 512;
737 else if (tmp < 12)
738 memsize = (tmp - 3) * 1024;
739 else
740 memsize = (tmp - 7) * 2048;
741 } else {
742 memsize = mem_tab[tmp & 0x07];
743 }
744
745 return memsize;
746 }
747
748 int
749 mach64_get_max_ramdac(struct mach64_softc *sc)
750 {
751 int i;
752
753 if ((mach64_chip_id == PCI_PRODUCT_ATI_MACH64_VT ||
754 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_II) &&
755 (mach64_chip_rev & 0x07))
756 return 170000;
757
758 for (i = 0; i < sizeof(mach64_info) / sizeof(mach64_info[0]); i++)
759 if (mach64_chip_id == mach64_info[i].chip_id)
760 return mach64_info[i].ramdac_freq;
761
762 if (sc->bits_per_pixel == 8)
763 return 135000;
764 else
765 return 80000;
766 }
767
768 void
769 mach64_get_mode(struct mach64_softc *sc, struct videomode *mode)
770 {
771 struct mach64_crtcregs crtc;
772
773 crtc.h_total_disp = regr(sc, CRTC_H_TOTAL_DISP);
774 crtc.h_sync_strt_wid = regr(sc, CRTC_H_SYNC_STRT_WID);
775 crtc.v_total_disp = regr(sc, CRTC_V_TOTAL_DISP);
776 crtc.v_sync_strt_wid = regr(sc, CRTC_V_SYNC_STRT_WID);
777
778 mode->htotal = ((crtc.h_total_disp & 0xffff) + 1) << 3;
779 mode->hdisplay = ((crtc.h_total_disp >> 16) + 1) << 3;
780 mode->hsync_start = ((crtc.h_sync_strt_wid & 0xffff) + 1) << 3;
781 mode->hsync_end = ((crtc.h_sync_strt_wid >> 16) << 3) +
782 mode->hsync_start;
783 mode->vtotal = (crtc.v_total_disp & 0xffff) + 1;
784 mode->vdisplay = (crtc.v_total_disp >> 16) + 1;
785 mode->vsync_start = (crtc.v_sync_strt_wid & 0xffff) + 1;
786 mode->vsync_end = (crtc.v_sync_strt_wid >> 16) + mode->vsync_start;
787
788 #ifdef MACH64_DEBUG
789 printf("mach64_get_mode: %d %d %d %d %d %d %d %d\n",
790 mode->hdisplay, mode->hsync_start, mode->hsync_end, mode->htotal,
791 mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal);
792 #endif
793 }
794
795 int
796 mach64_calc_crtcregs(struct mach64_softc *sc, struct mach64_crtcregs *crtc,
797 struct videomode *mode)
798 {
799
800 if (mode->dot_clock > sc->ramdac_freq)
801 /* Clock too high. */
802 return 1;
803
804 crtc->h_total_disp = (((mode->hdisplay >> 3) - 1) << 16) |
805 ((mode->htotal >> 3) - 1);
806 crtc->h_sync_strt_wid =
807 (((mode->hsync_end - mode->hsync_start) >> 3) << 16) |
808 ((mode->hsync_start >> 3) - 1);
809
810 crtc->v_total_disp = ((mode->vdisplay - 1) << 16) |
811 (mode->vtotal - 1);
812 crtc->v_sync_strt_wid =
813 ((mode->vsync_end - mode->vsync_start) << 16) |
814 (mode->vsync_start - 1);
815
816 if (mode->flags & VID_NVSYNC)
817 crtc->v_sync_strt_wid |= CRTC_VSYNC_NEG;
818
819 switch (sc->bits_per_pixel) {
820 case 8:
821 crtc->color_depth = CRTC_PIX_WIDTH_8BPP;
822 break;
823 case 16:
824 crtc->color_depth = CRTC_PIX_WIDTH_16BPP;
825 break;
826 case 32:
827 crtc->color_depth = CRTC_PIX_WIDTH_32BPP;
828 break;
829 }
830
831 crtc->gen_cntl = 0;
832 if (mode->flags & VID_INTERLACE)
833 crtc->gen_cntl |= CRTC_INTERLACE_EN;
834 if (mode->flags & VID_CSYNC)
835 crtc->gen_cntl |= CRTC_CSYNC_EN;
836
837 crtc->dot_clock = mode->dot_clock;
838
839 return 0;
840 }
841
842 void
843 mach64_set_crtcregs(struct mach64_softc *sc, struct mach64_crtcregs *crtc)
844 {
845
846 mach64_set_pll(sc, crtc->dot_clock);
847
848 if (sc->has_dsp)
849 mach64_set_dsp(sc);
850
851 regw(sc, CRTC_H_TOTAL_DISP, crtc->h_total_disp);
852 regw(sc, CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid);
853 regw(sc, CRTC_V_TOTAL_DISP, crtc->v_total_disp);
854 regw(sc, CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid);
855
856 regw(sc, CRTC_VLINE_CRNT_VLINE, 0);
857
858 regw(sc, CRTC_OFF_PITCH, (sc->virt_x >> 3) << 22);
859
860 regw(sc, CRTC_GEN_CNTL, crtc->gen_cntl | crtc->color_depth |
861 CRTC_EXT_DISP_EN | CRTC_EXT_EN);
862 }
863
864 int
865 mach64_modeswitch(struct mach64_softc *sc, struct videomode *mode)
866 {
867 struct mach64_crtcregs crtc;
868
869 if (mach64_calc_crtcregs(sc, &crtc, mode))
870 return 1;
871
872 mach64_set_crtcregs(sc, &crtc);
873 return 0;
874 }
875
876 void
877 mach64_reset_engine(struct mach64_softc *sc)
878 {
879
880 /* Reset engine.*/
881 regw(sc, GEN_TEST_CNTL, regr(sc, GEN_TEST_CNTL) & ~GUI_ENGINE_ENABLE);
882
883 /* Enable engine. */
884 regw(sc, GEN_TEST_CNTL, regr(sc, GEN_TEST_CNTL) | GUI_ENGINE_ENABLE);
885
886 /* Ensure engine is not locked up by clearing any FIFO or
887 host errors. */
888 regw(sc, BUS_CNTL, regr(sc, BUS_CNTL) | BUS_HOST_ERR_ACK |
889 BUS_FIFO_ERR_ACK);
890 }
891
892 void
893 mach64_init_engine(struct mach64_softc *sc)
894 {
895 u_int32_t pitch_value;
896
897 pitch_value = sc->virt_x;
898
899 if (sc->bits_per_pixel == 24)
900 pitch_value *= 3;
901
902 mach64_reset_engine(sc);
903
904 wait_for_fifo(sc, 14);
905
906 regw(sc, CONTEXT_MASK, 0xffffffff);
907
908 regw(sc, DST_OFF_PITCH, (pitch_value / 8) << 22);
909
910 regw(sc, DST_Y_X, 0);
911 regw(sc, DST_HEIGHT, 0);
912 regw(sc, DST_BRES_ERR, 0);
913 regw(sc, DST_BRES_INC, 0);
914 regw(sc, DST_BRES_DEC, 0);
915
916 regw(sc, DST_CNTL, DST_LAST_PEL | DST_X_LEFT_TO_RIGHT |
917 DST_Y_TOP_TO_BOTTOM);
918
919 regw(sc, SRC_OFF_PITCH, (pitch_value / 8) << 22);
920
921 regw(sc, SRC_Y_X, 0);
922 regw(sc, SRC_HEIGHT1_WIDTH1, 1);
923 regw(sc, SRC_Y_X_START, 0);
924 regw(sc, SRC_HEIGHT2_WIDTH2, 1);
925
926 regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT);
927
928 wait_for_fifo(sc, 13);
929 regw(sc, HOST_CNTL, 0);
930
931 regw(sc, PAT_REG0, 0);
932 regw(sc, PAT_REG1, 0);
933 regw(sc, PAT_CNTL, 0);
934
935 regw(sc, SC_LEFT, 0);
936 regw(sc, SC_TOP, 0);
937 regw(sc, SC_BOTTOM, default_mode.vdisplay - 1);
938 regw(sc, SC_RIGHT, pitch_value - 1);
939
940 regw(sc, DP_BKGD_CLR, 0);
941 regw(sc, DP_FRGD_CLR, 0xffffffff);
942 regw(sc, DP_WRITE_MASK, 0xffffffff);
943 regw(sc, DP_MIX, (MIX_SRC << 16) | MIX_DST);
944
945 regw(sc, DP_SRC, FRGD_SRC_FRGD_CLR);
946
947 wait_for_fifo(sc, 3);
948 regw(sc, CLR_CMP_CLR, 0);
949 regw(sc, CLR_CMP_MASK, 0xffffffff);
950 regw(sc, CLR_CMP_CNTL, 0);
951
952 wait_for_fifo(sc, 2);
953 switch (sc->bits_per_pixel) {
954 case 8:
955 regw(sc, DP_PIX_WIDTH, HOST_8BPP | SRC_8BPP | DST_8BPP);
956 regw(sc, DP_CHAIN_MASK, DP_CHAIN_8BPP);
957 /* XXX Macallan: huh? We /want/ an 8 bit per channel palette! */
958 /*regw(sc, DAC_CNTL, regr(sc, DAC_CNTL) & ~DAC_8BIT_EN);*/
959 regw(sc, DAC_CNTL, regr(sc, DAC_CNTL) | DAC_8BIT_EN);
960 break;
961 #if 0
962 case 32:
963 regw(sc, DP_PIX_WIDTH, HOST_32BPP | SRC_32BPP | DST_32BPP);
964 regw(sc, DP_CHAIN_MASK, DP_CHAIN_32BPP);
965 regw(sc, DAC_CNTL, regr(sc, DAC_CNTL) | DAC_8BIT_EN);
966 break;
967 #endif
968 }
969
970 wait_for_fifo(sc, 5);
971 regw(sc, CRTC_INT_CNTL, regr(sc, CRTC_INT_CNTL) & ~0x20);
972 regw(sc, GUI_TRAJ_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
973
974 wait_for_idle(sc);
975 }
976
977 void
978 mach64_adjust_frame(struct mach64_softc *sc, int x, int y)
979 {
980 int offset;
981
982 offset = ((x + y * sc->virt_x) * (sc->bits_per_pixel >> 3)) >> 3;
983
984 regw(sc, CRTC_OFF_PITCH, (regr(sc, CRTC_OFF_PITCH) & 0xfff00000) |
985 offset);
986 }
987
988 void
989 mach64_set_dsp(struct mach64_softc *sc)
990 {
991 u_int32_t fifo_depth, page_size, dsp_precision, dsp_loop_latency;
992 u_int32_t dsp_off, dsp_on, dsp_xclks_per_qw;
993 u_int32_t xclks_per_qw, y;
994 u_int32_t fifo_off, fifo_on;
995
996 if (mach64_chip_id == PCI_PRODUCT_ATI_MACH64_VT ||
997 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_II ||
998 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_IIP ||
999 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_IIC_PCI ||
1000 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_IIC_AGP_B ||
1001 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_IIC_AGP_P) {
1002 dsp_loop_latency = 0;
1003 fifo_depth = 24;
1004 } else {
1005 dsp_loop_latency = 2;
1006 fifo_depth = 32;
1007 }
1008
1009 dsp_precision = 0;
1010 xclks_per_qw = (sc->mclk_fb_div * sc->vclk_post_div * 64 << 11) /
1011 (sc->vclk_fb_div * sc->mclk_post_div * sc->bits_per_pixel);
1012 y = (xclks_per_qw * fifo_depth) >> 11;
1013 while (y) {
1014 y >>= 1;
1015 dsp_precision++;
1016 }
1017 dsp_precision -= 5;
1018 fifo_off = ((xclks_per_qw * (fifo_depth - 1)) >> 5) + (3 << 6);
1019
1020 switch (sc->memtype) {
1021 case DRAM:
1022 case EDO_DRAM:
1023 case PSEUDO_EDO:
1024 if (sc->memsize > 1024) {
1025 page_size = 9;
1026 dsp_loop_latency += 6;
1027 } else {
1028 page_size = 10;
1029 if (sc->memtype == DRAM)
1030 dsp_loop_latency += 8;
1031 else
1032 dsp_loop_latency += 7;
1033 }
1034 break;
1035 case SDRAM:
1036 case SGRAM:
1037 if (sc->memsize > 1024) {
1038 page_size = 8;
1039 dsp_loop_latency += 8;
1040 } else {
1041 page_size = 10;
1042 dsp_loop_latency += 9;
1043 }
1044 break;
1045 default:
1046 page_size = 10;
1047 dsp_loop_latency += 9;
1048 break;
1049 }
1050
1051 if (xclks_per_qw >= (page_size << 11))
1052 fifo_on = ((2 * page_size + 1) << 6) + (xclks_per_qw >> 5);
1053 else
1054 fifo_on = (3 * page_size + 2) << 6;
1055
1056 dsp_xclks_per_qw = xclks_per_qw >> dsp_precision;
1057 dsp_on = fifo_on >> dsp_precision;
1058 dsp_off = fifo_off >> dsp_precision;
1059
1060 #ifdef MACH64_DEBUG
1061 printf("dsp_xclks_per_qw = %d, dsp_on = %d, dsp_off = %d,\n"
1062 "dsp_precision = %d, dsp_loop_latency = %d,\n"
1063 "mclk_fb_div = %d, vclk_fb_div = %d,\n"
1064 "mclk_post_div = %d, vclk_post_div = %d\n",
1065 dsp_xclks_per_qw, dsp_on, dsp_off, dsp_precision, dsp_loop_latency,
1066 sc->mclk_fb_div, sc->vclk_fb_div,
1067 sc->mclk_post_div, sc->vclk_post_div);
1068 #endif
1069
1070 regw(sc, DSP_ON_OFF, ((dsp_on << 16) & DSP_ON) | (dsp_off & DSP_OFF));
1071 regw(sc, DSP_CONFIG, ((dsp_precision << 20) & DSP_PRECISION) |
1072 ((dsp_loop_latency << 16) & DSP_LOOP_LATENCY) |
1073 (dsp_xclks_per_qw & DSP_XCLKS_PER_QW));
1074 }
1075
1076 void
1077 mach64_set_pll(struct mach64_softc *sc, int clock)
1078 {
1079 int q;
1080
1081 q = (clock * sc->ref_div * 100) / (2 * sc->ref_freq);
1082 #ifdef MACH64_DEBUG
1083 printf("q = %d\n", q);
1084 #endif
1085 if (q > 25500) {
1086 printf("Warning: q > 25500\n");
1087 q = 25500;
1088 sc->vclk_post_div = 1;
1089 sc->log2_vclk_post_div = 0;
1090 } else if (q > 12750) {
1091 sc->vclk_post_div = 1;
1092 sc->log2_vclk_post_div = 0;
1093 } else if (q > 6350) {
1094 sc->vclk_post_div = 2;
1095 sc->log2_vclk_post_div = 1;
1096 } else if (q > 3150) {
1097 sc->vclk_post_div = 4;
1098 sc->log2_vclk_post_div = 2;
1099 } else if (q >= 1600) {
1100 sc->vclk_post_div = 8;
1101 sc->log2_vclk_post_div = 3;
1102 } else {
1103 printf("Warning: q < 1600\n");
1104 sc->vclk_post_div = 8;
1105 sc->log2_vclk_post_div = 3;
1106 }
1107 sc->vclk_fb_div = q * sc->vclk_post_div / 100;
1108
1109 regwb_pll(sc, MCLK_FB_DIV, sc->mclk_fb_div);
1110 regwb_pll(sc, VCLK_POST_DIV, sc->log2_vclk_post_div);
1111 regwb_pll(sc, VCLK0_FB_DIV, sc->vclk_fb_div);
1112 }
1113
1114 void
1115 mach64_init_lut(struct mach64_softc *sc)
1116 {
1117 /* XXX this is pretty dodgy since it's perfectly possible that
1118 both terminal emulations are compiled into the kernel, in this
1119 case we'd install the VT100 colour map which may be wrong */
1120 #ifdef WSEMUL_SUN
1121 mach64_putpalreg(sc,0,255,255,255);
1122 mach64_putpalreg(sc,1,0,0,0);
1123 mach64_putpalreg(sc,255,0,0,0);
1124 #endif
1125 #ifdef WSEMUL_VT100
1126 {
1127 int i,idx;
1128 idx=0;
1129 for(i=0;i<256;i++) {
1130 mach64_putpalreg(sc,i,rasops_cmap[idx],rasops_cmap[idx+1],rasops_cmap[idx+2]);
1131 idx+=3;
1132 }
1133 }
1134 #endif
1135 }
1136
1137 int mach64_putpalreg(struct mach64_softc *sc, uint8_t index, uint8_t r, uint8_t g, uint8_t b)
1138 {
1139 sc->sc_cmap_red[index]=r;
1140 sc->sc_cmap_green[index]=g;
1141 sc->sc_cmap_blue[index]=b;
1142 /* writing the dac index takes a while, in theory we can poll some register
1143 to see when it's ready - but we better avoid writing it unnecessarily */
1144 if(index!=sc->sc_dacw)
1145 {
1146 regwb(sc, DAC_MASK, 0xff);
1147 regwb(sc, DAC_WINDEX, index);
1148 }
1149 sc->sc_dacw=index+1;
1150 regwb(sc, DAC_DATA, r);
1151 regwb(sc, DAC_DATA, g);
1152 regwb(sc, DAC_DATA, b);
1153 return 0;
1154 }
1155
1156 int mach64_putcmap(struct mach64_softc *sc, struct wsdisplay_cmap *cm)
1157 {
1158 u_int index = cm->index;
1159 u_int count = cm->count;
1160 int i, error;
1161 u_char rbuf[256], gbuf[256], bbuf[256];
1162 u_char *r, *g, *b;
1163
1164 printf("putcmap: %d %d\n",index, count);
1165 if (cm->index >= 256 || cm->count > 256 ||
1166 (cm->index + cm->count) > 256)
1167 return EINVAL;
1168 error = copyin(cm->red, &rbuf[index], count);
1169 if (error)
1170 return error;
1171 error = copyin(cm->green, &gbuf[index], count);
1172 if (error)
1173 return error;
1174 error = copyin(cm->blue, &bbuf[index], count);
1175 if (error)
1176 return error;
1177
1178 memcpy(&sc->sc_cmap_red[index], &rbuf[index], count);
1179 memcpy(&sc->sc_cmap_green[index], &gbuf[index], count);
1180 memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count);
1181
1182 r = &sc->sc_cmap_red[index];
1183 g = &sc->sc_cmap_green[index];
1184 b = &sc->sc_cmap_blue[index];
1185
1186 for (i = 0; i < count; i++) {
1187 mach64_putpalreg(sc,index,*r, *g, *b);
1188 index++;
1189 r++, g++, b++;
1190 }
1191 return 0;
1192 }
1193
1194 int mach64_getcmap(struct mach64_softc *sc, struct wsdisplay_cmap *cm)
1195 {
1196 u_int index = cm->index;
1197 u_int count = cm->count;
1198 int error;
1199
1200 if (index >= 255 || count > 256 || index + count > 256)
1201 return EINVAL;
1202
1203 error = copyout(&sc->sc_cmap_red[index], cm->red, count);
1204 if (error)
1205 return error;
1206 error = copyout(&sc->sc_cmap_green[index], cm->green, count);
1207 if (error)
1208 return error;
1209 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count);
1210 if (error)
1211 return error;
1212
1213 return 0;
1214 }
1215
1216 void
1217 mach64_switch_screen(struct mach64_softc *sc)
1218 {
1219 struct mach64screen *scr, *oldscr;
1220 const struct wsscreen_descr *type;
1221
1222 scr = sc->wanted;
1223 if (!scr) {
1224 printf("mach64_switch_screen: disappeared\n");
1225 (*sc->switchcb)(sc->switchcbarg, EIO, 0);
1226 return;
1227 }
1228 type = scr->type;
1229 oldscr = sc->active; /* can be NULL! */
1230 #ifdef DIAGNOSTIC
1231 if (oldscr) {
1232 if (!oldscr->active)
1233 panic("mach64_switch_screen: not active");
1234 if (oldscr->type != sc->currenttype)
1235 panic("mach64_switch_screen: bad type");
1236 }
1237 #endif
1238 if (scr == oldscr)
1239 return;
1240
1241 #ifdef DIAGNOSTIC
1242 /* XXX Macallan: this one bites us at reboot */
1243 /* if (scr->active)
1244 panic("mach64_switch_screen: active");*/
1245 #endif
1246
1247 if (oldscr)
1248 oldscr->active = 0;
1249
1250 if (sc->currenttype != type) {
1251 mach64_set_screentype(sc, type);
1252 sc->currenttype = type;
1253 }
1254
1255 scr->dispoffset = scr->mindispoffset;
1256
1257 if (!oldscr || (scr->dispoffset != oldscr->dispoffset)) {
1258
1259 }
1260
1261 /* Clear the entire screen. */
1262
1263 scr->active = 1;
1264 mach64_restore_screen(scr, type, scr->mem);
1265
1266 sc->active = scr;
1267
1268 mach64_cursor(scr, scr->cursoron, scr->cursorrow, scr->cursorcol);
1269
1270 sc->wanted = 0;
1271 if (sc->switchcb)
1272 (*sc->switchcb)(sc->switchcbarg, 0, 0);
1273 }
1274
1275 void
1276 mach64_restore_screen(struct mach64screen *scr,
1277 const struct wsscreen_descr *type, u_int16_t *mem)
1278 {
1279
1280 }
1281
1282 int
1283 mach64_set_screentype(struct mach64_softc *sc, const struct wsscreen_descr *des)
1284 {
1285 struct mach64_crtcregs regs;
1286
1287 if (mach64_calc_crtcregs(sc, ®s,
1288 (struct videomode *)des->modecookie))
1289 return 1;
1290
1291 mach64_set_crtcregs(sc, ®s);
1292 return 0;
1293 }
1294
1295 int
1296 mach64_is_console(struct pci_attach_args *pa)
1297 {
1298 #ifdef __sparc__
1299 int node;
1300
1301 node = PCITAG_NODE(pa->pa_tag);
1302 if (node == -1)
1303 return 0;
1304
1305 return (node == prom_instance_to_package(prom_stdout()));
1306 #else
1307 return 1;
1308 #endif
1309 }
1310
1311 /*
1312 * wsdisplay_emulops
1313 */
1314
1315 void
1316 mach64_cursor(void *cookie, int on, int row, int col)
1317 {
1318
1319 }
1320
1321 #if 0
1322 int
1323 mach64_mapchar(void *cookie, int uni, u_int *index)
1324 {
1325
1326 return 0;
1327 }
1328
1329 void
1330 mach64_putchar(void *cookie, int row, int col, u_int c, long attr)
1331 {
1332
1333 }
1334 #endif
1335
1336 void
1337 mach64_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
1338 {
1339 struct rasops_info *ri=cookie;
1340 struct mach64_softc *sc=ri->ri_hw;
1341 int32_t xs,xd,y,width,height;
1342
1343 xs=ri->ri_xorigin+ri->ri_font->fontwidth*srccol;
1344 xd=ri->ri_xorigin+ri->ri_font->fontwidth*dstcol;
1345 y=ri->ri_yorigin+ri->ri_font->fontheight*row;
1346 width=ri->ri_font->fontwidth*ncols;
1347 height=ri->ri_font->fontheight;
1348 mach64_bitblt(sc,xs,y,xd,y,width,height,MIX_SRC,0xff);
1349 }
1350
1351 void
1352 mach64_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr)
1353 {
1354 struct rasops_info *ri=cookie;
1355 struct mach64_softc *sc=ri->ri_hw;
1356 int32_t x,y,width,height,fg,bg,ul;;
1357
1358 x=ri->ri_xorigin+ri->ri_font->fontwidth*startcol;
1359 y=ri->ri_yorigin+ri->ri_font->fontheight*row;
1360 width=ri->ri_font->fontwidth*ncols;
1361 height=ri->ri_font->fontheight;
1362 rasops_unpack_attr(fillattr,&fg,&bg,&ul);
1363
1364 mach64_rectfill(sc,x,y,width,height,bg);
1365
1366 }
1367
1368 void
1369 mach64_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
1370 {
1371 struct rasops_info *ri=cookie;
1372 struct mach64_softc *sc=ri->ri_hw;
1373 int32_t x,ys,yd,width,height;
1374
1375 x=ri->ri_xorigin;
1376 ys=ri->ri_yorigin+ri->ri_font->fontheight*srcrow;
1377 yd=ri->ri_yorigin+ri->ri_font->fontheight*dstrow;
1378 width=ri->ri_emuwidth;
1379 height=ri->ri_font->fontheight*nrows;
1380 mach64_bitblt(sc,x,ys,x,yd,width,height,MIX_SRC,0xff);
1381 }
1382
1383 void mach64_bitblt(struct mach64_softc *sc, int xs, int ys, int xd, int yd, int width, int height, int rop,
1384 int mask)
1385 {
1386 uint32_t dest_ctl=0;
1387 wait_for_idle(sc);
1388 regw(sc,DP_WRITE_MASK,mask); /* XXX only good for 8 bit */
1389 regw(sc,DP_PIX_WIDTH,DST_8BPP|SRC_8BPP|HOST_8BPP);
1390 regw(sc,DP_SRC,FRGD_SRC_BLIT);
1391 regw(sc,DP_MIX,(rop&0xffff)<<16);
1392 regw(sc,CLR_CMP_CNTL,0); /* no transparency */
1393 if(yd<ys) {
1394 dest_ctl=DST_Y_TOP_TO_BOTTOM;
1395 } else {
1396 ys+=height-1;
1397 yd+=height-1;
1398 dest_ctl=DST_Y_BOTTOM_TO_TOP;
1399 }
1400 if(xd<xs) {
1401 dest_ctl|=DST_X_LEFT_TO_RIGHT;
1402 regw(sc,SRC_CNTL,SRC_LINE_X_LEFT_TO_RIGHT);
1403 } else {
1404 dest_ctl|=DST_X_RIGHT_TO_LEFT;
1405 xs+=width-1;
1406 xd+=width-1;
1407 regw(sc,SRC_CNTL,SRC_LINE_X_RIGHT_TO_LEFT);
1408 }
1409 regw(sc,DST_CNTL,dest_ctl);
1410
1411 regw(sc,SRC_Y_X,(xs<<16)|ys);
1412 regw(sc,SRC_WIDTH1,width);
1413 regw(sc,DST_Y_X,(xd<<16)|yd);
1414 regw(sc,DST_HEIGHT_WIDTH,(width<<16)|height);
1415 /* as long as the other rasops* functions aren't aware of the blitter we must wait here
1416 or the blitter might not be done when someone else draws the next line */
1417 wait_for_idle(sc);
1418 }
1419
1420 void mach64_rectfill(struct mach64_softc *sc, int x, int y, int width, int height, int colour)
1421 {
1422 wait_for_idle(sc);
1423 regw(sc,DP_WRITE_MASK,0xff);
1424 regw(sc,DP_FRGD_CLR,colour);
1425 regw(sc,DP_PIX_WIDTH,DST_8BPP|SRC_8BPP|HOST_8BPP);
1426 regw(sc,DP_SRC,FRGD_SRC_FRGD_CLR);
1427 regw(sc,DP_MIX,(MIX_SRC)<<16);
1428 regw(sc,CLR_CMP_CNTL,0); /* no transparency */
1429 regw(sc,SRC_CNTL,SRC_LINE_X_LEFT_TO_RIGHT);
1430 regw(sc,DST_CNTL,DST_X_LEFT_TO_RIGHT|DST_Y_TOP_TO_BOTTOM);
1431
1432 regw(sc,SRC_Y_X,(x<<16)|y);
1433 regw(sc,SRC_WIDTH1,width);
1434 regw(sc,DST_Y_X,(x<<16)|y);
1435 regw(sc,DST_HEIGHT_WIDTH,(width<<16)|height);
1436 wait_for_idle(sc);
1437 }
1438
1439 void mach64_showpal(struct mach64_softc *sc)
1440 {
1441 int i,x=0;
1442 for (i=0;i<16;i++) {
1443 mach64_rectfill(sc,x,0,64,64,i);
1444 x+=64;
1445 }
1446 }
1447
1448 int
1449 mach64_allocattr(void *cookie, int fg, int bg, int flags, long *attrp)
1450 {
1451
1452 return 0;
1453 }
1454
1455 void
1456 mach64_eraserows(void *cookie, int row, int nrows, long fillattr)
1457 {
1458 struct rasops_info *ri=cookie;
1459 struct mach64_softc *sc=ri->ri_hw;
1460 int32_t x,y,width,height,fg,bg,ul;
1461
1462 x=ri->ri_xorigin;
1463 y=ri->ri_yorigin+ri->ri_font->fontheight*row;
1464 width=ri->ri_emuwidth;
1465 height=ri->ri_font->fontheight*nrows;
1466 rasops_unpack_attr(fillattr,&fg,&bg,&ul);
1467
1468 mach64_rectfill(sc,x,y,width,height,bg);
1469 }
1470
1471 /*
1472 * wsdisplay_accessops
1473 */
1474
1475 int
1476 mach64_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
1477 {
1478 /* we'll probably need to add more stuff here */
1479 struct mach64_softc *sc = v;
1480 struct wsdisplay_fbinfo *wdf;
1481 struct mach64screen *ms=sc->active;
1482 switch (cmd) {
1483 case WSDISPLAYIO_GTYPE:
1484 *(u_int *)data = WSDISPLAY_TYPE_PCIMISC; /* XXX ? */
1485 return 0;
1486
1487 case WSDISPLAYIO_GINFO:
1488 wdf = (void *)data;
1489 wdf->height = ms->ri.ri_height;
1490 wdf->width = ms->ri.ri_width;
1491 wdf->depth = ms->ri.ri_depth;
1492 wdf->cmsize = 256;
1493 return 0;
1494 case WSDISPLAYIO_GETCMAP:
1495 return mach64_getcmap(sc, (struct wsdisplay_cmap *)data);
1496
1497 case WSDISPLAYIO_PUTCMAP:
1498 return mach64_putcmap(sc, (struct wsdisplay_cmap *)data);
1499 /* PCI config read/write passthrough. */
1500 case PCI_IOC_CFGREAD:
1501 case PCI_IOC_CFGWRITE:
1502 return (pci_devioctl(sc->sc_pc, sc->sc_pcitag,
1503 cmd, data, flag, p));
1504 #ifdef notyet
1505 case WSDISPLAYIO_SMODE:
1506 {
1507 int new_mode=*(int*)data;
1508 if(new_mode!=sc->sc_mode)
1509 {
1510 sc->sc_mode=new_mode;
1511 if(new_mode==WSDISPLAYIO_MODE_EMUL)
1512 {
1513 /* we'll probably want to reset the console into a known state here
1514 just in case the Xserver crashed or didn't properly clean up after
1515 itself for whetever reason */
1516 }
1517 }
1518 }
1519 #endif
1520 }
1521 return EPASSTHROUGH;
1522 }
1523
1524 paddr_t
1525 mach64_mmap(void *v, off_t offset, int prot)
1526 {
1527 struct mach64_softc *sc = v;
1528 paddr_t pa;
1529 /* 'regular' framebuffer mmap()ing */
1530 if(offset<sc->sc_apersize) {
1531 pa = bus_space_mmap(sc->sc_memt,sc->sc_aperbase+offset,0,prot,BUS_SPACE_MAP_LINEAR);
1532 return pa;
1533 }
1534 /* allow XFree86 to mmap() PCI space as if the BARs contain physical addresses */
1535 if((offset>0x80000000) && (offset<=0xffffffff)) {
1536 pa = bus_space_mmap(sc->sc_memt,offset,0,prot,BUS_SPACE_MAP_LINEAR);
1537 return pa;
1538 }
1539 return -1;
1540 }
1541
1542 int
1543 mach64_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
1544 int *curxp, int *curyp, long *defattrp)
1545 {
1546 struct mach64_softc *sc = v;
1547 struct mach64screen *scr;
1548
1549 scr = malloc(sizeof(struct mach64screen), M_DEVBUF, M_WAITOK|M_ZERO);
1550 mach64_init_screen(sc, scr, type, 0, defattrp, sc->active == NULL);
1551 rasops_init(&scr->ri, mach64_console_screen.ri.ri_height / 16,
1552 mach64_console_screen.ri.ri_width / 8);
1553
1554 scr->mem = malloc(type->ncols * type->nrows * 2, M_DEVBUF,
1555 M_WAITOK);
1556 mach64_eraserows(sc, 0, type->nrows, *defattrp);
1557 if (sc->active == NULL) {
1558 scr->active = 1;
1559 sc->active = scr;
1560 sc->currenttype = type;
1561 }
1562
1563 *cookiep = scr;
1564 *curxp = scr->cursorcol;
1565 *curyp = scr->cursorrow;
1566
1567 return 0;
1568 }
1569
1570 void
1571 mach64_free_screen(void *v, void *cookie)
1572 {
1573 struct mach64_softc *sc = v;
1574 struct mach64screen *scr = cookie;
1575
1576 LIST_REMOVE(scr, next);
1577 if (scr != &mach64_console_screen)
1578 free(scr, M_DEVBUF);
1579 else
1580 panic("mach64_free_screen: console");
1581
1582 if (sc->active == scr)
1583 sc->active = 0;
1584 }
1585
1586 int
1587 mach64_show_screen(void *v, void *cookie, int waitok,
1588 void (*cb)(void *, int, int), void *cbarg)
1589 {
1590 struct mach64_softc *sc = v;
1591 struct mach64screen *scr, *oldscr;
1592
1593 scr = cookie;
1594 oldscr = sc->active;
1595 if (scr == oldscr)
1596 return 0;
1597
1598 sc->wanted = scr;
1599 sc->switchcb = cb;
1600 sc->switchcbarg = cbarg;
1601 if (cb) {
1602 callout_reset(&sc->switch_callout, 0,
1603 (void(*)(void *))mach64_switch_screen, sc);
1604 return EAGAIN;
1605 }
1606
1607 mach64_switch_screen(sc);
1608
1609 return 0;
1610 }
1611
1612 #if 0
1613 int
1614 mach64_load_font(void *v, void *cookie, struct wsdisplay_font *data)
1615 {
1616
1617 return 0;
1618 }
1619 #endif
1620