Home | History | Annotate | Line # | Download | only in ibus
pm.c revision 1.11.16.1
      1  1.11.16.1       snj /*	$NetBSD: pm.c,v 1.11.16.1 2017/06/15 06:02:57 snj 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.11.16.1       snj __KERNEL_RCSID(0, "$NetBSD: pm.c,v 1.11.16.1 2017/06/15 06:02:57 snj 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 	struct rasops_info *ri;
    559        1.2        ad 
    560        1.2        ad 	if (sc->sc_changed == 0)
    561        1.2        ad 		return (1);
    562        1.2        ad 
    563        1.2        ad 	vdac = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_VDAC);
    564        1.2        ad 	pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC);
    565        1.2        ad 	ri = &pm_ri;
    566        1.2        ad 	v = sc->sc_changed;
    567        1.2        ad 
    568        1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOCUR) != 0) {
    569        1.2        ad 		if (sc->sc_curenb)
    570        1.2        ad 			pm_cursor_on(sc);
    571        1.2        ad 		else
    572        1.2        ad 			pm_cursor_off();
    573        1.2        ad 	}
    574        1.2        ad 
    575        1.2        ad 	if ((v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) != 0) {
    576        1.2        ad 		x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
    577        1.2        ad 		y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
    578        1.2        ad 		pcc->xpos = x + PCC_X_OFFSET;
    579        1.2        ad 		pcc->ypos = y + PCC_Y_OFFSET;
    580        1.2        ad 		wbflush();
    581        1.2        ad 	}
    582        1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
    583        1.2        ad 		cp = sc->sc_cursor.cc_color;
    584        1.2        ad 
    585        1.2        ad 		vdac->overWA = 0x04;
    586        1.2        ad 		wbflush();
    587        1.2        ad 		for (i = 1; i < 6; i += 2) {
    588        1.2        ad 			vdac->over = cp[i];
    589        1.2        ad 			wbflush();
    590        1.2        ad 		}
    591        1.2        ad 
    592        1.2        ad 		vdac->overWA = 0x08;
    593        1.2        ad 		wbflush();
    594        1.2        ad 		vdac->over = 0x00;
    595        1.2        ad 		wbflush();
    596        1.2        ad 		vdac->over = 0x00;
    597        1.2        ad 		wbflush();
    598        1.2        ad 		vdac->over = 0x7f;
    599        1.2        ad 		wbflush();
    600        1.2        ad 
    601        1.2        ad 		vdac->overWA = 0x0c;
    602        1.2        ad 		wbflush();
    603        1.2        ad 		for (i = 0; i < 6; i += 2) {
    604        1.2        ad 			vdac->over = cp[i];
    605        1.2        ad 			wbflush();
    606        1.2        ad 		}
    607        1.2        ad 	}
    608        1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
    609        1.2        ad 		pcc->cmdr = (pm_creg | PCC_LODSA);
    610        1.2        ad 		wbflush();
    611        1.2        ad 
    612        1.2        ad 		p = sc->sc_cursor.cc_image;
    613        1.2        ad 		x = 0xffff >> (16 - sc->sc_cursor.cc_size.x);
    614        1.2        ad 		for (pe = p + 64; p < pe; p += 2) {
    615        1.2        ad 			pcc->memory = *p & x;
    616        1.2        ad 			wbflush();
    617        1.2        ad 		}
    618        1.2        ad 
    619        1.2        ad 		pcc->cmdr = (pm_creg &= ~PCC_LODSA);
    620        1.2        ad 		wbflush();
    621        1.2        ad 	}
    622        1.2        ad 
    623        1.2        ad 	if ((v & WSDISPLAY_CMAP_DOLUT) != 0) {
    624        1.2        ad 		cm = &sc->sc_cmap;
    625        1.2        ad 
    626        1.2        ad 		vdac->mapWA = 0;
    627        1.2        ad 		wbflush();
    628        1.2        ad 
    629        1.2        ad 		if (sc->sc_cmap_size == 2) {
    630        1.2        ad 			for (i = 0; i < 128; i++) {
    631        1.2        ad 				vdac->map = 0;
    632        1.2        ad 				wbflush();
    633        1.2        ad 				vdac->map = cm->g[0];
    634        1.2        ad 				wbflush();
    635        1.2        ad 				vdac->map = 0;
    636        1.2        ad 				wbflush();
    637        1.2        ad 			}
    638        1.2        ad 			for (; i < 256; i++) {
    639        1.2        ad 				vdac->map = 0;
    640        1.2        ad 				wbflush();
    641        1.2        ad 				vdac->map = cm->g[1];
    642        1.2        ad 				wbflush();
    643        1.2        ad 				vdac->map = 0;
    644        1.2        ad 				wbflush();
    645        1.2        ad 			}
    646        1.2        ad 		} else {
    647        1.2        ad 			for (i = 0; i < sc->sc_cmap_size; i++) {
    648        1.2        ad 				vdac->map = cm->r[i];
    649        1.2        ad 				wbflush();
    650        1.2        ad 				vdac->map = cm->g[i];
    651        1.2        ad 				wbflush();
    652        1.2        ad 				vdac->map = cm->b[i];
    653        1.2        ad 				wbflush();
    654        1.2        ad 			}
    655        1.2        ad 		}
    656        1.2        ad 	}
    657        1.2        ad 
    658        1.2        ad 	sc->sc_changed = 0;
    659        1.2        ad 	return (1);
    660        1.2        ad }
    661        1.2        ad 
    662        1.2        ad int
    663        1.2        ad pm_get_cmap(struct pm_softc *sc, struct wsdisplay_cmap *p)
    664        1.2        ad {
    665        1.2        ad 	u_int index, count;
    666        1.2        ad 	int rv;
    667        1.2        ad 
    668        1.2        ad 	index = p->index;
    669        1.2        ad 	count = p->count;
    670        1.2        ad 
    671  1.11.16.1       snj 	if (index >= sc->sc_cmap_size || count > sc->sc_cmap_size - index)
    672        1.2        ad 		return (EINVAL);
    673        1.2        ad 
    674        1.2        ad 	if ((rv = copyout(&sc->sc_cmap.r[index], p->red, count)) != 0)
    675        1.2        ad 		return (rv);
    676        1.2        ad 	if ((rv = copyout(&sc->sc_cmap.g[index], p->green, count)) != 0)
    677        1.2        ad 		return (rv);
    678        1.2        ad 	return (copyout(&sc->sc_cmap.b[index], p->blue, count));
    679        1.2        ad }
    680        1.2        ad 
    681        1.2        ad int
    682        1.2        ad pm_set_cmap(struct pm_softc *sc, struct wsdisplay_cmap *p)
    683        1.2        ad {
    684        1.2        ad 	u_int index, count;
    685        1.2        ad 	int rv;
    686        1.2        ad 
    687        1.2        ad 	index = p->index;
    688        1.2        ad 	count = p->count;
    689        1.2        ad 
    690  1.11.16.1       snj 	if (index >= sc->sc_cmap_size || count > sc->sc_cmap_size - index)
    691        1.2        ad 		return (EINVAL);
    692        1.2        ad 
    693        1.2        ad 	if ((rv = copyin(p->red, &sc->sc_cmap.r[index], count)) != 0)
    694        1.2        ad 		return (rv);
    695        1.2        ad 	if ((rv = copyin(p->green, &sc->sc_cmap.g[index], count)) != 0)
    696        1.2        ad 		return (rv);
    697        1.2        ad 	if ((rv = copyin(p->blue, &sc->sc_cmap.b[index], count)) != 0)
    698        1.2        ad 		return (rv);
    699        1.2        ad 	sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
    700        1.2        ad 	return (0);
    701        1.2        ad }
    702        1.2        ad 
    703        1.2        ad int
    704        1.2        ad pm_set_cursor(struct pm_softc *sc, struct wsdisplay_cursor *p)
    705        1.2        ad {
    706        1.2        ad 	u_int v, index, count;
    707        1.2        ad 	struct hwcursor64 *cc;
    708        1.2        ad 	int rv;
    709        1.2        ad 
    710        1.2        ad 	v = p->which;
    711        1.2        ad 	cc = &sc->sc_cursor;
    712        1.2        ad 
    713        1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOCUR) != 0)
    714        1.2        ad 		sc->sc_curenb = p->enable;
    715        1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOPOS) != 0)
    716        1.2        ad 		pm_set_curpos(sc, &p->pos);
    717        1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOHOT) != 0)
    718        1.2        ad 		cc->cc_hot = p->hot;
    719        1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
    720        1.2        ad 		index = p->cmap.index;
    721        1.2        ad 		count = p->cmap.count;
    722        1.2        ad 		if (index >= 2 || (index + count) > 2)
    723        1.2        ad 			return (EINVAL);
    724        1.2        ad 
    725        1.2        ad 		rv = copyin(p->cmap.red, &cc->cc_color[index], count);
    726        1.2        ad 		if (rv != 0)
    727        1.2        ad 			return (rv);
    728        1.2        ad 		rv = copyin(p->cmap.green, &cc->cc_color[index + 2], count);
    729        1.2        ad 		if (rv != 0)
    730        1.2        ad 			return (rv);
    731        1.2        ad 		rv = copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
    732        1.2        ad 		if (rv != 0)
    733        1.2        ad 			return (rv);
    734        1.2        ad 	}
    735        1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
    736        1.2        ad 		if (p->size.x > CURSOR_MAX_SIZE ||
    737        1.2        ad 		    p->size.y > CURSOR_MAX_SIZE)
    738        1.2        ad 			return (EINVAL);
    739        1.2        ad 
    740        1.2        ad 		cc->cc_size = p->size;
    741        1.2        ad 		memset(cc->cc_image, 0, sizeof(cc->cc_image));
    742        1.2        ad 		rv = copyin(p->image, cc->cc_image, p->size.y * 4);
    743        1.2        ad 		if (rv != 0)
    744        1.2        ad 			return (rv);
    745        1.2        ad 		rv = copyin(p->mask, cc->cc_image+32, p->size.y * 4);
    746        1.2        ad 		if (rv != 0)
    747        1.2        ad 			return (rv);
    748        1.2        ad 	}
    749        1.2        ad 
    750        1.2        ad 	sc->sc_changed |= v;
    751        1.2        ad 	return (0);
    752        1.2        ad }
    753        1.2        ad 
    754        1.2        ad int
    755        1.2        ad pm_get_cursor(struct pm_softc *sc, struct wsdisplay_cursor *p)
    756        1.2        ad {
    757        1.2        ad 
    758        1.2        ad 	return (ENOTTY); /* XXX */
    759        1.2        ad }
    760        1.2        ad 
    761        1.2        ad void
    762        1.2        ad pm_set_curpos(struct pm_softc *sc, struct wsdisplay_curpos *curpos)
    763        1.2        ad {
    764        1.2        ad 	struct rasops_info *ri;
    765        1.2        ad 	int x, y;
    766        1.2        ad 
    767        1.2        ad 	ri = &pm_ri;
    768        1.2        ad 	x = curpos->x;
    769        1.2        ad 	y = curpos->y;
    770        1.2        ad 
    771        1.2        ad 	if (y < 0)
    772        1.2        ad 		y = 0;
    773        1.2        ad 	else if (y > ri->ri_height)
    774        1.2        ad 		y = ri->ri_height;
    775        1.2        ad 	if (x < 0)
    776        1.2        ad 		x = 0;
    777        1.2        ad 	else if (x > ri->ri_width)
    778        1.2        ad 		x = ri->ri_width;
    779        1.2        ad 	sc->sc_cursor.cc_pos.x = x;
    780        1.2        ad 	sc->sc_cursor.cc_pos.y = y;
    781        1.2        ad }
    782