Home | History | Annotate | Line # | Download | only in ibus
pm.c revision 1.13
      1  1.13       spz /*	$NetBSD: pm.c,v 1.13 2017/06/13 19:13:55 spz Exp $	*/
      2   1.2        ad 
      3   1.2        ad /*-
      4   1.2        ad  * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
      5   1.2        ad  * All rights reserved.
      6   1.2        ad  *
      7   1.2        ad  * This code is derived from software contributed to The NetBSD Foundation
      8   1.2        ad  * by Andrew Doran.
      9   1.2        ad  *
     10   1.2        ad  * Redistribution and use in source and binary forms, with or without
     11   1.2        ad  * modification, are permitted provided that the following conditions
     12   1.2        ad  * are met:
     13   1.2        ad  * 1. Redistributions of source code must retain the above copyright
     14   1.2        ad  *    notice, this list of conditions and the following disclaimer.
     15   1.2        ad  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.2        ad  *    notice, this list of conditions and the following disclaimer in the
     17   1.2        ad  *    documentation and/or other materials provided with the distribution.
     18   1.2        ad  *
     19   1.2        ad  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20   1.2        ad  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.2        ad  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.2        ad  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23   1.2        ad  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.2        ad  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.2        ad  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.2        ad  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.2        ad  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.2        ad  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.2        ad  * POSSIBILITY OF SUCH DAMAGE.
     30   1.2        ad  */
     31   1.2        ad 
     32   1.2        ad #include <sys/cdefs.h>
     33  1.13       spz __KERNEL_RCSID(0, "$NetBSD: pm.c,v 1.13 2017/06/13 19:13:55 spz Exp $");
     34   1.2        ad 
     35   1.2        ad #include <sys/param.h>
     36  1.10      matt #include <sys/buf.h>
     37  1.10      matt #include <sys/bus.h>
     38   1.2        ad #include <sys/device.h>
     39   1.2        ad #include <sys/ioctl.h>
     40  1.10      matt #include <sys/intr.h>
     41  1.10      matt #include <sys/kernel.h>
     42  1.10      matt #include <sys/systm.h>
     43   1.2        ad 
     44   1.2        ad #include <dev/wscons/wsconsio.h>
     45   1.2        ad #include <dev/wscons/wsdisplayvar.h>
     46   1.2        ad #include <dev/rasops/rasops.h>
     47   1.2        ad #include <dev/wsfont/wsfont.h>
     48   1.2        ad 
     49   1.2        ad #include <pmax/pmax/kn01.h>
     50   1.2        ad 
     51   1.2        ad #include <pmax/ibus/ibusvar.h>
     52   1.2        ad #include <pmax/ibus/pmreg.h>
     53   1.2        ad 
     54   1.2        ad #include <uvm/uvm_extern.h>
     55   1.2        ad 
     56   1.2        ad #define	CURSOR_MAX_SIZE	16
     57   1.2        ad 
     58   1.2        ad struct hwcmap256 {
     59   1.2        ad 	uint8_t r[256];
     60   1.2        ad 	uint8_t g[256];
     61   1.2        ad 	uint8_t b[256];
     62   1.2        ad };
     63   1.2        ad 
     64   1.2        ad struct hwcursor64 {
     65   1.2        ad 	struct wsdisplay_curpos cc_pos;
     66   1.2        ad 	struct wsdisplay_curpos cc_hot;
     67   1.2        ad 	struct wsdisplay_curpos cc_size;
     68   1.2        ad 	uint8_t cc_color[6];
     69   1.2        ad 
     70   1.2        ad 	/*
     71   1.2        ad 	 * Max cursor size is 16x16.  The X server pads bitmap scanlines to
     72   1.2        ad 	 * a word boundary.  We take the easy route and waste some space.
     73   1.2        ad 	 */
     74   1.2        ad 	u_short cc_image[32 + 32];
     75   1.2        ad };
     76   1.2        ad 
     77   1.2        ad struct pm_softc {
     78   1.9   tsutsui 	device_t		sc_dev;
     79   1.2        ad 	size_t			sc_cmap_size;
     80   1.2        ad 	size_t			sc_fb_size;
     81   1.2        ad 	int			sc_type;
     82   1.2        ad 	int			sc_blanked;
     83   1.2        ad 	int			sc_curenb;
     84   1.2        ad 	int			sc_changed;
     85   1.2        ad 	int			sc_nscreens;
     86   1.2        ad 	struct hwcursor64	sc_cursor;
     87   1.2        ad 	struct hwcmap256	sc_cmap;
     88   1.2        ad };
     89   1.2        ad #define	WSDISPLAY_CMAP_DOLUT	0x20
     90   1.2        ad 
     91   1.9   tsutsui int	pm_match(device_t, cfdata_t, void *);
     92   1.9   tsutsui void	pm_attach(device_t, device_t, void *);
     93   1.5  christos int	pm_ioctl(void *, void *, u_long, void *, int, struct lwp *);
     94   1.4      jmmv paddr_t	pm_mmap(void *, void *, off_t, int);
     95   1.2        ad int	pm_alloc_screen(void *, const struct wsscreen_descr *,
     96   1.2        ad 				void **, int *, int *, long *);
     97   1.2        ad void	pm_free_screen(void *, void *);
     98   1.2        ad int	pm_show_screen(void *, void *, int,
     99   1.2        ad 			       void (*) (void *, int, int), void *);
    100   1.2        ad void	pm_cursor_off(void);
    101   1.2        ad void	pm_cursor_on(struct pm_softc *);
    102   1.2        ad int	pm_cnattach(void);
    103   1.2        ad void	pm_common_init(void);
    104   1.2        ad int	pm_flush(struct pm_softc *);
    105   1.2        ad int	pm_get_cmap(struct pm_softc *, struct wsdisplay_cmap *);
    106   1.2        ad int	pm_set_cmap(struct pm_softc *, struct wsdisplay_cmap *);
    107   1.2        ad int	pm_set_cursor(struct pm_softc *, struct wsdisplay_cursor *);
    108   1.2        ad int	pm_get_cursor(struct pm_softc *, struct wsdisplay_cursor *);
    109   1.2        ad void	pm_set_curpos(struct pm_softc *, struct wsdisplay_curpos *);
    110   1.2        ad void	pm_init_cmap(struct pm_softc *);
    111   1.2        ad 
    112   1.9   tsutsui CFATTACH_DECL_NEW(pm, sizeof(struct pm_softc),
    113   1.2        ad    pm_match, pm_attach, NULL, NULL);
    114   1.2        ad 
    115   1.2        ad struct rasops_info pm_ri;
    116   1.2        ad 
    117   1.2        ad struct wsscreen_descr pm_stdscreen = {
    118   1.2        ad 	"std", 0, 0,
    119   1.2        ad 	0, /* textops */
    120   1.2        ad 	0, 0,
    121   1.2        ad 	WSSCREEN_REVERSE
    122   1.2        ad };
    123   1.2        ad 
    124   1.2        ad const struct wsscreen_descr *_pm_scrlist[] = {
    125   1.2        ad 	&pm_stdscreen,
    126   1.2        ad };
    127   1.2        ad 
    128   1.2        ad const struct wsscreen_list pm_screenlist = {
    129   1.2        ad 	sizeof(_pm_scrlist) / sizeof(struct wsscreen_descr *), _pm_scrlist
    130   1.2        ad };
    131   1.2        ad 
    132   1.2        ad const struct wsdisplay_accessops pm_accessops = {
    133   1.2        ad 	pm_ioctl,
    134   1.2        ad 	pm_mmap,
    135   1.2        ad 	pm_alloc_screen,
    136   1.2        ad 	pm_free_screen,
    137   1.2        ad 	pm_show_screen,
    138   1.2        ad 	0 /* load_font */
    139   1.2        ad };
    140   1.2        ad 
    141   1.2        ad u_int	pm_creg;
    142   1.2        ad 
    143   1.2        ad int
    144   1.9   tsutsui pm_match(device_t parent, cfdata_t cf, void *aux)
    145   1.2        ad {
    146   1.2        ad 	struct ibus_attach_args *ia;
    147   1.5  christos 	void *pmaddr;
    148   1.2        ad 
    149   1.2        ad 	ia = aux;
    150   1.5  christos 	pmaddr = (void *)ia->ia_addr;
    151   1.2        ad 
    152   1.2        ad 	if (strcmp(ia->ia_name, "pm") != 0)
    153   1.2        ad 		return (0);
    154   1.2        ad 
    155   1.2        ad 	if (badaddr(pmaddr, 4))
    156   1.2        ad 		return (0);
    157   1.2        ad 
    158   1.2        ad 	return (1);
    159   1.2        ad }
    160   1.2        ad 
    161   1.2        ad void
    162   1.9   tsutsui pm_attach(device_t parent, device_t self, void *aux)
    163   1.2        ad {
    164   1.2        ad 	struct pm_softc *sc;
    165   1.2        ad 	struct rasops_info *ri;
    166   1.2        ad 	struct wsemuldisplaydev_attach_args waa;
    167   1.2        ad 	int console;
    168   1.2        ad 
    169   1.9   tsutsui 	sc = device_private(self);
    170   1.9   tsutsui 	sc->sc_dev = self;
    171   1.2        ad 	ri = &pm_ri;
    172   1.2        ad 	console = (ri->ri_bits != NULL);
    173   1.2        ad 
    174   1.8   tsutsui 	if (console) {
    175   1.2        ad 		sc->sc_nscreens = 1;
    176   1.8   tsutsui 		ri->ri_flg &= ~RI_NO_AUTO;
    177   1.8   tsutsui 	} else
    178   1.2        ad 		pm_common_init();
    179   1.2        ad 
    180   1.2        ad 	printf(": %dx%d, %dbpp\n", ri->ri_width, ri->ri_height, ri->ri_depth);
    181   1.2        ad 
    182   1.2        ad 	pm_init_cmap(sc);
    183   1.2        ad 
    184   1.2        ad 	sc->sc_blanked = 0;
    185   1.2        ad 	sc->sc_curenb = 0;
    186   1.2        ad 
    187   1.2        ad 	waa.console = console;
    188   1.2        ad 	waa.scrdata = &pm_screenlist;
    189   1.2        ad 	waa.accessops = &pm_accessops;
    190   1.2        ad 	waa.accesscookie = sc;
    191   1.2        ad 
    192   1.2        ad 	config_found(self, &waa, wsemuldisplaydevprint);
    193   1.2        ad }
    194   1.2        ad 
    195   1.2        ad void
    196   1.2        ad pm_init_cmap(struct pm_softc *sc)
    197   1.2        ad {
    198   1.2        ad 	struct hwcmap256 *cm;
    199   1.2        ad 	struct rasops_info *ri;
    200   1.2        ad 	const uint8_t *p;
    201   1.2        ad 	int index;
    202   1.2        ad 
    203   1.2        ad 	cm = &sc->sc_cmap;
    204   1.2        ad 	ri = &pm_ri;
    205   1.2        ad 
    206   1.2        ad 	if (ri->ri_depth == 8) {
    207   1.2        ad 		p = rasops_cmap;
    208   1.2        ad 		for (index = 0; index < 256; index++, p += 3) {
    209   1.2        ad 			cm->r[index] = p[0];
    210   1.2        ad 			cm->g[index] = p[1];
    211   1.2        ad 			cm->b[index] = p[2];
    212   1.2        ad 		}
    213   1.2        ad 
    214   1.2        ad 		sc->sc_type = WSDISPLAY_TYPE_PM_COLOR;
    215   1.2        ad 		sc->sc_cmap_size = 256;
    216   1.2        ad 		sc->sc_fb_size = 0x100000;
    217   1.2        ad 	} else {
    218   1.2        ad 		cm->r[0] = 0x00;
    219   1.2        ad 		cm->g[0] = 0x00;
    220   1.2        ad 		cm->b[0] = 0x00;
    221   1.2        ad 
    222   1.2        ad 		cm->r[1] = 0x00;
    223   1.2        ad 		cm->g[1] = 0xff;
    224   1.2        ad 		cm->b[1] = 0x00;
    225   1.2        ad 
    226   1.2        ad 		sc->sc_type = WSDISPLAY_TYPE_PM_MONO;
    227   1.2        ad 		sc->sc_cmap_size = 2;
    228   1.2        ad 		sc->sc_fb_size = 0x40000;
    229   1.2        ad 	}
    230   1.2        ad }
    231   1.2        ad 
    232   1.2        ad void
    233   1.2        ad pm_common_init(void)
    234   1.2        ad {
    235   1.2        ad 	struct rasops_info *ri;
    236   1.2        ad 	int cookie, bior, i;
    237   1.2        ad 	PCCRegs *pcc;
    238   1.2        ad 	VDACRegs *vdac;
    239   1.2        ad 	uint16_t kn01csr;
    240   1.2        ad 
    241   1.2        ad 	kn01csr = *(volatile uint16_t *)MIPS_PHYS_TO_KSEG1(KN01_SYS_CSR);
    242   1.2        ad 	pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC);
    243   1.2        ad 	vdac = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_VDAC);
    244   1.2        ad 	ri = &pm_ri;
    245   1.2        ad 
    246   1.2        ad 	ri->ri_flg = RI_CENTER;
    247   1.8   tsutsui 	if (ri->ri_bits == NULL)
    248   1.8   tsutsui 		ri->ri_flg |= RI_NO_AUTO;
    249   1.2        ad 	ri->ri_depth = ((kn01csr & KN01_CSR_MONO) != 0 ? 1 : 8);
    250   1.2        ad 	ri->ri_width = 1024;
    251   1.2        ad 	ri->ri_height = 864;
    252   1.2        ad 	ri->ri_stride = (ri->ri_depth == 8 ? 1024 : 2048 / 8);
    253   1.2        ad 	ri->ri_bits = (void *)MIPS_PHYS_TO_KSEG1(KN01_PHYS_FBUF_START);
    254   1.2        ad 
    255   1.2        ad 	/*
    256   1.2        ad 	 * Clear the screen.
    257   1.2        ad 	 */
    258   1.2        ad 	memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
    259   1.2        ad 
    260   1.2        ad 	/*
    261   1.2        ad 	 * Get a font to use.
    262   1.2        ad 	 */
    263   1.2        ad 	bior = (ri->ri_depth == 8 ? WSDISPLAY_FONTORDER_L2R :
    264   1.2        ad 	    WSDISPLAY_FONTORDER_R2L);
    265   1.2        ad 
    266   1.2        ad 	wsfont_init();
    267   1.2        ad 	if (ri->ri_depth == 8)
    268   1.2        ad 		cookie = wsfont_find(NULL, 12, 0, 0, bior,
    269  1.11  macallan 		    WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
    270   1.2        ad 	else
    271   1.2        ad 		cookie = wsfont_find(NULL, 8, 0, 0, bior,
    272  1.11  macallan 		    WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
    273   1.2        ad 	if (cookie <= 0)
    274   1.2        ad 		cookie = wsfont_find(NULL, 0, 0, 0, bior,
    275  1.11  macallan 		    WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
    276   1.2        ad 	if (cookie <= 0) {
    277   1.2        ad 		printf("pm: font table is empty\n");
    278   1.2        ad 		return;
    279   1.2        ad 	}
    280   1.2        ad 
    281   1.2        ad 	if (wsfont_lock(cookie, &ri->ri_font)) {
    282   1.2        ad 		printf("pm: couldn't lock font\n");
    283   1.2        ad 		return;
    284   1.2        ad 	}
    285   1.2        ad 	ri->ri_wsfcookie = cookie;
    286   1.2        ad 
    287   1.2        ad 	/*
    288   1.2        ad 	 * Set up the raster operations set.
    289   1.2        ad 	 */
    290   1.2        ad 	rasops_init(ri, 1000, 1000);
    291   1.2        ad 
    292   1.2        ad 	pm_stdscreen.nrows = ri->ri_rows;
    293   1.2        ad 	pm_stdscreen.ncols = ri->ri_cols;
    294   1.2        ad 	pm_stdscreen.textops = &ri->ri_ops;
    295   1.2        ad 	pm_stdscreen.capabilities = ri->ri_caps;
    296   1.2        ad 
    297   1.2        ad 	/*
    298   1.2        ad 	 * Initalize the VDAC.
    299   1.2        ad 	 */
    300   1.2        ad 	*(uint8_t *)MIPS_PHYS_TO_KSEG1(KN01_PHYS_COLMASK_START) = 0xff;
    301   1.2        ad 	wbflush();
    302   1.2        ad 
    303   1.2        ad 	vdac->overWA = 0x04; wbflush();
    304   1.2        ad 	vdac->over = 0x00; wbflush();
    305   1.2        ad 	vdac->over = 0x00; wbflush();
    306   1.2        ad 	vdac->over = 0x00; wbflush();
    307   1.2        ad 	vdac->overWA = 0x08; wbflush();
    308   1.2        ad 	vdac->over = 0x00; wbflush();
    309   1.2        ad 	vdac->over = 0x00; wbflush();
    310   1.2        ad 	vdac->over = 0x7f; wbflush();
    311   1.2        ad 	vdac->overWA = 0x0c; wbflush();
    312   1.2        ad 	vdac->over = 0xff; wbflush();
    313   1.2        ad 	vdac->over = 0xff; wbflush();
    314   1.2        ad 	vdac->over = 0xff; wbflush();
    315   1.2        ad 
    316   1.2        ad 	/*
    317   1.2        ad 	 * Set in the initial colormap.
    318   1.2        ad 	 */
    319   1.2        ad 	if (ri->ri_depth == 8) {
    320   1.2        ad 		vdac->mapWA = 0;
    321   1.2        ad 		wbflush();
    322   1.2        ad 
    323   1.2        ad 		for (i = 0; i < 256 * 3; i += 3) {
    324   1.2        ad 			vdac->map = rasops_cmap[i];
    325   1.2        ad 			wbflush();
    326   1.2        ad 			vdac->map = rasops_cmap[i + 1];
    327   1.2        ad 			wbflush();
    328   1.2        ad 			vdac->map = rasops_cmap[i + 2];
    329   1.2        ad 			wbflush();
    330   1.2        ad 		}
    331   1.2        ad 	} else {
    332   1.2        ad 		vdac->mapWA = 0;
    333   1.2        ad 		wbflush();
    334   1.2        ad 
    335   1.2        ad 		for (i = 0; i < 256; i++) {
    336   1.2        ad 			vdac->map = 0x00;
    337   1.2        ad 			wbflush();
    338   1.2        ad 			vdac->map = (i < 128 ? 0x00 : 0xff);
    339   1.2        ad 			wbflush();
    340   1.2        ad 			vdac->map = 0x00;
    341   1.2        ad 			wbflush();
    342   1.2        ad 		}
    343   1.2        ad 	}
    344   1.2        ad 
    345   1.2        ad 	/*
    346   1.2        ad 	 * Turn off the hardware cursor sprite for text mode.
    347   1.2        ad 	 */
    348   1.2        ad 	pcc->cmdr = PCC_FOPB | PCC_VBHI;
    349   1.2        ad 	wbflush();
    350   1.2        ad 	pm_creg = 0;
    351   1.2        ad 	pm_cursor_off();
    352   1.2        ad }
    353   1.2        ad 
    354   1.2        ad void
    355   1.2        ad pm_cursor_off(void)
    356   1.2        ad {
    357   1.2        ad 	PCCRegs *pcc;
    358   1.2        ad 
    359   1.2        ad 	pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC);
    360   1.2        ad 	pcc->cmdr = (pm_creg &= ~(PCC_ENPA | PCC_ENPB));
    361   1.2        ad 	wbflush();
    362   1.2        ad }
    363   1.2        ad 
    364   1.2        ad void
    365   1.2        ad pm_cursor_on(struct pm_softc *sc)
    366   1.2        ad {
    367   1.2        ad 	PCCRegs *pcc;
    368   1.2        ad 
    369   1.2        ad 	if (sc->sc_curenb) {
    370   1.2        ad 		pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC);
    371   1.2        ad 		pcc->cmdr = (pm_creg |= (PCC_ENPA | PCC_ENPB));
    372   1.2        ad 		wbflush();
    373   1.2        ad 	}
    374   1.2        ad }
    375   1.2        ad 
    376   1.2        ad int
    377   1.5  christos pm_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
    378   1.2        ad {
    379   1.2        ad 	struct pm_softc *sc;
    380   1.2        ad 	struct rasops_info *ri;
    381   1.2        ad 	int turnoff, rv, i;
    382   1.2        ad 	PCCRegs *pcc;
    383   1.2        ad 	VDACRegs *vdac;
    384   1.2        ad 
    385   1.2        ad 	sc = v;
    386   1.2        ad 	ri = &pm_ri;
    387   1.2        ad 	rv = 0;
    388   1.2        ad 	pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC);
    389   1.2        ad 	vdac = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_VDAC);
    390   1.2        ad 
    391   1.2        ad 	switch (cmd) {
    392   1.2        ad 	case WSDISPLAYIO_GTYPE:
    393   1.2        ad 		*(u_int *)data = sc->sc_type;
    394   1.2        ad 		break;
    395   1.2        ad 
    396   1.2        ad 	case WSDISPLAYIO_SMODE:
    397   1.2        ad 		if (*(u_int *)data == WSDISPLAYIO_MODE_EMUL) {
    398   1.2        ad 			pm_cursor_off();
    399   1.2        ad 			pm_init_cmap(sc);
    400   1.2        ad 			memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
    401   1.2        ad 			sc->sc_curenb = 0;
    402   1.2        ad 			sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
    403   1.2        ad 		}
    404   1.2        ad 		break;
    405   1.2        ad 
    406   1.2        ad 	case WSDISPLAYIO_GINFO:
    407   1.2        ad #define	wsd_fbip ((struct wsdisplay_fbinfo *)data)
    408   1.2        ad 		wsd_fbip->height = ri->ri_height;
    409   1.2        ad 		wsd_fbip->width = ri->ri_width;
    410   1.2        ad 		wsd_fbip->depth = ri->ri_depth;
    411   1.2        ad 		wsd_fbip->cmsize = sc->sc_cmap_size;
    412   1.2        ad #undef fbt
    413   1.2        ad 		break;
    414   1.2        ad 
    415   1.2        ad 	case WSDISPLAYIO_GETCMAP:
    416   1.2        ad 		rv = pm_get_cmap(sc, (struct wsdisplay_cmap *)data);
    417   1.2        ad 		break;
    418   1.2        ad 
    419   1.2        ad 	case WSDISPLAYIO_PUTCMAP:
    420   1.2        ad 		rv = pm_set_cmap(sc, (struct wsdisplay_cmap *)data);
    421   1.2        ad 		break;
    422   1.2        ad 
    423   1.2        ad 	case WSDISPLAYIO_SVIDEO:
    424   1.2        ad 		turnoff = (*(int *)data == WSDISPLAYIO_VIDEO_OFF);
    425   1.2        ad 		if ((sc->sc_blanked == 0) ^ turnoff) {
    426   1.2        ad 			sc->sc_blanked = turnoff;
    427   1.2        ad 			if (turnoff == 0) {
    428   1.2        ad 				pcc->cmdr =
    429   1.2        ad 				    (pm_creg &= ~(PCC_FOPA | PCC_FOPB));
    430   1.2        ad 				wbflush();
    431   1.2        ad 				pm_cursor_on(sc);
    432   1.2        ad 				sc->sc_changed |= WSDISPLAY_CURSOR_DOCMAP;
    433   1.2        ad 			} else {
    434   1.2        ad 				pm_cursor_off();
    435   1.2        ad 				pcc->cmdr =
    436   1.2        ad 				    (pm_creg |= (PCC_FOPA | PCC_FOPB));
    437   1.2        ad 				wbflush();
    438   1.2        ad 				vdac->overWA = 0x0c;
    439   1.2        ad 				wbflush();
    440   1.2        ad 				for (i = 0; i < 3; i++) {
    441   1.2        ad 					vdac->over = 0;
    442   1.2        ad 					wbflush();
    443   1.2        ad 				}
    444   1.2        ad 			}
    445   1.2        ad 		}
    446   1.2        ad 		break;
    447   1.2        ad 
    448   1.2        ad 	case WSDISPLAYIO_GVIDEO:
    449   1.2        ad 		*(u_int *)data = (sc->sc_blanked ?
    450   1.2        ad 		    WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON);
    451   1.2        ad 		break;
    452   1.2        ad 
    453   1.2        ad 	case WSDISPLAYIO_GCURPOS:
    454   1.2        ad 		*(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
    455   1.2        ad 		break;
    456   1.2        ad 
    457   1.2        ad 	case WSDISPLAYIO_SCURPOS:
    458   1.2        ad 		pm_set_curpos(sc, (struct wsdisplay_curpos *)data);
    459   1.2        ad 		sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS;
    460   1.2        ad 		break;
    461   1.2        ad 
    462   1.2        ad 	case WSDISPLAYIO_GCURMAX:
    463   1.2        ad 		((struct wsdisplay_curpos *)data)->x =
    464   1.2        ad 		((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
    465   1.2        ad 		break;
    466   1.2        ad 
    467   1.2        ad 	case WSDISPLAYIO_GCURSOR:
    468   1.2        ad 		rv = pm_get_cursor(sc, (struct wsdisplay_cursor *)data);
    469   1.2        ad 		break;
    470   1.2        ad 
    471   1.2        ad 	case WSDISPLAYIO_SCURSOR:
    472   1.2        ad 		rv = pm_set_cursor(sc, (struct wsdisplay_cursor *)data);
    473   1.2        ad 		break;
    474   1.2        ad 
    475   1.2        ad 	default:
    476   1.2        ad 		rv = ENOTTY;
    477   1.2        ad 		break;
    478   1.2        ad 	}
    479   1.2        ad 
    480   1.2        ad 	pm_flush(sc);
    481   1.2        ad 	return (rv);
    482   1.2        ad }
    483   1.2        ad 
    484   1.2        ad paddr_t
    485   1.4      jmmv pm_mmap(void *v, void *vs, off_t offset, int prot)
    486   1.2        ad {
    487   1.2        ad 	struct pm_softc *sc;
    488   1.2        ad 
    489   1.2        ad 	sc = v;
    490   1.2        ad 
    491   1.2        ad 	if (offset >= sc->sc_fb_size || offset < 0)
    492   1.2        ad 		return (-1);
    493   1.2        ad 
    494   1.2        ad 	return (mips_btop(KN01_PHYS_FBUF_START + offset));
    495   1.2        ad }
    496   1.2        ad 
    497   1.2        ad int
    498   1.2        ad pm_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
    499   1.2        ad 		int *curxp, int *curyp, long *attrp)
    500   1.2        ad {
    501   1.2        ad 	struct pm_softc *sc;
    502   1.2        ad 	struct rasops_info *ri;
    503   1.2        ad 	long defattr;
    504   1.2        ad 
    505   1.2        ad 	sc = v;
    506   1.2        ad 	ri = &pm_ri;
    507   1.2        ad 
    508   1.2        ad 	if (sc->sc_nscreens > 0)
    509   1.2        ad 		return (ENOMEM);
    510   1.2        ad 
    511   1.2        ad 	*cookiep = ri;	 /* one and only for now */
    512   1.2        ad 	*curxp = 0;
    513   1.2        ad 	*curyp = 0;
    514   1.2        ad 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
    515   1.2        ad 	*attrp = defattr;
    516   1.2        ad 	sc->sc_nscreens++;
    517   1.2        ad 	return (0);
    518   1.2        ad }
    519   1.2        ad 
    520   1.2        ad void
    521   1.2        ad pm_free_screen(void *v, void *cookie)
    522   1.2        ad {
    523   1.2        ad 
    524   1.2        ad 	panic("pm_free_screen: console");
    525   1.2        ad }
    526   1.2        ad 
    527   1.2        ad int
    528   1.2        ad pm_show_screen(void *v, void *cookie, int waitok,
    529   1.2        ad 	       void (*cb)(void *, int, int), void *cbarg)
    530   1.2        ad {
    531   1.2        ad 
    532   1.2        ad 	return (0);
    533   1.2        ad }
    534   1.2        ad 
    535   1.2        ad /* EXPORT */ int
    536   1.2        ad pm_cnattach(void)
    537   1.2        ad {
    538   1.2        ad 	struct rasops_info *ri;
    539   1.2        ad 	long defattr;
    540   1.2        ad 
    541   1.2        ad 	ri = &pm_ri;
    542   1.2        ad 
    543   1.2        ad 	pm_common_init();
    544   1.2        ad 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
    545   1.2        ad 	wsdisplay_cnattach(&pm_stdscreen, ri, 0, 0, defattr);
    546   1.2        ad 	return (1);
    547   1.2        ad }
    548   1.2        ad 
    549   1.2        ad int
    550   1.2        ad pm_flush(struct pm_softc *sc)
    551   1.2        ad {
    552   1.2        ad 	VDACRegs *vdac;
    553   1.2        ad 	PCCRegs *pcc;
    554   1.2        ad 	uint8_t *cp;
    555   1.2        ad 	int v, i, x, y;
    556   1.2        ad 	u_short *p, *pe;
    557   1.2        ad 	struct hwcmap256 *cm;
    558   1.2        ad 
    559   1.2        ad 	if (sc->sc_changed == 0)
    560   1.2        ad 		return (1);
    561   1.2        ad 
    562   1.2        ad 	vdac = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_VDAC);
    563   1.2        ad 	pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC);
    564   1.2        ad 	v = sc->sc_changed;
    565   1.2        ad 
    566   1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOCUR) != 0) {
    567   1.2        ad 		if (sc->sc_curenb)
    568   1.2        ad 			pm_cursor_on(sc);
    569   1.2        ad 		else
    570   1.2        ad 			pm_cursor_off();
    571   1.2        ad 	}
    572   1.2        ad 
    573   1.2        ad 	if ((v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) != 0) {
    574   1.2        ad 		x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
    575   1.2        ad 		y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
    576   1.2        ad 		pcc->xpos = x + PCC_X_OFFSET;
    577   1.2        ad 		pcc->ypos = y + PCC_Y_OFFSET;
    578   1.2        ad 		wbflush();
    579   1.2        ad 	}
    580   1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
    581   1.2        ad 		cp = sc->sc_cursor.cc_color;
    582   1.2        ad 
    583   1.2        ad 		vdac->overWA = 0x04;
    584   1.2        ad 		wbflush();
    585   1.2        ad 		for (i = 1; i < 6; i += 2) {
    586   1.2        ad 			vdac->over = cp[i];
    587   1.2        ad 			wbflush();
    588   1.2        ad 		}
    589   1.2        ad 
    590   1.2        ad 		vdac->overWA = 0x08;
    591   1.2        ad 		wbflush();
    592   1.2        ad 		vdac->over = 0x00;
    593   1.2        ad 		wbflush();
    594   1.2        ad 		vdac->over = 0x00;
    595   1.2        ad 		wbflush();
    596   1.2        ad 		vdac->over = 0x7f;
    597   1.2        ad 		wbflush();
    598   1.2        ad 
    599   1.2        ad 		vdac->overWA = 0x0c;
    600   1.2        ad 		wbflush();
    601   1.2        ad 		for (i = 0; i < 6; i += 2) {
    602   1.2        ad 			vdac->over = cp[i];
    603   1.2        ad 			wbflush();
    604   1.2        ad 		}
    605   1.2        ad 	}
    606   1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
    607   1.2        ad 		pcc->cmdr = (pm_creg | PCC_LODSA);
    608   1.2        ad 		wbflush();
    609   1.2        ad 
    610   1.2        ad 		p = sc->sc_cursor.cc_image;
    611   1.2        ad 		x = 0xffff >> (16 - sc->sc_cursor.cc_size.x);
    612   1.2        ad 		for (pe = p + 64; p < pe; p += 2) {
    613   1.2        ad 			pcc->memory = *p & x;
    614   1.2        ad 			wbflush();
    615   1.2        ad 		}
    616   1.2        ad 
    617   1.2        ad 		pcc->cmdr = (pm_creg &= ~PCC_LODSA);
    618   1.2        ad 		wbflush();
    619   1.2        ad 	}
    620   1.2        ad 
    621   1.2        ad 	if ((v & WSDISPLAY_CMAP_DOLUT) != 0) {
    622   1.2        ad 		cm = &sc->sc_cmap;
    623   1.2        ad 
    624   1.2        ad 		vdac->mapWA = 0;
    625   1.2        ad 		wbflush();
    626   1.2        ad 
    627   1.2        ad 		if (sc->sc_cmap_size == 2) {
    628   1.2        ad 			for (i = 0; i < 128; i++) {
    629   1.2        ad 				vdac->map = 0;
    630   1.2        ad 				wbflush();
    631   1.2        ad 				vdac->map = cm->g[0];
    632   1.2        ad 				wbflush();
    633   1.2        ad 				vdac->map = 0;
    634   1.2        ad 				wbflush();
    635   1.2        ad 			}
    636   1.2        ad 			for (; i < 256; i++) {
    637   1.2        ad 				vdac->map = 0;
    638   1.2        ad 				wbflush();
    639   1.2        ad 				vdac->map = cm->g[1];
    640   1.2        ad 				wbflush();
    641   1.2        ad 				vdac->map = 0;
    642   1.2        ad 				wbflush();
    643   1.2        ad 			}
    644   1.2        ad 		} else {
    645   1.2        ad 			for (i = 0; i < sc->sc_cmap_size; i++) {
    646   1.2        ad 				vdac->map = cm->r[i];
    647   1.2        ad 				wbflush();
    648   1.2        ad 				vdac->map = cm->g[i];
    649   1.2        ad 				wbflush();
    650   1.2        ad 				vdac->map = cm->b[i];
    651   1.2        ad 				wbflush();
    652   1.2        ad 			}
    653   1.2        ad 		}
    654   1.2        ad 	}
    655   1.2        ad 
    656   1.2        ad 	sc->sc_changed = 0;
    657   1.2        ad 	return (1);
    658   1.2        ad }
    659   1.2        ad 
    660   1.2        ad int
    661   1.2        ad pm_get_cmap(struct pm_softc *sc, struct wsdisplay_cmap *p)
    662   1.2        ad {
    663   1.2        ad 	u_int index, count;
    664   1.2        ad 	int rv;
    665   1.2        ad 
    666   1.2        ad 	index = p->index;
    667   1.2        ad 	count = p->count;
    668   1.2        ad 
    669  1.13       spz 	if (index >= sc->sc_cmap_size || count > sc->sc_cmap_size - index)
    670   1.2        ad 		return (EINVAL);
    671   1.2        ad 
    672   1.2        ad 	if ((rv = copyout(&sc->sc_cmap.r[index], p->red, count)) != 0)
    673   1.2        ad 		return (rv);
    674   1.2        ad 	if ((rv = copyout(&sc->sc_cmap.g[index], p->green, count)) != 0)
    675   1.2        ad 		return (rv);
    676   1.2        ad 	return (copyout(&sc->sc_cmap.b[index], p->blue, count));
    677   1.2        ad }
    678   1.2        ad 
    679   1.2        ad int
    680   1.2        ad pm_set_cmap(struct pm_softc *sc, struct wsdisplay_cmap *p)
    681   1.2        ad {
    682   1.2        ad 	u_int index, count;
    683   1.2        ad 	int rv;
    684   1.2        ad 
    685   1.2        ad 	index = p->index;
    686   1.2        ad 	count = p->count;
    687   1.2        ad 
    688  1.13       spz 	if (index >= sc->sc_cmap_size || count > sc->sc_cmap_size - index)
    689   1.2        ad 		return (EINVAL);
    690   1.2        ad 
    691   1.2        ad 	if ((rv = copyin(p->red, &sc->sc_cmap.r[index], count)) != 0)
    692   1.2        ad 		return (rv);
    693   1.2        ad 	if ((rv = copyin(p->green, &sc->sc_cmap.g[index], count)) != 0)
    694   1.2        ad 		return (rv);
    695   1.2        ad 	if ((rv = copyin(p->blue, &sc->sc_cmap.b[index], count)) != 0)
    696   1.2        ad 		return (rv);
    697   1.2        ad 	sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
    698   1.2        ad 	return (0);
    699   1.2        ad }
    700   1.2        ad 
    701   1.2        ad int
    702   1.2        ad pm_set_cursor(struct pm_softc *sc, struct wsdisplay_cursor *p)
    703   1.2        ad {
    704   1.2        ad 	u_int v, index, count;
    705   1.2        ad 	struct hwcursor64 *cc;
    706   1.2        ad 	int rv;
    707   1.2        ad 
    708   1.2        ad 	v = p->which;
    709   1.2        ad 	cc = &sc->sc_cursor;
    710   1.2        ad 
    711   1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOCUR) != 0)
    712   1.2        ad 		sc->sc_curenb = p->enable;
    713   1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOPOS) != 0)
    714   1.2        ad 		pm_set_curpos(sc, &p->pos);
    715   1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOHOT) != 0)
    716   1.2        ad 		cc->cc_hot = p->hot;
    717   1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
    718   1.2        ad 		index = p->cmap.index;
    719   1.2        ad 		count = p->cmap.count;
    720   1.2        ad 		if (index >= 2 || (index + count) > 2)
    721   1.2        ad 			return (EINVAL);
    722   1.2        ad 
    723   1.2        ad 		rv = copyin(p->cmap.red, &cc->cc_color[index], count);
    724   1.2        ad 		if (rv != 0)
    725   1.2        ad 			return (rv);
    726   1.2        ad 		rv = copyin(p->cmap.green, &cc->cc_color[index + 2], count);
    727   1.2        ad 		if (rv != 0)
    728   1.2        ad 			return (rv);
    729   1.2        ad 		rv = copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
    730   1.2        ad 		if (rv != 0)
    731   1.2        ad 			return (rv);
    732   1.2        ad 	}
    733   1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
    734   1.2        ad 		if (p->size.x > CURSOR_MAX_SIZE ||
    735   1.2        ad 		    p->size.y > CURSOR_MAX_SIZE)
    736   1.2        ad 			return (EINVAL);
    737   1.2        ad 
    738   1.2        ad 		cc->cc_size = p->size;
    739   1.2        ad 		memset(cc->cc_image, 0, sizeof(cc->cc_image));
    740   1.2        ad 		rv = copyin(p->image, cc->cc_image, p->size.y * 4);
    741   1.2        ad 		if (rv != 0)
    742   1.2        ad 			return (rv);
    743   1.2        ad 		rv = copyin(p->mask, cc->cc_image+32, p->size.y * 4);
    744   1.2        ad 		if (rv != 0)
    745   1.2        ad 			return (rv);
    746   1.2        ad 	}
    747   1.2        ad 
    748   1.2        ad 	sc->sc_changed |= v;
    749   1.2        ad 	return (0);
    750   1.2        ad }
    751   1.2        ad 
    752   1.2        ad int
    753   1.2        ad pm_get_cursor(struct pm_softc *sc, struct wsdisplay_cursor *p)
    754   1.2        ad {
    755   1.2        ad 
    756   1.2        ad 	return (ENOTTY); /* XXX */
    757   1.2        ad }
    758   1.2        ad 
    759   1.2        ad void
    760   1.2        ad pm_set_curpos(struct pm_softc *sc, struct wsdisplay_curpos *curpos)
    761   1.2        ad {
    762   1.2        ad 	struct rasops_info *ri;
    763   1.2        ad 	int x, y;
    764   1.2        ad 
    765   1.2        ad 	ri = &pm_ri;
    766   1.2        ad 	x = curpos->x;
    767   1.2        ad 	y = curpos->y;
    768   1.2        ad 
    769   1.2        ad 	if (y < 0)
    770   1.2        ad 		y = 0;
    771   1.2        ad 	else if (y > ri->ri_height)
    772   1.2        ad 		y = ri->ri_height;
    773   1.2        ad 	if (x < 0)
    774   1.2        ad 		x = 0;
    775   1.2        ad 	else if (x > ri->ri_width)
    776   1.2        ad 		x = ri->ri_width;
    777   1.2        ad 	sc->sc_cursor.cc_pos.x = x;
    778   1.2        ad 	sc->sc_cursor.cc_pos.y = y;
    779   1.2        ad }
    780