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