1139825Simp/*- 242805Skato * Copyright (c) 1999 FreeBSD(98) port team. 342805Skato * All rights reserved. 442805Skato * 542805Skato * Redistribution and use in source and binary forms, with or without 642805Skato * modification, are permitted provided that the following conditions 742805Skato * are met: 842805Skato * 1. Redistributions of source code must retain the above copyright 942805Skato * notice, this list of conditions and the following disclaimer as 1042805Skato * the first lines of this file unmodified. 1142805Skato * 2. Redistributions in binary form must reproduce the above copyright 1242805Skato * notice, this list of conditions and the following disclaimer in the 1342805Skato * documentation and/or other materials provided with the distribution. 1442805Skato * 3. The name of the author may not be used to endorse or promote products 1542805Skato * derived from this software without specific prior written permission. 1642805Skato * 1742805Skato * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1842805Skato * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1942805Skato * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2042805Skato * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2142805Skato * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2242805Skato * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2342805Skato * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2442805Skato * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2542805Skato * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2642805Skato * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2742805Skato * 2850477Speter * $FreeBSD$ 2942795Skato */ 3042795Skato 3142795Skato#include "opt_gdc.h" 3242795Skato#include "opt_fb.h" 3342795Skato#include "opt_syscons.h" 3442795Skato 3542795Skato#include <sys/param.h> 3642795Skato#include <sys/systm.h> 3742795Skato#include <sys/kernel.h> 38130174Sphk#include <sys/module.h> 39111311Snyan#include <sys/conf.h> 4042795Skato#include <sys/bus.h> 4183547Snyan#include <machine/bus.h> 4283547Snyan#include <sys/rman.h> 4383547Snyan#include <machine/resource.h> 4442795Skato 4567142Snyan#include <sys/fbio.h> 46111311Snyan#include <sys/fcntl.h> 4767142Snyan 4842795Skato#include <vm/vm.h> 4942795Skato#include <vm/pmap.h> 50130431Simp#include <vm/vm_param.h> 5142795Skato 5242795Skato#include <machine/md_var.h> 5342795Skato#include <machine/pc/bios.h> 5442795Skato 5542795Skato#include <dev/fb/fbreg.h> 5642795Skato 57139946Simp#ifdef LINE30 58146049Snyan#include <pc98/cbus/cbus.h> 59139946Simp#endif 6042795Skato#include <pc98/pc98/pc98_machdep.h> 6145783Skato#include <isa/isavar.h> 6242795Skato 6383547Snyan#define TEXT_GDC 0x60 6483547Snyan#define GRAPHIC_GDC 0xa0 6542805Skato#define ROW 25 6642805Skato#define COL 80 6742805Skato 6842795Skato#define DRIVER_NAME "gdc" 6942795Skato 7042795Skato/* cdev driver declaration */ 7142795Skato 72183397Sed#define GDC_UNIT(dev) dev2unit(dev) 7342795Skato#define GDC_MKMINOR(unit) (unit) 7442795Skato 7545783Skatotypedef struct gdc_softc { 7645783Skato video_adapter_t *adp; 7783547Snyan struct resource *res_tgdc, *res_ggdc; 7883547Snyan struct resource *res_egc, *res_pegc, *res_grcg, *res_kcg; 7983547Snyan struct resource *res_tmem, *res_gmem1, *res_gmem2; 80111311Snyan#ifdef FB_INSTALL_CDEV 81111311Snyan genfb_softc_t gensc; 82111311Snyan#endif 8345783Skato} gdc_softc_t; 8442795Skato 8545783Skato#define GDC_SOFTC(unit) \ 8645783Skato ((gdc_softc_t *)devclass_get_softc(gdc_devclass, unit)) 8745783Skato 8883547Snyanstatic bus_addr_t gdc_iat[] = {0, 2, 4, 6, 8, 10, 12, 14}; 8983547Snyan 9048187Skatostatic devclass_t gdc_devclass; 9145783Skato 9242795Skatostatic int gdc_probe_unit(int unit, gdc_softc_t *sc, int flags); 9342795Skatostatic int gdc_attach_unit(int unit, gdc_softc_t *sc, int flags); 9483547Snyanstatic int gdc_alloc_resource(device_t dev); 9583547Snyanstatic int gdc_release_resource(device_t dev); 9642795Skato 97153165Sru#ifdef FB_INSTALL_CDEV 9842795Skato 9942795Skatostatic d_open_t gdcopen; 10042795Skatostatic d_close_t gdcclose; 10142795Skatostatic d_read_t gdcread; 10248187Skatostatic d_write_t gdcwrite; 10342795Skatostatic d_ioctl_t gdcioctl; 10448187Skatostatic d_mmap_t gdcmmap; 10542795Skato 10659689Snyanstatic struct cdevsw gdc_cdevsw = { 107126080Sphk .d_version = D_VERSION, 108126080Sphk .d_flags = D_NEEDGIANT, 109111815Sphk .d_open = gdcopen, 110111815Sphk .d_close = gdcclose, 111111815Sphk .d_read = gdcread, 112111815Sphk .d_write = gdcwrite, 113111815Sphk .d_ioctl = gdcioctl, 114111815Sphk .d_mmap = gdcmmap, 115111815Sphk .d_name = DRIVER_NAME, 11642795Skato}; 11742795Skato 11842795Skato#endif /* FB_INSTALL_CDEV */ 11942795Skato 12062952Snyanstatic void 12162952Snyangdc_identify(driver_t *driver, device_t parent) 12262952Snyan{ 12362952Snyan BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, DRIVER_NAME, 0); 12462952Snyan} 12562952Snyan 12642795Skatostatic int 12763011Snyangdcprobe(device_t dev) 12842795Skato{ 12983547Snyan int error; 13042795Skato 13151276Snyan /* Check isapnp ids */ 13251276Snyan if (isa_get_vendorid(dev)) 13351276Snyan return (ENXIO); 13451276Snyan 13545783Skato device_set_desc(dev, "Generic GDC"); 13683547Snyan 13783547Snyan error = gdc_alloc_resource(dev); 13883547Snyan if (error) 13983547Snyan return (error); 14083547Snyan 14183547Snyan error = gdc_probe_unit(device_get_unit(dev), 14283547Snyan device_get_softc(dev), 14383547Snyan device_get_flags(dev)); 14483547Snyan 14583547Snyan gdc_release_resource(dev); 14683547Snyan 14783547Snyan return (error); 14842795Skato} 14942795Skato 15042795Skatostatic int 15145783Skatogdc_attach(device_t dev) 15242795Skato{ 15342795Skato gdc_softc_t *sc; 15448187Skato int error; 15542795Skato 15683547Snyan error = gdc_alloc_resource(dev); 15783547Snyan if (error) 15883547Snyan return (error); 15983547Snyan 16045783Skato sc = device_get_softc(dev); 16183547Snyan error = gdc_attach_unit(device_get_unit(dev), 16283547Snyan sc, 16383547Snyan device_get_flags(dev)); 16483547Snyan if (error) { 16583547Snyan gdc_release_resource(dev); 16648187Skato return error; 16783547Snyan } 16848187Skato 16948187Skato#ifdef FB_INSTALL_CDEV 17048187Skato /* attach a virtual frame buffer device */ 171120472Sphk error = fb_attach(GDC_MKMINOR(device_get_unit(dev)), 172111311Snyan sc->adp, &gdc_cdevsw); 17383547Snyan if (error) { 17483547Snyan gdc_release_resource(dev); 17548187Skato return error; 17683547Snyan } 17748187Skato#endif /* FB_INSTALL_CDEV */ 17848187Skato 17948187Skato if (bootverbose) 180174985Swkoszek vidd_diag(sc->adp, bootverbose); 18148187Skato 18248187Skato return 0; 18342795Skato} 18442795Skato 18542795Skatostatic int 18642795Skatogdc_probe_unit(int unit, gdc_softc_t *sc, int flags) 18742795Skato{ 18842795Skato video_switch_t *sw; 18942795Skato 19042795Skato sw = vid_get_switch(DRIVER_NAME); 19142795Skato if (sw == NULL) 19248187Skato return ENXIO; 19342795Skato return (*sw->probe)(unit, &sc->adp, NULL, flags); 19442795Skato} 19542795Skato 19642795Skatostatic int 19742795Skatogdc_attach_unit(int unit, gdc_softc_t *sc, int flags) 19842795Skato{ 19942795Skato video_switch_t *sw; 20042795Skato 20142795Skato sw = vid_get_switch(DRIVER_NAME); 20242795Skato if (sw == NULL) 20342795Skato return ENXIO; 20448187Skato return (*sw->init)(unit, sc->adp, flags); 20548187Skato} 20642795Skato 20783547Snyan 20883547Snyanstatic int 20983547Snyangdc_alloc_resource(device_t dev) 21083547Snyan{ 21183547Snyan int rid; 21283547Snyan gdc_softc_t *sc; 21383547Snyan 21483547Snyan sc = device_get_softc(dev); 21583547Snyan 21683547Snyan /* TEXT GDC */ 21783547Snyan rid = 0; 21883547Snyan bus_set_resource(dev, SYS_RES_IOPORT, rid, TEXT_GDC, 1); 21983547Snyan sc->res_tgdc = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, 22083547Snyan gdc_iat, 8, RF_ACTIVE); 22183547Snyan if (sc->res_tgdc == NULL) { 22283547Snyan gdc_release_resource(dev); 22383547Snyan return (ENXIO); 22483547Snyan } 22583547Snyan isa_load_resourcev(sc->res_tgdc, gdc_iat, 8); 22683547Snyan 22783547Snyan /* GRAPHIC GDC */ 22883547Snyan rid = 8; 22983547Snyan bus_set_resource(dev, SYS_RES_IOPORT, rid, GRAPHIC_GDC, 1); 23083547Snyan sc->res_ggdc = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, 23183547Snyan gdc_iat, 8, RF_ACTIVE); 23283547Snyan if (sc->res_ggdc == NULL) { 23383547Snyan gdc_release_resource(dev); 23483547Snyan return (ENXIO); 23583547Snyan } 23683547Snyan isa_load_resourcev(sc->res_ggdc, gdc_iat, 8); 23783547Snyan 23883547Snyan /* EGC */ 23983547Snyan rid = 16; 24083547Snyan bus_set_resource(dev, SYS_RES_IOPORT, rid, 0x4a0, 1); 24183547Snyan sc->res_egc = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, 24283547Snyan gdc_iat, 8, RF_ACTIVE); 24383547Snyan if (sc->res_egc == NULL) { 24483547Snyan gdc_release_resource(dev); 24583547Snyan return (ENXIO); 24683547Snyan } 24783547Snyan isa_load_resourcev(sc->res_egc, gdc_iat, 8); 24883547Snyan 24983547Snyan /* PEGC */ 25083547Snyan rid = 24; 25183547Snyan bus_set_resource(dev, SYS_RES_IOPORT, rid, 0x9a0, 1); 25283547Snyan sc->res_pegc = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, 25383547Snyan gdc_iat, 8, RF_ACTIVE); 25483547Snyan if (sc->res_pegc == NULL) { 25583547Snyan gdc_release_resource(dev); 25683547Snyan return (ENXIO); 25783547Snyan } 25883547Snyan isa_load_resourcev(sc->res_pegc, gdc_iat, 8); 25983547Snyan 26083547Snyan /* CRTC/GRCG */ 26183547Snyan rid = 32; 26283547Snyan bus_set_resource(dev, SYS_RES_IOPORT, rid, 0x70, 1); 26383547Snyan sc->res_grcg = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, 26483547Snyan gdc_iat, 8, RF_ACTIVE); 26583547Snyan if (sc->res_grcg == NULL) { 26683547Snyan gdc_release_resource(dev); 26783547Snyan return (ENXIO); 26883547Snyan } 26983547Snyan isa_load_resourcev(sc->res_grcg, gdc_iat, 8); 27083547Snyan 27183547Snyan /* KCG */ 27283547Snyan rid = 40; 27383547Snyan bus_set_resource(dev, SYS_RES_IOPORT, rid, 0xa1, 1); 27483547Snyan sc->res_kcg = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, 27583547Snyan gdc_iat, 8, RF_ACTIVE); 27683547Snyan if (sc->res_kcg == NULL) { 27783547Snyan gdc_release_resource(dev); 27883547Snyan return (ENXIO); 27983547Snyan } 28083547Snyan isa_load_resourcev(sc->res_kcg, gdc_iat, 8); 28183547Snyan 28283547Snyan 28383547Snyan /* TEXT Memory */ 28483547Snyan rid = 0; 28583547Snyan sc->res_tmem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 28683547Snyan 0xa0000, 0xa4fff, 0x5000, RF_ACTIVE); 28783547Snyan if (sc->res_tmem == NULL) { 28883547Snyan gdc_release_resource(dev); 28983547Snyan return (ENXIO); 29083547Snyan } 29183547Snyan 29283547Snyan /* GRAPHIC Memory */ 29383547Snyan rid = 1; 29483547Snyan sc->res_gmem1 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 29583547Snyan 0xa8000, 0xbffff, 0x18000, 29683547Snyan RF_ACTIVE); 29783547Snyan if (sc->res_gmem1 == NULL) { 29883547Snyan gdc_release_resource(dev); 29983547Snyan return (ENXIO); 30083547Snyan } 30183547Snyan rid = 2; 30283547Snyan sc->res_gmem2 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 30383547Snyan 0xe0000, 0xe7fff, 0x8000, 30483547Snyan RF_ACTIVE); 30583547Snyan if (sc->res_gmem2 == NULL) { 30683547Snyan gdc_release_resource(dev); 30783547Snyan return (ENXIO); 30883547Snyan } 30983547Snyan 31083547Snyan return (0); 31183547Snyan} 31283547Snyan 31383547Snyanstatic int 31483547Snyangdc_release_resource(device_t dev) 31583547Snyan{ 31683547Snyan gdc_softc_t *sc; 31783547Snyan 31883547Snyan sc = device_get_softc(dev); 31983547Snyan 32083547Snyan if (sc->res_tgdc) 32183547Snyan bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->res_tgdc); 32283547Snyan if (sc->res_ggdc) 32383547Snyan bus_release_resource(dev, SYS_RES_IOPORT, 8, sc->res_ggdc); 32483547Snyan if (sc->res_egc) 32583547Snyan bus_release_resource(dev, SYS_RES_IOPORT, 16, sc->res_egc); 32683547Snyan if (sc->res_pegc) 32783547Snyan bus_release_resource(dev, SYS_RES_IOPORT, 24, sc->res_pegc); 32883547Snyan if (sc->res_grcg) 32983547Snyan bus_release_resource(dev, SYS_RES_IOPORT, 32, sc->res_grcg); 33083547Snyan if (sc->res_kcg) 33183547Snyan bus_release_resource(dev, SYS_RES_IOPORT, 40, sc->res_kcg); 33283547Snyan 33383547Snyan if (sc->res_tmem) 33483547Snyan bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->res_tmem); 33583547Snyan if (sc->res_gmem1) 33683547Snyan bus_release_resource(dev, SYS_RES_MEMORY, 1, sc->res_gmem1); 33783547Snyan if (sc->res_gmem2) 33883547Snyan bus_release_resource(dev, SYS_RES_MEMORY, 2, sc->res_gmem2); 33983547Snyan 34083547Snyan return (0); 34183547Snyan} 34283547Snyan 34348187Skato/* cdev driver functions */ 34442795Skato 34542795Skato#ifdef FB_INSTALL_CDEV 34642795Skato 34748187Skatostatic int 348130585Sphkgdcopen(struct cdev *dev, int flag, int mode, struct thread *td) 34948187Skato{ 35048187Skato gdc_softc_t *sc; 35142795Skato 35248187Skato sc = GDC_SOFTC(GDC_UNIT(dev)); 35348187Skato if (sc == NULL) 35448187Skato return ENXIO; 35548187Skato if (mode & (O_CREAT | O_APPEND | O_TRUNC)) 35648187Skato return ENODEV; 35748187Skato 358111311Snyan return genfbopen(&sc->gensc, sc->adp, flag, mode, td); 35942795Skato} 36042795Skato 36148187Skatostatic int 362130585Sphkgdcclose(struct cdev *dev, int flag, int mode, struct thread *td) 36348187Skato{ 36448187Skato gdc_softc_t *sc; 36548187Skato 36648187Skato sc = GDC_SOFTC(GDC_UNIT(dev)); 367111311Snyan return genfbclose(&sc->gensc, sc->adp, flag, mode, td); 36848187Skato} 36948187Skato 37048187Skatostatic int 371130585Sphkgdcread(struct cdev *dev, struct uio *uio, int flag) 37248187Skato{ 37348187Skato gdc_softc_t *sc; 37448187Skato 37548187Skato sc = GDC_SOFTC(GDC_UNIT(dev)); 37648187Skato return genfbread(&sc->gensc, sc->adp, uio, flag); 37748187Skato} 37848187Skato 37948187Skatostatic int 380130585Sphkgdcwrite(struct cdev *dev, struct uio *uio, int flag) 38148187Skato{ 38248187Skato gdc_softc_t *sc; 38348187Skato 38448187Skato sc = GDC_SOFTC(GDC_UNIT(dev)); 38548187Skato return genfbread(&sc->gensc, sc->adp, uio, flag); 38648187Skato} 38748187Skato 38848187Skatostatic int 389130585Sphkgdcioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td) 39048187Skato{ 39148187Skato gdc_softc_t *sc; 39248187Skato 39348187Skato sc = GDC_SOFTC(GDC_UNIT(dev)); 394111311Snyan return genfbioctl(&sc->gensc, sc->adp, cmd, arg, flag, td); 39548187Skato} 39648187Skato 39748187Skatostatic int 398201223Srnolandgdcmmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, 399201223Srnoland int prot, vm_memattr_t *memattr) 40048187Skato{ 40148187Skato gdc_softc_t *sc; 40248187Skato 40348187Skato sc = GDC_SOFTC(GDC_UNIT(dev)); 404201223Srnoland return genfbmmap(&sc->gensc, sc->adp, offset, paddr, prot, memattr); 40548187Skato} 40648187Skato 40748187Skato#endif /* FB_INSTALL_CDEV */ 40848187Skato 40962952Snyanstatic device_method_t gdc_methods[] = { 41062952Snyan DEVMETHOD(device_identify, gdc_identify), 41163011Snyan DEVMETHOD(device_probe, gdcprobe), 41262952Snyan DEVMETHOD(device_attach, gdc_attach), 41362952Snyan { 0, 0 } 41462952Snyan}; 41562952Snyan 41662952Snyanstatic driver_t gdcdriver = { 41762952Snyan DRIVER_NAME, 41862952Snyan gdc_methods, 41962952Snyan sizeof(gdc_softc_t), 42062952Snyan}; 42162952Snyan 42262952SnyanDRIVER_MODULE(gdc, isa, gdcdriver, gdc_devclass, 0, 0); 42362952Snyan 42442795Skato/* LOW-LEVEL */ 42542795Skato 42642795Skato 427146049Snyan#include <pc98/cbus/30line.h> 42842795Skato 42942795Skato#define TEXT_BUF_BASE 0x000a0000 43042795Skato#define TEXT_BUF_SIZE 0x00008000 43142795Skato#define GRAPHICS_BUF_BASE 0x000a8000 43242795Skato#define GRAPHICS_BUF_SIZE 0x00040000 43342795Skato#define VIDEO_BUF_BASE 0x000a0000 43442795Skato#define VIDEO_BUF_SIZE 0x00048000 43542795Skato 43642795Skato#define probe_done(adp) ((adp)->va_flags & V_ADP_PROBED) 43742795Skato#define init_done(adp) ((adp)->va_flags & V_ADP_INITIALIZED) 43842795Skato#define config_done(adp) ((adp)->va_flags & V_ADP_REGISTERED) 43942795Skato 44042795Skato/* 44142795Skato * NOTE: `va_window' should have a virtual address, but is initialized 44242795Skato * with a physical address in the following table, they will be 44342795Skato * converted at run-time. 44442795Skato */ 44542795Skatostatic video_adapter_t adapter_init_value[] = { 44642795Skato { 0, 44742795Skato KD_PC98, "gdc", /* va_type, va_name */ 44842795Skato 0, 0, /* va_unit, va_minor */ 44942795Skato V_ADP_COLOR | V_ADP_MODECHANGE | V_ADP_BORDER, 45083547Snyan TEXT_GDC, 16, TEXT_GDC, /* va_io*, XXX */ 45142795Skato VIDEO_BUF_BASE, VIDEO_BUF_SIZE, /* va_mem* */ 45248187Skato TEXT_BUF_BASE, TEXT_BUF_SIZE, TEXT_BUF_SIZE, 0, /* va_window* */ 45342795Skato 0, 0, /* va_buffer, va_buffer_size */ 45443709Skato 0, M_PC98_80x25, 0, /* va_*mode* */ 45543709Skato }, 45642795Skato}; 45742795Skato 45842795Skatostatic video_adapter_t biosadapter[1]; 45942795Skato 46042795Skato/* video driver declarations */ 46142795Skatostatic int gdc_configure(int flags); 46248187Skatostatic int gdc_err(video_adapter_t *adp, ...); 46342795Skatostatic vi_probe_t gdc_probe; 46442795Skatostatic vi_init_t gdc_init; 46542795Skatostatic vi_get_info_t gdc_get_info; 46642795Skatostatic vi_query_mode_t gdc_query_mode; 46742795Skatostatic vi_set_mode_t gdc_set_mode; 46842795Skatostatic vi_set_border_t gdc_set_border; 46942795Skatostatic vi_save_state_t gdc_save_state; 47042795Skatostatic vi_load_state_t gdc_load_state; 47142795Skatostatic vi_read_hw_cursor_t gdc_read_hw_cursor; 47242795Skatostatic vi_set_hw_cursor_t gdc_set_hw_cursor; 47342795Skatostatic vi_set_hw_cursor_shape_t gdc_set_hw_cursor_shape; 47448187Skatostatic vi_blank_display_t gdc_blank_display; 47548187Skatostatic vi_mmap_t gdc_mmap_buf; 47648187Skatostatic vi_ioctl_t gdc_dev_ioctl; 47759689Snyanstatic vi_clear_t gdc_clear; 47859689Snyanstatic vi_fill_rect_t gdc_fill_rect; 47959689Snyanstatic vi_bitblt_t gdc_bitblt; 48042795Skatostatic vi_diag_t gdc_diag; 48159689Snyanstatic vi_save_palette_t gdc_save_palette; 48259689Snyanstatic vi_load_palette_t gdc_load_palette; 48359689Snyanstatic vi_set_win_org_t gdc_set_origin; 48442795Skato 48542795Skatostatic video_switch_t gdcvidsw = { 48642795Skato gdc_probe, 48742795Skato gdc_init, 48842795Skato gdc_get_info, 48942795Skato gdc_query_mode, 49042795Skato gdc_set_mode, 49142795Skato (vi_save_font_t *)gdc_err, 49242795Skato (vi_load_font_t *)gdc_err, 49342795Skato (vi_show_font_t *)gdc_err, 49459689Snyan gdc_save_palette, 49559689Snyan gdc_load_palette, 49642795Skato gdc_set_border, 49742795Skato gdc_save_state, 49842795Skato gdc_load_state, 49959689Snyan gdc_set_origin, 50042795Skato gdc_read_hw_cursor, 50142795Skato gdc_set_hw_cursor, 50242795Skato gdc_set_hw_cursor_shape, 50348187Skato gdc_blank_display, 50448187Skato gdc_mmap_buf, 50548187Skato gdc_dev_ioctl, 50659689Snyan gdc_clear, 50759689Snyan gdc_fill_rect, 50859689Snyan gdc_bitblt, 50948187Skato (int (*)(void))gdc_err, 51048187Skato (int (*)(void))gdc_err, 51142795Skato gdc_diag, 51242795Skato}; 51342795Skato 51442795SkatoVIDEO_DRIVER(gdc, gdcvidsw, gdc_configure); 51542795Skato 51642795Skato/* GDC BIOS standard video modes */ 51742795Skato#define EOT (-1) 51842795Skato#define NA (-2) 51942795Skato 52042795Skatostatic video_info_t bios_vmode[] = { 52142795Skato { M_PC98_80x25, V_INFO_COLOR, 80, 25, 8, 16, 4, 1, 52248187Skato TEXT_BUF_BASE, TEXT_BUF_SIZE, TEXT_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 523139946Simp#ifdef LINE30 52442795Skato { M_PC98_80x30, V_INFO_COLOR, 80, 30, 8, 16, 4, 1, 52548187Skato TEXT_BUF_BASE, TEXT_BUF_SIZE, TEXT_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 526139946Simp#endif 52759689Snyan#ifndef GDC_NOGRAPHICS 52859689Snyan { M_PC98_EGC640x400, V_INFO_COLOR | V_INFO_GRAPHICS, 52959689Snyan 640, 400, 8, 16, 4, 4, 53059689Snyan GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0, 531117832Snyan V_INFO_MM_PLANAR }, 53259689Snyan { M_PC98_PEGC640x400, V_INFO_COLOR | V_INFO_GRAPHICS | V_INFO_VESA, 53359689Snyan 640, 400, 8, 16, 8, 1, 53459689Snyan GRAPHICS_BUF_BASE, 0x00008000, 0x00008000, 0, 0, 53559689Snyan V_INFO_MM_PACKED, 1 }, 536139946Simp#ifdef LINE30 53759689Snyan { M_PC98_PEGC640x480, V_INFO_COLOR | V_INFO_GRAPHICS | V_INFO_VESA, 53859689Snyan 640, 480, 8, 16, 8, 1, 53959689Snyan GRAPHICS_BUF_BASE, 0x00008000, 0x00008000, 0, 0, 54059689Snyan V_INFO_MM_PACKED, 1 }, 54159689Snyan#endif 542139946Simp#endif 54342795Skato { EOT }, 54442795Skato}; 54542795Skato 54648187Skatostatic int gdc_init_done = FALSE; 54742795Skato 54842795Skato/* local functions */ 54942795Skatostatic int map_gen_mode_num(int type, int color, int mode); 55042795Skatostatic int probe_adapters(void); 55142795Skato 55242795Skato#define prologue(adp, flag, err) \ 55348187Skato if (!gdc_init_done || !((adp)->va_flags & (flag))) \ 55442795Skato return (err) 55542795Skato 55642795Skato/* a backdoor for the console driver */ 55742795Skatostatic int 55842795Skatogdc_configure(int flags) 55942795Skato{ 56042795Skato probe_adapters(); 56142795Skato biosadapter[0].va_flags |= V_ADP_INITIALIZED; 56242795Skato if (!config_done(&biosadapter[0])) { 56342795Skato if (vid_register(&biosadapter[0]) < 0) 56442795Skato return 1; 56542795Skato biosadapter[0].va_flags |= V_ADP_REGISTERED; 56642795Skato } 56742795Skato 56842795Skato return 1; 56942795Skato} 57042795Skato 57142795Skato/* local subroutines */ 57242795Skato 57342795Skato/* map a generic video mode to a known mode number */ 57442795Skatostatic int 57542795Skatomap_gen_mode_num(int type, int color, int mode) 57642795Skato{ 57742795Skato static struct { 57842795Skato int from; 57942795Skato int to; 58042795Skato } mode_map[] = { 58142795Skato { M_TEXT_80x25, M_PC98_80x25, }, 582139946Simp#ifdef LINE30 58342795Skato { M_TEXT_80x30, M_PC98_80x30, }, 584139946Simp#endif 58542795Skato }; 58642795Skato int i; 58742795Skato 58842795Skato for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) { 58942795Skato if (mode_map[i].from == mode) 59042795Skato return mode_map[i].to; 59142795Skato } 59242795Skato return mode; 59342795Skato} 59442795Skato 59559689Snyanstatic int 59659689Snyanverify_adapter(video_adapter_t *adp) 59759689Snyan{ 59859689Snyan#ifndef GDC_NOGRAPHICS 59959689Snyan int i; 60059689Snyan 60159689Snyan if (PC98_SYSTEM_PARAMETER(0x45c) & 0x40) { /* PEGC exists */ 60259689Snyan adp->va_flags |= V_ADP_VESA; /* XXX */ 60359689Snyan } else { 60459689Snyan for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { 60559689Snyan if (bios_vmode[i].vi_flags & V_INFO_VESA) 60659689Snyan bios_vmode[i].vi_mode = NA; 60759689Snyan } 60859689Snyan } 60959689Snyan#endif 61059689Snyan return 0; 61159689Snyan} 61259689Snyan 61342795Skato/* probe video adapters and return the number of detected adapters */ 61442795Skatostatic int 61542795Skatoprobe_adapters(void) 61642795Skato{ 61742795Skato video_info_t info; 61842795Skato 61942795Skato /* do this test only once */ 62048187Skato if (gdc_init_done) 62142795Skato return 1; 62248187Skato gdc_init_done = TRUE; 62342795Skato 62442795Skato biosadapter[0] = adapter_init_value[0]; 62542795Skato biosadapter[0].va_flags |= V_ADP_PROBED; 62642803Skato biosadapter[0].va_mode = 62742803Skato biosadapter[0].va_initial_mode = biosadapter[0].va_initial_bios_mode; 62842795Skato 62964392Snyan if ((PC98_SYSTEM_PARAMETER(0x597) & 0x80) || 63064392Snyan (PC98_SYSTEM_PARAMETER(0x458) & 0x80)) { 63164392Snyan gdc_FH = (inb(0x9a8) & 1) ? _31KHZ : _24KHZ; 63264392Snyan } else { 63364392Snyan gdc_FH = _24KHZ; 63464392Snyan } 63564392Snyan 63659689Snyan gdc_get_info(&biosadapter[0], biosadapter[0].va_initial_mode, &info); 63759689Snyan initialize_gdc(T25_G400, info.vi_flags & V_INFO_GRAPHICS); 63842795Skato 63942795Skato biosadapter[0].va_window = BIOS_PADDRTOVADDR(info.vi_window); 64042795Skato biosadapter[0].va_window_size = info.vi_window_size; 64142795Skato biosadapter[0].va_window_gran = info.vi_window_gran; 64242795Skato biosadapter[0].va_buffer = 0; 64342795Skato biosadapter[0].va_buffer_size = 0; 64443709Skato if (info.vi_flags & V_INFO_GRAPHICS) { 64543709Skato switch (info.vi_depth/info.vi_planes) { 64643709Skato case 1: 64743709Skato biosadapter[0].va_line_width = info.vi_width/8; 64843709Skato break; 64943709Skato case 2: 65043709Skato biosadapter[0].va_line_width = info.vi_width/4; 65143709Skato break; 65243709Skato case 4: 65343709Skato biosadapter[0].va_line_width = info.vi_width/2; 65443709Skato break; 65543709Skato case 8: 65643709Skato default: /* shouldn't happen */ 65743709Skato biosadapter[0].va_line_width = info.vi_width; 65843709Skato break; 65943709Skato } 66043709Skato } else { 66143709Skato biosadapter[0].va_line_width = info.vi_width; 66243709Skato } 66343709Skato bcopy(&info, &biosadapter[0].va_info, sizeof(info)); 66442795Skato 66559689Snyan verify_adapter(&biosadapter[0]); 66659689Snyan 66742795Skato return 1; 66842795Skato} 66942795Skato 67042795Skatostatic void master_gdc_cmd(unsigned int cmd) 67142795Skato{ 67283547Snyan while ( (inb(TEXT_GDC) & 2) != 0); 67383547Snyan outb(TEXT_GDC+2, cmd); 67442795Skato} 67542795Skato 67642795Skatostatic void master_gdc_prm(unsigned int pmtr) 67742795Skato{ 67883547Snyan while ( (inb(TEXT_GDC) & 2) != 0); 67983547Snyan outb(TEXT_GDC, pmtr); 68042795Skato} 68142795Skato 68242795Skatostatic void master_gdc_word_prm(unsigned int wpmtr) 68342795Skato{ 68442795Skato master_gdc_prm(wpmtr & 0x00ff); 68542795Skato master_gdc_prm((wpmtr >> 8) & 0x00ff); 68642795Skato} 68742795Skato 688139946Simp#ifdef LINE30 68942795Skatostatic void master_gdc_fifo_empty(void) 69042795Skato{ 69183547Snyan while ( (inb(TEXT_GDC) & 4) == 0); 69242795Skato} 693139946Simp#endif 69442795Skato 69542795Skatostatic void master_gdc_wait_vsync(void) 69642795Skato{ 69783547Snyan while ( (inb(TEXT_GDC) & 0x20) != 0); 69883547Snyan while ( (inb(TEXT_GDC) & 0x20) == 0); 69942795Skato} 70042795Skato 70142795Skatostatic void gdc_cmd(unsigned int cmd) 70242795Skato{ 70383547Snyan while ( (inb(GRAPHIC_GDC) & 2) != 0); 70483547Snyan outb( GRAPHIC_GDC+2, cmd); 70542795Skato} 70642795Skato 707139946Simp#ifdef LINE30 70842795Skatostatic void gdc_prm(unsigned int pmtr) 70942795Skato{ 71083547Snyan while ( (inb(GRAPHIC_GDC) & 2) != 0); 71183547Snyan outb( GRAPHIC_GDC, pmtr); 71242795Skato} 71342795Skato 71442795Skatostatic void gdc_word_prm(unsigned int wpmtr) 71542795Skato{ 71642795Skato gdc_prm(wpmtr & 0x00ff); 71742795Skato gdc_prm((wpmtr >> 8) & 0x00ff); 71842795Skato} 71942795Skato 72042795Skatostatic void gdc_fifo_empty(void) 72142795Skato{ 72283547Snyan while ( (inb(GRAPHIC_GDC) & 0x04) == 0); 72342795Skato} 724139946Simp#endif 72542795Skato 72642795Skatostatic void gdc_wait_vsync(void) 72742795Skato{ 72883547Snyan while ( (inb(GRAPHIC_GDC) & 0x20) != 0); 72983547Snyan while ( (inb(GRAPHIC_GDC) & 0x20) == 0); 73042795Skato} 73142795Skato 732139946Simp#ifdef LINE30 73342795Skatostatic int check_gdc_clock(void) 73442795Skato{ 73542795Skato if ((inb(IO_SYSPORT) & 0x80) == 0){ 73642795Skato return _5MHZ; 73742795Skato } else { 73842795Skato return _2_5MHZ; 73942795Skato } 74042795Skato} 741139946Simp#endif 74242795Skato 74359689Snyanstatic void initialize_gdc(unsigned int mode, int isGraph) 74442795Skato{ 745139946Simp#ifdef LINE30 74642795Skato /* start 30line initialize */ 74759689Snyan int m_mode, s_mode, gdc_clock, hsync_clock; 74859689Snyan 74942795Skato gdc_clock = check_gdc_clock(); 75059689Snyan m_mode = (mode == T25_G400) ? _25L : _30L; 75159689Snyan s_mode = 2*mode+gdc_clock; 75259689Snyan gdc_INFO = m_mode; 75342795Skato 75464392Snyan master_gdc_wait_vsync(); 75564392Snyan 75659689Snyan if ((PC98_SYSTEM_PARAMETER(0x597) & 0x80) || 75759689Snyan (PC98_SYSTEM_PARAMETER(0x458) & 0x80)) { 75864392Snyan if (PC98_SYSTEM_PARAMETER(0x481) & 0x08) { 75967788Snyan hsync_clock = (m_mode == _25L) ? gdc_FH : _31KHZ; 76064392Snyan outb(0x9a8, (hsync_clock == _31KHZ) ? 1 : 0); 76164392Snyan } else { 76264392Snyan hsync_clock = gdc_FH; 76364392Snyan } 76459689Snyan } else { 76559689Snyan hsync_clock = _24KHZ; 76642795Skato } 76742795Skato 76859689Snyan if ((gdc_clock == _2_5MHZ) && 76959689Snyan (slave_param[hsync_clock][s_mode][GDC_LF] > 400)) { 77059689Snyan outb(0x6a, 0x83); 77159689Snyan outb(0x6a, 0x85); 77259689Snyan gdc_clock = _5MHZ; 77359689Snyan s_mode = 2*mode+gdc_clock; 77459689Snyan } 77542795Skato 77642795Skato master_gdc_cmd(_GDC_RESET); 77742795Skato master_gdc_cmd(_GDC_MASTER); 77842795Skato gdc_cmd(_GDC_RESET); 77942795Skato gdc_cmd(_GDC_SLAVE); 78042795Skato 78142795Skato /* GDC Master */ 78242795Skato master_gdc_cmd(_GDC_SYNC); 78342795Skato master_gdc_prm(0x00); /* flush less */ /* text & graph */ 78459689Snyan master_gdc_prm(master_param[hsync_clock][m_mode][GDC_CR]); 78559689Snyan master_gdc_word_prm(((master_param[hsync_clock][m_mode][GDC_HFP] << 10) 78659689Snyan + (master_param[hsync_clock][m_mode][GDC_VS] << 5) 78759689Snyan + master_param[hsync_clock][m_mode][GDC_HS])); 78859689Snyan master_gdc_prm(master_param[hsync_clock][m_mode][GDC_HBP]); 78959689Snyan master_gdc_prm(master_param[hsync_clock][m_mode][GDC_VFP]); 79059689Snyan master_gdc_word_prm(((master_param[hsync_clock][m_mode][GDC_VBP] << 10) 79159689Snyan + (master_param[hsync_clock][m_mode][GDC_LF]))); 79242795Skato master_gdc_fifo_empty(); 79342795Skato master_gdc_cmd(_GDC_PITCH); 79442795Skato master_gdc_prm(MasterPCH); 79542795Skato master_gdc_fifo_empty(); 79642795Skato 79742795Skato /* GDC slave */ 79842795Skato gdc_cmd(_GDC_SYNC); 79942795Skato gdc_prm(0x06); 80059689Snyan gdc_prm(slave_param[hsync_clock][s_mode][GDC_CR]); 80159689Snyan gdc_word_prm((slave_param[hsync_clock][s_mode][GDC_HFP] << 10) 80259689Snyan + (slave_param[hsync_clock][s_mode][GDC_VS] << 5) 80359689Snyan + (slave_param[hsync_clock][s_mode][GDC_HS])); 80459689Snyan gdc_prm(slave_param[hsync_clock][s_mode][GDC_HBP]); 80559689Snyan gdc_prm(slave_param[hsync_clock][s_mode][GDC_VFP]); 80659689Snyan gdc_word_prm((slave_param[hsync_clock][s_mode][GDC_VBP] << 10) 80759689Snyan + (slave_param[hsync_clock][s_mode][GDC_LF])); 80842795Skato gdc_fifo_empty(); 80942795Skato gdc_cmd(_GDC_PITCH); 81042795Skato gdc_prm(SlavePCH[gdc_clock]); 81142795Skato gdc_fifo_empty(); 81242795Skato 81342795Skato /* set Master GDC scroll param */ 81442795Skato master_gdc_wait_vsync(); 81542795Skato master_gdc_wait_vsync(); 81642795Skato master_gdc_wait_vsync(); 81742795Skato master_gdc_cmd(_GDC_SCROLL); 81842795Skato master_gdc_word_prm(0); 81959689Snyan master_gdc_word_prm((master_param[hsync_clock][m_mode][GDC_LF] << 4) 82059689Snyan | 0x0000); 82142795Skato master_gdc_fifo_empty(); 82242795Skato 82342795Skato /* set Slave GDC scroll param */ 82442795Skato gdc_wait_vsync(); 82542795Skato gdc_cmd(_GDC_SCROLL); 82642795Skato gdc_word_prm(0); 82759689Snyan if (gdc_clock == _5MHZ) { 82842795Skato gdc_word_prm((SlaveScrlLF[mode] << 4) | 0x4000); 82959689Snyan } else { 83042795Skato gdc_word_prm(SlaveScrlLF[mode] << 4); 83142795Skato } 83242795Skato gdc_fifo_empty(); 83342795Skato 83442795Skato gdc_word_prm(0); 83559689Snyan if (gdc_clock == _5MHZ) { 83642795Skato gdc_word_prm((SlaveScrlLF[mode] << 4) | 0x4000); 83759689Snyan } else { 83842795Skato gdc_word_prm(SlaveScrlLF[mode] << 4); 83942795Skato } 84042795Skato gdc_fifo_empty(); 84142795Skato 84242795Skato /* sync start */ 84359689Snyan gdc_cmd(isGraph ? _GDC_START : _GDC_STOP); 84442795Skato 84542795Skato gdc_wait_vsync(); 84642795Skato gdc_wait_vsync(); 84742795Skato gdc_wait_vsync(); 84842795Skato 84959689Snyan master_gdc_cmd(isGraph ? _GDC_STOP : _GDC_START); 850139946Simp#else 851139946Simp master_gdc_wait_vsync(); 852139946Simp master_gdc_cmd(isGraph ? _GDC_STOP : _GDC_START); /* text */ 853139946Simp gdc_wait_vsync(); 854139946Simp gdc_cmd(isGraph ? _GDC_START : _GDC_STOP); /* graphics */ 855139946Simp#endif 85642795Skato} 85742795Skato 85859689Snyan#ifndef GDC_NOGRAPHICS 85959689Snyanstatic u_char b_palette[] = { 86059689Snyan /* R G B */ 86159689Snyan 0x00, 0x00, 0x00, /* 0 */ 86259689Snyan 0x00, 0x00, 0x7f, /* 1 */ 86359689Snyan 0x7f, 0x00, 0x00, /* 2 */ 86459689Snyan 0x7f, 0x00, 0x7f, /* 3 */ 86559689Snyan 0x00, 0x7f, 0x00, /* 4 */ 86659689Snyan 0x00, 0x7f, 0x7f, /* 5 */ 86759689Snyan 0x7f, 0x7f, 0x00, /* 6 */ 86859689Snyan 0x7f, 0x7f, 0x7f, /* 7 */ 86959689Snyan 0x40, 0x40, 0x40, /* 8 */ 87059689Snyan 0x00, 0x00, 0xff, /* 9 */ 87159689Snyan 0xff, 0x00, 0x00, /* 10 */ 87259689Snyan 0xff, 0x00, 0xff, /* 11 */ 87359689Snyan 0x00, 0xff, 0x00, /* 12 */ 87459689Snyan 0x00, 0xff, 0xff, /* 13 */ 87559689Snyan 0xff, 0xff, 0x00, /* 14 */ 87659689Snyan 0xff, 0xff, 0xff, /* 15 */ 87759689Snyan}; 87859689Snyan#endif 87942795Skato 88042795Skatostatic int 88159689Snyangdc_load_palette(video_adapter_t *adp, u_char *palette) 88259689Snyan{ 88359689Snyan#ifndef GDC_NOGRAPHICS 88459689Snyan int i; 88559689Snyan 88659689Snyan if (adp->va_info.vi_flags & V_INFO_VESA) { 88759689Snyan gdc_wait_vsync(); 88859689Snyan for (i = 0; i < 256; ++i) { 88959689Snyan outb(0xa8, i); 89059689Snyan outb(0xac, *palette++); /* R */ 89159689Snyan outb(0xaa, *palette++); /* G */ 89259689Snyan outb(0xae, *palette++); /* B */ 89359689Snyan } 89459689Snyan } else { 89559689Snyan /* 89659689Snyan * XXX - Even though PC-98 text color is independent of palette, 89759689Snyan * we should set palette in text mode. 89859689Snyan * Because the background color of text mode is palette 0's one. 89959689Snyan */ 90059689Snyan outb(0x6a, 1); /* 16 colors mode */ 90159689Snyan bcopy(palette, b_palette, sizeof(b_palette)); 90259689Snyan 90359689Snyan gdc_wait_vsync(); 90459689Snyan for (i = 0; i < 16; ++i) { 90559689Snyan outb(0xa8, i); 90659689Snyan outb(0xac, *palette++ >> 4); /* R */ 90759689Snyan outb(0xaa, *palette++ >> 4); /* G */ 90859689Snyan outb(0xae, *palette++ >> 4); /* B */ 90959689Snyan } 91059689Snyan } 91159689Snyan#endif 91259689Snyan return 0; 91359689Snyan} 91459689Snyan 91559689Snyanstatic int 91659689Snyangdc_save_palette(video_adapter_t *adp, u_char *palette) 91759689Snyan{ 91859689Snyan#ifndef GDC_NOGRAPHICS 91959689Snyan int i; 92059689Snyan 92159689Snyan if (adp->va_info.vi_flags & V_INFO_VESA) { 92259689Snyan for (i = 0; i < 256; ++i) { 92359689Snyan outb(0xa8, i); 92459689Snyan *palette++ = inb(0xac); /* R */ 92559689Snyan *palette++ = inb(0xaa); /* G */ 92659689Snyan *palette++ = inb(0xae); /* B */ 92759689Snyan } 92859689Snyan } else { 92959689Snyan bcopy(b_palette, palette, sizeof(b_palette)); 93059689Snyan } 93159689Snyan#endif 93259689Snyan return 0; 93359689Snyan} 93459689Snyan 93559689Snyanstatic int 93659689Snyangdc_set_origin(video_adapter_t *adp, off_t offset) 93759689Snyan{ 93859689Snyan#ifndef GDC_NOGRAPHICS 93959689Snyan if (adp->va_info.vi_flags & V_INFO_VESA) { 94059689Snyan writew(BIOS_PADDRTOVADDR(0x000e0004), offset >> 15); 94159689Snyan } 94259689Snyan#endif 94359689Snyan return 0; 94459689Snyan} 94559689Snyan 94659689Snyan/* entry points */ 94759689Snyan 94842795Skatostatic int 94948187Skatogdc_err(video_adapter_t *adp, ...) 95048187Skato{ 95148187Skato return ENODEV; 95248187Skato} 95348187Skato 95448187Skatostatic int 95542795Skatogdc_probe(int unit, video_adapter_t **adpp, void *arg, int flags) 95642795Skato{ 95742795Skato probe_adapters(); 95842795Skato if (unit >= 1) 95942795Skato return ENXIO; 96042795Skato 96142795Skato *adpp = &biosadapter[unit]; 96242795Skato 96342795Skato return 0; 96442795Skato} 96542795Skato 96642795Skatostatic int 96742795Skatogdc_init(int unit, video_adapter_t *adp, int flags) 96842795Skato{ 96942795Skato if ((unit >= 1) || (adp == NULL) || !probe_done(adp)) 97042795Skato return ENXIO; 97142795Skato 97242795Skato if (!init_done(adp)) { 97342795Skato /* nothing to do really... */ 97442795Skato adp->va_flags |= V_ADP_INITIALIZED; 97542795Skato } 97642795Skato 97742795Skato if (!config_done(adp)) { 97842795Skato if (vid_register(adp) < 0) 97942795Skato return ENXIO; 98042795Skato adp->va_flags |= V_ADP_REGISTERED; 98142795Skato } 98242795Skato 98342795Skato return 0; 98442795Skato} 98542795Skato 98642795Skato/* 98742795Skato * get_info(): 98842795Skato * Return the video_info structure of the requested video mode. 98942795Skato */ 99042795Skatostatic int 99142795Skatogdc_get_info(video_adapter_t *adp, int mode, video_info_t *info) 99242795Skato{ 99342795Skato int i; 99442795Skato 99548187Skato if (!gdc_init_done) 99648187Skato return ENXIO; 99742795Skato 99842795Skato mode = map_gen_mode_num(adp->va_type, adp->va_flags & V_ADP_COLOR, mode); 99942795Skato for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { 100042795Skato if (bios_vmode[i].vi_mode == NA) 100142795Skato continue; 100242795Skato if (mode == bios_vmode[i].vi_mode) { 100342795Skato *info = bios_vmode[i]; 100448187Skato info->vi_buffer_size = info->vi_window_size*info->vi_planes; 100542795Skato return 0; 100642795Skato } 100742795Skato } 100848187Skato return EINVAL; 100942795Skato} 101042795Skato 101142795Skato/* 101242795Skato * query_mode(): 101342795Skato * Find a video mode matching the requested parameters. 101442795Skato * Fields filled with 0 are considered "don't care" fields and 101542795Skato * match any modes. 101642795Skato */ 101742795Skatostatic int 101842795Skatogdc_query_mode(video_adapter_t *adp, video_info_t *info) 101942795Skato{ 102042795Skato int i; 102142795Skato 102248187Skato if (!gdc_init_done) 102354358Skato return ENXIO; 102442795Skato 102542795Skato for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { 102642795Skato if (bios_vmode[i].vi_mode == NA) 102742795Skato continue; 102842795Skato 102942795Skato if ((info->vi_width != 0) 103042795Skato && (info->vi_width != bios_vmode[i].vi_width)) 103142795Skato continue; 103242795Skato if ((info->vi_height != 0) 103342795Skato && (info->vi_height != bios_vmode[i].vi_height)) 103442795Skato continue; 103542795Skato if ((info->vi_cwidth != 0) 103642795Skato && (info->vi_cwidth != bios_vmode[i].vi_cwidth)) 103742795Skato continue; 103842795Skato if ((info->vi_cheight != 0) 103942795Skato && (info->vi_cheight != bios_vmode[i].vi_cheight)) 104042795Skato continue; 104142795Skato if ((info->vi_depth != 0) 104242795Skato && (info->vi_depth != bios_vmode[i].vi_depth)) 104342795Skato continue; 104442795Skato if ((info->vi_planes != 0) 104542795Skato && (info->vi_planes != bios_vmode[i].vi_planes)) 104642795Skato continue; 104742795Skato /* XXX: should check pixel format, memory model */ 104842795Skato if ((info->vi_flags != 0) 104942795Skato && (info->vi_flags != bios_vmode[i].vi_flags)) 105042795Skato continue; 105142795Skato 105242795Skato /* verify if this mode is supported on this adapter */ 105354358Skato if (gdc_get_info(adp, bios_vmode[i].vi_mode, info)) 105442795Skato continue; 105554358Skato return 0; 105642795Skato } 105754358Skato return ENODEV; 105842795Skato} 105942795Skato 106042795Skato/* 106142795Skato * set_mode(): 106242795Skato * Change the video mode. 106342795Skato */ 106442795Skatostatic int 106542795Skatogdc_set_mode(video_adapter_t *adp, int mode) 106642795Skato{ 106742795Skato video_info_t info; 106842795Skato 106948187Skato prologue(adp, V_ADP_MODECHANGE, ENODEV); 107042795Skato 107142795Skato mode = map_gen_mode_num(adp->va_type, 107242795Skato adp->va_flags & V_ADP_COLOR, mode); 107342795Skato if (gdc_get_info(adp, mode, &info)) 107448187Skato return EINVAL; 107542795Skato 107644421Skato switch (info.vi_mode) { 107759689Snyan#ifndef GDC_NOGRAPHICS 107859689Snyan case M_PC98_PEGC640x480: /* PEGC 640x480 */ 107959689Snyan initialize_gdc(T30_G480, info.vi_flags & V_INFO_GRAPHICS); 108059689Snyan break; 108159689Snyan case M_PC98_PEGC640x400: /* PEGC 640x400 */ 108259689Snyan case M_PC98_EGC640x400: /* EGC GRAPHICS */ 108359689Snyan#endif 108459689Snyan case M_PC98_80x25: /* VGA TEXT */ 108559689Snyan initialize_gdc(T25_G400, info.vi_flags & V_INFO_GRAPHICS); 108659689Snyan break; 108759689Snyan case M_PC98_80x30: /* VGA TEXT */ 108859689Snyan initialize_gdc(T30_G400, info.vi_flags & V_INFO_GRAPHICS); 108959689Snyan break; 109042795Skato default: 109159689Snyan break; 109242795Skato } 109359689Snyan 109459689Snyan#ifndef GDC_NOGRAPHICS 109559689Snyan if (info.vi_flags & V_INFO_VESA) { 109659689Snyan outb(0x6a, 0x07); /* enable mode F/F change */ 109759689Snyan outb(0x6a, 0x21); /* enhanced graphics */ 109859689Snyan if (info.vi_height > 400) 109959689Snyan outb(0x6a, 0x69); /* 800 lines */ 110059689Snyan writeb(BIOS_PADDRTOVADDR(0x000e0100), 0); /* packed pixel */ 110159689Snyan } else { 110259689Snyan if (adp->va_flags & V_ADP_VESA) { 110359689Snyan outb(0x6a, 0x07); /* enable mode F/F change */ 110459689Snyan outb(0x6a, 0x20); /* normal graphics */ 110559689Snyan outb(0x6a, 0x68); /* 400 lines */ 110659689Snyan } 110759689Snyan outb(0x6a, 1); /* 16 colors */ 110859689Snyan } 110942795Skato#endif 111042795Skato 111142795Skato adp->va_mode = mode; 111242795Skato adp->va_flags &= ~V_ADP_COLOR; 111342795Skato adp->va_flags |= 111442795Skato (info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0; 111542795Skato#if 0 111642795Skato adp->va_crtc_addr = 111742795Skato (adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC; 111842795Skato#endif 111942795Skato adp->va_window = BIOS_PADDRTOVADDR(info.vi_window); 112042795Skato adp->va_window_size = info.vi_window_size; 112142795Skato adp->va_window_gran = info.vi_window_gran; 112242795Skato if (info.vi_buffer_size == 0) { 112342795Skato adp->va_buffer = 0; 112442795Skato adp->va_buffer_size = 0; 112542795Skato } else { 112642795Skato adp->va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer); 112742795Skato adp->va_buffer_size = info.vi_buffer_size; 112842795Skato } 112943709Skato if (info.vi_flags & V_INFO_GRAPHICS) { 113043709Skato switch (info.vi_depth/info.vi_planes) { 113143709Skato case 1: 113243709Skato adp->va_line_width = info.vi_width/8; 113343709Skato break; 113443709Skato case 2: 113543709Skato adp->va_line_width = info.vi_width/4; 113643709Skato break; 113743709Skato case 4: 113843709Skato adp->va_line_width = info.vi_width/2; 113943709Skato break; 114043709Skato case 8: 114143709Skato default: /* shouldn't happen */ 114243709Skato adp->va_line_width = info.vi_width; 114343709Skato break; 114443709Skato } 114543709Skato } else { 114643709Skato adp->va_line_width = info.vi_width; 114743709Skato } 114843709Skato bcopy(&info, &adp->va_info, sizeof(info)); 114942795Skato 115042795Skato /* move hardware cursor out of the way */ 1151174985Swkoszek vidd_set_hw_cursor(adp, -1, -1); 115242795Skato 115342795Skato return 0; 115442795Skato} 115542795Skato 115642795Skato/* 115742795Skato * set_border(): 115842795Skato * Change the border color. 115942795Skato */ 116042795Skatostatic int 116142795Skatogdc_set_border(video_adapter_t *adp, int color) 116242795Skato{ 116342795Skato outb(0x6c, color << 4); 116442795Skato return 0; 116542795Skato} 116642795Skato 116742795Skato/* 116842795Skato * save_state(): 116942795Skato * Read video card register values. 117042795Skato */ 117142795Skatostatic int 117242795Skatogdc_save_state(video_adapter_t *adp, void *p, size_t size) 117342795Skato{ 117448187Skato return ENODEV; 117542795Skato} 117642795Skato 117742795Skato/* 117842795Skato * load_state(): 117942795Skato * Set video card registers at once. 118042795Skato */ 118142795Skatostatic int 118242795Skatogdc_load_state(video_adapter_t *adp, void *p) 118342795Skato{ 118448187Skato return ENODEV; 118542795Skato} 118642795Skato 118742795Skato/* 118842795Skato * read_hw_cursor(): 118942795Skato * Read the position of the hardware text cursor. 119042795Skato */ 119142795Skatostatic int 119242795Skatogdc_read_hw_cursor(video_adapter_t *adp, int *col, int *row) 119342795Skato{ 119442795Skato u_int16_t off; 119542795Skato int s; 119642795Skato 119748187Skato if (!gdc_init_done) 119848187Skato return ENXIO; 119942795Skato 120043709Skato if (adp->va_info.vi_flags & V_INFO_GRAPHICS) 120148187Skato return ENODEV; 120242795Skato 120342795Skato s = spltty(); 120442795Skato master_gdc_cmd(0xe0); /* _GDC_CSRR */ 120542795Skato while((inb(TEXT_GDC + 0) & 0x1) == 0) {} /* GDC wait */ 120642795Skato off = inb(TEXT_GDC + 2); /* EADl */ 120742795Skato off |= (inb(TEXT_GDC + 2) << 8); /* EADh */ 120842795Skato inb(TEXT_GDC + 2); /* dummy */ 120942795Skato inb(TEXT_GDC + 2); /* dummy */ 121042795Skato inb(TEXT_GDC + 2); /* dummy */ 121142795Skato splx(s); 121242795Skato 121342795Skato if (off >= ROW*COL) 121442795Skato off = 0; 121543709Skato *row = off / adp->va_info.vi_width; 121643709Skato *col = off % adp->va_info.vi_width; 121742795Skato 121842795Skato return 0; 121942795Skato} 122042795Skato 122142795Skato/* 122242795Skato * set_hw_cursor(): 122342795Skato * Move the hardware text cursor. If col and row are both -1, 122442795Skato * the cursor won't be shown. 122542795Skato */ 122642795Skatostatic int 122742795Skatogdc_set_hw_cursor(video_adapter_t *adp, int col, int row) 122842795Skato{ 122942795Skato u_int16_t off; 123042795Skato int s; 123142795Skato 123248187Skato if (!gdc_init_done) 123348187Skato return ENXIO; 123442795Skato 123542795Skato if ((col == -1) && (row == -1)) { 123642795Skato off = -1; 123742795Skato } else { 123843709Skato if (adp->va_info.vi_flags & V_INFO_GRAPHICS) 123948187Skato return ENODEV; 124043709Skato off = row*adp->va_info.vi_width + col; 124142795Skato } 124242795Skato 124342795Skato s = spltty(); 124442795Skato master_gdc_cmd(0x49); /* _GDC_CSRW */ 124542795Skato master_gdc_word_prm(off); 124642795Skato splx(s); 124742795Skato 124842795Skato return 0; 124942795Skato} 125042795Skato 125142795Skato/* 125242795Skato * set_hw_cursor_shape(): 125342795Skato * Change the shape of the hardware text cursor. If the height is zero 125442795Skato * or negative, the cursor won't be shown. 125542795Skato */ 125642795Skatostatic int 125742795Skatogdc_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, 125842795Skato int celsize, int blink) 125942795Skato{ 126042795Skato int start; 126142795Skato int end; 126242795Skato int s; 126342795Skato 126448187Skato if (!gdc_init_done) 126548187Skato return ENXIO; 126648187Skato 126742795Skato start = celsize - (base + height); 126842795Skato end = celsize - base - 1; 126964394Snyan 127064394Snyan#if 0 127142795Skato /* 127242795Skato * muPD7220 GDC has anomaly that if end == celsize - 1 then start 127342795Skato * must be 0, otherwise the cursor won't be correctly shown 127442795Skato * in the first row in the screen. We shall set end to celsize - 2; 127542795Skato * if end == celsize -1 && start > 0. XXX 127642795Skato */ 127764394Snyan if ((end == celsize - 1) && (start > 0) && (start < end)) 127842795Skato --end; 127964394Snyan#endif 128042795Skato 128142795Skato s = spltty(); 128242795Skato master_gdc_cmd(0x4b); /* _GDC_CSRFORM */ 128342795Skato master_gdc_prm(((height > 0) ? 0x80 : 0) /* cursor on/off */ 128448187Skato | ((celsize - 1) & 0x1f)); /* cel size */ 128542795Skato master_gdc_word_prm(((end & 0x1f) << 11) /* end line */ 128642795Skato | (12 << 6) /* blink rate */ 128764394Snyan | (blink ? 0 : 0x20) /* blink on/off */ 128842795Skato | (start & 0x1f)); /* start line */ 128942795Skato splx(s); 129042795Skato 129148187Skato return 0; 129242795Skato} 129342795Skato 129448187Skato/* 129548187Skato * blank_display() 129648187Skato * Put the display in power save/power off mode. 129748187Skato */ 129848187Skatostatic int 129948187Skatogdc_blank_display(video_adapter_t *adp, int mode) 130042795Skato{ 130148187Skato int s; 130258780Snyan static int standby = 0; 130342795Skato 130448187Skato if (!gdc_init_done) 130548187Skato return ENXIO; 130648187Skato 130748187Skato s = splhigh(); 130848187Skato switch (mode) { 130948187Skato case V_DISPLAY_SUSPEND: 131048187Skato case V_DISPLAY_STAND_BY: 131158780Snyan outb(0x09a2, 0x80 | 0x40); /* V/H-SYNC mask */ 131258780Snyan if (inb(0x09a2) == (0x80 | 0x40)) 131358780Snyan standby = 1; 1314102412Scharnier /* FALLTHROUGH */ 131548187Skato 131648187Skato case V_DISPLAY_BLANK: 1317150127Snyan while (!(inb(TEXT_GDC) & 0x20)) /* V-SYNC wait */ 1318150127Snyan ; 1319150127Snyan outb(TEXT_GDC + 8, 0x0e); /* DISP off */ 132048187Skato break; 132148187Skato 132248187Skato case V_DISPLAY_ON: 1323150127Snyan while (!(inb(TEXT_GDC) & 0x20)) /* V-SYNC wait */ 1324150127Snyan ; 1325150127Snyan outb(TEXT_GDC + 8, 0x0f); /* DISP on */ 132658780Snyan if (standby) { 132758780Snyan outb(0x09a2, 0x00); /* V/H-SYNC unmask */ 132858780Snyan standby = 0; 132958780Snyan } 133048187Skato break; 133142795Skato } 133248187Skato splx(s); 133348187Skato return 0; 133442795Skato} 133542795Skato 133642795Skato/* 133742795Skato * mmap(): 133842795Skato * Mmap frame buffer. 133942795Skato */ 134042795Skatostatic int 1341201223Srnolandgdc_mmap_buf(video_adapter_t *adp, vm_ooffset_t offset, vm_offset_t *paddr, 1342201223Srnoland int prot, vm_memattr_t *memattr) 134342795Skato{ 134448187Skato /* FIXME: is this correct? XXX */ 134548187Skato if (offset > VIDEO_BUF_SIZE - PAGE_SIZE) 134642795Skato return -1; 1347111481Smux *paddr = adp->va_info.vi_window + offset; 1348111481Smux return 0; 134942795Skato} 135042795Skato 1351117832Snyan#ifndef GDC_NOGRAPHICS 1352117832Snyanstatic void 1353117832Snyanplanar_fill(video_adapter_t *adp, int val) 1354117832Snyan{ 1355117832Snyan 1356117832Snyan outb(0x7c, 0x80); /* GRCG on & TDW mode */ 1357117832Snyan outb(0x7e, 0); /* tile B */ 1358117832Snyan outb(0x7e, 0); /* tile R */ 1359117832Snyan outb(0x7e, 0); /* tile G */ 1360117832Snyan outb(0x7e, 0); /* tile I */ 1361117832Snyan 1362117832Snyan fillw_io(0, adp->va_window, 0x8000 / 2); /* XXX */ 1363117832Snyan 1364117832Snyan outb(0x7c, 0); /* GRCG off */ 1365117832Snyan} 1366117832Snyan 1367117832Snyanstatic void 1368117832Snyanpacked_fill(video_adapter_t *adp, int val) 1369117832Snyan{ 1370117832Snyan int length; 1371117832Snyan int at; /* position in the frame buffer */ 1372117832Snyan int l; 1373117832Snyan 1374117832Snyan at = 0; 1375117832Snyan length = adp->va_line_width*adp->va_info.vi_height; 1376117832Snyan while (length > 0) { 1377117832Snyan l = imin(length, adp->va_window_size); 1378174985Swkoszek vidd_set_win_org(adp, at); 1379117832Snyan bzero_io(adp->va_window, l); 1380117832Snyan length -= l; 1381117832Snyan at += l; 1382117832Snyan } 1383117832Snyan} 1384117832Snyan 138548187Skatostatic int 138659689Snyangdc_clear(video_adapter_t *adp) 138759689Snyan{ 1388117832Snyan 1389117832Snyan switch (adp->va_info.vi_mem_model) { 1390117832Snyan case V_INFO_MM_TEXT: 1391117832Snyan /* do nothing? XXX */ 1392117832Snyan break; 1393117832Snyan case V_INFO_MM_PLANAR: 1394117832Snyan planar_fill(adp, 0); 1395117832Snyan break; 1396117832Snyan case V_INFO_MM_PACKED: 1397117832Snyan packed_fill(adp, 0); 1398117832Snyan break; 1399117832Snyan } 1400117832Snyan 1401117832Snyan return 0; 140259689Snyan} 1403117832Snyan#else /* GDC_NOGRAPHICS */ 1404117832Snyanstatic int 1405117832Snyangdc_clear(video_adapter_t *adp) 1406117832Snyan{ 140759689Snyan 1408117832Snyan return 0; 1409117832Snyan} 1410117832Snyan#endif /* GDC_NOGRAPHICS */ 1411117832Snyan 141259689Snyanstatic int 141359689Snyangdc_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) 141459689Snyan{ 141559689Snyan return ENODEV; 141659689Snyan} 141759689Snyan 141859689Snyanstatic int 141959689Snyangdc_bitblt(video_adapter_t *adp,...) 142059689Snyan{ 142159689Snyan /* FIXME */ 142259689Snyan return ENODEV; 142359689Snyan} 142459689Snyan 142559689Snyanstatic int 142648187Skatogdc_dev_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg) 142748187Skato{ 142848187Skato switch (cmd) { 142948187Skato case FBIO_GETWINORG: /* get frame buffer window origin */ 143048187Skato *(u_int *)arg = 0; 143148187Skato return 0; 143248187Skato 143348187Skato case FBIO_SETWINORG: /* set frame buffer window origin */ 143448187Skato case FBIO_SETDISPSTART: /* set display start address */ 143548187Skato case FBIO_SETLINEWIDTH: /* set scan line length in pixel */ 143648187Skato case FBIO_GETPALETTE: /* get color palette */ 143748187Skato case FBIO_SETPALETTE: /* set color palette */ 143848187Skato case FBIOGETCMAP: /* get color palette */ 143948187Skato case FBIOPUTCMAP: /* set color palette */ 144048187Skato return ENODEV; 144148187Skato 144248187Skato case FBIOGTYPE: /* get frame buffer type info. */ 144348187Skato ((struct fbtype *)arg)->fb_type = fb_type(adp->va_type); 144448187Skato ((struct fbtype *)arg)->fb_height = adp->va_info.vi_height; 144548187Skato ((struct fbtype *)arg)->fb_width = adp->va_info.vi_width; 144648187Skato ((struct fbtype *)arg)->fb_depth = adp->va_info.vi_depth; 144748187Skato if ((adp->va_info.vi_depth <= 1) || (adp->va_info.vi_depth > 8)) 144848187Skato ((struct fbtype *)arg)->fb_cmsize = 0; 144948187Skato else 145048187Skato ((struct fbtype *)arg)->fb_cmsize = 1 << adp->va_info.vi_depth; 145148187Skato ((struct fbtype *)arg)->fb_size = adp->va_buffer_size; 145248187Skato return 0; 145348187Skato 145448187Skato default: 145548187Skato return fb_commonioctl(adp, cmd, arg); 145648187Skato } 145748187Skato} 145848187Skato 145942795Skato/* 146042795Skato * diag(): 146142795Skato * Print some information about the video adapter and video modes, 146242795Skato * with requested level of details. 146342795Skato */ 146442795Skatostatic int 146542795Skatogdc_diag(video_adapter_t *adp, int level) 146642795Skato{ 1467153165Sru#if defined(FB_DEBUG) && FB_DEBUG > 1 146842795Skato int i; 146943338Skato#endif 147042795Skato 147148187Skato if (!gdc_init_done) 147248187Skato return ENXIO; 147342795Skato 147442795Skato fb_dump_adp_info(DRIVER_NAME, adp, level); 147542795Skato 1476153165Sru#if defined(FB_DEBUG) && FB_DEBUG > 1 147742795Skato for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { 147842795Skato if (bios_vmode[i].vi_mode == NA) 147942795Skato continue; 148042795Skato if (get_mode_param(bios_vmode[i].vi_mode) == NULL) 148142795Skato continue; 148242795Skato fb_dump_mode_info(DRIVER_NAME, adp, &bios_vmode[i], level); 148342795Skato } 148442795Skato#endif 148542795Skato 148642795Skato return 0; 148742795Skato} 1488