Home | History | Annotate | Line # | Download | only in sbus
p9100.c revision 1.20
      1  1.20     perry /*	$NetBSD: p9100.c,v 1.20 2005/02/27 00:27:48 perry Exp $ */
      2   1.1        pk 
      3   1.1        pk /*-
      4   1.1        pk  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5   1.1        pk  * All rights reserved.
      6   1.1        pk  *
      7   1.1        pk  * This code is derived from software contributed to The NetBSD Foundation
      8   1.1        pk  * by Matt Thomas.
      9   1.1        pk  *
     10   1.1        pk  * Redistribution and use in source and binary forms, with or without
     11   1.1        pk  * modification, are permitted provided that the following conditions
     12   1.1        pk  * are met:
     13   1.1        pk  * 1. Redistributions of source code must retain the above copyright
     14   1.1        pk  *    notice, this list of conditions and the following disclaimer.
     15   1.1        pk  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1        pk  *    notice, this list of conditions and the following disclaimer in the
     17   1.1        pk  *    documentation and/or other materials provided with the distribution.
     18   1.1        pk  * 3. All advertising materials mentioning features or use of this software
     19   1.1        pk  *    must display the following acknowledgement:
     20   1.1        pk  *        This product includes software developed by the NetBSD
     21   1.1        pk  *        Foundation, Inc. and its contributors.
     22   1.1        pk  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23   1.1        pk  *    contributors may be used to endorse or promote products derived
     24   1.1        pk  *    from this software without specific prior written permission.
     25   1.1        pk  *
     26   1.1        pk  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27   1.1        pk  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28   1.1        pk  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29   1.1        pk  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30   1.1        pk  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31   1.1        pk  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32   1.1        pk  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33   1.1        pk  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34   1.1        pk  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35   1.1        pk  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36   1.1        pk  * POSSIBILITY OF SUCH DAMAGE.
     37   1.1        pk  */
     38   1.1        pk 
     39   1.1        pk /*
     40   1.1        pk  * color display (p9100) driver.
     41   1.1        pk  *
     42   1.1        pk  * Does not handle interrupts, even though they can occur.
     43   1.1        pk  *
     44   1.1        pk  * XXX should defer colormap updates to vertical retrace interrupts
     45   1.1        pk  */
     46   1.5     lukem 
     47   1.5     lukem #include <sys/cdefs.h>
     48  1.20     perry __KERNEL_RCSID(0, "$NetBSD: p9100.c,v 1.20 2005/02/27 00:27:48 perry Exp $");
     49   1.1        pk 
     50   1.1        pk #include <sys/param.h>
     51   1.1        pk #include <sys/systm.h>
     52   1.1        pk #include <sys/buf.h>
     53   1.1        pk #include <sys/device.h>
     54   1.1        pk #include <sys/ioctl.h>
     55   1.1        pk #include <sys/malloc.h>
     56   1.1        pk #include <sys/mman.h>
     57   1.1        pk #include <sys/tty.h>
     58   1.1        pk #include <sys/conf.h>
     59   1.1        pk 
     60   1.1        pk #include <machine/bus.h>
     61   1.1        pk #include <machine/autoconf.h>
     62   1.1        pk 
     63   1.1        pk #include <dev/sun/fbio.h>
     64   1.1        pk #include <dev/sun/fbvar.h>
     65   1.1        pk #include <dev/sun/btreg.h>
     66   1.1        pk #include <dev/sun/btvar.h>
     67   1.1        pk #if 0
     68   1.1        pk #include <dev/sbus/p9100reg.h>
     69   1.1        pk #endif
     70   1.1        pk 
     71   1.1        pk #include <dev/sbus/sbusvar.h>
     72   1.1        pk 
     73   1.1        pk #include "tctrl.h"
     74   1.1        pk #if NTCTRL > 0
     75   1.1        pk #include <machine/tctrl.h>
     76   1.1        pk #include <sparc/dev/tctrlvar.h>/*XXX*/
     77   1.1        pk #endif
     78   1.1        pk 
     79   1.1        pk /* per-display variables */
     80   1.1        pk struct p9100_softc {
     81   1.1        pk 	struct device	sc_dev;		/* base device */
     82   1.1        pk 	struct sbusdev	sc_sd;		/* sbus device */
     83   1.1        pk 	struct fbdevice	sc_fb;		/* frame buffer device */
     84   1.1        pk 	bus_space_tag_t	sc_bustag;
     85   1.8        pk 
     86   1.8        pk 	bus_addr_t	sc_ctl_paddr;	/* phys address description */
     87   1.1        pk 	bus_size_t	sc_ctl_psize;	/*   for device mmap() */
     88   1.1        pk 	bus_space_handle_t sc_ctl_memh;	/*   bus space handle */
     89   1.8        pk 
     90   1.8        pk 	bus_addr_t	sc_cmd_paddr;	/* phys address description */
     91   1.1        pk 	bus_size_t	sc_cmd_psize;	/*   for device mmap() */
     92   1.1        pk 	bus_space_handle_t sc_cmd_memh;	/*   bus space handle */
     93   1.8        pk 
     94   1.8        pk 	bus_addr_t	sc_fb_paddr;	/* phys address description */
     95   1.1        pk 	bus_size_t	sc_fb_psize;	/*   for device mmap() */
     96   1.1        pk 	bus_space_handle_t sc_fb_memh;	/*   bus space handle */
     97   1.8        pk 
     98   1.1        pk 	uint32_t sc_junk;
     99   1.1        pk 
    100   1.1        pk 	union	bt_cmap sc_cmap;	/* Brooktree color map */
    101   1.1        pk };
    102   1.1        pk 
    103   1.1        pk /* The Tadpole 3GX Technical Reference Manual lies.  The ramdac registers
    104   1.1        pk  * are map in 4 byte increments, not 8.
    105   1.1        pk  */
    106   1.1        pk #define	SCRN_RPNT_CTL_1	0x0138	/* Screen Respaint Timing Control 1 */
    107   1.1        pk #define	VIDEO_ENABLED	0x00000020
    108   1.1        pk #define	PWRUP_CNFG	0x0194	/* Power Up Configuration */
    109   1.1        pk #define	DAC_CMAP_WRIDX	0x0200	/* IBM RGB528 Palette Address (Write) */
    110   1.1        pk #define	DAC_CMAP_DATA	0x0204	/* IBM RGB528 Palette Data */
    111   1.1        pk #define	DAC_PXL_MASK	0x0208	/* IBM RGB528 Pixel Mask */
    112   1.1        pk #define	DAC_CMAP_RDIDX	0x020c	/* IBM RGB528 Palette Address (Read) */
    113   1.1        pk #define	DAC_INDX_LO	0x0210	/* IBM RGB528 Index Low */
    114   1.1        pk #define	DAC_INDX_HI	0x0214	/* IBM RGB528 Index High */
    115   1.1        pk #define	DAC_INDX_DATA	0x0218	/* IBM RGB528 Index Data (Indexed Registers) */
    116   1.1        pk #define	DAC_INDX_CTL	0x021c	/* IBM RGB528 Index Control */
    117   1.1        pk 
    118   1.1        pk /* autoconfiguration driver */
    119   1.1        pk static int	p9100_sbus_match(struct device *, struct cfdata *, void *);
    120   1.1        pk static void	p9100_sbus_attach(struct device *, struct device *, void *);
    121   1.1        pk 
    122   1.1        pk static void	p9100unblank(struct device *);
    123   1.1        pk static void	p9100_shutdown(void *);
    124   1.1        pk 
    125  1.12   thorpej CFATTACH_DECL(pnozz, sizeof(struct p9100_softc),
    126  1.13   thorpej     p9100_sbus_match, p9100_sbus_attach, NULL, NULL);
    127   1.1        pk 
    128   1.1        pk extern struct cfdriver pnozz_cd;
    129   1.1        pk 
    130  1.10   gehenna dev_type_open(p9100open);
    131  1.10   gehenna dev_type_ioctl(p9100ioctl);
    132  1.10   gehenna dev_type_mmap(p9100mmap);
    133  1.10   gehenna 
    134  1.10   gehenna const struct cdevsw pnozz_cdevsw = {
    135  1.10   gehenna 	p9100open, nullclose, noread, nowrite, p9100ioctl,
    136  1.14  jdolecek 	nostop, notty, nopoll, p9100mmap, nokqfilter,
    137  1.10   gehenna };
    138  1.10   gehenna 
    139   1.1        pk /* frame buffer generic driver */
    140   1.1        pk static struct fbdriver p9100fbdriver = {
    141  1.10   gehenna 	p9100unblank, p9100open, nullclose, p9100ioctl, nopoll,
    142  1.14  jdolecek 	p9100mmap, nokqfilter
    143   1.1        pk };
    144   1.1        pk 
    145   1.1        pk static void p9100loadcmap(struct p9100_softc *, int, int);
    146   1.1        pk static void p9100_set_video(struct p9100_softc *, int);
    147   1.1        pk static int p9100_get_video(struct p9100_softc *);
    148   1.1        pk static uint32_t p9100_ctl_read_4(struct p9100_softc *, bus_size_t);
    149   1.1        pk static void p9100_ctl_write_4(struct p9100_softc *, bus_size_t, uint32_t);
    150   1.1        pk #if 0
    151   1.1        pk static uint8_t p9100_ramdac_read(struct p9100_softc *, bus_size_t);
    152   1.1        pk #endif
    153   1.1        pk static void p9100_ramdac_write(struct p9100_softc *, bus_size_t, uint8_t);
    154   1.1        pk 
    155   1.1        pk /*
    156   1.1        pk  * Match a p9100.
    157   1.1        pk  */
    158   1.1        pk static int
    159   1.1        pk p9100_sbus_match(struct device *parent, struct cfdata *cf, void *aux)
    160   1.1        pk {
    161   1.1        pk 	struct sbus_attach_args *sa = aux;
    162   1.1        pk 
    163   1.1        pk 	return (strcmp("p9100", sa->sa_name) == 0);
    164   1.1        pk }
    165   1.1        pk 
    166   1.1        pk 
    167   1.1        pk /*
    168   1.1        pk  * Attach a display.  We need to notice if it is the console, too.
    169   1.1        pk  */
    170   1.1        pk static void
    171   1.1        pk p9100_sbus_attach(struct device *parent, struct device *self, void *args)
    172   1.1        pk {
    173   1.1        pk 	struct p9100_softc *sc = (struct p9100_softc *)self;
    174   1.1        pk 	struct sbus_attach_args *sa = args;
    175   1.1        pk 	struct fbdevice *fb = &sc->sc_fb;
    176   1.1        pk 	int isconsole;
    177   1.1        pk 	int node;
    178   1.1        pk 	int i;
    179   1.1        pk 
    180   1.1        pk 	/* Remember cookies for p9100_mmap() */
    181   1.1        pk 	sc->sc_bustag = sa->sa_bustag;
    182  1.20     perry 	sc->sc_ctl_paddr = sbus_bus_addr(sa->sa_bustag,
    183   1.9   thorpej 		sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base);
    184   1.9   thorpej 	sc->sc_ctl_psize = (bus_size_t)sa->sa_reg[0].oa_size;
    185   1.3       eeh 
    186  1.20     perry 	sc->sc_cmd_paddr = sbus_bus_addr(sa->sa_bustag,
    187   1.9   thorpej 		sa->sa_reg[1].oa_space, sa->sa_reg[1].oa_base);
    188   1.9   thorpej 	sc->sc_cmd_psize = (bus_size_t)sa->sa_reg[1].oa_size;
    189   1.3       eeh 
    190  1.20     perry 	sc->sc_fb_paddr = sbus_bus_addr(sa->sa_bustag,
    191   1.9   thorpej 		sa->sa_reg[2].oa_space, sa->sa_reg[2].oa_base);
    192   1.9   thorpej 	sc->sc_fb_psize = (bus_size_t)sa->sa_reg[2].oa_size;
    193   1.1        pk 
    194   1.1        pk 	fb->fb_driver = &p9100fbdriver;
    195   1.1        pk 	fb->fb_device = &sc->sc_dev;
    196   1.1        pk 	fb->fb_flags = sc->sc_dev.dv_cfdata->cf_flags & FB_USERMASK;
    197   1.1        pk 	fb->fb_type.fb_type = FBTYPE_SUN3COLOR;
    198   1.7     cyber 	fb->fb_pixels = NULL;
    199   1.1        pk 
    200   1.1        pk 	node = sa->sa_node;
    201   1.7     cyber 	isconsole = fb_is_console(node);
    202   1.7     cyber 	if (!isconsole) {
    203   1.7     cyber 		printf("\n%s: fatal error: PROM didn't configure device: not console\n", self->dv_xname);
    204   1.7     cyber 		return;
    205   1.7     cyber 	}
    206   1.1        pk 
    207   1.1        pk 	/*
    208   1.1        pk 	 * When the ROM has mapped in a p9100 display, the address
    209   1.1        pk 	 * maps only the video RAM, so in any case we have to map the
    210   1.1        pk 	 * registers ourselves.  We only need the video RAM if we are
    211   1.1        pk 	 * going to print characters via rconsole.
    212   1.1        pk 	 */
    213   1.8        pk 	if (sbus_bus_map(sc->sc_bustag,
    214   1.9   thorpej 			 sa->sa_reg[0].oa_space,
    215   1.9   thorpej 			 sa->sa_reg[0].oa_base,
    216   1.8        pk 			 sc->sc_ctl_psize,
    217   1.8        pk 			 BUS_SPACE_MAP_LINEAR, &sc->sc_ctl_memh) != 0) {
    218   1.1        pk 		printf("%s: cannot map control registers\n", self->dv_xname);
    219   1.1        pk 		return;
    220   1.1        pk 	}
    221   1.1        pk 
    222   1.8        pk 	if (sbus_bus_map(sc->sc_bustag,
    223   1.9   thorpej 			 sa->sa_reg[1].oa_space,
    224   1.9   thorpej 			 sa->sa_reg[1].oa_base,
    225   1.8        pk 			 sc->sc_cmd_psize,
    226   1.8        pk 			 BUS_SPACE_MAP_LINEAR, &sc->sc_cmd_memh) != 0) {
    227   1.1        pk 		printf("%s: cannot map command registers\n", self->dv_xname);
    228   1.1        pk 		return;
    229   1.1        pk 	}
    230   1.1        pk 
    231   1.1        pk 	if (sa->sa_npromvaddrs != 0)
    232   1.1        pk 		fb->fb_pixels = (caddr_t)sa->sa_promvaddrs[0];
    233   1.7     cyber 
    234   1.7     cyber 	if (fb->fb_pixels == NULL) {
    235   1.8        pk 		if (sbus_bus_map(sc->sc_bustag,
    236   1.9   thorpej 				sa->sa_reg[2].oa_space,
    237   1.9   thorpej 				sa->sa_reg[2].oa_base,
    238   1.8        pk 				sc->sc_fb_psize,
    239   1.8        pk 				BUS_SPACE_MAP_LINEAR, &sc->sc_fb_memh) != 0) {
    240   1.1        pk 			printf("%s: cannot map framebuffer\n", self->dv_xname);
    241   1.1        pk 			return;
    242   1.1        pk 		}
    243   1.1        pk 		fb->fb_pixels = (char *)sc->sc_fb_memh;
    244   1.1        pk 	} else {
    245   1.1        pk 		sc->sc_fb_memh = (bus_space_handle_t) fb->fb_pixels;
    246   1.1        pk 	}
    247   1.1        pk 
    248   1.1        pk 	i = p9100_ctl_read_4(sc, 0x0004);
    249   1.1        pk 	switch ((i >> 26) & 7) {
    250   1.1        pk 	    case 5: fb->fb_type.fb_depth = 32; break;
    251   1.1        pk 	    case 7: fb->fb_type.fb_depth = 24; break;
    252   1.1        pk 	    case 3: fb->fb_type.fb_depth = 16; break;
    253   1.1        pk 	    case 2: fb->fb_type.fb_depth = 8; break;
    254   1.1        pk 	    default: {
    255   1.1        pk 		panic("pnozz: can't determine screen depth (0x%02x)", i);
    256   1.1        pk 	    }
    257   1.1        pk 	}
    258   1.1        pk 	fb_setsize_obp(fb, fb->fb_type.fb_depth, 800, 600, node);
    259   1.1        pk 
    260   1.1        pk 	sbus_establish(&sc->sc_sd, &sc->sc_dev);
    261   1.1        pk 
    262   1.1        pk 	fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes;
    263   1.1        pk 	printf(": rev %d, %dx%d, depth %d",
    264   1.1        pk 	       (i & 7), fb->fb_type.fb_width, fb->fb_type.fb_height,
    265   1.1        pk 	       fb->fb_type.fb_depth);
    266   1.1        pk 
    267  1.19        pk 	fb->fb_type.fb_cmsize = prom_getpropint(node, "cmsize", 256);
    268   1.1        pk 	if ((1 << fb->fb_type.fb_depth) != fb->fb_type.fb_cmsize)
    269   1.1        pk 		printf(", %d entry colormap", fb->fb_type.fb_cmsize);
    270   1.1        pk 
    271   1.1        pk 	/* Initialize the default color map. */
    272   1.1        pk 	bt_initcmap(&sc->sc_cmap, 256);
    273   1.1        pk 	p9100loadcmap(sc, 0, 256);
    274   1.1        pk 
    275   1.1        pk 	/* make sure we are not blanked */
    276   1.7     cyber 	if (isconsole)
    277   1.7     cyber 		p9100_set_video(sc, 1);
    278   1.1        pk 
    279   1.1        pk 	if (shutdownhook_establish(p9100_shutdown, sc) == NULL) {
    280   1.1        pk 		panic("%s: could not establish shutdown hook",
    281   1.1        pk 		      sc->sc_dev.dv_xname);
    282   1.1        pk 	}
    283   1.1        pk 
    284   1.1        pk 	if (isconsole) {
    285   1.1        pk 		printf(" (console)\n");
    286   1.1        pk #ifdef RASTERCONSOLE
    287   1.1        pk 		for (i = 0; i < fb->fb_type.fb_size; i++) {
    288   1.1        pk 		     if (fb->fb_pixels[i] == 0) {
    289   1.1        pk 			 fb->fb_pixels[i] = 1;
    290   1.1        pk 		     } else if (fb->fb_pixels[i] == (char) 255) {
    291   1.1        pk 			 fb->fb_pixels[i] = 0;
    292   1.1        pk 		     }
    293   1.1        pk 		}
    294   1.1        pk 		p9100loadcmap(sc, 255, 1);
    295   1.1        pk 		fbrcons_init(fb);
    296   1.1        pk #endif
    297   1.1        pk 	} else
    298   1.1        pk 		printf("\n");
    299   1.1        pk 
    300   1.1        pk 	fb_attach(fb, isconsole);
    301   1.1        pk }
    302   1.1        pk 
    303   1.1        pk static void
    304   1.1        pk p9100_shutdown(arg)
    305   1.1        pk 	void *arg;
    306   1.1        pk {
    307   1.1        pk 	struct p9100_softc *sc = arg;
    308   1.2       mrg #ifdef RASTERCONSOLE
    309   1.1        pk 	struct fbdevice *fb = &sc->sc_fb;
    310   1.1        pk 	int i;
    311   1.1        pk 
    312   1.1        pk 	for (i = 0; i < fb->fb_type.fb_size; i++) {
    313   1.1        pk 	     if (fb->fb_pixels[i] == 1) {
    314   1.1        pk 		 fb->fb_pixels[i] = 0;
    315   1.1        pk 	     } else if (fb->fb_pixels[i] == 0) {
    316   1.1        pk 		 fb->fb_pixels[i] = 255;
    317   1.1        pk 	     }
    318   1.1        pk 	}
    319   1.1        pk 	sc->sc_cmap.cm_map[0][0] = 0xff;
    320   1.1        pk 	sc->sc_cmap.cm_map[0][1] = 0xff;
    321   1.1        pk 	sc->sc_cmap.cm_map[0][2] = 0xff;
    322   1.1        pk 	sc->sc_cmap.cm_map[1][0] = 0;
    323   1.1        pk 	sc->sc_cmap.cm_map[1][1] = 0;
    324   1.1        pk 	sc->sc_cmap.cm_map[1][2] = 0x80;
    325   1.1        pk 	p9100loadcmap(sc, 0, 2);
    326   1.1        pk 	sc->sc_cmap.cm_map[255][0] = 0;
    327   1.1        pk 	sc->sc_cmap.cm_map[255][1] = 0;
    328   1.1        pk 	sc->sc_cmap.cm_map[255][2] = 0;
    329   1.1        pk 	p9100loadcmap(sc, 255, 1);
    330   1.1        pk #endif
    331   1.1        pk 	p9100_set_video(sc, 1);
    332   1.1        pk }
    333   1.1        pk 
    334   1.1        pk int
    335  1.16      fvdl p9100open(dev_t dev, int flags, int mode, struct proc *p)
    336   1.1        pk {
    337   1.1        pk 	int unit = minor(dev);
    338   1.1        pk 
    339   1.1        pk 	if (unit >= pnozz_cd.cd_ndevs || pnozz_cd.cd_devs[unit] == NULL)
    340   1.1        pk 		return (ENXIO);
    341   1.1        pk 	return (0);
    342   1.1        pk }
    343   1.1        pk 
    344   1.1        pk int
    345  1.16      fvdl p9100ioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
    346   1.1        pk {
    347   1.1        pk 	struct p9100_softc *sc = pnozz_cd.cd_devs[minor(dev)];
    348   1.1        pk 	struct fbgattr *fba;
    349   1.1        pk 	int error;
    350   1.1        pk 
    351   1.1        pk 	switch (cmd) {
    352   1.1        pk 
    353   1.1        pk 	case FBIOGTYPE:
    354   1.1        pk 		*(struct fbtype *)data = sc->sc_fb.fb_type;
    355   1.1        pk 		break;
    356   1.1        pk 
    357   1.1        pk 	case FBIOGATTR:
    358   1.1        pk 		fba = (struct fbgattr *)data;
    359   1.1        pk 		fba->real_type = sc->sc_fb.fb_type.fb_type;
    360   1.1        pk 		fba->owner = 0;		/* XXX ??? */
    361   1.1        pk 		fba->fbtype = sc->sc_fb.fb_type;
    362   1.1        pk 		fba->sattr.flags = 0;
    363   1.1        pk 		fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type;
    364   1.1        pk 		fba->sattr.dev_specific[0] = -1;
    365   1.1        pk 		fba->emu_types[0] = sc->sc_fb.fb_type.fb_type;
    366   1.1        pk 		fba->emu_types[1] = -1;
    367   1.1        pk 		break;
    368   1.1        pk 
    369   1.1        pk 	case FBIOGETCMAP:
    370   1.1        pk #define p ((struct fbcmap *)data)
    371   1.1        pk 		return (bt_getcmap(p, &sc->sc_cmap, 256, 1));
    372   1.1        pk 
    373   1.1        pk 	case FBIOPUTCMAP:
    374   1.1        pk 		/* copy to software map */
    375   1.1        pk 		error = bt_putcmap(p, &sc->sc_cmap, 256, 1);
    376   1.1        pk 		if (error)
    377   1.1        pk 			return (error);
    378   1.1        pk 		/* now blast them into the chip */
    379   1.1        pk 		/* XXX should use retrace interrupt */
    380   1.1        pk 		p9100loadcmap(sc, p->index, p->count);
    381   1.1        pk #undef p
    382   1.1        pk 		break;
    383   1.1        pk 
    384   1.1        pk 	case FBIOGVIDEO:
    385   1.1        pk 		*(int *)data = p9100_get_video(sc);
    386   1.1        pk 		break;
    387   1.1        pk 
    388   1.1        pk 	case FBIOSVIDEO:
    389   1.1        pk 		p9100_set_video(sc, *(int *)data);
    390   1.1        pk 		break;
    391   1.1        pk 
    392   1.1        pk 	default:
    393   1.1        pk 		return (ENOTTY);
    394   1.1        pk 	}
    395   1.1        pk 	return (0);
    396   1.1        pk }
    397   1.1        pk 
    398   1.1        pk static uint32_t
    399   1.1        pk p9100_ctl_read_4(struct p9100_softc *sc, bus_size_t off)
    400   1.1        pk {
    401   1.1        pk 	sc->sc_junk = bus_space_read_4(sc->sc_bustag, sc->sc_fb_memh, off);
    402   1.1        pk 	return bus_space_read_4(sc->sc_bustag, sc->sc_ctl_memh, off);
    403   1.1        pk }
    404   1.1        pk 
    405   1.1        pk static void
    406   1.1        pk p9100_ctl_write_4(struct p9100_softc *sc, bus_size_t off, uint32_t v)
    407   1.1        pk {
    408   1.1        pk 	sc->sc_junk = bus_space_read_4(sc->sc_bustag, sc->sc_fb_memh, off);
    409   1.1        pk 	bus_space_write_4(sc->sc_bustag, sc->sc_ctl_memh, off, v);
    410   1.1        pk }
    411   1.1        pk 
    412   1.1        pk #if 0
    413   1.1        pk static uint8_t
    414   1.1        pk p9100_ramdac_read(struct p9100_softc *sc, bus_size_t off)
    415   1.1        pk {
    416   1.1        pk 	sc->sc_junk = p9100_ctl_read_4(sc, PWRUP_CNFG);
    417   1.1        pk 	return p9100_ctl_read_4(sc, off) >> 16;
    418   1.1        pk }
    419   1.1        pk #endif
    420   1.1        pk 
    421   1.1        pk static void
    422   1.1        pk p9100_ramdac_write(struct p9100_softc *sc, bus_size_t off, uint8_t v)
    423   1.1        pk {
    424   1.1        pk 	sc->sc_junk = p9100_ctl_read_4(sc, PWRUP_CNFG);
    425   1.1        pk 	p9100_ctl_write_4(sc, off, v << 16);
    426   1.1        pk }
    427   1.1        pk 
    428   1.1        pk /*
    429   1.1        pk  * Undo the effect of an FBIOSVIDEO that turns the video off.
    430   1.1        pk  */
    431   1.1        pk static void
    432   1.1        pk p9100unblank(struct device *dev)
    433   1.1        pk {
    434   1.1        pk 
    435   1.1        pk 	p9100_set_video((struct p9100_softc *)dev, 1);
    436   1.1        pk }
    437   1.1        pk 
    438   1.1        pk static void
    439   1.1        pk p9100_set_video(struct p9100_softc *sc, int enable)
    440   1.1        pk {
    441   1.1        pk 	u_int32_t v = p9100_ctl_read_4(sc, SCRN_RPNT_CTL_1);
    442   1.1        pk 	if (enable)
    443   1.1        pk 		v |= VIDEO_ENABLED;
    444   1.1        pk 	else
    445   1.1        pk 		v &= ~VIDEO_ENABLED;
    446   1.1        pk 	p9100_ctl_write_4(sc, SCRN_RPNT_CTL_1, v);
    447   1.1        pk #if NTCTRL > 0
    448   1.1        pk 	/* Turn On/Off the TFT if we know how.
    449   1.1        pk 	 */
    450   1.1        pk 	tadpole_set_video(enable);
    451   1.1        pk #endif
    452   1.1        pk }
    453   1.1        pk 
    454   1.1        pk static int
    455   1.1        pk p9100_get_video(struct p9100_softc *sc)
    456   1.1        pk {
    457   1.1        pk 	return (p9100_ctl_read_4(sc, SCRN_RPNT_CTL_1) & VIDEO_ENABLED) != 0;
    458   1.1        pk }
    459   1.1        pk 
    460   1.1        pk /*
    461   1.1        pk  * Load a subset of the current (new) colormap into the IBM RAMDAC.
    462   1.1        pk  */
    463   1.1        pk static void
    464   1.1        pk p9100loadcmap(struct p9100_softc *sc, int start, int ncolors)
    465   1.1        pk {
    466   1.1        pk 	u_char *p;
    467   1.1        pk 
    468   1.1        pk 	p9100_ramdac_write(sc, DAC_CMAP_WRIDX, start);
    469   1.1        pk 
    470   1.1        pk 	for (p = sc->sc_cmap.cm_map[start], ncolors *= 3; ncolors-- > 0; p++) {
    471   1.1        pk 		p9100_ramdac_write(sc, DAC_CMAP_DATA, *p);
    472   1.1        pk 	}
    473   1.1        pk }
    474   1.1        pk 
    475   1.1        pk /*
    476   1.1        pk  * Return the address that would map the given device at the given
    477   1.1        pk  * offset, allowing for the given protection, or return -1 for error.
    478   1.1        pk  */
    479   1.1        pk paddr_t
    480   1.1        pk p9100mmap(dev_t dev, off_t off, int prot)
    481   1.1        pk {
    482   1.1        pk 	struct p9100_softc *sc = pnozz_cd.cd_devs[minor(dev)];
    483   1.1        pk 
    484   1.1        pk 	if (off & PGOFSET)
    485   1.1        pk 		panic("p9100mmap");
    486   1.1        pk 	if (off < 0)
    487   1.1        pk 		return (-1);
    488   1.1        pk 
    489   1.1        pk #define CG3_MMAP_OFFSET	0x04000000
    490   1.1        pk 	/* Make Xsun think we are a CG3 (SUN3COLOR)
    491   1.1        pk 	 */
    492   1.1        pk 	if (off >= CG3_MMAP_OFFSET && off < CG3_MMAP_OFFSET + sc->sc_fb_psize) {
    493   1.1        pk 		off -= CG3_MMAP_OFFSET;
    494   1.3       eeh 		return (bus_space_mmap(sc->sc_bustag,
    495   1.3       eeh 			sc->sc_fb_paddr,
    496   1.3       eeh 			off,
    497   1.3       eeh 			prot,
    498   1.3       eeh 			BUS_SPACE_MAP_LINEAR));
    499   1.1        pk 	}
    500   1.1        pk 
    501   1.1        pk 	if (off >= sc->sc_fb_psize + sc->sc_ctl_psize + sc->sc_cmd_psize)
    502   1.1        pk 		return (-1);
    503   1.1        pk 
    504   1.1        pk 	if (off < sc->sc_fb_psize) {
    505   1.3       eeh 		return (bus_space_mmap(sc->sc_bustag,
    506   1.3       eeh 			sc->sc_fb_paddr,
    507   1.3       eeh 			off,
    508   1.3       eeh 			prot,
    509   1.3       eeh 			BUS_SPACE_MAP_LINEAR));
    510   1.1        pk 	}
    511   1.1        pk 	off -= sc->sc_fb_psize;
    512   1.1        pk 	if (off < sc->sc_ctl_psize) {
    513   1.3       eeh 		return (bus_space_mmap(sc->sc_bustag,
    514   1.3       eeh 			sc->sc_ctl_paddr,
    515   1.3       eeh 			off,
    516   1.3       eeh 			prot,
    517   1.3       eeh 			BUS_SPACE_MAP_LINEAR));
    518   1.1        pk 	}
    519   1.1        pk 	off -= sc->sc_ctl_psize;
    520   1.1        pk 
    521   1.3       eeh 	return (bus_space_mmap(sc->sc_bustag,
    522   1.3       eeh 		sc->sc_cmd_paddr,
    523   1.3       eeh 		off,
    524   1.3       eeh 		prot,
    525   1.3       eeh 		BUS_SPACE_MAP_LINEAR));
    526   1.1        pk }
    527