1/* $NetBSD: vga_ofbus.c,v 1.14 2008/04/17 00:03:36 macallan Exp $ */ 2 3/* 4 * Copyright (c) 1995, 1996 Carnegie-Mellon University. 5 * All rights reserved. 6 * 7 * Author: Chris G. Demetriou 8 * 9 * Permission to use, copy, modify and distribute this software and 10 * its documentation is hereby granted, provided that both the copyright 11 * notice and this permission notice appear in all copies of the 12 * software, derivative works or modified versions, and any portions 13 * thereof, and that both notices appear in supporting documentation. 14 * 15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 17 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 * 19 * Carnegie Mellon requests users of this software to return to 20 * 21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 22 * School of Computer Science 23 * Carnegie Mellon University 24 * Pittsburgh PA 15213-3890 25 * 26 * any improvements or extensions that they make and grant Carnegie the 27 * rights to redistribute these changes. 28 */ 29 30#include <sys/cdefs.h> 31__KERNEL_RCSID(0, "$NetBSD: vga_ofbus.c,v 1.14 2008/04/17 00:03:36 macallan Exp $"); 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/kernel.h> 36#include <sys/device.h> 37#include <sys/malloc.h> 38#include <sys/proc.h> 39#include <sys/kauth.h> 40 41#include <dev/isa/isavar.h> 42 43#include <dev/ic/mc6845reg.h> 44#include <dev/ic/pcdisplayvar.h> 45#include <dev/ic/vgareg.h> 46#include <dev/ic/vgavar.h> 47 48#include <dev/wscons/wsconsio.h> 49#include <dev/wscons/wsdisplayvar.h> 50 51#include <dev/ofw/openfirm.h> 52 53#include <shark/ofw/vga_ofbusvar.h> 54 55struct vga_ofbus_softc { 56 struct vga_softc sc_vga; 57 58 int sc_phandle; 59}; 60 61#if (NIGSFB_OFBUS > 0) || (NVGA_OFBUS > 0) 62extern int console_ihandle; 63#endif 64 65int vga_ofbus_match (device_t, cfdata_t, void *); 66void vga_ofbus_attach (device_t, device_t, void *); 67 68CFATTACH_DECL_NEW(vga_ofbus, sizeof(struct vga_ofbus_softc), 69 vga_ofbus_match, vga_ofbus_attach, NULL, NULL); 70 71static const char *compat_strings[] = { "pnpPNP,900", 0 }; 72 73static int vga_ofbus_ioctl(void *, u_long, void *, int, struct lwp *); 74static paddr_t vga_ofbus_mmap(void *, off_t, int); 75 76static const struct vga_funcs vga_ofbus_funcs = { 77 vga_ofbus_ioctl, 78 vga_ofbus_mmap 79}; 80static uint32_t vga_reg[12]; 81extern paddr_t isa_io_physaddr, isa_mem_physaddr; 82 83int 84vga_ofbus_match(device_t parent, cfdata_t match, void *aux) 85{ 86 struct ofbus_attach_args *oba = aux; 87 88 if (of_compatible(oba->oba_phandle, compat_strings) == -1) 89 return (0); 90 91 if (!vga_is_console(&isa_io_bs_tag, WSDISPLAY_TYPE_ISAVGA) && 92 !vga_common_probe(&isa_io_bs_tag, &isa_mem_bs_tag)) 93 return (0); 94 95 return (2); /* more than generic pcdisplay */ 96} 97 98void 99vga_ofbus_attach(device_t parent, device_t self, void *aux) 100{ 101 struct vga_ofbus_softc *osc = device_private(self); 102 struct vga_softc *sc = &osc->sc_vga; 103 struct ofbus_attach_args *oba = aux; 104 int vga_handle, i; 105 106 sc->sc_dev = self; 107 aprint_normal("\n"); 108 osc->sc_phandle = oba->oba_phandle; 109 110 vga_handle = OF_finddevice("/vlbus/display"); 111 OF_getprop(vga_handle, "reg", vga_reg, sizeof(vga_reg)); 112 113 /* for some idiotic reason we get this in the wrong byte order */ 114 for (i = 0; i < 12; i++) { 115 vga_reg[i] = be32toh(vga_reg[i]); 116 aprint_debug_dev(self, "vga_reg[%2d] = 0x%08x\n", 117 i, vga_reg[i]); 118 } 119 120 vga_common_attach(sc, &isa_io_bs_tag, &isa_mem_bs_tag, 121 WSDISPLAY_TYPE_ISAVGA, 0, &vga_ofbus_funcs); 122 if (vga_reg[10] > 0) { 123 aprint_normal_dev(self, "aperture at 0x%08x\n", vga_reg[10]); 124 } 125} 126 127int 128vga_ofbus_cnattach(bus_space_tag_t iot, bus_space_tag_t memt) 129{ 130 int chosen_phandle; 131 int stdout_ihandle, stdout_phandle, ret; 132 char buf[128]; 133 134 stdout_phandle = 0; 135 136 /* 137 * Find out whether the firmware's chosen stdout is 138 * a display. If so, use the existing ihandle so the firmware 139 * doesn't become Unhappy. If not, just open it. 140 */ 141 if ((chosen_phandle = OF_finddevice("/chosen")) == -1 || 142 OF_getprop(chosen_phandle, "stdout", &stdout_ihandle, 143 sizeof(stdout_ihandle)) != sizeof(stdout_ihandle)) { 144 return ENXIO; 145 } 146 stdout_ihandle = of_decode_int((unsigned char *)&stdout_ihandle); 147 if ((stdout_phandle = OF_instance_to_package(stdout_ihandle)) == -1 || 148 OF_getprop(stdout_phandle, "device_type", buf, sizeof(buf)) <= 0) { 149 return ENXIO; 150 } 151 152 if (strcmp(buf, "display") != 0) { 153 /* The display is not stdout device. */ 154 return ENXIO; 155 } 156 157 if (OF_call_method("text-mode3", stdout_ihandle, 0, 0) != 0) { 158 printf("vga_ofbus_match: text-mode3 method invocation on VGA " 159 "screen device failed\n"); 160 } 161 162 ret = vga_cnattach(iot, memt, WSDISPLAY_TYPE_ISAVGA, 1); 163#if (NIGSFB_OFBUS > 0) || (NVGA_OFBUS > 0) 164 if (ret == 0) 165 console_ihandle = stdout_ihandle; 166#endif 167 168 return ret; 169} 170 171static int 172vga_ofbus_ioctl(void *cookie, u_long cmd, void *data, int flag, struct lwp *l) 173{ 174 /* we should catch WSDISPLAYIO_SMODE here */ 175 return 0; 176} 177 178static paddr_t 179vga_ofbus_mmap(void *cookie, off_t offset, int prot) 180{ 181 182 /* only the superuser may mmap IO and aperture */ 183 if (curlwp != NULL) { 184 if (kauth_authorize_generic(kauth_cred_get(), 185 KAUTH_GENERIC_ISSUSER, NULL) != 0) { 186 return -1; 187 } 188 } 189 190 /* 191 * XXX 192 * we should really use bus_space_mmap here but for some reason 193 * the ISA tags contain kernel virtual addresses and translating them 194 * back to physical addresses doesn't really work 195 */ 196 /* access to IO ports */ 197 if ((offset >= PCI_MAGIC_IO_RANGE) && 198 (offset < (PCI_MAGIC_IO_RANGE + 0x10000))) { 199 paddr_t pa; 200 201 pa = isa_io_physaddr + offset - PCI_MAGIC_IO_RANGE; 202 return arm_btop(pa); 203 } 204 205 /* legacy VGA aperture */ 206 if ((offset >= 0xa0000) && (offset < 0xc0000)) { 207 208 return arm_btop(isa_mem_physaddr + offset); 209 } 210 211 /* SVGA aperture, we get the address from OpenFirmware */ 212 if (vga_reg[10] == 0) 213 return -1; 214 215 if ((offset >= vga_reg[10]) && 216 (offset < (vga_reg[10] + vga_reg[11]))) { 217 218 return arm_btop(isa_mem_physaddr + offset); 219 } 220 221 return -1; 222} 223