130165b7fSToomas Soome /*
230165b7fSToomas Soome  * This file and its contents are supplied under the terms of the
330165b7fSToomas Soome  * Common Development and Distribution License ("CDDL"), version 1.0.
430165b7fSToomas Soome  * You may only use this file in accordance with the terms of version
530165b7fSToomas Soome  * 1.0 of the CDDL.
630165b7fSToomas Soome  *
730165b7fSToomas Soome  * A full copy of the text of the CDDL should have accompanied this
830165b7fSToomas Soome  * source.  A copy of the CDDL is also available via the Internet at
930165b7fSToomas Soome  * http://www.illumos.org/license/CDDL.
1030165b7fSToomas Soome  */
1130165b7fSToomas Soome 
1230165b7fSToomas Soome /*
1330165b7fSToomas Soome  * Copyright 2016 Toomas Soome <tsoome@me.com>
14*24571f7bSPaul Winder  * Copyright 2020 RackTop Systems, Inc.
1530165b7fSToomas Soome  */
1630165b7fSToomas Soome 
1730165b7fSToomas Soome /*
1830165b7fSToomas Soome  * Generic framebuffer interface. Implementing common interfaces
1930165b7fSToomas Soome  * for bitmapped frame buffer and vgatext.
2030165b7fSToomas Soome  */
2130165b7fSToomas Soome #include <sys/types.h>
2230165b7fSToomas Soome #include <sys/ddi.h>
2330165b7fSToomas Soome #include <sys/sunddi.h>
2482bb7c22SToomas Soome #include <sys/file.h>
2530165b7fSToomas Soome #include <sys/visual_io.h>
2630165b7fSToomas Soome #include <sys/vgareg.h>
2730165b7fSToomas Soome #include <sys/vgasubr.h>
2882bb7c22SToomas Soome #include <sys/pci.h>
2982bb7c22SToomas Soome #include <sys/boot_console.h>
3082bb7c22SToomas Soome #include <sys/kd.h>
3182bb7c22SToomas Soome #include <sys/fbio.h>
3230165b7fSToomas Soome #include <sys/gfx_private.h>
3330165b7fSToomas Soome #include "gfxp_fb.h"
3430165b7fSToomas Soome 
3582bb7c22SToomas Soome #define	MYNAME	"gfxp_fb"
3682bb7c22SToomas Soome 
3730165b7fSToomas Soome /* need to keep vgatext symbols for compatibility */
3830165b7fSToomas Soome #pragma weak gfxp_vgatext_softc_alloc = gfxp_fb_softc_alloc
3930165b7fSToomas Soome #pragma weak gfxp_vgatext_softc_free = gfxp_fb_softc_free
4030165b7fSToomas Soome #pragma weak gfxp_vgatext_attach = gfxp_fb_attach
4130165b7fSToomas Soome #pragma weak gfxp_vgatext_detach = gfxp_fb_detach
4230165b7fSToomas Soome #pragma weak gfxp_vgatext_open = gfxp_fb_open
4330165b7fSToomas Soome #pragma weak gfxp_vgatext_close = gfxp_fb_close
4430165b7fSToomas Soome #pragma weak gfxp_vgatext_ioctl = gfxp_fb_ioctl
4530165b7fSToomas Soome #pragma weak gfxp_vgatext_devmap = gfxp_fb_devmap
4630165b7fSToomas Soome 
4782bb7c22SToomas Soome /*
4882bb7c22SToomas Soome  * NOTE: this function is duplicated here and in consplat/vgatext while
4982bb7c22SToomas Soome  *       we work on a set of commitable interfaces to sunpci.c.
5082bb7c22SToomas Soome  *
5182bb7c22SToomas Soome  * Use the class code to determine if the device is a PCI-to-PCI bridge.
5282bb7c22SToomas Soome  * Returns:  B_TRUE  if the device is a bridge.
5382bb7c22SToomas Soome  *           B_FALSE if the device is not a bridge or the property cannot be
5482bb7c22SToomas Soome  *		     retrieved.
5582bb7c22SToomas Soome  */
5682bb7c22SToomas Soome static boolean_t
is_pci_bridge(dev_info_t * dip)5782bb7c22SToomas Soome is_pci_bridge(dev_info_t *dip)
5882bb7c22SToomas Soome {
5982bb7c22SToomas Soome 	uint32_t class_code;
6082bb7c22SToomas Soome 
6182bb7c22SToomas Soome 	class_code = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, dip,
6282bb7c22SToomas Soome 	    DDI_PROP_DONTPASS, "class-code", 0xffffffff);
6382bb7c22SToomas Soome 
6482bb7c22SToomas Soome 	if (class_code == 0xffffffff || class_code == DDI_PROP_NOT_FOUND)
6582bb7c22SToomas Soome 		return (B_FALSE);
6682bb7c22SToomas Soome 
6782bb7c22SToomas Soome 	class_code &= 0x00ffff00;
6882bb7c22SToomas Soome 	if (class_code == ((PCI_CLASS_BRIDGE << 16) | (PCI_BRIDGE_PCI << 8)))
6982bb7c22SToomas Soome 		return (B_TRUE);
7082bb7c22SToomas Soome 
7182bb7c22SToomas Soome 	return (B_FALSE);
7282bb7c22SToomas Soome }
7382bb7c22SToomas Soome 
7482bb7c22SToomas Soome #define	STREQ(a, b)	(strcmp((a), (b)) == 0)
7582bb7c22SToomas Soome 
7682bb7c22SToomas Soome static void
gfxp_check_for_console(dev_info_t * devi,struct gfxp_fb_softc * softc,int pci_pcie_bus)7782bb7c22SToomas Soome gfxp_check_for_console(dev_info_t *devi, struct gfxp_fb_softc *softc,
7882bb7c22SToomas Soome     int pci_pcie_bus)
7982bb7c22SToomas Soome {
8082bb7c22SToomas Soome 	ddi_acc_handle_t pci_conf;
8182bb7c22SToomas Soome 	dev_info_t *pdevi;
8282bb7c22SToomas Soome 	uint16_t data16;
8382bb7c22SToomas Soome 
84*24571f7bSPaul Winder 	/*
85*24571f7bSPaul Winder 	 * fb_info is filled in by data gathered by the bootloader.
86*24571f7bSPaul Winder 	 * In particular we are interested in "paddr" which is the physical
87*24571f7bSPaul Winder 	 * address of the framebuffer. If that is not zero, then we have
88*24571f7bSPaul Winder 	 * a valid framebuffer and we can use this device as a console.
89*24571f7bSPaul Winder 	 */
90*24571f7bSPaul Winder 	if (fb_info.paddr != 0) {
91*24571f7bSPaul Winder 		softc->flags |= GFXP_FLAG_CONSOLE;
92*24571f7bSPaul Winder 		return;
93*24571f7bSPaul Winder 	}
94*24571f7bSPaul Winder 
9582bb7c22SToomas Soome 	/*
9682bb7c22SToomas Soome 	 * Based on Section 11.3, "PCI Display Subsystem Initialization",
9782bb7c22SToomas Soome 	 * of the 1.1 PCI-to-PCI Bridge Architecture Specification
9882bb7c22SToomas Soome 	 * determine if this is the boot console device.  First, see
9982bb7c22SToomas Soome 	 * if the SBIOS has turned on PCI I/O for this device.  Then if
10082bb7c22SToomas Soome 	 * this is PCI/PCI-E, verify the parent bridge has VGAEnable set.
10182bb7c22SToomas Soome 	 */
10282bb7c22SToomas Soome 
10382bb7c22SToomas Soome 	if (pci_config_setup(devi, &pci_conf) != DDI_SUCCESS) {
10482bb7c22SToomas Soome 		cmn_err(CE_WARN, MYNAME ": can't get PCI conf handle");
10582bb7c22SToomas Soome 		return;
10682bb7c22SToomas Soome 	}
10782bb7c22SToomas Soome 
10882bb7c22SToomas Soome 	data16 = pci_config_get16(pci_conf, PCI_CONF_COMM);
10982bb7c22SToomas Soome 	if (data16 & PCI_COMM_IO)
11082bb7c22SToomas Soome 		softc->flags |= GFXP_FLAG_CONSOLE;
11182bb7c22SToomas Soome 
11282bb7c22SToomas Soome 	pci_config_teardown(&pci_conf);
11382bb7c22SToomas Soome 
11482bb7c22SToomas Soome 	/* If IO not enabled or ISA/EISA, just return */
11582bb7c22SToomas Soome 	if (!(softc->flags & GFXP_FLAG_CONSOLE) || !pci_pcie_bus)
11682bb7c22SToomas Soome 		return;
11782bb7c22SToomas Soome 
11882bb7c22SToomas Soome 	/*
11982bb7c22SToomas Soome 	 * Check for VGA Enable in the Bridge Control register for all
12082bb7c22SToomas Soome 	 * PCI/PCIEX parents.  If not set all the way up the chain,
12182bb7c22SToomas Soome 	 * this cannot be the boot console.
12282bb7c22SToomas Soome 	 */
12382bb7c22SToomas Soome 
12482bb7c22SToomas Soome 	pdevi = devi;
12582bb7c22SToomas Soome 	while (pdevi = ddi_get_parent(pdevi)) {
12682bb7c22SToomas Soome 		int	error;
12782bb7c22SToomas Soome 		ddi_acc_handle_t ppci_conf;
12882bb7c22SToomas Soome 		char	*parent_type = NULL;
12982bb7c22SToomas Soome 
13082bb7c22SToomas Soome 		error = ddi_prop_lookup_string(DDI_DEV_T_ANY, pdevi,
13182bb7c22SToomas Soome 		    DDI_PROP_DONTPASS, "device_type", &parent_type);
13282bb7c22SToomas Soome 		if (error != DDI_SUCCESS) {
13382bb7c22SToomas Soome 			return;
13482bb7c22SToomas Soome 		}
13582bb7c22SToomas Soome 
13682bb7c22SToomas Soome 		/* Verify still on the PCI/PCIEX parent tree */
13782bb7c22SToomas Soome 		if (!STREQ(parent_type, "pci") &&
13882bb7c22SToomas Soome 		    !STREQ(parent_type, "pciex")) {
13982bb7c22SToomas Soome 			ddi_prop_free(parent_type);
14082bb7c22SToomas Soome 			return;
14182bb7c22SToomas Soome 		}
14282bb7c22SToomas Soome 
14382bb7c22SToomas Soome 		ddi_prop_free(parent_type);
14482bb7c22SToomas Soome 		parent_type = NULL;
14582bb7c22SToomas Soome 
14682bb7c22SToomas Soome 		/* VGAEnable is set only for PCI-to-PCI bridges. */
14782bb7c22SToomas Soome 		if (is_pci_bridge(pdevi) == B_FALSE)
14882bb7c22SToomas Soome 			continue;
14982bb7c22SToomas Soome 
15082bb7c22SToomas Soome 		if (pci_config_setup(pdevi, &ppci_conf) != DDI_SUCCESS)
15182bb7c22SToomas Soome 			continue;
15282bb7c22SToomas Soome 
15382bb7c22SToomas Soome 		data16 = pci_config_get16(ppci_conf, PCI_BCNF_BCNTRL);
15482bb7c22SToomas Soome 		pci_config_teardown(&ppci_conf);
15582bb7c22SToomas Soome 
15682bb7c22SToomas Soome 		if (!(data16 & PCI_BCNF_BCNTRL_VGA_ENABLE)) {
15782bb7c22SToomas Soome 			softc->flags &= ~GFXP_FLAG_CONSOLE;
15882bb7c22SToomas Soome 			return;
15982bb7c22SToomas Soome 		}
16082bb7c22SToomas Soome 	}
16182bb7c22SToomas Soome }
16282bb7c22SToomas Soome 
16330165b7fSToomas Soome gfxp_fb_softc_ptr_t
gfxp_fb_softc_alloc(void)16430165b7fSToomas Soome gfxp_fb_softc_alloc(void)
16530165b7fSToomas Soome {
16630165b7fSToomas Soome 	return (kmem_zalloc(sizeof (struct gfxp_fb_softc), KM_SLEEP));
16730165b7fSToomas Soome }
16830165b7fSToomas Soome 
16930165b7fSToomas Soome void
gfxp_fb_softc_free(gfxp_fb_softc_ptr_t ptr)17030165b7fSToomas Soome gfxp_fb_softc_free(gfxp_fb_softc_ptr_t ptr)
17130165b7fSToomas Soome {
17230165b7fSToomas Soome 	kmem_free(ptr, sizeof (struct gfxp_fb_softc));
17330165b7fSToomas Soome }
17430165b7fSToomas Soome 
17582bb7c22SToomas Soome void
gfxp_fb_resume(struct gfxp_fb_softc * softc)17682bb7c22SToomas Soome gfxp_fb_resume(struct gfxp_fb_softc *softc)
17782bb7c22SToomas Soome {
17882bb7c22SToomas Soome 	if (softc->gfxp_ops->resume != NULL)
17982bb7c22SToomas Soome 		softc->gfxp_ops->resume(softc);
18082bb7c22SToomas Soome }
18182bb7c22SToomas Soome 
18282bb7c22SToomas Soome int
gfxp_fb_suspend(struct gfxp_fb_softc * softc)18382bb7c22SToomas Soome gfxp_fb_suspend(struct gfxp_fb_softc *softc)
18482bb7c22SToomas Soome {
18582bb7c22SToomas Soome 	if (softc->gfxp_ops->suspend != NULL)
18682bb7c22SToomas Soome 		return (softc->gfxp_ops->suspend(softc));
18782bb7c22SToomas Soome 	return (DDI_FAILURE);
18882bb7c22SToomas Soome }
18982bb7c22SToomas Soome 
19030165b7fSToomas Soome int
gfxp_fb_attach(dev_info_t * devi,ddi_attach_cmd_t cmd,gfxp_fb_softc_ptr_t ptr)19130165b7fSToomas Soome gfxp_fb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd, gfxp_fb_softc_ptr_t ptr)
19230165b7fSToomas Soome {
19382bb7c22SToomas Soome 	struct gfxp_fb_softc *softc = (struct gfxp_fb_softc *)ptr;
19482bb7c22SToomas Soome 	int	error;
19582bb7c22SToomas Soome 	char	*parent_type = NULL;
19682bb7c22SToomas Soome 	int pci_pcie_bus = 0;
19782bb7c22SToomas Soome 	int value;
19882bb7c22SToomas Soome 
19982bb7c22SToomas Soome 	if (softc == NULL)
20082bb7c22SToomas Soome 		return (DDI_FAILURE);
20182bb7c22SToomas Soome 
20282bb7c22SToomas Soome 	switch (cmd) {
20382bb7c22SToomas Soome 	case DDI_ATTACH:
20482bb7c22SToomas Soome 		break;
20582bb7c22SToomas Soome 
20682bb7c22SToomas Soome 	case DDI_RESUME:
20782bb7c22SToomas Soome 		gfxp_fb_resume(softc);
20882bb7c22SToomas Soome 		return (DDI_SUCCESS);
20982bb7c22SToomas Soome 
21082bb7c22SToomas Soome 	default:
21182bb7c22SToomas Soome 		return (DDI_FAILURE);
21282bb7c22SToomas Soome 	}
21382bb7c22SToomas Soome 
21482bb7c22SToomas Soome 	/* DDI_ATTACH */
21582bb7c22SToomas Soome 	softc->devi = devi; /* Copy and init DEVI */
21682bb7c22SToomas Soome 	softc->polledio.arg = (struct vis_polledio_arg *)softc;
21782bb7c22SToomas Soome 	softc->mode = -1;	/* the actual value will be set by tem */
21882bb7c22SToomas Soome 	mutex_init(&(softc->lock), NULL, MUTEX_DRIVER, NULL);
21982bb7c22SToomas Soome 
22082bb7c22SToomas Soome 	error = ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_get_parent(devi),
22182bb7c22SToomas Soome 	    DDI_PROP_DONTPASS, "device_type", &parent_type);
22282bb7c22SToomas Soome 	if (error != DDI_SUCCESS) {
22382bb7c22SToomas Soome 		cmn_err(CE_WARN, MYNAME ": can't determine parent type.");
22482bb7c22SToomas Soome 		goto fail;
22582bb7c22SToomas Soome 	}
22682bb7c22SToomas Soome 
22782bb7c22SToomas Soome 	if (STREQ(parent_type, "pci") || STREQ(parent_type, "pciex")) {
22882bb7c22SToomas Soome 		pci_pcie_bus = 1;
22982bb7c22SToomas Soome 	}
23082bb7c22SToomas Soome 	ddi_prop_free(parent_type);
23182bb7c22SToomas Soome 	gfxp_check_for_console(devi, softc, pci_pcie_bus);
23282bb7c22SToomas Soome 
23382bb7c22SToomas Soome 	value = GFXP_IS_CONSOLE(softc) ? 1 : 0;
23482bb7c22SToomas Soome 	if (ddi_prop_update_int(DDI_DEV_T_NONE, devi,
23582bb7c22SToomas Soome 	    "primary-controller", value) != DDI_SUCCESS) {
23682bb7c22SToomas Soome 		cmn_err(CE_WARN,
23782bb7c22SToomas Soome 		    "Cannot %s primary-controller "
23882bb7c22SToomas Soome 		    "property for driver", value ? "set" : "clear");
23982bb7c22SToomas Soome 	}
24082bb7c22SToomas Soome 
24182bb7c22SToomas Soome 	switch (fb_info.fb_type) {
24282bb7c22SToomas Soome 	case FB_TYPE_UNINITIALIZED:
24382bb7c22SToomas Soome 		/*
24482bb7c22SToomas Soome 		 * While booting from MB1, we do not have FB.
24582bb7c22SToomas Soome 		 * Fall through.
24682bb7c22SToomas Soome 		 */
24782bb7c22SToomas Soome 	case FB_TYPE_EGA_TEXT:
24882bb7c22SToomas Soome 		softc->fb_type = GFXP_VGATEXT;
24982bb7c22SToomas Soome 		error = gfxp_vga_attach(devi, softc);
25082bb7c22SToomas Soome 		break;
25182bb7c22SToomas Soome 
25282bb7c22SToomas Soome 	case FB_TYPE_INDEXED:	/* FB types */
25382bb7c22SToomas Soome 	case FB_TYPE_RGB:
25482bb7c22SToomas Soome 		softc->fb_type = GFXP_BITMAP;
25582bb7c22SToomas Soome 		error = gfxp_bm_attach(devi, softc);
25682bb7c22SToomas Soome 		break;
25782bb7c22SToomas Soome 
25882bb7c22SToomas Soome 	default:
25982bb7c22SToomas Soome 		error = DDI_FAILURE;
26082bb7c22SToomas Soome 	}
26182bb7c22SToomas Soome 
26282bb7c22SToomas Soome 	if (error == DDI_SUCCESS)
26382bb7c22SToomas Soome 		return (error);
26482bb7c22SToomas Soome 
26582bb7c22SToomas Soome 	(void) ddi_prop_remove(DDI_DEV_T_ANY, devi, "primary-controller");
26682bb7c22SToomas Soome fail:
26782bb7c22SToomas Soome 	(void) gfxp_fb_detach(devi, DDI_DETACH, (void *)softc);
26882bb7c22SToomas Soome 	return (error);
26930165b7fSToomas Soome }
27030165b7fSToomas Soome 
27130165b7fSToomas Soome int
gfxp_fb_detach(dev_info_t * devi,ddi_detach_cmd_t cmd,gfxp_fb_softc_ptr_t ptr)27230165b7fSToomas Soome gfxp_fb_detach(dev_info_t *devi, ddi_detach_cmd_t cmd, gfxp_fb_softc_ptr_t ptr)
27330165b7fSToomas Soome {
27482bb7c22SToomas Soome 	struct gfxp_fb_softc *softc = (struct gfxp_fb_softc *)ptr;
27582bb7c22SToomas Soome 	int error;
27682bb7c22SToomas Soome 
27782bb7c22SToomas Soome 	if (softc == NULL)
27882bb7c22SToomas Soome 		return (DDI_FAILURE);
27982bb7c22SToomas Soome 
28082bb7c22SToomas Soome 	switch (cmd) {
28182bb7c22SToomas Soome 	case DDI_SUSPEND:
28282bb7c22SToomas Soome 		return (gfxp_fb_suspend(softc));
28382bb7c22SToomas Soome 
28482bb7c22SToomas Soome 	case DDI_DETACH:
28582bb7c22SToomas Soome 		(void) ddi_prop_remove(DDI_DEV_T_ANY, devi,
28682bb7c22SToomas Soome 		    "primary-controller");
287584b574aSToomas Soome 		error = DDI_SUCCESS;
28882bb7c22SToomas Soome 		switch (softc->fb_type) {
28982bb7c22SToomas Soome 		case GFXP_BITMAP:
29082bb7c22SToomas Soome 			error = gfxp_bm_detach(devi, softc);
29182bb7c22SToomas Soome 			break;
29282bb7c22SToomas Soome 		case GFXP_VGATEXT:
29382bb7c22SToomas Soome 			error = gfxp_vga_detach(devi, softc);
29482bb7c22SToomas Soome 			break;
29582bb7c22SToomas Soome 		}
29682bb7c22SToomas Soome 		mutex_destroy(&(softc->lock));
29782bb7c22SToomas Soome 		return (error);
29882bb7c22SToomas Soome 
29982bb7c22SToomas Soome 	default:
30082bb7c22SToomas Soome 		cmn_err(CE_WARN, "gfxp_fb_detach: unknown cmd 0x%x\n",
30182bb7c22SToomas Soome 		    cmd);
30282bb7c22SToomas Soome 		return (DDI_FAILURE);
30382bb7c22SToomas Soome 	}
30430165b7fSToomas Soome }
30530165b7fSToomas Soome 
30630165b7fSToomas Soome /*ARGSUSED*/
30730165b7fSToomas Soome int
gfxp_fb_open(dev_t * devp,int flag,int otyp,cred_t * cred,gfxp_fb_softc_ptr_t ptr)30830165b7fSToomas Soome gfxp_fb_open(dev_t *devp, int flag, int otyp, cred_t *cred,
30930165b7fSToomas Soome     gfxp_fb_softc_ptr_t ptr)
31030165b7fSToomas Soome {
31130165b7fSToomas Soome 	struct gfxp_fb_softc *softc = (struct gfxp_fb_softc *)ptr;
31230165b7fSToomas Soome 
31330165b7fSToomas Soome 	if (softc == NULL || otyp == OTYP_BLK)
31430165b7fSToomas Soome 		return (ENXIO);
31530165b7fSToomas Soome 
31630165b7fSToomas Soome 	return (0);
31730165b7fSToomas Soome }
31830165b7fSToomas Soome 
31930165b7fSToomas Soome /*ARGSUSED*/
32030165b7fSToomas Soome int
gfxp_fb_close(dev_t devp,int flag,int otyp,cred_t * cred,gfxp_fb_softc_ptr_t ptr)32130165b7fSToomas Soome gfxp_fb_close(dev_t devp, int flag, int otyp, cred_t *cred,
32230165b7fSToomas Soome     gfxp_fb_softc_ptr_t ptr)
32330165b7fSToomas Soome {
32430165b7fSToomas Soome 	return (0);
32530165b7fSToomas Soome }
32630165b7fSToomas Soome 
32782bb7c22SToomas Soome static int
do_gfx_ioctl(int cmd,intptr_t data,int mode,struct gfxp_fb_softc * softc)32882bb7c22SToomas Soome do_gfx_ioctl(int cmd, intptr_t data, int mode, struct gfxp_fb_softc *softc)
32982bb7c22SToomas Soome {
33082bb7c22SToomas Soome 	static char kernel_only[] =
33182bb7c22SToomas Soome 	    "gfxp_fb_ioctl: %s is a kernel only ioctl";
33282bb7c22SToomas Soome 	int err;
33382bb7c22SToomas Soome 	int kd_mode;
33482bb7c22SToomas Soome 
33582bb7c22SToomas Soome 	switch (cmd) {
33682bb7c22SToomas Soome 	case KDSETMODE:
33782bb7c22SToomas Soome 		kd_mode = (int)data;
33882bb7c22SToomas Soome 		if ((kd_mode == softc->mode) || (!GFXP_IS_CONSOLE(softc)))
33982bb7c22SToomas Soome 			break;
34082bb7c22SToomas Soome 		return (softc->gfxp_ops->kdsetmode(softc, kd_mode));
34182bb7c22SToomas Soome 
34282bb7c22SToomas Soome 	case KDGETMODE:
34382bb7c22SToomas Soome 		kd_mode = softc->mode;
34482bb7c22SToomas Soome 		if (ddi_copyout(&kd_mode, (void *)data, sizeof (int), mode))
34582bb7c22SToomas Soome 			return (EFAULT);
34682bb7c22SToomas Soome 		break;
34782bb7c22SToomas Soome 
34882bb7c22SToomas Soome 	case VIS_GETIDENTIFIER:
34982bb7c22SToomas Soome 		if (ddi_copyout(softc->gfxp_ops->ident, (void *)data,
35082bb7c22SToomas Soome 		    sizeof (struct vis_identifier), mode))
35182bb7c22SToomas Soome 			return (EFAULT);
35282bb7c22SToomas Soome 		break;
35382bb7c22SToomas Soome 
35482bb7c22SToomas Soome 	case VIS_DEVINIT:
35582bb7c22SToomas Soome 
35682bb7c22SToomas Soome 		if (!(mode & FKIOCTL)) {
35782bb7c22SToomas Soome 			cmn_err(CE_CONT, kernel_only, "VIS_DEVINIT");
35882bb7c22SToomas Soome 			return (ENXIO);
35982bb7c22SToomas Soome 		}
36082bb7c22SToomas Soome 
36182bb7c22SToomas Soome 		err = softc->gfxp_ops->devinit(softc,
36282bb7c22SToomas Soome 		    (struct vis_devinit *)data);
36382bb7c22SToomas Soome 		if (err != 0) {
36482bb7c22SToomas Soome 			cmn_err(CE_WARN,
36582bb7c22SToomas Soome 			    "gfxp_fb_ioctl:  could not initialize console");
36682bb7c22SToomas Soome 			return (err);
36782bb7c22SToomas Soome 		}
36882bb7c22SToomas Soome 		break;
36982bb7c22SToomas Soome 
37082bb7c22SToomas Soome 	case VIS_CONSCLEAR:	/* clear screen */
37182bb7c22SToomas Soome 	{
37282bb7c22SToomas Soome 		struct vis_consclear pma;
37382bb7c22SToomas Soome 
37482bb7c22SToomas Soome 		if (ddi_copyin((void *)data, &pma,
37582bb7c22SToomas Soome 		    sizeof (struct vis_consclear), mode))
37682bb7c22SToomas Soome 			return (EFAULT);
37782bb7c22SToomas Soome 
37882bb7c22SToomas Soome 		return (softc->gfxp_ops->cons_clear(softc, &pma));
37982bb7c22SToomas Soome 	}
38082bb7c22SToomas Soome 
38182bb7c22SToomas Soome 	case VIS_CONSCOPY:	/* move */
38282bb7c22SToomas Soome 	{
38382bb7c22SToomas Soome 		struct vis_conscopy pma;
38482bb7c22SToomas Soome 
38582bb7c22SToomas Soome 		if (ddi_copyin((void *)data, &pma,
38682bb7c22SToomas Soome 		    sizeof (struct vis_conscopy), mode))
38782bb7c22SToomas Soome 			return (EFAULT);
38882bb7c22SToomas Soome 
38982bb7c22SToomas Soome 		softc->gfxp_ops->cons_copy(softc, &pma);
39082bb7c22SToomas Soome 		break;
39182bb7c22SToomas Soome 	}
39282bb7c22SToomas Soome 
39382bb7c22SToomas Soome 	case VIS_CONSDISPLAY:	/* display */
39482bb7c22SToomas Soome 	{
39582bb7c22SToomas Soome 		struct vis_consdisplay display_request;
39682bb7c22SToomas Soome 
39782bb7c22SToomas Soome 		if (ddi_copyin((void *)data, &display_request,
39882bb7c22SToomas Soome 		    sizeof (display_request), mode))
39982bb7c22SToomas Soome 			return (EFAULT);
40082bb7c22SToomas Soome 
40182bb7c22SToomas Soome 		softc->gfxp_ops->cons_display(softc, &display_request);
40282bb7c22SToomas Soome 		break;
40382bb7c22SToomas Soome 	}
40482bb7c22SToomas Soome 
40582bb7c22SToomas Soome 	case VIS_CONSCURSOR:
40682bb7c22SToomas Soome 	{
40782bb7c22SToomas Soome 		struct vis_conscursor cursor_request;
40882bb7c22SToomas Soome 
40982bb7c22SToomas Soome 		if (ddi_copyin((void *)data, &cursor_request,
41082bb7c22SToomas Soome 		    sizeof (cursor_request), mode))
41182bb7c22SToomas Soome 			return (EFAULT);
41282bb7c22SToomas Soome 
41382bb7c22SToomas Soome 		softc->gfxp_ops->cons_cursor(softc, &cursor_request);
41482bb7c22SToomas Soome 
41582bb7c22SToomas Soome 		if (cursor_request.action == VIS_GET_CURSOR &&
41682bb7c22SToomas Soome 		    ddi_copyout(&cursor_request, (void *)data,
41782bb7c22SToomas Soome 		    sizeof (cursor_request), mode))
41882bb7c22SToomas Soome 			return (EFAULT);
41982bb7c22SToomas Soome 		break;
42082bb7c22SToomas Soome 	}
42182bb7c22SToomas Soome 
42282bb7c22SToomas Soome 	case VIS_GETCMAP:
42382bb7c22SToomas Soome 	case VIS_PUTCMAP:
42482bb7c22SToomas Soome 	case FBIOPUTCMAP:
42582bb7c22SToomas Soome 	case FBIOGETCMAP:
42682bb7c22SToomas Soome 		/*
42782bb7c22SToomas Soome 		 * At the moment, text mode is not considered to have
42882bb7c22SToomas Soome 		 * a color map.
42982bb7c22SToomas Soome 		 */
43082bb7c22SToomas Soome 		return (EINVAL);
43182bb7c22SToomas Soome 
43282bb7c22SToomas Soome 	case FBIOGATTR:
43382bb7c22SToomas Soome 		if (copyout(softc->fbgattr, (void *)data,
43482bb7c22SToomas Soome 		    sizeof (struct fbgattr)))
43582bb7c22SToomas Soome 			return (EFAULT);
43682bb7c22SToomas Soome 		break;
43782bb7c22SToomas Soome 
43882bb7c22SToomas Soome 	case FBIOGTYPE:
43982bb7c22SToomas Soome 		if (copyout(&softc->fbgattr->fbtype, (void *)data,
44082bb7c22SToomas Soome 		    sizeof (struct fbtype)))
44182bb7c22SToomas Soome 			return (EFAULT);
44282bb7c22SToomas Soome 		break;
44382bb7c22SToomas Soome 
44482bb7c22SToomas Soome 	default:
44582bb7c22SToomas Soome 		cmn_err(CE_CONT, "!unimplemented cmd: 0x%x\n", cmd);
44682bb7c22SToomas Soome 		return (ENXIO);
44782bb7c22SToomas Soome 	}
44882bb7c22SToomas Soome 	return (0);
44982bb7c22SToomas Soome }
45082bb7c22SToomas Soome 
45182bb7c22SToomas Soome /*ARGSUSED*/
45230165b7fSToomas Soome int
gfxp_fb_ioctl(dev_t dev,int cmd,intptr_t data,int mode,cred_t * cred,int * rval,gfxp_fb_softc_ptr_t ptr)45330165b7fSToomas Soome gfxp_fb_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
45430165b7fSToomas Soome     cred_t *cred, int *rval, gfxp_fb_softc_ptr_t ptr)
45530165b7fSToomas Soome {
45682bb7c22SToomas Soome 	struct gfxp_fb_softc *softc = (struct gfxp_fb_softc *)ptr;
45782bb7c22SToomas Soome 	int error = DDI_FAILURE;
45882bb7c22SToomas Soome 
45982bb7c22SToomas Soome 	if (softc == NULL)
46082bb7c22SToomas Soome 		return (error);
46182bb7c22SToomas Soome 	mutex_enter(&(softc->lock));
46282bb7c22SToomas Soome 	error = do_gfx_ioctl(cmd, data, mode, softc);
46382bb7c22SToomas Soome 	mutex_exit(&(softc->lock));
46482bb7c22SToomas Soome 	return (error);
46530165b7fSToomas Soome }
46630165b7fSToomas Soome 
46730165b7fSToomas Soome int
gfxp_fb_devmap(dev_t dev,devmap_cookie_t dhp,offset_t off,size_t len,size_t * maplen,uint_t model,void * ptr)46830165b7fSToomas Soome gfxp_fb_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off,
46930165b7fSToomas Soome     size_t len, size_t *maplen, uint_t model, void *ptr)
47030165b7fSToomas Soome {
47182bb7c22SToomas Soome 	struct gfxp_fb_softc *softc = (struct gfxp_fb_softc *)ptr;
47282bb7c22SToomas Soome 
47382bb7c22SToomas Soome 	if (softc == NULL)
47482bb7c22SToomas Soome 		return (DDI_FAILURE);
47582bb7c22SToomas Soome 
47682bb7c22SToomas Soome 	return (softc->gfxp_ops->devmap(dev, dhp, off, len, maplen,
47782bb7c22SToomas Soome 	    model, ptr));
47830165b7fSToomas Soome }
479