Home | History | Annotate | Line # | Download | only in ibus
pm.c revision 1.14
      1  1.14      flxd /*	$NetBSD: pm.c,v 1.14 2018/01/05 13:11:32 flxd 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.14      flxd __KERNEL_RCSID(0, "$NetBSD: pm.c,v 1.14 2018/01/05 13:11:32 flxd 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.14      flxd int	pm_check_vfb(void);
     94   1.5  christos int	pm_ioctl(void *, void *, u_long, void *, int, struct lwp *);
     95   1.4      jmmv paddr_t	pm_mmap(void *, void *, off_t, int);
     96   1.2        ad int	pm_alloc_screen(void *, const struct wsscreen_descr *,
     97   1.2        ad 				void **, int *, int *, long *);
     98   1.2        ad void	pm_free_screen(void *, void *);
     99   1.2        ad int	pm_show_screen(void *, void *, int,
    100   1.2        ad 			       void (*) (void *, int, int), void *);
    101   1.2        ad void	pm_cursor_off(void);
    102   1.2        ad void	pm_cursor_on(struct pm_softc *);
    103   1.2        ad int	pm_cnattach(void);
    104   1.2        ad void	pm_common_init(void);
    105   1.2        ad int	pm_flush(struct pm_softc *);
    106   1.2        ad int	pm_get_cmap(struct pm_softc *, struct wsdisplay_cmap *);
    107   1.2        ad int	pm_set_cmap(struct pm_softc *, struct wsdisplay_cmap *);
    108   1.2        ad int	pm_set_cursor(struct pm_softc *, struct wsdisplay_cursor *);
    109   1.2        ad int	pm_get_cursor(struct pm_softc *, struct wsdisplay_cursor *);
    110   1.2        ad void	pm_set_curpos(struct pm_softc *, struct wsdisplay_curpos *);
    111   1.2        ad void	pm_init_cmap(struct pm_softc *);
    112   1.2        ad 
    113   1.9   tsutsui CFATTACH_DECL_NEW(pm, sizeof(struct pm_softc),
    114   1.2        ad    pm_match, pm_attach, NULL, NULL);
    115   1.2        ad 
    116   1.2        ad struct rasops_info pm_ri;
    117   1.2        ad 
    118   1.2        ad struct wsscreen_descr pm_stdscreen = {
    119   1.2        ad 	"std", 0, 0,
    120   1.2        ad 	0, /* textops */
    121   1.2        ad 	0, 0,
    122   1.2        ad 	WSSCREEN_REVERSE
    123   1.2        ad };
    124   1.2        ad 
    125   1.2        ad const struct wsscreen_descr *_pm_scrlist[] = {
    126   1.2        ad 	&pm_stdscreen,
    127   1.2        ad };
    128   1.2        ad 
    129   1.2        ad const struct wsscreen_list pm_screenlist = {
    130   1.2        ad 	sizeof(_pm_scrlist) / sizeof(struct wsscreen_descr *), _pm_scrlist
    131   1.2        ad };
    132   1.2        ad 
    133   1.2        ad const struct wsdisplay_accessops pm_accessops = {
    134   1.2        ad 	pm_ioctl,
    135   1.2        ad 	pm_mmap,
    136   1.2        ad 	pm_alloc_screen,
    137   1.2        ad 	pm_free_screen,
    138   1.2        ad 	pm_show_screen,
    139   1.2        ad 	0 /* load_font */
    140   1.2        ad };
    141   1.2        ad 
    142   1.2        ad u_int	pm_creg;
    143   1.2        ad 
    144   1.2        ad int
    145   1.9   tsutsui pm_match(device_t parent, cfdata_t cf, void *aux)
    146   1.2        ad {
    147   1.2        ad 	struct ibus_attach_args *ia;
    148   1.5  christos 	void *pmaddr;
    149   1.2        ad 
    150   1.2        ad 	ia = aux;
    151   1.5  christos 	pmaddr = (void *)ia->ia_addr;
    152   1.2        ad 
    153   1.2        ad 	if (strcmp(ia->ia_name, "pm") != 0)
    154   1.2        ad 		return (0);
    155   1.2        ad 
    156   1.2        ad 	if (badaddr(pmaddr, 4))
    157   1.2        ad 		return (0);
    158   1.2        ad 
    159   1.2        ad 	return (1);
    160   1.2        ad }
    161   1.2        ad 
    162   1.2        ad void
    163   1.9   tsutsui pm_attach(device_t parent, device_t self, void *aux)
    164   1.2        ad {
    165   1.2        ad 	struct pm_softc *sc;
    166   1.2        ad 	struct rasops_info *ri;
    167   1.2        ad 	struct wsemuldisplaydev_attach_args waa;
    168   1.2        ad 	int console;
    169   1.2        ad 
    170   1.9   tsutsui 	sc = device_private(self);
    171   1.9   tsutsui 	sc->sc_dev = self;
    172   1.2        ad 	ri = &pm_ri;
    173   1.2        ad 	console = (ri->ri_bits != NULL);
    174   1.2        ad 
    175   1.8   tsutsui 	if (console) {
    176   1.2        ad 		sc->sc_nscreens = 1;
    177   1.8   tsutsui 		ri->ri_flg &= ~RI_NO_AUTO;
    178  1.14      flxd 	} else if (!pm_check_vfb()) {
    179  1.14      flxd 		printf(": VFB01/VFB02 frame buffer option not found\n");
    180  1.14      flxd 		return;
    181   1.8   tsutsui 	} else
    182   1.2        ad 		pm_common_init();
    183   1.2        ad 
    184   1.2        ad 	printf(": %dx%d, %dbpp\n", ri->ri_width, ri->ri_height, ri->ri_depth);
    185   1.2        ad 
    186   1.2        ad 	pm_init_cmap(sc);
    187   1.2        ad 
    188   1.2        ad 	sc->sc_blanked = 0;
    189   1.2        ad 	sc->sc_curenb = 0;
    190   1.2        ad 
    191   1.2        ad 	waa.console = console;
    192   1.2        ad 	waa.scrdata = &pm_screenlist;
    193   1.2        ad 	waa.accessops = &pm_accessops;
    194   1.2        ad 	waa.accesscookie = sc;
    195   1.2        ad 
    196   1.2        ad 	config_found(self, &waa, wsemuldisplaydevprint);
    197   1.2        ad }
    198   1.2        ad 
    199  1.14      flxd int
    200  1.14      flxd pm_check_vfb(void)
    201  1.14      flxd {
    202  1.14      flxd 	int *mem;
    203  1.14      flxd 	const int magic = 0xcafebabe;
    204  1.14      flxd 
    205  1.14      flxd 	mem = (void *)MIPS_PHYS_TO_KSEG1(KN01_PHYS_FBUF_START);
    206  1.14      flxd 
    207  1.14      flxd 	*mem = magic;
    208  1.14      flxd 	wbflush();
    209  1.14      flxd 	if (*mem != magic)
    210  1.14      flxd 		return 0;
    211  1.14      flxd 
    212  1.14      flxd 	*mem = ~magic;
    213  1.14      flxd 	wbflush();
    214  1.14      flxd 	if (*mem != ~magic)
    215  1.14      flxd 		return 0;
    216  1.14      flxd 
    217  1.14      flxd 	return 1;
    218  1.14      flxd }
    219  1.14      flxd 
    220   1.2        ad void
    221   1.2        ad pm_init_cmap(struct pm_softc *sc)
    222   1.2        ad {
    223   1.2        ad 	struct hwcmap256 *cm;
    224   1.2        ad 	struct rasops_info *ri;
    225   1.2        ad 	const uint8_t *p;
    226   1.2        ad 	int index;
    227   1.2        ad 
    228   1.2        ad 	cm = &sc->sc_cmap;
    229   1.2        ad 	ri = &pm_ri;
    230   1.2        ad 
    231   1.2        ad 	if (ri->ri_depth == 8) {
    232   1.2        ad 		p = rasops_cmap;
    233   1.2        ad 		for (index = 0; index < 256; index++, p += 3) {
    234   1.2        ad 			cm->r[index] = p[0];
    235   1.2        ad 			cm->g[index] = p[1];
    236   1.2        ad 			cm->b[index] = p[2];
    237   1.2        ad 		}
    238   1.2        ad 
    239   1.2        ad 		sc->sc_type = WSDISPLAY_TYPE_PM_COLOR;
    240   1.2        ad 		sc->sc_cmap_size = 256;
    241   1.2        ad 		sc->sc_fb_size = 0x100000;
    242   1.2        ad 	} else {
    243   1.2        ad 		cm->r[0] = 0x00;
    244   1.2        ad 		cm->g[0] = 0x00;
    245   1.2        ad 		cm->b[0] = 0x00;
    246   1.2        ad 
    247   1.2        ad 		cm->r[1] = 0x00;
    248   1.2        ad 		cm->g[1] = 0xff;
    249   1.2        ad 		cm->b[1] = 0x00;
    250   1.2        ad 
    251   1.2        ad 		sc->sc_type = WSDISPLAY_TYPE_PM_MONO;
    252   1.2        ad 		sc->sc_cmap_size = 2;
    253   1.2        ad 		sc->sc_fb_size = 0x40000;
    254   1.2        ad 	}
    255   1.2        ad }
    256   1.2        ad 
    257   1.2        ad void
    258   1.2        ad pm_common_init(void)
    259   1.2        ad {
    260   1.2        ad 	struct rasops_info *ri;
    261   1.2        ad 	int cookie, bior, i;
    262   1.2        ad 	PCCRegs *pcc;
    263   1.2        ad 	VDACRegs *vdac;
    264   1.2        ad 	uint16_t kn01csr;
    265   1.2        ad 
    266   1.2        ad 	kn01csr = *(volatile uint16_t *)MIPS_PHYS_TO_KSEG1(KN01_SYS_CSR);
    267   1.2        ad 	pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC);
    268   1.2        ad 	vdac = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_VDAC);
    269   1.2        ad 	ri = &pm_ri;
    270   1.2        ad 
    271   1.2        ad 	ri->ri_flg = RI_CENTER;
    272   1.8   tsutsui 	if (ri->ri_bits == NULL)
    273   1.8   tsutsui 		ri->ri_flg |= RI_NO_AUTO;
    274   1.2        ad 	ri->ri_depth = ((kn01csr & KN01_CSR_MONO) != 0 ? 1 : 8);
    275   1.2        ad 	ri->ri_width = 1024;
    276   1.2        ad 	ri->ri_height = 864;
    277   1.2        ad 	ri->ri_stride = (ri->ri_depth == 8 ? 1024 : 2048 / 8);
    278   1.2        ad 	ri->ri_bits = (void *)MIPS_PHYS_TO_KSEG1(KN01_PHYS_FBUF_START);
    279   1.2        ad 
    280   1.2        ad 	/*
    281   1.2        ad 	 * Clear the screen.
    282   1.2        ad 	 */
    283   1.2        ad 	memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
    284   1.2        ad 
    285   1.2        ad 	/*
    286   1.2        ad 	 * Get a font to use.
    287   1.2        ad 	 */
    288   1.2        ad 	bior = (ri->ri_depth == 8 ? WSDISPLAY_FONTORDER_L2R :
    289   1.2        ad 	    WSDISPLAY_FONTORDER_R2L);
    290   1.2        ad 
    291   1.2        ad 	wsfont_init();
    292   1.2        ad 	if (ri->ri_depth == 8)
    293   1.2        ad 		cookie = wsfont_find(NULL, 12, 0, 0, bior,
    294  1.11  macallan 		    WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
    295   1.2        ad 	else
    296   1.2        ad 		cookie = wsfont_find(NULL, 8, 0, 0, bior,
    297  1.11  macallan 		    WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
    298   1.2        ad 	if (cookie <= 0)
    299   1.2        ad 		cookie = wsfont_find(NULL, 0, 0, 0, bior,
    300  1.11  macallan 		    WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
    301   1.2        ad 	if (cookie <= 0) {
    302   1.2        ad 		printf("pm: font table is empty\n");
    303   1.2        ad 		return;
    304   1.2        ad 	}
    305   1.2        ad 
    306   1.2        ad 	if (wsfont_lock(cookie, &ri->ri_font)) {
    307   1.2        ad 		printf("pm: couldn't lock font\n");
    308   1.2        ad 		return;
    309   1.2        ad 	}
    310   1.2        ad 	ri->ri_wsfcookie = cookie;
    311   1.2        ad 
    312   1.2        ad 	/*
    313   1.2        ad 	 * Set up the raster operations set.
    314   1.2        ad 	 */
    315   1.2        ad 	rasops_init(ri, 1000, 1000);
    316   1.2        ad 
    317   1.2        ad 	pm_stdscreen.nrows = ri->ri_rows;
    318   1.2        ad 	pm_stdscreen.ncols = ri->ri_cols;
    319   1.2        ad 	pm_stdscreen.textops = &ri->ri_ops;
    320   1.2        ad 	pm_stdscreen.capabilities = ri->ri_caps;
    321   1.2        ad 
    322   1.2        ad 	/*
    323   1.2        ad 	 * Initalize the VDAC.
    324   1.2        ad 	 */
    325   1.2        ad 	*(uint8_t *)MIPS_PHYS_TO_KSEG1(KN01_PHYS_COLMASK_START) = 0xff;
    326   1.2        ad 	wbflush();
    327   1.2        ad 
    328   1.2        ad 	vdac->overWA = 0x04; wbflush();
    329   1.2        ad 	vdac->over = 0x00; wbflush();
    330   1.2        ad 	vdac->over = 0x00; wbflush();
    331   1.2        ad 	vdac->over = 0x00; wbflush();
    332   1.2        ad 	vdac->overWA = 0x08; wbflush();
    333   1.2        ad 	vdac->over = 0x00; wbflush();
    334   1.2        ad 	vdac->over = 0x00; wbflush();
    335   1.2        ad 	vdac->over = 0x7f; wbflush();
    336   1.2        ad 	vdac->overWA = 0x0c; wbflush();
    337   1.2        ad 	vdac->over = 0xff; wbflush();
    338   1.2        ad 	vdac->over = 0xff; wbflush();
    339   1.2        ad 	vdac->over = 0xff; wbflush();
    340   1.2        ad 
    341   1.2        ad 	/*
    342   1.2        ad 	 * Set in the initial colormap.
    343   1.2        ad 	 */
    344   1.2        ad 	if (ri->ri_depth == 8) {
    345   1.2        ad 		vdac->mapWA = 0;
    346   1.2        ad 		wbflush();
    347   1.2        ad 
    348   1.2        ad 		for (i = 0; i < 256 * 3; i += 3) {
    349   1.2        ad 			vdac->map = rasops_cmap[i];
    350   1.2        ad 			wbflush();
    351   1.2        ad 			vdac->map = rasops_cmap[i + 1];
    352   1.2        ad 			wbflush();
    353   1.2        ad 			vdac->map = rasops_cmap[i + 2];
    354   1.2        ad 			wbflush();
    355   1.2        ad 		}
    356   1.2        ad 	} else {
    357   1.2        ad 		vdac->mapWA = 0;
    358   1.2        ad 		wbflush();
    359   1.2        ad 
    360   1.2        ad 		for (i = 0; i < 256; i++) {
    361   1.2        ad 			vdac->map = 0x00;
    362   1.2        ad 			wbflush();
    363   1.2        ad 			vdac->map = (i < 128 ? 0x00 : 0xff);
    364   1.2        ad 			wbflush();
    365   1.2        ad 			vdac->map = 0x00;
    366   1.2        ad 			wbflush();
    367   1.2        ad 		}
    368   1.2        ad 	}
    369   1.2        ad 
    370   1.2        ad 	/*
    371   1.2        ad 	 * Turn off the hardware cursor sprite for text mode.
    372   1.2        ad 	 */
    373   1.2        ad 	pcc->cmdr = PCC_FOPB | PCC_VBHI;
    374   1.2        ad 	wbflush();
    375   1.2        ad 	pm_creg = 0;
    376   1.2        ad 	pm_cursor_off();
    377   1.2        ad }
    378   1.2        ad 
    379   1.2        ad void
    380   1.2        ad pm_cursor_off(void)
    381   1.2        ad {
    382   1.2        ad 	PCCRegs *pcc;
    383   1.2        ad 
    384   1.2        ad 	pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC);
    385   1.2        ad 	pcc->cmdr = (pm_creg &= ~(PCC_ENPA | PCC_ENPB));
    386   1.2        ad 	wbflush();
    387   1.2        ad }
    388   1.2        ad 
    389   1.2        ad void
    390   1.2        ad pm_cursor_on(struct pm_softc *sc)
    391   1.2        ad {
    392   1.2        ad 	PCCRegs *pcc;
    393   1.2        ad 
    394   1.2        ad 	if (sc->sc_curenb) {
    395   1.2        ad 		pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC);
    396   1.2        ad 		pcc->cmdr = (pm_creg |= (PCC_ENPA | PCC_ENPB));
    397   1.2        ad 		wbflush();
    398   1.2        ad 	}
    399   1.2        ad }
    400   1.2        ad 
    401   1.2        ad int
    402   1.5  christos pm_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
    403   1.2        ad {
    404   1.2        ad 	struct pm_softc *sc;
    405   1.2        ad 	struct rasops_info *ri;
    406   1.2        ad 	int turnoff, rv, i;
    407   1.2        ad 	PCCRegs *pcc;
    408   1.2        ad 	VDACRegs *vdac;
    409   1.2        ad 
    410   1.2        ad 	sc = v;
    411   1.2        ad 	ri = &pm_ri;
    412   1.2        ad 	rv = 0;
    413   1.2        ad 	pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC);
    414   1.2        ad 	vdac = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_VDAC);
    415   1.2        ad 
    416   1.2        ad 	switch (cmd) {
    417   1.2        ad 	case WSDISPLAYIO_GTYPE:
    418   1.2        ad 		*(u_int *)data = sc->sc_type;
    419   1.2        ad 		break;
    420   1.2        ad 
    421   1.2        ad 	case WSDISPLAYIO_SMODE:
    422   1.2        ad 		if (*(u_int *)data == WSDISPLAYIO_MODE_EMUL) {
    423   1.2        ad 			pm_cursor_off();
    424   1.2        ad 			pm_init_cmap(sc);
    425   1.2        ad 			memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
    426   1.2        ad 			sc->sc_curenb = 0;
    427   1.2        ad 			sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
    428   1.2        ad 		}
    429   1.2        ad 		break;
    430   1.2        ad 
    431   1.2        ad 	case WSDISPLAYIO_GINFO:
    432   1.2        ad #define	wsd_fbip ((struct wsdisplay_fbinfo *)data)
    433   1.2        ad 		wsd_fbip->height = ri->ri_height;
    434   1.2        ad 		wsd_fbip->width = ri->ri_width;
    435   1.2        ad 		wsd_fbip->depth = ri->ri_depth;
    436   1.2        ad 		wsd_fbip->cmsize = sc->sc_cmap_size;
    437   1.2        ad #undef fbt
    438   1.2        ad 		break;
    439   1.2        ad 
    440   1.2        ad 	case WSDISPLAYIO_GETCMAP:
    441   1.2        ad 		rv = pm_get_cmap(sc, (struct wsdisplay_cmap *)data);
    442   1.2        ad 		break;
    443   1.2        ad 
    444   1.2        ad 	case WSDISPLAYIO_PUTCMAP:
    445   1.2        ad 		rv = pm_set_cmap(sc, (struct wsdisplay_cmap *)data);
    446   1.2        ad 		break;
    447   1.2        ad 
    448   1.2        ad 	case WSDISPLAYIO_SVIDEO:
    449   1.2        ad 		turnoff = (*(int *)data == WSDISPLAYIO_VIDEO_OFF);
    450   1.2        ad 		if ((sc->sc_blanked == 0) ^ turnoff) {
    451   1.2        ad 			sc->sc_blanked = turnoff;
    452   1.2        ad 			if (turnoff == 0) {
    453   1.2        ad 				pcc->cmdr =
    454   1.2        ad 				    (pm_creg &= ~(PCC_FOPA | PCC_FOPB));
    455   1.2        ad 				wbflush();
    456   1.2        ad 				pm_cursor_on(sc);
    457   1.2        ad 				sc->sc_changed |= WSDISPLAY_CURSOR_DOCMAP;
    458   1.2        ad 			} else {
    459   1.2        ad 				pm_cursor_off();
    460   1.2        ad 				pcc->cmdr =
    461   1.2        ad 				    (pm_creg |= (PCC_FOPA | PCC_FOPB));
    462   1.2        ad 				wbflush();
    463   1.2        ad 				vdac->overWA = 0x0c;
    464   1.2        ad 				wbflush();
    465   1.2        ad 				for (i = 0; i < 3; i++) {
    466   1.2        ad 					vdac->over = 0;
    467   1.2        ad 					wbflush();
    468   1.2        ad 				}
    469   1.2        ad 			}
    470   1.2        ad 		}
    471   1.2        ad 		break;
    472   1.2        ad 
    473   1.2        ad 	case WSDISPLAYIO_GVIDEO:
    474   1.2        ad 		*(u_int *)data = (sc->sc_blanked ?
    475   1.2        ad 		    WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON);
    476   1.2        ad 		break;
    477   1.2        ad 
    478   1.2        ad 	case WSDISPLAYIO_GCURPOS:
    479   1.2        ad 		*(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
    480   1.2        ad 		break;
    481   1.2        ad 
    482   1.2        ad 	case WSDISPLAYIO_SCURPOS:
    483   1.2        ad 		pm_set_curpos(sc, (struct wsdisplay_curpos *)data);
    484   1.2        ad 		sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS;
    485   1.2        ad 		break;
    486   1.2        ad 
    487   1.2        ad 	case WSDISPLAYIO_GCURMAX:
    488   1.2        ad 		((struct wsdisplay_curpos *)data)->x =
    489   1.2        ad 		((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
    490   1.2        ad 		break;
    491   1.2        ad 
    492   1.2        ad 	case WSDISPLAYIO_GCURSOR:
    493   1.2        ad 		rv = pm_get_cursor(sc, (struct wsdisplay_cursor *)data);
    494   1.2        ad 		break;
    495   1.2        ad 
    496   1.2        ad 	case WSDISPLAYIO_SCURSOR:
    497   1.2        ad 		rv = pm_set_cursor(sc, (struct wsdisplay_cursor *)data);
    498   1.2        ad 		break;
    499   1.2        ad 
    500   1.2        ad 	default:
    501   1.2        ad 		rv = ENOTTY;
    502   1.2        ad 		break;
    503   1.2        ad 	}
    504   1.2        ad 
    505   1.2        ad 	pm_flush(sc);
    506   1.2        ad 	return (rv);
    507   1.2        ad }
    508   1.2        ad 
    509   1.2        ad paddr_t
    510   1.4      jmmv pm_mmap(void *v, void *vs, off_t offset, int prot)
    511   1.2        ad {
    512   1.2        ad 	struct pm_softc *sc;
    513   1.2        ad 
    514   1.2        ad 	sc = v;
    515   1.2        ad 
    516   1.2        ad 	if (offset >= sc->sc_fb_size || offset < 0)
    517   1.2        ad 		return (-1);
    518   1.2        ad 
    519   1.2        ad 	return (mips_btop(KN01_PHYS_FBUF_START + offset));
    520   1.2        ad }
    521   1.2        ad 
    522   1.2        ad int
    523   1.2        ad pm_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
    524   1.2        ad 		int *curxp, int *curyp, long *attrp)
    525   1.2        ad {
    526   1.2        ad 	struct pm_softc *sc;
    527   1.2        ad 	struct rasops_info *ri;
    528   1.2        ad 	long defattr;
    529   1.2        ad 
    530   1.2        ad 	sc = v;
    531   1.2        ad 	ri = &pm_ri;
    532   1.2        ad 
    533   1.2        ad 	if (sc->sc_nscreens > 0)
    534   1.2        ad 		return (ENOMEM);
    535   1.2        ad 
    536   1.2        ad 	*cookiep = ri;	 /* one and only for now */
    537   1.2        ad 	*curxp = 0;
    538   1.2        ad 	*curyp = 0;
    539   1.2        ad 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
    540   1.2        ad 	*attrp = defattr;
    541   1.2        ad 	sc->sc_nscreens++;
    542   1.2        ad 	return (0);
    543   1.2        ad }
    544   1.2        ad 
    545   1.2        ad void
    546   1.2        ad pm_free_screen(void *v, void *cookie)
    547   1.2        ad {
    548   1.2        ad 
    549   1.2        ad 	panic("pm_free_screen: console");
    550   1.2        ad }
    551   1.2        ad 
    552   1.2        ad int
    553   1.2        ad pm_show_screen(void *v, void *cookie, int waitok,
    554   1.2        ad 	       void (*cb)(void *, int, int), void *cbarg)
    555   1.2        ad {
    556   1.2        ad 
    557   1.2        ad 	return (0);
    558   1.2        ad }
    559   1.2        ad 
    560   1.2        ad /* EXPORT */ int
    561   1.2        ad pm_cnattach(void)
    562   1.2        ad {
    563   1.2        ad 	struct rasops_info *ri;
    564   1.2        ad 	long defattr;
    565   1.2        ad 
    566   1.2        ad 	ri = &pm_ri;
    567   1.2        ad 
    568   1.2        ad 	pm_common_init();
    569   1.2        ad 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
    570   1.2        ad 	wsdisplay_cnattach(&pm_stdscreen, ri, 0, 0, defattr);
    571   1.2        ad 	return (1);
    572   1.2        ad }
    573   1.2        ad 
    574   1.2        ad int
    575   1.2        ad pm_flush(struct pm_softc *sc)
    576   1.2        ad {
    577   1.2        ad 	VDACRegs *vdac;
    578   1.2        ad 	PCCRegs *pcc;
    579   1.2        ad 	uint8_t *cp;
    580   1.2        ad 	int v, i, x, y;
    581   1.2        ad 	u_short *p, *pe;
    582   1.2        ad 	struct hwcmap256 *cm;
    583   1.2        ad 
    584   1.2        ad 	if (sc->sc_changed == 0)
    585   1.2        ad 		return (1);
    586   1.2        ad 
    587   1.2        ad 	vdac = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_VDAC);
    588   1.2        ad 	pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC);
    589   1.2        ad 	v = sc->sc_changed;
    590   1.2        ad 
    591   1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOCUR) != 0) {
    592   1.2        ad 		if (sc->sc_curenb)
    593   1.2        ad 			pm_cursor_on(sc);
    594   1.2        ad 		else
    595   1.2        ad 			pm_cursor_off();
    596   1.2        ad 	}
    597   1.2        ad 
    598   1.2        ad 	if ((v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) != 0) {
    599   1.2        ad 		x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
    600   1.2        ad 		y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
    601   1.2        ad 		pcc->xpos = x + PCC_X_OFFSET;
    602   1.2        ad 		pcc->ypos = y + PCC_Y_OFFSET;
    603   1.2        ad 		wbflush();
    604   1.2        ad 	}
    605   1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
    606   1.2        ad 		cp = sc->sc_cursor.cc_color;
    607   1.2        ad 
    608   1.2        ad 		vdac->overWA = 0x04;
    609   1.2        ad 		wbflush();
    610   1.2        ad 		for (i = 1; i < 6; i += 2) {
    611   1.2        ad 			vdac->over = cp[i];
    612   1.2        ad 			wbflush();
    613   1.2        ad 		}
    614   1.2        ad 
    615   1.2        ad 		vdac->overWA = 0x08;
    616   1.2        ad 		wbflush();
    617   1.2        ad 		vdac->over = 0x00;
    618   1.2        ad 		wbflush();
    619   1.2        ad 		vdac->over = 0x00;
    620   1.2        ad 		wbflush();
    621   1.2        ad 		vdac->over = 0x7f;
    622   1.2        ad 		wbflush();
    623   1.2        ad 
    624   1.2        ad 		vdac->overWA = 0x0c;
    625   1.2        ad 		wbflush();
    626   1.2        ad 		for (i = 0; i < 6; i += 2) {
    627   1.2        ad 			vdac->over = cp[i];
    628   1.2        ad 			wbflush();
    629   1.2        ad 		}
    630   1.2        ad 	}
    631   1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
    632   1.2        ad 		pcc->cmdr = (pm_creg | PCC_LODSA);
    633   1.2        ad 		wbflush();
    634   1.2        ad 
    635   1.2        ad 		p = sc->sc_cursor.cc_image;
    636   1.2        ad 		x = 0xffff >> (16 - sc->sc_cursor.cc_size.x);
    637   1.2        ad 		for (pe = p + 64; p < pe; p += 2) {
    638   1.2        ad 			pcc->memory = *p & x;
    639   1.2        ad 			wbflush();
    640   1.2        ad 		}
    641   1.2        ad 
    642   1.2        ad 		pcc->cmdr = (pm_creg &= ~PCC_LODSA);
    643   1.2        ad 		wbflush();
    644   1.2        ad 	}
    645   1.2        ad 
    646   1.2        ad 	if ((v & WSDISPLAY_CMAP_DOLUT) != 0) {
    647   1.2        ad 		cm = &sc->sc_cmap;
    648   1.2        ad 
    649   1.2        ad 		vdac->mapWA = 0;
    650   1.2        ad 		wbflush();
    651   1.2        ad 
    652   1.2        ad 		if (sc->sc_cmap_size == 2) {
    653   1.2        ad 			for (i = 0; i < 128; i++) {
    654   1.2        ad 				vdac->map = 0;
    655   1.2        ad 				wbflush();
    656   1.2        ad 				vdac->map = cm->g[0];
    657   1.2        ad 				wbflush();
    658   1.2        ad 				vdac->map = 0;
    659   1.2        ad 				wbflush();
    660   1.2        ad 			}
    661   1.2        ad 			for (; i < 256; i++) {
    662   1.2        ad 				vdac->map = 0;
    663   1.2        ad 				wbflush();
    664   1.2        ad 				vdac->map = cm->g[1];
    665   1.2        ad 				wbflush();
    666   1.2        ad 				vdac->map = 0;
    667   1.2        ad 				wbflush();
    668   1.2        ad 			}
    669   1.2        ad 		} else {
    670   1.2        ad 			for (i = 0; i < sc->sc_cmap_size; i++) {
    671   1.2        ad 				vdac->map = cm->r[i];
    672   1.2        ad 				wbflush();
    673   1.2        ad 				vdac->map = cm->g[i];
    674   1.2        ad 				wbflush();
    675   1.2        ad 				vdac->map = cm->b[i];
    676   1.2        ad 				wbflush();
    677   1.2        ad 			}
    678   1.2        ad 		}
    679   1.2        ad 	}
    680   1.2        ad 
    681   1.2        ad 	sc->sc_changed = 0;
    682   1.2        ad 	return (1);
    683   1.2        ad }
    684   1.2        ad 
    685   1.2        ad int
    686   1.2        ad pm_get_cmap(struct pm_softc *sc, struct wsdisplay_cmap *p)
    687   1.2        ad {
    688   1.2        ad 	u_int index, count;
    689   1.2        ad 	int rv;
    690   1.2        ad 
    691   1.2        ad 	index = p->index;
    692   1.2        ad 	count = p->count;
    693   1.2        ad 
    694  1.13       spz 	if (index >= sc->sc_cmap_size || count > sc->sc_cmap_size - index)
    695   1.2        ad 		return (EINVAL);
    696   1.2        ad 
    697   1.2        ad 	if ((rv = copyout(&sc->sc_cmap.r[index], p->red, count)) != 0)
    698   1.2        ad 		return (rv);
    699   1.2        ad 	if ((rv = copyout(&sc->sc_cmap.g[index], p->green, count)) != 0)
    700   1.2        ad 		return (rv);
    701   1.2        ad 	return (copyout(&sc->sc_cmap.b[index], p->blue, count));
    702   1.2        ad }
    703   1.2        ad 
    704   1.2        ad int
    705   1.2        ad pm_set_cmap(struct pm_softc *sc, struct wsdisplay_cmap *p)
    706   1.2        ad {
    707   1.2        ad 	u_int index, count;
    708   1.2        ad 	int rv;
    709   1.2        ad 
    710   1.2        ad 	index = p->index;
    711   1.2        ad 	count = p->count;
    712   1.2        ad 
    713  1.13       spz 	if (index >= sc->sc_cmap_size || count > sc->sc_cmap_size - index)
    714   1.2        ad 		return (EINVAL);
    715   1.2        ad 
    716   1.2        ad 	if ((rv = copyin(p->red, &sc->sc_cmap.r[index], count)) != 0)
    717   1.2        ad 		return (rv);
    718   1.2        ad 	if ((rv = copyin(p->green, &sc->sc_cmap.g[index], count)) != 0)
    719   1.2        ad 		return (rv);
    720   1.2        ad 	if ((rv = copyin(p->blue, &sc->sc_cmap.b[index], count)) != 0)
    721   1.2        ad 		return (rv);
    722   1.2        ad 	sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
    723   1.2        ad 	return (0);
    724   1.2        ad }
    725   1.2        ad 
    726   1.2        ad int
    727   1.2        ad pm_set_cursor(struct pm_softc *sc, struct wsdisplay_cursor *p)
    728   1.2        ad {
    729   1.2        ad 	u_int v, index, count;
    730   1.2        ad 	struct hwcursor64 *cc;
    731   1.2        ad 	int rv;
    732   1.2        ad 
    733   1.2        ad 	v = p->which;
    734   1.2        ad 	cc = &sc->sc_cursor;
    735   1.2        ad 
    736   1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOCUR) != 0)
    737   1.2        ad 		sc->sc_curenb = p->enable;
    738   1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOPOS) != 0)
    739   1.2        ad 		pm_set_curpos(sc, &p->pos);
    740   1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOHOT) != 0)
    741   1.2        ad 		cc->cc_hot = p->hot;
    742   1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
    743   1.2        ad 		index = p->cmap.index;
    744   1.2        ad 		count = p->cmap.count;
    745   1.2        ad 		if (index >= 2 || (index + count) > 2)
    746   1.2        ad 			return (EINVAL);
    747   1.2        ad 
    748   1.2        ad 		rv = copyin(p->cmap.red, &cc->cc_color[index], count);
    749   1.2        ad 		if (rv != 0)
    750   1.2        ad 			return (rv);
    751   1.2        ad 		rv = copyin(p->cmap.green, &cc->cc_color[index + 2], count);
    752   1.2        ad 		if (rv != 0)
    753   1.2        ad 			return (rv);
    754   1.2        ad 		rv = copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
    755   1.2        ad 		if (rv != 0)
    756   1.2        ad 			return (rv);
    757   1.2        ad 	}
    758   1.2        ad 	if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
    759   1.2        ad 		if (p->size.x > CURSOR_MAX_SIZE ||
    760   1.2        ad 		    p->size.y > CURSOR_MAX_SIZE)
    761   1.2        ad 			return (EINVAL);
    762   1.2        ad 
    763   1.2        ad 		cc->cc_size = p->size;
    764   1.2        ad 		memset(cc->cc_image, 0, sizeof(cc->cc_image));
    765   1.2        ad 		rv = copyin(p->image, cc->cc_image, p->size.y * 4);
    766   1.2        ad 		if (rv != 0)
    767   1.2        ad 			return (rv);
    768   1.2        ad 		rv = copyin(p->mask, cc->cc_image+32, p->size.y * 4);
    769   1.2        ad 		if (rv != 0)
    770   1.2        ad 			return (rv);
    771   1.2        ad 	}
    772   1.2        ad 
    773   1.2        ad 	sc->sc_changed |= v;
    774   1.2        ad 	return (0);
    775   1.2        ad }
    776   1.2        ad 
    777   1.2        ad int
    778   1.2        ad pm_get_cursor(struct pm_softc *sc, struct wsdisplay_cursor *p)
    779   1.2        ad {
    780   1.2        ad 
    781   1.2        ad 	return (ENOTTY); /* XXX */
    782   1.2        ad }
    783   1.2        ad 
    784   1.2        ad void
    785   1.2        ad pm_set_curpos(struct pm_softc *sc, struct wsdisplay_curpos *curpos)
    786   1.2        ad {
    787   1.2        ad 	struct rasops_info *ri;
    788   1.2        ad 	int x, y;
    789   1.2        ad 
    790   1.2        ad 	ri = &pm_ri;
    791   1.2        ad 	x = curpos->x;
    792   1.2        ad 	y = curpos->y;
    793   1.2        ad 
    794   1.2        ad 	if (y < 0)
    795   1.2        ad 		y = 0;
    796   1.2        ad 	else if (y > ri->ri_height)
    797   1.2        ad 		y = ri->ri_height;
    798   1.2        ad 	if (x < 0)
    799   1.2        ad 		x = 0;
    800   1.2        ad 	else if (x > ri->ri_width)
    801   1.2        ad 		x = ri->ri_width;
    802   1.2        ad 	sc->sc_cursor.cc_pos.x = x;
    803   1.2        ad 	sc->sc_cursor.cc_pos.y = y;
    804   1.2        ad }
    805