summaryrefslogtreecommitdiff
path: root/usr/src/uts/sun/io/cgsix.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/sun/io/cgsix.c')
-rw-r--r--usr/src/uts/sun/io/cgsix.c2886
1 files changed, 0 insertions, 2886 deletions
diff --git a/usr/src/uts/sun/io/cgsix.c b/usr/src/uts/sun/io/cgsix.c
deleted file mode 100644
index 0d856fd298..0000000000
--- a/usr/src/uts/sun/io/cgsix.c
+++ /dev/null
@@ -1,2886 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-
-#pragma weak setintrenable
-/*
- * Cgsix theory of operation:
- *
- * Most cg6 operations are done by mapping the cg6 components into
- * user process memory. User processes that share mappings (typically
- * pixrect programs) must cooperate among themselves to prevent damaging
- * the state of the cg6. User processes may also acquire private
- * mappings (MAP_PRIVATE flag to mmap(2)), in which case the cg6 segment
- * driver will preserve device state for each mapping.
- *
- * Note that the segment driver may go away in the future.
- *
- * cg6_mmap interprets the device offset as follows:
- *
- * CG6_VBASE 0x70000000
- * CG6_VADDR_FBC 0x70000000 fbc mapping
- * CG6_VADDR_TEC 0x70001000 tec mapping
- * CG6_VADDR_CMAP 0x70002000 colormap dacs
- * CG6_VADDR_FHC 0x70004000 fhc mapping
- * CG6_VADDR_THC 0x70005000 thc mapping
- * CG6_VADDR_ROM 0x70006000 eprom mapping
- * CG6_VADDR_COLOR 0x70016000 framebuffer mapping
- * CG6_VADDR_DHC 0x78000000 dac hardware
- * CG6_VADDR_ALT 0x78002000 alternate registers (?)
- * CG6_VADDR_UART 0x78004000 uart, if any
- * CG6_VADDR_VRT 0x78006000 vertical retrace counter page
- *
- * The lengths of these mappings should be:
- *
- * CG6_CMAP_SZ 0x2000
- * CG6_FBCTEC_SZ 0x2000
- * CG6_FHCTHC_SZ 0x2000
- * CG6_ROM_SZ 0x10000
- * CG6_FB_SZ 0x100000
- * CG6_DHC_SZ 0x2000
- * CG6_ALT_SZ 0x2000
- *
- * Mappings to the fbc and tec registers may be MAP_PRIVATE, in which case
- * the segment driver keeps a per-context copy of the fbc and tec
- * registers in local memory. Only one context at a time may have valid
- * mappings. If a process tries to access the registers through an
- * invalid mapping, the segment driver in invoked to swap register state
- * and validate the mappings.
- *
- * In the case of the buggy LSC revision 2. chip, the framebuffer mapping
- * is also considered part of a context. This is to ensure that the
- * registers are idle before the framebuffer is touched.
- *
- * Mappings to FBC, TEC and framebuffer may be made seperately, in which
- * case the driver uses heuristics to bind seperate mappings into a single
- * context. These heuristics may break down if mappings are done in a
- * funny order or in a multi-threaded environment, so seperate mappings
- * are not recommended.
- *
- * Finally, processes have the option of mapping the "vertical retrace
- * page". This is a page in shared memory containing a 32-bit integer
- * that is incremented each time a vertical retrace interrupt occurs. It
- * is used so that programs may synchronize themselves with vertical
- * retrace.
- */
-
-/*
- * SBus accelerated 8 bit color frame buffer driver
- */
-
-#include <sys/debug.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/buf.h>
-#include <sys/errno.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-
-#include <sys/model.h>
-
-#include <sys/file.h>
-#include <sys/uio.h>
-#include <sys/ioctl.h>
-#include <sys/proc.h>
-#include <sys/user.h>
-#include <sys/sysmacros.h>
-#include <sys/mman.h>
-#include <sys/cred.h>
-#include <sys/open.h>
-#include <sys/stat.h>
-
-#include <sys/visual_io.h>
-#include <sys/fbio.h>
-
-#include <sys/cg6reg.h>
-#include <sys/kmem.h>
-#include <sys/cmn_err.h>
-#include <sys/vnode.h>
-
-#include <vm/page.h>
-#include <vm/as.h>
-#include <vm/hat.h>
-#include <vm/seg.h>
-
-#include <sys/pixrect.h>
-#include <sys/pr_impl_util.h>
-#include <sys/pr_planegroups.h>
-#include <sys/memvar.h>
-#include <sys/cg3var.h> /* for CG3_MMAP_OFFSET */
-#include <sys/cg6var.h>
-#include <sys/kstat.h>
-
-#include <sys/kmem.h>
-#include <sys/conf.h>
-#include <sys/ddi.h>
-#include <sys/devops.h>
-#include <sys/sunddi.h>
-#include <sys/ddi_impldefs.h>
-#include <sys/fs/snode.h>
-
-#include <sys/modctl.h>
-
-#include <sys/machsystm.h>
-
-#define KIOIP KSTAT_INTR_PTR(softc->intrstats)
-
-#define CG6DEBUG 0
-
-/* configuration options */
-#define CG6DELAY(c, n) \
-{ \
- register int N = n; \
- while (--N > 0) { \
- if (c) \
- break; \
- drv_usecwait(1); \
- } \
-}
-
-#if CG6DEBUG >= 2
-int cg6_debug = 0;
-
-#define DEBUGF(level, args) \
- { if (cg6_debug >= (level)) cmn_err args; }
-#define DUMP_SEGS(level, s, c) \
- { if (cg6_debug >= (level)) dump_segs(s, c); }
-#else
-#define DEBUGF(level, args) /* nothing */
-#define DUMP_SEGS(level, s, c) /* nothing */
-#endif
-
-#define getprop(devi, name, def) \
- ddi_getprop(DDI_DEV_T_ANY, (devi), \
- DDI_PROP_DONTPASS, (name), (def))
-
-/* config info */
-
-static int cg6_open(dev_t *, int, int, cred_t *);
-static int cg6_close(dev_t, int, int, cred_t *);
-static int cg6_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
-static int cg6_mmap(dev_t, off_t, int);
-static int cg6_devmap(dev_t, devmap_cookie_t, offset_t, size_t,
- size_t *, uint_t);
-static int cg6_segmap(dev_t, off_t,
- struct as *, caddr_t *, off_t, uint_t,
- uint_t, uint_t, cred_t *);
-
-static struct vis_identifier cg6_ident = { "SUNWcg6" };
-
-static struct cb_ops cg6_cb_ops = {
- cg6_open, /* open */
- cg6_close, /* close */
- nodev, /* strategy */
- nodev, /* print */
- nodev, /* dump */
- nodev, /* read */
- nodev, /* write */
- cg6_ioctl, /* ioctl */
- cg6_devmap, /* devmap */
- cg6_mmap, /* mmap */
- cg6_segmap, /* segmap */
- nochpoll, /* poll */
- ddi_prop_op, /* cb_prop_op */
- 0, /* streamtab */
- D_NEW|D_MP|D_DEVMAP|D_HOTPLUG, /* Driver compatibility flag */
- CB_REV, /* rev */
- nodev, /* int (*cb_aread)() */
- nodev /* int (*cb_awrite)() */
-};
-
-static int cg6_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
- void *arg, void **result);
-static int cg6_attach(dev_info_t *, ddi_attach_cmd_t);
-static int cg6_detach(dev_info_t *, ddi_detach_cmd_t);
-static int cg6_power(dev_info_t *, int, int);
-
-struct dev_ops cgsix_ops = {
- DEVO_REV, /* devo_rev, */
- 0, /* refcnt */
- cg6_info, /* info */
- nulldev, /* identify */
- nulldev, /* probe */
- cg6_attach, /* attach */
- cg6_detach, /* detach */
- nodev, /* reset */
- &cg6_cb_ops, /* driver operations */
- (struct bus_ops *)0, /* bus operations */
- cg6_power,
- ddi_quiesce_not_supported, /* devo_quiesce */
-};
-
-/*
- * This stucture is used to contain the driver
- * private mapping data (one for each requested
- * device mapping). A pointer to this data is
- * passed into each mapping callback routine.
- */
-struct cg6map_pvt {
- struct cg6_softc *softc;
- devmap_cookie_t dhp; /* handle of devmap object */
- uint_t type; /* mapping type */
- off_t offset; /* starting offset of this map */
- size_t len; /* length of this map */
- struct cg6_cntxt *context; /* associated context */
- struct cg6map_pvt *next; /* List of associated pvt's for */
- /* this context */
-};
-
-static struct ddi_device_acc_attr endian_attr = {
- DDI_DEVICE_ATTR_V0,
- DDI_NEVERSWAP_ACC,
- DDI_STRICTORDER_ACC
-};
-
-/* how much to map */
-#define CG6MAPSIZE MMAPSIZE(0)
-
-/* vertical retrace counter page */
-#ifndef CG6_VRT_SZ
-#define CG6_VRT_SZ 8192
-#endif
-
-/* boardrev bits */
-#define BRDRV_SETRES 0x01 /* board supports set resolution */
-#define BRDRV_TYPE 0x78 /* board type: */
-#define BRDRV_GX 0x00
-#define BRDRV_LSC 0x08
-#define BRDRV_DUPLO 0x10
-#define BRDRV_LEGOHR 0x18
-#define BRDRV_QAUDRO 0x20
-#define BRDRV_HIRES 0x80 /* hires dacs (junior vs. senior) */
-
-#define CG6_FBC_WAIT 500000 /* .5 seconds */
-
-/* enable/disable interrupt */
-#define TEC_EN_VBLANK_IRQ 0x20
-#define TEC_HCMISC_IRQBIT 0x10
-
-/* position value to use to disable HW cursor */
-#define CG6_CURSOR_OFFPOS ((uint_t)0xffe0ffe0)
-
-/*
- * Per-context info:
- * many registers in the tec and fbc do
- * not need to be saved/restored.
- */
-
-struct cg6_cntxt {
- struct cg6_cntxt *link; /* link to next (private) context if any */
- struct cg6map_pvt *pvt; /* List of associated pvt's for this context */
- pid_t pid; /* "owner" of this context */
- int flag;
-
- struct {
- uint_t mv;
- uint_t clip;
- uint_t vdc;
- uint_t data[64][2];
- } tec;
-
- struct {
- uint_t status;
- uint_t clipcheck;
- struct l_fbc_misc misc;
- uint_t x0, y0, x1, y1, x2, y2, x3, y3;
- uint_t rasteroffx, rasteroffy;
- uint_t autoincx, autoincy;
- uint_t clipminx, clipminy, clipmaxx, clipmaxy;
- uint_t fcolor, bcolor;
- struct l_fbc_rasterop rasterop;
- uint_t planemask, pixelmask;
- union l_fbc_pattalign pattalign;
- uint_t pattern0, pattern1, pattern2, pattern3, pattern4, pattern5,
- pattern6, pattern7;
- } fbc;
-};
-
-/* per-unit data */
-struct cg6_softc {
- Pixrect pr; /* kernel pixrect */
- struct mprp_data prd; /* pixrect private data */
-#define _w pr.pr_size.x
-#define _h pr.pr_size.y
-#define _fb prd.mpr.md_image
-#define _linebytes prd.mpr.md_linebytes
- size_t size; /* total size of frame buffer */
- size_t ndvramsz; /* size of non-display Video RAM */
- caddr_t ndvram; /* Storage for nd-VRAM, while suspended */
- size_t dummysize; /* total size of overlay plane */
- kmutex_t interlock; /* interrupt locking */
- off_t addr_rom; /* varies between p4 & sbus */
- caddr_t fbctec; /* fbc&tec kernel map addr. */
- caddr_t cmap; /* colormap kernel map addr. */
- caddr_t fhcthc; /* fhc&thc kernel map addr. */
- caddr_t rom; /* rom kernel map addr. */
- caddr_t dhc; /* dac hardware */
- caddr_t alt; /* alt registers */
- caddr_t uart; /* uart registers */
- pfn_t fbpfnum; /* pfn of fb for mmap() */
-
- struct softcur {
- short enable; /* cursor enable */
- short pad1;
- struct fbcurpos pos; /* cursor position */
- struct fbcurpos hot; /* cursor hot spot */
- struct fbcurpos size; /* cursor bitmap size */
- uint32_t image[32]; /* cursor image bitmap */
- uint32_t mask[32]; /* cursor mask bitmap */
- } cur;
-
- union { /* shadow overlay color map */
- uint32_t omap_int[2]; /* cheating here to save space */
- uchar_t omap_char[3][2];
- } omap_image;
-#define omap_rgb omap_image.omap_char[0]
- ushort_t omap_update; /* overlay colormap update flag */
- uint32_t cmap_index; /* colormap update index */
- uint32_t cmap_count; /* colormap update count */
- union { /* shadow color map */
- uint32_t cmap_int[CG6_CMAP_ENTRIES * 3 / sizeof (uint32_t)];
- uchar_t cmap_char[3][CG6_CMAP_ENTRIES];
- } cmap_image;
-#define cmap_rgb cmap_image.cmap_char[0]
-
-#define CG6VRTIOCTL 1 /* FBIOVERTICAL in effect */
-#define CG6VRTCTR 2 /* OWGX vertical retrace counter */
- size_t fbmappable; /* bytes mappable */
- int *vrtpage; /* pointer to VRT page */
- ddi_umem_cookie_t vrtcookie; /* pointer to VRT allocation */
- int vrtmaps; /* number of VRT page maps */
- int vrtflag; /* vrt interrupt flag */
- struct cg6_info cg6info; /* info about this cg6 */
- struct mon_info moninfo; /* info about this monitor */
- struct cg6_cntxt *curctx; /* context switching */
- struct cg6_cntxt shared_ctx; /* shared context */
- struct cg6_cntxt *pvt_ctx; /* list of non-shared contexts */
- int chiprev; /* fbc chip revision # */
- int emulation; /* emulation type, normally cgsix */
- dev_info_t *devi; /* back pointer */
- ddi_iblock_cookie_t iblock_cookie; /* block interrupts */
- kmutex_t mutex; /* mutex locking */
- kcondvar_t vrtsleep; /* for waiting on vertical retrace */
- int mapped_by_prom; /* $#!@ SVr4 */
- off_t mapped_by_driver;
- int waiting;
- int cg6_suspended; /* true if driver is suspended */
- int vidon; /* video enable state */
- int intr_flag;
- kstat_t *intrstats; /* interrupt statistics */
-};
-
-static int cg6map_map(devmap_cookie_t, dev_t, uint_t, offset_t, size_t,
- void **);
-static int cg6map_contextmgt(devmap_cookie_t, void *, offset_t, size_t,
- uint_t, uint_t);
-static int cg6map_dup(devmap_cookie_t, void *, devmap_cookie_t, void **);
-static void cg6map_unmap(devmap_cookie_t, void *, offset_t, size_t,
- devmap_cookie_t, void **, devmap_cookie_t, void **);
-static int cg6map_access(devmap_cookie_t, void *, offset_t, size_t,
- uint_t, uint_t);
-static
-struct devmap_callback_ctl cg6map_ops = {
- DEVMAP_OPS_REV, /* devmap_ops version number */
- cg6map_map, /* devmap_ops map routine */
- cg6map_access, /* devmap_ops access routine */
- cg6map_dup, /* devmap_ops dup routine */
- cg6map_unmap, /* devmap_ops unmap routine */
-};
-
-static size_t pagesize;
-static void *cg6_softc_head;
-clock_t cg6_ctxholdval = 1;
-
-/* default structure for FBIOGATTR ioctl */
-static struct fbgattr cg6_attr = {
-/* real_type owner */
- FBTYPE_SUNFAST_COLOR, 0,
-/* fbtype: type h w depth cms size */
- {FBTYPE_SUNFAST_COLOR, 0, 0, CG6_DEPTH, CG6_CMAP_ENTRIES, 0},
-/* fbsattr: flags emu_type dev_specific */
- {0, FBTYPE_SUN4COLOR, {0}},
-/* emu_types */
- {FBTYPE_SUNFAST_COLOR, FBTYPE_SUN3COLOR, FBTYPE_SUN4COLOR, -1}
-};
-
-
-/*
- * handy macros
- */
-#define getsoftc(instance) \
- ((struct cg6_softc *)ddi_get_soft_state(cg6_softc_head, (instance)))
-
-#define btob(n) ptob(btopr(n)) /* TODO, change this? */
-
-
-
-/* convert softc to data pointers */
-
-#define S_FBC(softc) ((struct fbc *)(softc)->fbctec)
-#define S_TEC(softc) ((struct tec *)((softc)->fbctec + CG6_TEC_POFF))
-#define S_FHC(softc) ((uint_t *)(softc)->fhcthc)
-#define S_THC(softc) ((struct thc *)((softc)->fhcthc + CG6_TEC_POFF))
-#define S_CMAP(softc) ((struct cg6_cmap *)(softc)->cmap)
-
-#define cg6_set_video(softc, on) thc_set_video(S_THC(softc), (on))
-#define cg6_get_video(softc) thc_get_video(S_THC(softc))
-
-#define cg6_int_enable(softc) \
- {\
- thc_int_enable(S_THC(softc)); }
-
-#define cg6_int_disable_intr(softc) \
- {\
- thc_int_disable(S_THC(softc)); }
-
-#define cg6_int_disable(softc) \
- {\
- mutex_enter(&(softc)->interlock); \
- softc->intr_flag = 1; \
- cg6_int_disable_intr(softc); \
- mutex_exit(&(softc)->interlock); }
-
-#define cg6_int_pending(softc) thc_int_pending(S_THC(softc))
-
-/* check if color map update is pending */
-#define cg6_update_pending(softc) \
- ((softc)->cmap_count || (softc)->omap_update)
-
-/*
- * forward references
- */
-static uint_t cg6_intr(caddr_t);
-static void cg6_reset_cmap(volatile uchar_t *, uint_t);
-static void cg6_update_cmap(struct cg6_softc *, uint_t, uint_t);
-static void cg6_cmap_bcopy(uchar_t *, uchar_t *, uint_t);
-static void cg6_restore_prom_cmap(struct cg6_softc *, volatile uchar_t *,
- uint_t);
-
-static void cg6_setcurpos(struct cg6_softc *);
-static void cg6_setcurshape(struct cg6_softc *);
-static void cg6_reset(struct cg6_softc *);
-static int cg6_cntxsave(volatile struct fbc *, volatile struct tec *,
- struct cg6_cntxt *);
-static int cg6_cntxrestore(volatile struct fbc *, volatile struct tec *,
- struct cg6_cntxt *);
-static struct cg6_cntxt *ctx_map_insert(struct cg6_softc *, int);
-static pid_t getpid(void);
-
-/* Loadable Driver stuff */
-
-static struct modldrv modldrv = {
- &mod_driverops, /* Type of module. This one is a driver */
- "cgsix driver", /* Name of the module. */
- &cgsix_ops, /* driver ops */
-};
-
-static struct modlinkage modlinkage = {
- MODREV_1, (void *) &modldrv, NULL
-};
-
-int
-_init(void)
-{
- register int e;
-
- if ((e = ddi_soft_state_init(&cg6_softc_head,
- sizeof (struct cg6_softc), 1)) != 0) {
- DEBUGF(1, (CE_CONT, "done\n"));
- return (e);
- }
-
- e = mod_install(&modlinkage);
-
- if (e) {
- ddi_soft_state_fini(&cg6_softc_head);
- DEBUGF(1, (CE_CONT, "done\n"));
- }
- DEBUGF(1, (CE_CONT, "cgsix: _init done rtn=%d\n", e));
- return (e);
-}
-
-int
-_fini(void)
-{
- register int e;
-
- DEBUGF(1, (CE_CONT, "cgsix: _fini, mem used=%d\n", total_memory));
-
- if ((e = mod_remove(&modlinkage)) != 0)
- return (e);
-
- ddi_soft_state_fini(&cg6_softc_head);
-
- return (0);
-}
-
-int
-_info(struct modinfo *modinfop)
-{
- return (mod_info(&modlinkage, modinfop));
-}
-
-static int
-cg6_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
-{
- register struct cg6_softc *softc;
- caddr_t reg;
- int w, h, bytes;
- char *tmp;
- char name[16];
- int unit = ddi_get_instance(devi);
- int proplen;
- caddr_t fb_ndvram;
-
- DEBUGF(1, (CE_CONT, "cg6_attach unit=%d cmd=%d\n", unit, (int)cmd));
-
- switch (cmd) {
- case DDI_ATTACH:
- break;
-
- case DDI_RESUME:
- if ((softc = ddi_get_driver_private(devi)) == NULL)
- return (DDI_FAILURE);
- if (!softc->cg6_suspended)
- return (DDI_SUCCESS);
- mutex_enter(&softc->mutex);
- cg6_reset(softc);
- if (softc->curctx) {
- /* Restore the video state */
- cg6_set_video(softc, softc->vidon);
-
- /* Restore non display RAM */
- if (ddi_map_regs(devi, 0, (caddr_t *)&fb_ndvram,
- CG6_ADDR_COLOR + softc->_w * softc->_h,
- softc->ndvramsz) == -1) {
- mutex_exit(&softc->mutex);
- return (DDI_FAILURE);
- }
- bcopy(softc->ndvram, fb_ndvram, softc->ndvramsz);
- ddi_unmap_regs(devi, 0, (caddr_t *)&fb_ndvram,
- CG6_ADDR_COLOR + softc->_w * softc->_h,
- softc->ndvramsz);
- kmem_free(softc->ndvram, softc->ndvramsz);
-
- /* Restore other frame buffer state */
- (void) cg6_cntxrestore(S_FBC(softc), S_TEC(softc),
- softc->curctx);
- cg6_setcurpos(softc);
- cg6_setcurshape(softc);
- cg6_update_cmap(softc, (uint_t)_ZERO_,
- CG6_CMAP_ENTRIES);
- cg6_int_enable(softc); /* Schedule the update */
- }
- softc->cg6_suspended = 0;
- mutex_exit(&softc->mutex);
- return (DDI_SUCCESS);
-
- default:
- return (DDI_FAILURE);
- }
-
- DEBUGF(1, (CE_CONT, "cg6_attach unit=%d\n", unit));
-
- pagesize = (size_t)ddi_ptob(devi, 1);
-
- /* Allocate softc struct */
- if (ddi_soft_state_zalloc(cg6_softc_head, unit) != 0) {
- return (DDI_FAILURE);
- }
-
- softc = getsoftc(unit);
-
- /* link it in */
- softc->devi = devi;
- DEBUGF(1, (CE_CONT, "cg6_attach devi=0x%x unit=%d\n", devi, unit));
- ddi_set_driver_private(devi, softc);
-
- /* Grab properties from PROM */
- /* TODO don't really want default w, h */
- if (ddi_prop_op(DDI_DEV_T_ANY, devi, PROP_LEN_AND_VAL_ALLOC,
- DDI_PROP_DONTPASS, "emulation", (caddr_t)&tmp, &proplen) ==
- DDI_PROP_SUCCESS) {
- if (strcmp(tmp, "cgthree+") == 0)
- softc->emulation = FBTYPE_SUN3COLOR;
- else if (strcmp(tmp, "cgfour+") == 0)
- softc->emulation = FBTYPE_SUN4COLOR;
- else if (strcmp(tmp, "bwtwo+") == 0)
- softc->emulation = FBTYPE_SUN2BW;
- else
- softc->emulation = FBTYPE_SUNFAST_COLOR;
- kmem_free(tmp, proplen);
- } else
- softc->emulation = FBTYPE_SUNFAST_COLOR;
-
- softc->_w = w = getprop(devi, "width", 1152);
- softc->_h = h = getprop(devi, "height", 900);
- bytes = getprop(devi, "linebytes", mpr_linebytes(w, 8));
-
- softc->_linebytes = bytes;
-
- /* Compute size of color frame buffer */
- bytes = btob(bytes * h);
- softc->size = (size_t)ddi_ptob(devi, ddi_btopr(devi, bytes));
-
- softc->cg6info.vmsize = getprop(devi, "vmsize", 1);
- if (softc->cg6info.vmsize > 1) {
- softc->size = (size_t)ddi_ptob(devi,
- ddi_btopr(devi, 8 * 1024 * 1024));
- softc->fbmappable = 8 * 1024 * 1024;
- } else
- softc->fbmappable = 1024 * 1024;
-
- /* Compute size of dummy overlay/enable planes */
- softc->dummysize = btob(mpr_linebytes(w, 1) * h) * 2;
-
- /*
- * only use address property if we are console fb NOTE: if the prom has
- * already mapped the fb *and* it has mapped all of fbmappable, then we
- * don't need a new mapping
- */
- if (reg = (caddr_t)(uintptr_t)getprop(devi, "address", 0)) {
- softc->_fb = (MPR_T *) reg;
- softc->mapped_by_prom = 1;
- if (ddi_ptob(devi, ddi_btopr(devi, w * h)) <=
- getprop(devi, "fbmapped", w * h))
- bytes = 0;
- DEBUGF(2, (CE_CONT, "cg6 mapped by PROM\n"));
- }
-
- softc->cg6info.line_bytes = softc->_linebytes;
- softc->cg6info.accessible_width = getprop(devi, "awidth", 1152);
- softc->cg6info.accessible_height = (uint_t)
- (softc->cg6info.vmsize * 1024 * 1024) /
- softc->cg6info.accessible_width;
- softc->cg6info.hdb_capable = getprop(devi, "dblbuf", 0);
- softc->cg6info.boardrev = getprop(devi, "boardrev", 0);
- softc->vrtpage = NULL;
- softc->vrtmaps = 0;
- softc->vrtflag = 0;
-
-#ifdef DEBUG
- softc->cg6info.pad1 = CG6_VADDR_COLOR + CG6_FB_SZ;
-#endif
-
- /*
- * get monitor attributes
- */
- softc->moninfo.mon_type = getprop(devi, "montype", 0);
- softc->moninfo.pixfreq = getprop(devi, "pixfreq", 929405);
- softc->moninfo.hfreq = getprop(devi, "hfreq", 61795);
- softc->moninfo.vfreq = getprop(devi, "vfreq", 66);
- softc->moninfo.hfporch = getprop(devi, "hfporch", 32);
- softc->moninfo.vfporch = getprop(devi, "vfporch", 2);
- softc->moninfo.hbporch = getprop(devi, "hbporch", 192);
- softc->moninfo.vbporch = getprop(devi, "vbporch", 31);
- softc->moninfo.hsync = getprop(devi, "hsync", 128);
- softc->moninfo.vsync = getprop(devi, "vsync", 4);
-
- /*
- * map in the registers. Map fbc&tec together. Likewise for fhc&thc.
- */
- softc->addr_rom = CG6_ADDR_ROM_SBUS;
-
- if (ddi_map_regs(devi, 0, &softc->fbctec, CG6_ADDR_FBC,
- (off_t)CG6_FBCTEC_SZ) != 0) {
- (void) cg6_detach(devi, DDI_DETACH);
- return (DDI_FAILURE);
- }
- if (ddi_map_regs(devi, 0, &softc->cmap, CG6_ADDR_CMAP,
- (off_t)CG6_CMAP_SZ) != 0) {
- (void) cg6_detach(devi, DDI_DETACH);
- return (DDI_FAILURE);
- }
- if (ddi_map_regs(devi, 0, &softc->fhcthc, CG6_ADDR_FHC,
- (off_t)CG6_FHCTHC_SZ) != 0) {
- (void) cg6_detach(devi, DDI_DETACH);
- return (DDI_FAILURE);
- }
-
- softc->chiprev =
- *S_FHC(softc) >> FHC_CONFIG_REV_SHIFT & FHC_CONFIG_REV_MASK;
-
- cg6_reset(softc);
-
- if (ddi_get_iblock_cookie(devi, 0, &softc->iblock_cookie)
- != DDI_SUCCESS) {
- DEBUGF(2, (CE_CONT,
- "cg6_attach%d ddi_get_iblock_cookie failed\n", unit));
- (void) cg6_detach(devi, DDI_DETACH);
- return (DDI_FAILURE);
- }
-
- mutex_init(&softc->interlock, NULL, MUTEX_DRIVER, softc->iblock_cookie);
- mutex_init(&softc->mutex, NULL, MUTEX_DRIVER, softc->iblock_cookie);
- cv_init(&softc->vrtsleep, NULL, CV_DRIVER, NULL);
-
- if (ddi_add_intr(devi, 0, &softc->iblock_cookie, 0,
- cg6_intr, (caddr_t)softc) != DDI_SUCCESS) {
- DEBUGF(2, (CE_CONT,
- "cg6_attach%d add_intr failed\n", unit));
- (void) cg6_detach(devi, DDI_DETACH);
- return (DDI_FAILURE);
- }
-
- /*
- * Initialize hardware colormap and software colormap images. It might
- * make sense to read the hardware colormap here.
- */
- cg6_reset_cmap(softc->cmap_rgb, CG6_CMAP_ENTRIES);
- cg6_reset_cmap(softc->omap_rgb, 2);
- cg6_update_cmap(softc, (uint_t)_ZERO_, CG6_CMAP_ENTRIES);
- cg6_update_cmap(softc, (uint_t)_ZERO_, (uint_t)_ZERO_);
-
- DEBUGF(2, (CE_CONT,
- "cg6_attach%d just before create_minor node\n", unit));
- (void) sprintf(name, "cgsix%d", unit);
- if (ddi_create_minor_node(devi, name, S_IFCHR,
- unit, DDI_NT_DISPLAY, NULL) == DDI_FAILURE) {
- ddi_remove_minor_node(devi, NULL);
- DEBUGF(2, (CE_CONT,
- "cg6_attach%d create_minor node failed\n", unit));
- return (DDI_FAILURE);
- }
- ddi_report_dev(devi);
-
- if (softc->chiprev == 0)
- cmn_err(CE_CONT, "?Revision 0 FBC\n");
-
- cmn_err(CE_CONT,
- "?cgsix%d: screen %dx%d, %s buffered, %dM mappable, rev %d\n",
- unit, w, h, softc->cg6info.hdb_capable ? "double" : "single",
- softc->cg6info.vmsize, softc->chiprev);
-
- softc->pvt_ctx = NULL;
-
- /*
- * Initialize power management bookkeeping; components are created idle
- */
- if (pm_create_components(devi, 2) == DDI_SUCCESS) {
- (void) pm_busy_component(devi, 0);
- pm_set_normal_power(devi, 0, 1);
- pm_set_normal_power(devi, 1, 1);
-
- (void) sprintf(name, "cgsixc%d", unit);
- softc->intrstats = kstat_create("cgsix", unit, name,
- "controller", KSTAT_TYPE_INTR,
- 1, KSTAT_FLAG_PERSISTENT);
- if (softc->intrstats) {
- kstat_install(softc->intrstats);
- }
-
- return (DDI_SUCCESS);
- } else {
- return (DDI_FAILURE);
- }
-}
-
-static int
-cg6_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
-{
- int instance = ddi_get_instance(devi);
- register struct cg6_softc *softc = getsoftc(instance);
- caddr_t fb_ndvram;
-
- DEBUGF(1, (CE_CONT, "cg6_detach softc=%x, devi=0x%x\n", softc, devi));
-
- switch (cmd) {
- case DDI_DETACH:
- break;
-
- case DDI_SUSPEND:
- if (softc == NULL)
- return (DDI_FAILURE);
- if (softc->cg6_suspended)
- return (DDI_FAILURE);
-
- mutex_enter(&softc->mutex);
-
- if (softc->curctx) {
- struct fbc *fbc0 = S_FBC(softc);
-
- /* Save the video state */
- softc->vidon = cg6_get_video(softc);
-
- /* Save non display RAM */
- softc->ndvramsz = (softc->cg6info.vmsize * 1024 * 1024)
- - (softc->_w * softc->_h);
- if ((softc->ndvram = kmem_alloc(softc->ndvramsz,
- KM_NOSLEEP)) == NULL) {
- mutex_exit(&softc->mutex);
- return (DDI_FAILURE);
- }
-
- /*
- * If FBC is busy, wait for maximum of 2 seconds for it
- * to be idle
- */
- CG6DELAY(!(fbc0->l_fbc_status & L_FBC_BUSY),
- 4*CG6_FBC_WAIT);
-
- if (fbc0->l_fbc_status & L_FBC_BUSY) {
-
- /*
- * if still busy, try another 2 seconds before
- * giving up
- */
- CG6DELAY(!(fbc0->l_fbc_status & L_FBC_BUSY),
- 4*CG6_FBC_WAIT);
- if (fbc0->l_fbc_status & L_FBC_BUSY)
- cmn_err(CE_WARN, "cg6_detach: FBC still busy");
- }
-
- if (ddi_map_regs(devi, 0, &fb_ndvram, CG6_ADDR_COLOR +
- softc->_w * softc->_h, softc->ndvramsz) == -1) {
- kmem_free(softc->ndvram, softc->ndvramsz);
- mutex_exit(&softc->mutex);
- return (DDI_FAILURE);
- }
- bcopy(fb_ndvram, softc->ndvram, softc->ndvramsz);
- ddi_unmap_regs(devi, 0, &fb_ndvram, CG6_ADDR_COLOR +
- softc->_w * softc->_h, softc->ndvramsz);
-
- /* Save other frame buffer state */
- (void) cg6_cntxsave(S_FBC(softc), S_TEC(softc),
- softc->curctx);
- }
- softc->cg6_suspended = 1;
- mutex_exit(&softc->mutex);
- return (DDI_SUCCESS);
-
- default:
- return (DDI_FAILURE);
- }
-
- /* shut off video if not console */
-
- if (!softc->mapped_by_prom)
- cg6_set_video(softc, 0);
-
- mutex_enter(&softc->mutex);
- cg6_int_disable(softc);
- mutex_exit(&softc->mutex);
-
- ddi_remove_intr(devi, 0, softc->iblock_cookie);
-
- if (softc->fbctec)
- ddi_unmap_regs(devi, 0,
- &softc->fbctec, CG6_ADDR_FBC, CG6_FBCTEC_SZ);
- if (softc->cmap)
- ddi_unmap_regs(devi, 0, &softc->cmap, CG6_ADDR_CMAP,
- CG6_CMAP_SZ);
- if (softc->fhcthc)
- ddi_unmap_regs(devi, 0,
- &softc->fhcthc, CG6_ADDR_FHC, CG6_FHCTHC_SZ);
- if (softc->intrstats) {
- kstat_delete(softc->intrstats);
- }
- softc->intrstats = NULL;
-
- if (softc->vrtpage != NULL)
- ddi_umem_free(softc->vrtcookie);
-
- mutex_destroy(&softc->mutex);
-
- cv_destroy(&softc->vrtsleep);
-
- ASSERT(softc->curctx == NULL);
-
- /* free softc struct */
- (void) ddi_soft_state_free(cg6_softc_head, instance);
- pm_destroy_components(devi);
-
- return (DDI_SUCCESS);
-}
-
-static int
-cg6_power(dev_info_t *dip, int cmpt, int level)
-{
- struct cg6_softc *softc;
-
- /*
- * Framebuffer is represented by cmpt 0. In cg6, no power
- * management is done on the framebuffer itself. Only the
- * monitor (cmpt 1) is being power managed.
- */
- if (cmpt == 0)
- return (DDI_SUCCESS);
-
- if (cmpt != 1 || 0 > level || level > 1 ||
- (softc = ddi_get_driver_private(dip)) == NULL)
- return (DDI_FAILURE);
-
- if (level) {
- /* Turn on sync and video. */
- mutex_enter(&softc->mutex);
- S_THC(softc)->l_thc_hcmisc |= THC_HCMISC_RESET;
- drv_usecwait(500);
- S_THC(softc)->l_thc_hcmisc |=
- (THC_HCMISC_SYNCEN | THC_HCMISC_VIDEO);
- S_THC(softc)->l_thc_hcmisc &= ~THC_HCMISC_RESET;
- cg6_update_cmap(softc, (uint_t)_ZERO_, CG6_CMAP_ENTRIES);
- cg6_int_enable(softc);
- mutex_exit(&softc->mutex);
- } else {
- /* Turn off sync and video. */
- mutex_enter(&softc->mutex);
- S_THC(softc)->l_thc_hcmisc |= THC_HCMISC_RESET;
- drv_usecwait(500);
- S_THC(softc)->l_thc_hcmisc &=
- ~(THC_HCMISC_VIDEO | THC_HCMISC_SYNCEN);
- S_THC(softc)->l_thc_hcmisc &= ~THC_HCMISC_RESET;
- mutex_exit(&softc->mutex);
- }
- return (DDI_SUCCESS);
-}
-
-/* ARGSUSED */
-static int
-cg6_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
-{
- int error = DDI_SUCCESS;
- minor_t instance;
- struct cg6_softc *softc;
-
- instance = getminor((dev_t)arg);
-
- switch (infocmd) {
- case DDI_INFO_DEVT2DEVINFO:
- if ((softc = getsoftc(instance)) == NULL) {
- error = DDI_FAILURE;
- } else {
- *result = (void *) softc->devi;
- error = DDI_SUCCESS;
- }
- break;
- case DDI_INFO_DEVT2INSTANCE:
- *result = (void *) (uintptr_t)instance;
- error = DDI_SUCCESS;
- break;
- default:
- error = DDI_FAILURE;
- }
- return (error);
-}
-
-/*ARGSUSED*/
-static int
-cg6_open(dev_t *devp, int flag, int otyp, cred_t *cred)
-{
- int unit = getminor(*devp);
- struct cg6_softc *softc = getsoftc(unit);
- int error = 0;
-
- DEBUGF(2, (CE_CONT, "cg6_open(%d), mem used=%d\n", unit, total_memory));
-
- /*
- * is this gorp necessary?
- */
- if (otyp != OTYP_CHR) {
- error = EINVAL;
- } else
- if (softc == NULL) {
- error = ENXIO;
- }
-
- return (error);
-}
-
-/*ARGSUSED*/
-static
-int
-cg6_close(dev_t dev, int flag, int otyp, cred_t *cred)
-{
- int unit = getminor(dev);
- struct cg6_softc *softc = getsoftc(unit);
- int error = 0;
-
- DEBUGF(2, (CE_CONT, "cg6_close(%d, %d, %d), mem used=%d\n",
- unit, flag, otyp, total_memory));
-
- if (otyp != OTYP_CHR) {
- error = EINVAL;
- } else if (softc == NULL) {
- error = ENXIO;
- } else {
- mutex_enter(&softc->mutex);
- cg6_reset_cmap(softc->cmap_rgb, CG6_CMAP_ENTRIES);
- cg6_restore_prom_cmap(softc, softc->cmap_rgb, CG6_CMAP_ENTRIES);
- softc->cur.enable = 0;
- softc->curctx = NULL;
- cg6_reset(softc);
- mutex_exit(&softc->mutex);
- }
-
- return (error);
-}
-
-/*ARGSUSED*/
-static int
-cg6_mmap(dev_t dev, off_t off, int prot)
-{
- struct cg6_softc *softc = getsoftc(getminor(dev));
- ssize_t diff;
- caddr_t page;
- intptr_t rval = 0;
-
- DEBUGF(off ? 5 : 1, (CE_CONT, "cg6_mmap(%d, 0x%x)\n",
- getminor(dev), (uint_t)off));
-
- if ((diff = off - CG6_VADDR_COLOR) >= 0 && diff < softc->fbmappable)
- rval = softc->fbpfnum + diff / pagesize;
- else if ((diff = off - CG6_VADDR_FBC) >= 0 && diff < CG6_FBCTEC_SZ)
- page = softc->fbctec + diff;
- else if ((diff = off - CG6_VADDR_CMAP) >= 0 && diff < CG6_CMAP_SZ)
- page = softc->cmap + diff;
- else if ((diff = off - CG6_VADDR_FHC) >= 0 && diff < CG6_FHCTHC_SZ)
- page = softc->fhcthc + diff;
- else if ((diff = off - CG6_VADDR_ROM) >= 0 && diff < CG6_ROM_SZ)
- page = softc->rom + diff;
- else if ((diff = off - CG6_VADDR_DHC) >= 0 && diff < CG6_DHC_SZ)
- page = softc->dhc + diff;
- else if ((diff = off - CG6_VADDR_ALT) >= 0 && diff < CG6_ALT_SZ)
- page = softc->alt + diff;
- else if ((diff = off - CG6_VADDR_VRT) >= 0 && diff < CG6_VRT_SZ)
- page = softc->vrtpage ?
- (caddr_t)softc->vrtpage + diff : (caddr_t)-1;
- else if ((diff = off - CG3_MMAP_OFFSET) >= 0 &&
- diff < softc->fbmappable)
- rval = softc->fbpfnum + diff / pagesize;
- else if (off < CG6_VBASE) {
-
- /*
- * getting more and more complicated; what we return depends on what
- * we're emulating
- */
-
- if (softc->emulation == FBTYPE_SUN3COLOR) {
- if (off >= 0 && off < softc->fbmappable)
- rval = softc->fbpfnum + diff / pagesize;
- else
- page = (caddr_t)-1;
- } else { /* softc->emulation == FBTYPE_SUN4COLOR */
- if (off >= 0 && off < softc->dummysize)
- page = softc->rom;
- else if ((diff = off - softc->dummysize) < softc->fbmappable)
- rval = softc->fbpfnum + diff / pagesize;
- }
- /* TODO: bw2? */
- } else
- page = (caddr_t)-1;
-
- if (rval == 0)
- if (page != (caddr_t)-1)
- rval = hat_getkpfnum(page);
- else
- rval = -1;
-
- DEBUGF(5, (CE_CONT, "cg6_mmap returning 0x%x\n", rval));
-
- return ((int)rval); /* XXX64 */
-}
-
-/*ARGSUSED*/
-static int
-cg6_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *cred, int *rval)
-{
- struct cg6_softc *softc = getsoftc(getminor(dev));
- int cursor_cmap;
- int i;
-
- uchar_t *iobuf_cmap_red;
- uchar_t *iobuf_cmap_green;
- uchar_t *iobuf_cmap_blue;
- uchar_t *stack_cmap;
-
- STRUCT_DECL(fbcmap, fbcmap);
- STRUCT_DECL(fbcursor, fbcursor);
-
- uint_t index;
- uint_t count;
- uchar_t *map;
- uint_t entries;
-
- DEBUGF(3, (CE_CONT, "cg6_ioctl(%d, 0x%x)\n", getminor(dev), cmd));
-
- /* default to updating normal colormap */
- cursor_cmap = 0;
-
-
- switch (cmd) {
-
- case VIS_GETIDENTIFIER:
-
- if (ddi_copyout((caddr_t)&cg6_ident,
- (caddr_t)data,
- sizeof (struct vis_identifier),
- mode))
- return (EFAULT);
- break;
-
- case FBIOPUTCMAP:
- case FBIOGETCMAP:
-
-
- cmap_ioctl:
-
- if (cursor_cmap == 0) {
- STRUCT_INIT(fbcmap, mode);
- if (ddi_copyin((caddr_t)data,
- STRUCT_BUF(fbcmap), STRUCT_SIZE(fbcmap), mode))
- return (EFAULT);
- }
- index = STRUCT_FGET(fbcmap, index);
- count = STRUCT_FGET(fbcmap, count);
-
- if (count == 0) {
- return (0);
- }
- if (cursor_cmap == 0) {
- switch (PIX_ATTRGROUP(index)) {
-
- case 0:
- case PIXPG_8BIT_COLOR:
- map = softc->cmap_rgb;
- entries = CG6_CMAP_ENTRIES;
- break;
- default:
- return (EINVAL);
- }
- } else {
- map = softc->omap_rgb;
- entries = 2;
- }
-
- if ((index &= PIX_ALL_PLANES) >= entries ||
- index + count > entries) {
- return (EINVAL);
- }
- /*
- * Allocate memory for color map RGB entries.
- */
- stack_cmap = kmem_alloc((CG6_CMAP_ENTRIES * 3), KM_SLEEP);
-
- iobuf_cmap_red = stack_cmap;
- iobuf_cmap_green = stack_cmap + CG6_CMAP_ENTRIES;
- iobuf_cmap_blue = stack_cmap + (CG6_CMAP_ENTRIES * 2);
-
- if (cmd == FBIOPUTCMAP) {
- int error;
-
- DEBUGF(3, (CE_CONT, "FBIOPUTCMAP\n"));
-
- if (error = ddi_copyin(
- STRUCT_FGETP(fbcmap, red),
- iobuf_cmap_red, count, mode)) {
- kmem_free(stack_cmap, (CG6_CMAP_ENTRIES * 3));
- return (error);
- }
-
- if (error = ddi_copyin(
- STRUCT_FGETP(fbcmap, green),
- iobuf_cmap_green, count, mode)) {
- kmem_free(stack_cmap, (CG6_CMAP_ENTRIES * 3));
- return (error);
- }
- if (error = ddi_copyin(
- STRUCT_FGETP(fbcmap, blue),
- iobuf_cmap_blue, count, mode)) {
- kmem_free(stack_cmap, (CG6_CMAP_ENTRIES * 3));
- return (error);
- }
-
- mutex_enter(&softc->mutex);
- map += index * 3;
- if (cg6_update_pending(softc))
- cg6_int_disable(softc);
-
- /*
- * Copy color map entries from stack to the color map
- * table in the softc area.
- */
-
- cg6_cmap_bcopy(iobuf_cmap_red, map++, count);
- cg6_cmap_bcopy(iobuf_cmap_green, map++, count);
- cg6_cmap_bcopy(iobuf_cmap_blue, map, count);
-
- /* cursor colormap update */
- if (entries < CG6_CMAP_ENTRIES)
- count = 0;
- cg6_update_cmap(softc, index, count);
- cg6_int_enable(softc);
- mutex_exit(&softc->mutex);
-
- } else {
- /* FBIOGETCMAP */
- DEBUGF(3, (CE_CONT, "FBIOGETCMAP\n"));
-
- mutex_enter(&softc->mutex);
- map += index * 3;
-
- /*
- * Copy color map entries from soft area to
- * local storage and prepare for a copyout
- */
-
- cg6_cmap_bcopy(iobuf_cmap_red, map++, -count);
- cg6_cmap_bcopy(iobuf_cmap_green, map++, -count);
- cg6_cmap_bcopy(iobuf_cmap_blue, map, -count);
-
- mutex_exit(&softc->mutex);
-
- if (ddi_copyout(iobuf_cmap_red,
- STRUCT_FGETP(fbcmap, red), count,
- mode)) {
- kmem_free(stack_cmap, (CG6_CMAP_ENTRIES * 3));
- return (EFAULT);
- }
- if (ddi_copyout(iobuf_cmap_green,
- STRUCT_FGETP(fbcmap, green), count,
- mode)) {
- kmem_free(stack_cmap, (CG6_CMAP_ENTRIES * 3));
- return (EFAULT);
- }
- if (ddi_copyout(iobuf_cmap_blue,
- STRUCT_FGETP(fbcmap, blue), count,
- mode)) {
- kmem_free(stack_cmap, (CG6_CMAP_ENTRIES * 3));
- return (EFAULT);
- }
- }
- kmem_free(stack_cmap, (CG6_CMAP_ENTRIES * 3));
- break;
-
- case FBIOSATTR: {
- struct fbsattr attr;
-
- if (ddi_copyin((caddr_t)data,
- (caddr_t)&attr,
- sizeof (attr),
- mode))
- return (EFAULT);
- DEBUGF(3, (CE_CONT, "FBIOSATTR, type=%d\n", attr.emu_type));
- if (attr.emu_type != -1)
- switch (attr.emu_type) {
-
- case FBTYPE_SUN3COLOR:
- case FBTYPE_SUN4COLOR:
- case FBTYPE_SUN2BW:
- case FBTYPE_SUNFAST_COLOR:
- mutex_enter(&softc->mutex);
- softc->emulation = attr.emu_type;
- mutex_exit(&softc->mutex);
- break;
- default:
- return (EINVAL);
- }
- /* ignore device-dependent stuff */
- }
- break;
-
- case FBIOGATTR: {
- struct fbgattr attr;
-
- DEBUGF(3, (CE_CONT, "FBIOGATTR, emu_type=%d\n",
- softc->emulation));
- bcopy((caddr_t)&cg6_attr, (caddr_t)&attr, sizeof (attr));
- mutex_enter(&softc->mutex);
- attr.fbtype.fb_type = softc->emulation;
- attr.fbtype.fb_width = softc->_w;
- attr.fbtype.fb_height = softc->_h;
- /* XXX not quite like a cg4 */
- attr.fbtype.fb_size = (int)softc->size;
- attr.sattr.emu_type = softc->emulation;
- mutex_exit(&softc->mutex);
-
- if (ddi_copyout((caddr_t)&attr,
- (caddr_t)data,
- sizeof (struct fbgattr),
- mode))
- return (EFAULT);
- }
- break;
-
- /*
- * always claim to be a cg4 if they call this ioctl. This is to
- * support older software which was staticly-linked before cg6 was
- * invented, and to support newer software which has come to expect
- * this behavior.
- */
- case FBIOGTYPE: {
- struct fbtype fb;
-
- mutex_enter(&softc->mutex);
-
- bcopy(&cg6_attr.fbtype, &fb, sizeof (struct fbtype));
- DEBUGF(3, (CE_CONT, "FBIOGTYPE\n"));
- fb.fb_type = FBTYPE_SUN4COLOR;
- fb.fb_width = softc->_w;
- fb.fb_height = softc->_h;
- /* XXX not quite like a cg4 */
- fb.fb_size = (int)softc->size;
-
- mutex_exit(&softc->mutex);
-
- if (ddi_copyout((caddr_t)&fb,
- (caddr_t)data,
- sizeof (struct fbtype),
- mode))
- return (EFAULT);
- }
- break;
- case FBIOSVIDEO:
-
- DEBUGF(3, (CE_CONT, "FBIOSVIDEO\n"));
- if (ddi_copyin((caddr_t)data,
- (caddr_t)&i,
- sizeof (int),
- mode))
- return (EFAULT);
- mutex_enter(&softc->mutex);
- cg6_set_video(softc, i & FBVIDEO_ON);
- mutex_exit(&softc->mutex);
- break;
-
- case FBIOGVIDEO:
-
- DEBUGF(3, (CE_CONT, "FBIOGVIDEO\n"));
- mutex_enter(&softc->mutex);
- i = cg6_get_video(softc) ? FBVIDEO_ON : FBVIDEO_OFF;
- mutex_exit(&softc->mutex);
-
- if (ddi_copyout((caddr_t)&i,
- (caddr_t)data,
- sizeof (int),
- mode))
- return (EFAULT);
- break;
-
- /* informational ioctls */
-
- case FBIOGXINFO:
- if (ddi_copyout((caddr_t)&softc->cg6info,
- (caddr_t)data,
- sizeof (struct cg6_info),
- mode))
- return (EFAULT);
- return (0);
-
- case FBIOMONINFO:
- if (ddi_copyout((caddr_t)&softc->moninfo,
- (caddr_t)data,
- sizeof (struct mon_info),
- mode))
- return (EFAULT);
- return (0);
-
- /* vertical retrace interrupt */
-
- case FBIOVERTICAL:
-
- mutex_enter(&softc->mutex);
- softc->vrtflag |= CG6VRTIOCTL;
- cg6_int_enable(softc);
- cv_wait(&softc->vrtsleep, &softc->mutex);
- mutex_exit(&softc->mutex);
- return (0);
-
- case FBIOVRTOFFSET:
-
- i = CG6_VADDR_VRT;
-
- if (ddi_copyout((caddr_t)&i,
- (caddr_t)data,
- sizeof (int),
- mode))
- return (EFAULT);
- return (0);
-
- /* HW cursor control */
- case FBIOSCURSOR: {
-
- int set;
- ssize_t cbytes;
- uint32_t stack_image[32], stack_mask[32];
-
- STRUCT_INIT(fbcursor, mode);
- if (ddi_copyin((void *)data, STRUCT_BUF(fbcursor),
- STRUCT_SIZE(fbcursor), mode))
- return (EFAULT);
-
- set = STRUCT_FGET(fbcursor, set);
-
- /* Compute cursor bitmap bytes */
- cbytes = STRUCT_FGET(fbcursor, size.y) *
- sizeof (softc->cur.image[0]);
- if (set & FB_CUR_SETSHAPE) {
- if (STRUCT_FGET(fbcursor, size.x) > 32 ||
- STRUCT_FGET(fbcursor, size.y) > 32) {
- return (EINVAL);
- }
-
-
- /* copy cursor image into softc */
- if (STRUCT_FGETP(fbcursor, image) &&
- ddi_copyin(STRUCT_FGETP(fbcursor, image),
- &stack_image, cbytes, mode))
- return (EFAULT);
-
- if (STRUCT_FGETP(fbcursor, mask) &&
- ddi_copyin(STRUCT_FGETP(fbcursor, mask),
- &stack_mask, cbytes, mode))
- return (EFAULT);
- }
-
- mutex_enter(&softc->mutex);
- if (set & FB_CUR_SETCUR)
- softc->cur.enable = STRUCT_FGET(fbcursor, enable);
-
- if (set & FB_CUR_SETPOS)
- softc->cur.pos = STRUCT_FGET(fbcursor, pos);
-
- if (set & FB_CUR_SETHOT)
- softc->cur.hot = STRUCT_FGET(fbcursor, hot);
-
- /* update hardware */
-
- cg6_setcurpos(softc);
-
- if (set & FB_CUR_SETSHAPE) {
-
- if (STRUCT_FGETP(fbcursor, image)) {
- bzero((caddr_t)softc->cur.image,
- sizeof (softc->cur.image));
- bcopy((caddr_t)&stack_image,
- (caddr_t)softc->cur.image,
- cbytes);
- }
- if (STRUCT_FGETP(fbcursor, mask)) {
- bzero((caddr_t)softc->cur.mask,
- sizeof (softc->cur.mask));
- bcopy((caddr_t)&stack_mask,
- (caddr_t)softc->cur.mask,
- cbytes);
- }
- /* load into hardware */
- softc->cur.size = STRUCT_FGET(fbcursor, size);
- cg6_setcurshape(softc);
- }
- mutex_exit(&softc->mutex);
- /* load colormap */
- if (set & FB_CUR_SETCMAP) {
- cursor_cmap = 1;
- cmd = FBIOPUTCMAP;
- STRUCT_SET_HANDLE(fbcmap, mode,
- STRUCT_FADDR(fbcursor, cmap));
- goto cmap_ioctl;
- }
- }
- break;
-
- case FBIOGCURSOR: {
- ssize_t cbytes;
- uint32_t stack_image[32], stack_mask[32];
-
- STRUCT_INIT(fbcursor, mode);
- if (ddi_copyin((void *)data, STRUCT_BUF(fbcursor),
- STRUCT_SIZE(fbcursor), mode))
- return (EFAULT);
-
- mutex_enter(&softc->mutex);
-
- STRUCT_FSET(fbcursor, set, 0);
- STRUCT_FSET(fbcursor, enable, softc->cur.enable);
- STRUCT_FSET(fbcursor, pos, softc->cur.pos);
- STRUCT_FSET(fbcursor, hot, softc->cur.hot);
- STRUCT_FSET(fbcursor, size, softc->cur.size);
- STRUCT_FSET(fbcursor, cmap.index, 0);
- STRUCT_FSET(fbcursor, cmap.count, 2);
-
- /* compute cursor bitmap bytes */
- cbytes = softc->cur.size.y * sizeof (softc->cur.image[0]);
-
- bcopy(softc->cur.image, &stack_image, cbytes);
- bcopy(softc->cur.mask, &stack_mask, cbytes);
-
- mutex_exit(&softc->mutex);
-
- if (ddi_copyout(STRUCT_BUF(fbcursor), (void *)data,
- STRUCT_SIZE(fbcursor), mode))
- return (EFAULT);
-
- /* if image pointer is non-null copy both bitmaps */
- if (STRUCT_FGETP(fbcursor, image)) {
- if (ddi_copyout(&stack_image,
- STRUCT_FGETP(fbcursor, image),
- cbytes, mode))
- return (EFAULT);
-
- if (ddi_copyout(&stack_mask,
- STRUCT_FGETP(fbcursor, mask),
- cbytes, mode))
- return (EFAULT);
- }
-
- /* if red pointer is non-null copy colormap */
- if (STRUCT_FGETP(fbcursor, cmap.red)) {
- cursor_cmap = 1;
- cmd = FBIOGETCMAP;
- /*
- * XX64 The code used to do this:
- *
- * data = (int)&((struct fbcursor *)data)->cmap;
- *
- * However the cmap_ioctl handler doesn't look
- * at 'data' so this assignment doesn't do anything.
- * Instead we made it set the correct field in the
- * fbcurpos structure we were passed in from
- * userland.
- */
- STRUCT_SET_HANDLE(fbcmap, mode,
- STRUCT_FADDR(fbcursor, cmap));
- goto cmap_ioctl;
- }
- }
- break;
-
- case FBIOSCURPOS: {
-
- struct fbcurpos stack_curpos; /* cursor position */
-
- if (ddi_copyin((caddr_t)data,
- (caddr_t)&stack_curpos,
- sizeof (struct fbcurpos),
- mode))
- return (EFAULT);
-
- mutex_enter(&softc->mutex);
- bcopy((caddr_t)&stack_curpos, (caddr_t)&softc->cur.pos,
- sizeof (struct fbcurpos));
- cg6_setcurpos(softc);
- mutex_exit(&softc->mutex);
- }
- break;
-
- case FBIOGCURPOS: {
- struct fbcurpos stack_curpos; /* cursor position */
-
- mutex_enter(&softc->mutex);
- bcopy((caddr_t)&softc->cur.pos, (caddr_t)&stack_curpos,
- sizeof (struct fbcurpos));
- mutex_exit(&softc->mutex);
-
- if (ddi_copyout((caddr_t)&stack_curpos,
- (caddr_t)data,
- sizeof (struct fbcurpos),
- mode))
- return (EFAULT);
- }
- break;
-
- case FBIOGCURMAX: {
- static struct fbcurpos curmax = {32, 32};
-
- if (ddi_copyout((caddr_t)&curmax,
- (caddr_t)data,
- sizeof (struct fbcurpos),
- mode))
- return (EFAULT);
- }
- break;
-
-#if CG6DEBUG >= 3
- case 255:
- cg6_debug = (int)data;
- if (cg6_debug == -1)
- cg6_debug = CG6DEBUG;
- cmn_err(CE_CONT, "cg6_debug is now %d\n", cg6_debug);
- break;
-#endif
-
- default:
- return (ENOTTY);
- } /* switch(cmd) */
-
- return (0);
-}
-
-static uint_t
-cg6_intr(caddr_t arg)
-{
- struct cg6_softc *softc = (struct cg6_softc *)arg;
- volatile uint32_t *in;
- volatile uint32_t *out;
- volatile uint32_t tmp;
-
- DEBUGF(7, (CE_CONT,
- "cg6_intr: softc=%x, vrtflag=%x\n", softc, softc->vrtflag));
-
- mutex_enter(&softc->mutex);
- mutex_enter(&softc->interlock);
-
- if (!cg6_int_pending(softc)) {
- if (softc->intr_flag) {
- softc->intr_flag = 0;
- } else {
- if (softc->intrstats) {
- KIOIP->intrs[KSTAT_INTR_SPURIOUS]++;
- }
- mutex_exit(&softc->interlock);
- mutex_exit(&softc->mutex);
- return (DDI_INTR_UNCLAIMED); /* nope, not mine */
- }
- }
-
- if (!(cg6_update_pending(softc) || (softc)->vrtflag)) {
- /* TODO catch stray interrupts? */
- cg6_int_disable_intr(softc);
- if (softc->intrstats) {
- KIOIP->intrs[KSTAT_INTR_HARD]++;
- }
- mutex_exit(&softc->interlock);
- mutex_exit(&softc->mutex);
- return (DDI_INTR_CLAIMED);
- }
- if (softc->vrtflag & CG6VRTCTR) {
- if (softc->vrtmaps == 0) {
- softc->vrtflag &= ~CG6VRTCTR;
- } else
- *softc->vrtpage += 1;
- }
- if (softc->vrtflag & CG6VRTIOCTL) {
- softc->vrtflag &= ~CG6VRTIOCTL;
- cv_broadcast(&softc->vrtsleep);
- }
- if (cg6_update_pending(softc)) {
- volatile struct cg6_cmap *cmap = S_CMAP(softc);
- LOOP_T count = softc->cmap_count;
-
- /* load cursor color map */
- if (softc->omap_update) {
- in = &softc->omap_image.omap_int[0];
- out = (uint32_t *)& cmap->omap;
-
- /* background color */
- cmap->addr = 1 << 24;
- tmp = in[0];
- *out = tmp;
- *out = tmp <<= 8;
- *out = tmp <<= 8;
-
- /* foreground color */
- cmap->addr = 3 << 24;
- *out = tmp <<= 8;
- tmp = in[1];
- *out = tmp;
- *out = tmp <<= 8;
- }
- /* load main color map */
- if (count) {
- LOOP_T index = softc->cmap_index;
-
- in = &softc->cmap_image.cmap_int[0];
- out = (uint32_t *)& cmap->cmap;
-
- /* count multiples of 4 RGB entries */
- count = (count + (index & 3) + 3) >> 2;
-
- /* round index to 4 entry boundary */
- index &= ~3;
-
- cmap->addr = index << 24;
- PTR_INCR(uint32_t *, in, index * 3);
-
- /* copy 4 bytes (4/3 RGB entries) per loop iteration */
- count *= 3;
- /* CSTYLED */
- PR_LOOPV(count, tmp = *in++;
- *out = tmp;
- *out = tmp <<= 8;
- *out = tmp <<= 8;
- /* CSTYLED */
- *out = tmp <<= 8);
-
- softc->cmap_count = 0;
- }
- softc->omap_update = 0;
- }
- cg6_int_disable_intr(softc);
- if (softc->vrtflag)
- cg6_int_enable(softc);
- if (softc->intrstats) {
- KIOIP->intrs[KSTAT_INTR_HARD]++;
- }
- mutex_exit(&softc->interlock);
- mutex_exit(&softc->mutex);
- return (DDI_INTR_CLAIMED);
-}
-
-/*
- * Initialize a colormap: background = white, all others = black
- */
-static void
-cg6_reset_cmap(volatile uchar_t *cmap, uint_t entries)
-{
- bzero((char *)cmap, entries * 3);
- cmap[0] = 255;
- cmap[1] = 255;
- cmap[2] = 255;
-}
-
-/*
- * Compute color map update parameters: starting index and count.
- * If count is already nonzero, adjust values as necessary.
- * Zero count argument indicates cursor color map update desired.
- */
-static void
-cg6_update_cmap(struct cg6_softc *softc, uint_t index, uint_t count)
-{
- uint_t high, low;
-
- if (count == 0) {
- softc->omap_update = 1;
- return;
- }
-
- high = softc->cmap_count;
-
- if (high != 0) {
- high += (low = softc->cmap_index);
-
- if (index < low)
- softc->cmap_index = low = index;
-
- if (index + count > high)
- high = index + count;
-
- softc->cmap_count = high - low;
- } else {
- softc->cmap_index = index;
- softc->cmap_count = count;
- }
-}
-
-/*
- * Copy colormap entries between red, green, or blue array and
- * interspersed rgb array.
- *
- * count > 0 : copy count bytes from buf to rgb
- * count < 0 : copy -count bytes from rgb to buf
- */
-static void
-cg6_cmap_bcopy(uchar_t *bufp, uchar_t *rgb, uint_t count)
-{
- LOOP_T rcount = count;
-
- if (--rcount >= 0)
- PR_LOOPVP(rcount,
- /* CSTYLED */
- *rgb = *bufp++;
- /* CSTYLED */
- rgb += 3);
- else {
- rcount = -rcount - 2;
- PR_LOOPVP(rcount,
- /* CSTYLED */
- *bufp++ = *rgb;
- /* CSTYLED */
- rgb += 3);
- }
-}
-
-/*
- * This routine restores the color map to it's post-attach time values.
- */
-static void
-cg6_restore_prom_cmap(struct cg6_softc *softc,
- volatile uchar_t *cmap,
- uint_t entries)
-{
- volatile struct cg6_cmap *hwcmap = S_CMAP(softc);
- volatile uint32_t *in, *out, tmp;
- LOOP_T count;
-
- out = (uint32_t *)&hwcmap->cmap;
- in = (uint32_t *)cmap;
-
- if (entries != 0) {
- hwcmap->addr = 0;
-
- count = ((entries + 3) >> 2) * 3;
- /* CSTYLED */
- PR_LOOPV(count, tmp = *in++;
- *out = tmp;
- *out = tmp <<= 8;
- *out = tmp <<= 8;
- /* CSTYLED */
- *out = tmp <<= 8);
- }
-}
-
-/*
- * enable/disable/update HW cursor
- */
-static void
-cg6_setcurpos(struct cg6_softc *softc)
-{
- volatile struct thc *thc = S_THC(softc);
-
- thc->l_thc_cursor = softc->cur.enable ?
- (((softc->cur.pos.x - softc->cur.hot.x) << 16) |
- ((softc->cur.pos.y - softc->cur.hot.y) & 0xffff)) :
- CG6_CURSOR_OFFPOS;
-}
-
-/*
- * load HW cursor bitmaps
- */
-static void
-cg6_setcurshape(struct cg6_softc *softc)
-{
- uint_t tmp, edge = 0;
- volatile uint_t *image, *mask, *hw;
- volatile struct thc *thc = S_THC(softc);
- int i;
-
- /* compute right edge mask */
- if (softc->cur.size.x)
- edge = (uint_t)~ 0 << (32 - softc->cur.size.x);
-
- image = softc->cur.image;
- mask = softc->cur.mask;
- hw = (uint_t *)&thc->l_thc_cursora00;
-
- for (i = 0; i < 32; i++) {
- hw[i] = (tmp = mask[i] & edge);
- hw[i + 32] = tmp & image[i];
- }
-}
-
-static void
-cg6_reset(struct cg6_softc *softc)
-{
- volatile struct thc *thc = S_THC(softc);
-
- /* disable HW cursor */
- thc->l_thc_cursor = CG6_CURSOR_OFFPOS;
-
- /* reinitialize TEC */
- {
- volatile struct tec *tec = S_TEC(softc);
-
- tec->l_tec_mv = 0;
- tec->l_tec_clip = 0;
- tec->l_tec_vdc = 0;
- }
-
- /* reinitialize FBC config register */
- {
- volatile uint_t *fhc = S_FHC(softc);
- uint_t rev, conf;
-
- rev = *fhc >> FHC_CONFIG_REV_SHIFT & FHC_CONFIG_REV_MASK;
- if (rev <= 4) {
-
- /* PROM knows how to deal with LSC and above */
- /* rev == 0 : FBC 0 (not available to customers) */
- /* rev == 1 : FBC 1 */
- /* rev == 2 : FBC 2 */
- /* rev == 3 : Toshiba (never built) */
- /* rev == 4 : Standard Cell (not built yet) */
- /* rev == 5 : LSC rev 2 (buggy) */
- /* rev == 6 : LSC rev 3 */
- conf = *fhc & FHC_CONFIG_RES_MASK |
- FHC_CONFIG_CPU_68020;
-
-#if FBC_REV0
- /* FBC0: test window = 0, disable fast rops */
- if (rev == 0)
- conf |= FHC_CONFIG_TEST |
- FHC_CONFIG_FROP_DISABLE;
- else
-#endif /* FBC_REV0 */
-
- /* test window = 1K x 1K */
- conf |= FHC_CONFIG_TEST |
- (10 + 1) << FHC_CONFIG_TESTX_SHIFT |
- (10 + 1) << FHC_CONFIG_TESTY_SHIFT;
-
- /* FBC[01]: disable destination cache */
- if (rev <= 1)
- conf |= FHC_CONFIG_DST_DISABLE;
-
- *fhc = conf;
- }
- }
-
- /* reprogram DAC to enable HW cursor use */
- {
- volatile struct cg6_cmap *cmap = S_CMAP(softc);
-
- /* command register */
- cmap->addr = 6 << 24;
-
- /* turn on CR1:0, overlay enable */
- cmap->ctrl = cmap->ctrl | (0x3 << 24);
- }
-}
-
- /*
- * This code is no longer used, since OBP proms now do all device
- * initialization. Nevertheless, it is instructive and I'm going to
- * keep it in as a comment, should anyone ever want to know how to
- * do minimal device initialization. Note the c++ style embedded
- * comments.
- *
- * cg6_init(softc)
- * struct cg6_softc *softc;
- * {
- * // Initialize DAC
- * {
- * register struct cg6_cmap *cmap = S_CMAP(softc);
- * register char *p;
- *
- * static char dacval[] = {
- * 4, 0xff,
- * 5, 0,
- * 6, 0x73,
- * 7, 0,
- * 0
- * };
- *
- * // initialize DAC
- * for (p = dacval; *p; p += 2) {
- * cmap->addr = p[0] << 24;
- * cmap->ctrl = p[1] << 24;
- * }
- * }
- *
- * // Initialize THC
- * {
- * register struct thc *thc = S_THC(softc);
- * int vidon;
- *
- * vidon = thc_get_video(thc);
- * thc->l_thc_hcmisc = THC_HCMISC_RESET | THC_HCMISC_INIT;
- * thc->l_thc_hcmisc = THC_HCMISC_INIT;
- *
- * thc->l_thc_hchs = 0x010009;
- * thc->l_thc_hchsdvs = 0x570000;
- * thc->l_thc_hchd = 0x15005d;
- * thc->l_thc_hcvs = 0x010005;
- * thc->l_thc_hcvd = 0x2403a8;
- * thc->l_thc_hcr = 0x00016b;
- *
- * thc->l_thc_hcmisc = THC_HCMISC_RESET | THC_HCMISC_INIT;
- * thc->l_thc_hcmisc = THC_HCMISC_INIT;
- *
- * if (vidon)
- * thc_set_video(thc, _ONE_);
- *
- * DEBUGF(1, (CE_CONT, "TEC rev %d\n",
- * thc->l_thc_hcmisc >> THC_HCMISC_REV_SHIFT &
- * THC_HCMISC_REV_MASK));
- * }
- *
- * //
- * // Initialize FHC for 1152 X 900 screen
- * //
- * {
- * volatile uint_t *fhc = S_FHC(softc), rev;
- *
- * rev = *fhc >> FHC_CONFIG_REV_SHIFT & FHC_CONFIG_REV_MASK;
- * DEBUGF(1, (CE_CONT, "cg6_init: FBC rev %d\n", rev));
- *
- * //
- * // FBC0: disable fast rops FBC[01]: disable destination cache
- * //
- * *fhc = FHC_CONFIG_1152 |
- * FHC_CONFIG_CPU_68020 |
- * FHC_CONFIG_TEST |
- *
- * #if FBC_REV0
- * (rev == 0 ? FHC_CONFIG_FROP_DISABLE : 0) |
- * #endif
- *
- * (rev <= 1 ? FHC_CONFIG_DST_DISABLE : 0);
- * }
- * }
- */
-
-/*
- * from here on down, is the lego segment driver. this virtualizes the
- * lego register file by associating a register save area with each
- * mapping of the lego device (each lego segment). only one of these
- * mappings is valid at any time; a page fault on one of the invalid
- * mappings saves off the current lego context, invalidates the current
- * valid mapping, restores the former register contents appropriate to
- * the faulting mapping, and then validates it.
- *
- * this implements a graphical context switch that is transparent to the user.
- *
- * the TEC and FBC contain the interesting context registers.
- *
- */
-
-/*
- * Per-segment info:
- * Some, but not all, segments are part of a context.
- * Any segment that is a MAP_PRIVATE mapping to the TEC or FBC
- * will be part of a unique context. MAP_SHARED mappings are part
- * of the shared context and all such programs must arbitrate among
- * themselves to keep from stepping on each other's register settings.
- * Mappings to the framebuffer may or may not be part of a context,
- * depending on exact hardware type.
- */
-
-#define CG6MAP_SHARED 0x02 /* shared context */
-#define CG6MAP_VRT 0x04 /* vrt page */
-#define CG6MAP_FBCTEC 0X08 /* mapping includes fbc and/or tec */
-#define CG6MAP_FB 0X10 /* mapping includes framebuffer */
-
-#define CG6MAP_CTX (CG6MAP_FBCTEC | CG6MAP_FB) /* needs context */
-
-static struct cg6map_pvt *
-cg6_pvt_alloc(struct cg6_cntxt *ctx,
- uint_t type,
- offset_t off,
- size_t len,
- struct cg6_softc *softc)
-{
- struct cg6map_pvt *pvt;
-
- /*
- * create the private data portion of the devmap object
- */
- pvt = kmem_zalloc(sizeof (struct cg6map_pvt), KM_SLEEP);
- pvt->type = type;
- pvt->offset = off;
- pvt->len = len;
- pvt->context = ctx;
- pvt->softc = softc;
-
- /*
- * Link this pvt into the list of associated pvt's for this
- * context
- */
- pvt->next = ctx->pvt;
- ctx->pvt = pvt;
-
- return (pvt);
-}
-
-/*
- * This routine is called through the cb_ops table to handle
- * the creation of lego (cg6) segments.
- */
-/*ARGSUSED*/
-static int
-cg6_segmap(dev_t dev,
- off_t off,
- struct as *as,
- caddr_t *addrp,
- off_t len,
- uint_t prot,
- uint_t maxprot,
- uint_t flags,
- cred_t *cred)
-{
- struct cg6_softc *softc = getsoftc(getminor(dev));
- int error;
-
- DEBUGF(3, (CE_CONT, "segmap: off=%x, len=%x\n", off, len));
- mutex_enter(&softc->mutex);
-
- /*
- * check to see if this is a VRT page
- */
- if (off == CG6_VADDR_VRT) {
- if (len != pagesize) {
- mutex_exit(&softc->mutex);
- DEBUGF(3, (CE_CONT,
- "rejecting because off=vrt and len=%x\n", len))
- return (EINVAL);
- }
- if (softc->vrtmaps++ == 0) {
- if (softc->vrtpage == NULL) {
- softc->vrtpage = (int *)ddi_umem_alloc(
- pagesize, KM_SLEEP,
- (void **)&softc->vrtcookie);
- }
- *softc->vrtpage = 0;
- softc->vrtflag |= CG6VRTCTR;
- cg6_int_enable(softc);
- }
- }
-
- /*
- * use the devmap framework for setting up the user mapping.
- */
- error = devmap_setup(dev, (offset_t)off, as, addrp, (size_t)len, prot,
- maxprot, flags, cred);
-
- mutex_exit(&softc->mutex);
-
- return (error);
-}
-
-/* ARGSUSED */
-static int
-cg6map_map(devmap_cookie_t dhp, dev_t dev, uint_t flags, offset_t off,
- size_t len, void **pvtp)
-{
- struct cg6_softc *softc = getsoftc(getminor(dev));
- struct cg6_cntxt *ctx = (struct cg6_cntxt *)NULL;
- struct cg6_cntxt *shared_ctx = &softc->shared_ctx;
- struct cg6map_pvt *pvt;
- uint_t maptype = 0;
-
- DEBUGF(3, (CE_CONT, "cg6map_map: off = %x, len = %x\n",
- (uint_t)off, (uint_t)len));
-
- /*
- * LSC DFB BUG KLUDGE: DFB must always be mapped private on the buggy
- * (chip rev. 5) LSC chip. This is done to ensure that nobody ever
- * touches the framebuffer without the segment driver getting involved
- * to make sure the registers are idle. This involves taking a page
- * fault, invalidating all other process's mappings to the fb, (and
- * performing a context switch?)
- *
- * Under pixrects, which maps the chips and the FB all at once, the
- * entire mapping becomes a context. This won't hurt pixrects but
- * entails unnecessary context switching. Under other libraries such
- * as XGL, which maps the chips private and the FB shared, the FB
- * becomes part of the context. Programs which only map the FB will
- * also become contexts, but since they don't map the chips, there's
- * no context to switch.
- */
- if (off + len > CG6_VADDR_FBC && off < CG6_VADDR_FBC + CG6_FBCTEC_SZ)
- maptype |= CG6MAP_FBCTEC;
- if (off + len > CG6_VADDR_COLOR && off < CG6_VADDR_COLOR + CG6_FB_SZ)
- maptype |= CG6MAP_FB;
-
- /*
- * we now support MAP_SHARED and MAP_PRIVATE:
- *
- * MAP_SHARED means you get the shared context which is the traditional
- * mapping method.
- *
- * MAP_PRIVATE means you get your very own LEGO context.
- *
- * Note that you can't get to here without asking for one or the other,
- * but not both.
- */
- if (softc->chiprev == 5 && (maptype & CG6MAP_FB))
- flags = (flags & ~MAP_TYPE) | MAP_PRIVATE;
-
- if (flags & MAP_SHARED) { /* shared mapping */
- ctx = shared_ctx;
- ctx->flag = CG6MAP_CTX;
- } else {
- ctx = ctx_map_insert(softc, maptype);
- ctx->flag |= maptype;
- DEBUGF(2, (CE_CONT, "cg6map_map: ** MAP_PRIVATE **. ctx = %x\n",
- ctx));
- }
-
- pvt = cg6_pvt_alloc(ctx, maptype, off, len, softc);
- pvt->dhp = dhp;
-
- *pvtp = pvt;
-
- devmap_set_ctx_timeout(dhp, cg6_ctxholdval);
- return (DDI_SUCCESS);
-}
-
-/*
- * An access has been made to a context other than the current one
- */
-/* ARGSUSED */
-static int
-cg6map_access(devmap_cookie_t dhp, void *pvt, offset_t offset, size_t len,
- uint_t type, uint_t rw)
-{
- return (devmap_do_ctxmgt(dhp, pvt, offset, len, type, rw,
- cg6map_contextmgt));
-}
-
-/*
- * called by the devmap framework to perform context switching.
- */
-/* ARGSUSED */
-static int
-cg6map_contextmgt(devmap_cookie_t dhp, void *pvt, offset_t offset,
- size_t len, uint_t type, uint_t rw)
-{
- struct cg6map_pvt *p = (struct cg6map_pvt *)pvt;
- struct cg6map_pvt *pvts;
- struct cg6_softc *softc = p->softc;
- volatile struct fbc *fbc;
- int err = 0;
-
- ASSERT(pvt);
-
- mutex_enter(&softc->mutex);
-
- DEBUGF(6, (CE_CONT, "cg6map_contextmgt: pvt = %x, dhp = %x, \
-curctx = %x, context = %x\n",
- p, dhp, softc->curctx, p->context));
- /*
- * Do we need to switch contexts?
- */
- if (softc->curctx != p->context) {
-
- fbc = S_FBC(softc);
-
- /*
- * If there's a current context, save it
- */
- if (softc->curctx != (struct cg6_cntxt *)NULL) {
- /*
- * Set segdev for current context and all associated
- * handles to intercept references to their addresses
- */
- ASSERT(softc->curctx->pvt);
- for (pvts = softc->curctx->pvt; pvts != NULL;
- pvts = pvts->next) {
- err = devmap_unload(pvts->dhp, pvts->offset,
- pvts->len);
- if (err) {
- mutex_exit(&softc->mutex);
- return (err);
- }
- }
-
- if (cg6_cntxsave(fbc, S_TEC(softc),
- softc->curctx) == 0) {
- DEBUGF(1, (CE_CONT,
- "cgsix: context save failed\n"));
- /*
- * At this point we have no current context.
- */
- softc->curctx = NULL;
- mutex_exit(&softc->mutex);
- return (-1);
- }
- }
-
- /*
- * Idle the chips
- */
- CG6DELAY(!(fbc->l_fbc_status & L_FBC_BUSY), CG6_FBC_WAIT);
- if (fbc->l_fbc_status & L_FBC_BUSY) {
- DEBUGF(1, (CE_CONT, "cgsix: idle_cg6: status = %x\n",
- fbc->l_fbc_status));
- /*
- * At this point we have no current context.
- */
- softc->curctx = NULL;
- mutex_exit(&softc->mutex);
- return (-1);
- }
-
- DEBUGF(4, (CE_CONT, "loading context %x\n", p->context));
-
- if (p->context->flag & CG6MAP_FBCTEC)
- if (cg6_cntxrestore(fbc, S_TEC(softc),
- p->context) == 0) {
- DEBUGF(1, (CE_CONT,
- "cgsix: context restore failed\n"));
- /*
- * At this point we have no current context.
- */
- softc->curctx = NULL;
- mutex_exit(&softc->mutex);
- return (-1);
- }
-
- /*
- * switch software "context"
- */
- softc->curctx = p->context;
- }
-
- ASSERT(p->context->pvt);
- if ((type == DEVMAP_LOCK) || (type == DEVMAP_UNLOCK)) {
- if ((err = devmap_load(p->dhp, offset, len, type, rw)) != 0) {
- mutex_exit(&softc->mutex);
- return (err);
- }
- } else {
- if ((err = devmap_load(p->dhp, p->offset, p->len, type,
- rw)) != 0) {
- mutex_exit(&softc->mutex);
- return (err);
- }
- }
-
- mutex_exit(&softc->mutex);
-
- return (err);
-}
-
-/* ARGSUSED */
-static void
-cg6map_unmap(devmap_cookie_t dhp, void *pvtp, offset_t off, size_t len,
- devmap_cookie_t new_dhp1, void **pvtp1,
- devmap_cookie_t new_dhp2, void **pvtp2)
-{
- struct cg6map_pvt *p = (struct cg6map_pvt *)pvtp;
- struct cg6_softc *softc = p->softc;
- struct cg6_cntxt *ctx = p->context;
- struct cg6map_pvt *ptmp;
- struct cg6map_pvt *ppvts;
- struct cg6_cntxt *shared_ctx = &softc->shared_ctx;
- size_t length;
-
- DEBUGF(3, (CE_CONT, "cg6map_unmap: pvt = %x, dhp = %x, \
-off = %x, len = %x, dhp1 = %x, dhp2 = %x\n",
- pvtp, dhp, (uint_t)off, len, new_dhp1, new_dhp2));
-
- mutex_enter(&softc->mutex);
-
- /*
- * We are unmapping at the end of the mapping, if
- * new_dhp1 is not NULL.
- */
- if (new_dhp1 != NULL) {
- ptmp = cg6_pvt_alloc(ctx, p->type,
- p->offset,
- (off - p->offset),
- softc);
- ptmp->dhp = new_dhp1;
- *pvtp1 = ptmp;
- }
-
- /*
- * We are unmapping at the beginning of the mapping, if
- * new_dhp2 is not NULL.
- */
- if (new_dhp2 != NULL) {
- length = p->len - len - (off - p->offset);
- ptmp = cg6_pvt_alloc(ctx, p->type, (off + len), length, softc);
- ptmp->dhp = new_dhp2;
-
- *pvtp2 = ptmp;
- }
-
- /*
- * Remove the original pvt data
- */
- ppvts = NULL;
- for (ptmp = ctx->pvt; ptmp != NULL; ptmp = ptmp->next) {
- if (ptmp == pvtp) {
- if (ppvts == NULL) {
- ctx->pvt = ptmp->next;
- } else {
- ppvts->next = ptmp->next;
- }
- kmem_free(pvtp, sizeof (struct cg6map_pvt));
- break;
- }
- ppvts = ptmp;
- }
-
- /*
- * We want to remove the conext if both new_dhp1 and new_dhp2 are NULL.
- */
- if (new_dhp1 == NULL && new_dhp2 == NULL) {
- /*
- * Remove the context if this is not the shared context
- * xand there are no more associated pvt's
- */
- if ((ctx != shared_ctx) && (ctx->pvt == NULL)) {
- struct cg6_cntxt *ctxptr;
-
- if (ctx == softc->curctx)
- softc->curctx = NULL;
-
- /*
- * Scan private context list for entry to remove.
- * Check first to see if it's the head of our list.
- */
- if (softc->pvt_ctx == ctx) {
- softc->pvt_ctx = ctx->link;
- kmem_free(ctx, sizeof (struct cg6_cntxt));
- } else {
- for (ctxptr = softc->pvt_ctx; ctxptr != NULL;
- ctxptr = ctxptr->link) {
- if (ctxptr->link == ctx) {
- ctxptr->link = ctx->link;
- kmem_free(ctx,
- sizeof (struct cg6_cntxt));
- }
- }
- }
- }
-
- /*
- * If the curctx is the shared context, and there are no
- * more pvt's for the shared context, set the curctx to
- * NULL to force a context switch on the next device access.
- */
- if ((softc->curctx == shared_ctx) && (softc->curctx->pvt ==
- NULL)) {
- softc->curctx = NULL;
- }
- }
-
- mutex_exit(&softc->mutex);
-}
-
-/* ARGSUSED */
-static int
-cg6map_dup(devmap_cookie_t dhp, void *oldpvt, devmap_cookie_t new_dhp,
- void **newpvt)
-{
- struct cg6map_pvt *p = (struct cg6map_pvt *)oldpvt;
- struct cg6_softc *softc = p->softc;
- struct cg6map_pvt *pvt;
- struct cg6_cntxt *ctx;
- uint_t maptype;
-
- DEBUGF(3, (CE_CONT, "cg6map_dup: pvt=%x, dhp=%x, newdhp=%x\n",
- oldpvt, dhp, new_dhp));
-
- mutex_enter(&softc->mutex);
- if (p->context != &softc->shared_ctx) {
- maptype = p->type;
- ctx = ctx_map_insert(softc, maptype);
- } else
- ctx = &softc->shared_ctx;
-
- pvt = cg6_pvt_alloc(ctx, p->type, p->offset, p->len, softc);
-
- pvt->dhp = new_dhp;
- *newpvt = pvt;
-
- if (p->context && (p->context->flag & CG6MAP_VRT)) {
- softc->vrtflag |= CG6VRTCTR;
- if (softc->vrtmaps == 0)
- cg6_int_enable(softc);
- softc->vrtmaps++;
- }
-
- mutex_exit(&softc->mutex);
- return (0);
-}
-
-/*
- * please don't mess with these defines... they may look like
- * a strange place for defines, but the context management code
- * wants them as they are. JMP
- *
- */
-#undef L_TEC_VDC_INTRNL0
-#define L_TEC_VDC_INTRNL0 0x8000
-#undef L_TEC_VDC_INTRNL1
-#define L_TEC_VDC_INTRNL1 0xa000
-
-static int
-cg6_cntxsave(fbc, tec, saved)
- volatile struct fbc *fbc;
- volatile struct tec *tec;
- struct cg6_cntxt *saved;
-{
- int dreg; /* counts through the data registers */
- uint_t *dp; /* points to a tec data register */
-
- DEBUGF(5, (CE_CONT, "saving registers for %d\n", saved->pid));
-
- CDELAY(!(fbc->l_fbc_status & L_FBC_BUSY), CG6_FBC_WAIT);
- if (fbc->l_fbc_status & L_FBC_BUSY) {
- DEBUGF(1, (CE_CONT, "cgsix: idle_cg6: status = %x\n",
- fbc->l_fbc_status));
- return (0);
- }
-
- /*
- * start dumping stuff out.
- */
- saved->fbc.status = fbc->l_fbc_status;
- saved->fbc.clipcheck = fbc->l_fbc_clipcheck;
- saved->fbc.misc = fbc->l_fbc_misc;
- saved->fbc.x0 = fbc->l_fbc_x0;
- saved->fbc.y0 = fbc->l_fbc_y0;
- saved->fbc.x1 = fbc->l_fbc_x1;
- saved->fbc.y1 = fbc->l_fbc_y1;
- saved->fbc.x2 = fbc->l_fbc_x2;
- saved->fbc.y2 = fbc->l_fbc_y2;
- saved->fbc.x3 = fbc->l_fbc_x3;
- saved->fbc.y3 = fbc->l_fbc_y3;
- saved->fbc.rasteroffx = fbc->l_fbc_rasteroffx;
- saved->fbc.rasteroffy = fbc->l_fbc_rasteroffy;
- saved->fbc.autoincx = fbc->l_fbc_autoincx;
- saved->fbc.autoincy = fbc->l_fbc_autoincy;
- saved->fbc.clipminx = fbc->l_fbc_clipminx;
- saved->fbc.clipminy = fbc->l_fbc_clipminy;
- saved->fbc.clipmaxx = fbc->l_fbc_clipmaxx;
- saved->fbc.clipmaxy = fbc->l_fbc_clipmaxy;
- saved->fbc.fcolor = fbc->l_fbc_fcolor;
- saved->fbc.bcolor = fbc->l_fbc_bcolor;
- saved->fbc.rasterop = fbc->l_fbc_rasterop;
- saved->fbc.planemask = fbc->l_fbc_planemask;
- saved->fbc.pixelmask = fbc->l_fbc_pixelmask;
- saved->fbc.pattalign = fbc->l_fbc_pattalign;
- saved->fbc.pattern0 = fbc->l_fbc_pattern0;
- saved->fbc.pattern1 = fbc->l_fbc_pattern1;
- saved->fbc.pattern2 = fbc->l_fbc_pattern2;
- saved->fbc.pattern3 = fbc->l_fbc_pattern3;
- saved->fbc.pattern4 = fbc->l_fbc_pattern4;
- saved->fbc.pattern5 = fbc->l_fbc_pattern5;
- saved->fbc.pattern6 = fbc->l_fbc_pattern6;
- saved->fbc.pattern7 = fbc->l_fbc_pattern7;
-
- /*
- * the tec matrix and clipping registers are easy.
- */
- saved->tec.mv = tec->l_tec_mv;
- saved->tec.clip = tec->l_tec_clip;
- saved->tec.vdc = tec->l_tec_vdc;
-
- /*
- * the tec data registers are a little more non-obvious.
- * internally, they are 36 bits. what we see in the register
- * file is a 32-bit window onto the underlying data register.
- * changing the data-type in the VDC gets us either of two parts
- * of the data register. the internal format is opaque to us.
- */
- tec->l_tec_vdc = (uint_t)L_TEC_VDC_INTRNL0;
- for (dreg = 0, dp = (uint_t *)&tec->l_tec_data00; dreg < 64;
- dreg++, dp++) {
- saved->tec.data[dreg][0] = *dp;
- }
- tec->l_tec_vdc = (uint_t)L_TEC_VDC_INTRNL1;
- for (dreg = 0, dp = (uint_t *)&tec->l_tec_data00; dreg < 64;
- dreg++, dp++) {
- saved->tec.data[dreg][1] = *dp;
- }
-
- return (1);
-}
-
-static int
-cg6_cntxrestore(fbc, tec, saved)
- volatile struct fbc *fbc;
- volatile struct tec *tec;
- struct cg6_cntxt *saved;
-{
- int dreg;
- uint_t *dp;
-
- DEBUGF(5, (CE_CONT, "restoring registers for %d\n", saved->pid));
-
- /*
- * reload the tec data registers. see above for "how do they get
- * 36 bits in that itty-bitty int"
- */
- tec->l_tec_vdc = (uint_t)L_TEC_VDC_INTRNL0;
- for (dreg = 0, dp = (uint_t *)&tec->l_tec_data00;
- dreg < 64; dreg++, dp++) {
- *dp = saved->tec.data[dreg][0];
- }
- tec->l_tec_vdc = (uint_t)L_TEC_VDC_INTRNL1;
- for (dreg = 0, dp = (uint_t *)&tec->l_tec_data00;
- dreg < 64; dreg++, dp++) {
- *dp = saved->tec.data[dreg][1];
- }
-
- /*
- * the tec matrix and clipping registers are next.
- */
- tec->l_tec_mv = saved->tec.mv;
- tec->l_tec_clip = saved->tec.clip;
- tec->l_tec_vdc = saved->tec.vdc;
-
- /*
- * now the FBC vertex and address registers
- */
- fbc->l_fbc_x0 = saved->fbc.x0;
- fbc->l_fbc_y0 = saved->fbc.y0;
- fbc->l_fbc_x1 = saved->fbc.x1;
- fbc->l_fbc_y1 = saved->fbc.y1;
- fbc->l_fbc_x2 = saved->fbc.x2;
- fbc->l_fbc_y2 = saved->fbc.y2;
- fbc->l_fbc_x3 = saved->fbc.x3;
- fbc->l_fbc_y3 = saved->fbc.y3;
- fbc->l_fbc_rasteroffx = saved->fbc.rasteroffx;
- fbc->l_fbc_rasteroffy = saved->fbc.rasteroffy;
- fbc->l_fbc_autoincx = saved->fbc.autoincx;
- fbc->l_fbc_autoincy = saved->fbc.autoincy;
- fbc->l_fbc_clipminx = saved->fbc.clipminx;
- fbc->l_fbc_clipminy = saved->fbc.clipminy;
- fbc->l_fbc_clipmaxx = saved->fbc.clipmaxx;
- fbc->l_fbc_clipmaxy = saved->fbc.clipmaxy;
-
- /*
- * restoring the attribute registers
- */
- fbc->l_fbc_fcolor = saved->fbc.fcolor;
- fbc->l_fbc_bcolor = saved->fbc.bcolor;
- fbc->l_fbc_rasterop = saved->fbc.rasterop;
- fbc->l_fbc_planemask = saved->fbc.planemask;
- fbc->l_fbc_pixelmask = saved->fbc.pixelmask;
- fbc->l_fbc_pattalign = saved->fbc.pattalign;
- fbc->l_fbc_pattern0 = saved->fbc.pattern0;
- fbc->l_fbc_pattern1 = saved->fbc.pattern1;
- fbc->l_fbc_pattern2 = saved->fbc.pattern2;
- fbc->l_fbc_pattern3 = saved->fbc.pattern3;
- fbc->l_fbc_pattern4 = saved->fbc.pattern4;
- fbc->l_fbc_pattern5 = saved->fbc.pattern5;
- fbc->l_fbc_pattern6 = saved->fbc.pattern6;
- fbc->l_fbc_pattern7 = saved->fbc.pattern7;
-
- fbc->l_fbc_clipcheck = saved->fbc.clipcheck;
- fbc->l_fbc_misc = saved->fbc.misc;
-
- /*
- * lastly, let's restore the status
- */
- fbc->l_fbc_status = saved->fbc.status;
-
- return (1);
-}
-
-/*
- * ctx_map_insert()
- *
- * Insert a mapping into the mapping list of a private context. First
- * determine if there's an existing context (e.g. one with the same PID
- * as the current one and that does not already have a mapping of this
- * type yet). If not, allocate a new one. Then insert mapping into this
- * context's list.
- *
- * The softc mutex must be held across calls to this routine.
- */
-static
-struct cg6_cntxt *
-ctx_map_insert(struct cg6_softc *softc, int maptype)
-{
- struct cg6_cntxt *ctx;
- pid_t curpid = getpid();
-
- DEBUGF(4, (CE_CONT, "ctx_map_insert: maptype=0x%x curpid=%d\n",
- maptype, curpid));
-
- /*
- * If this is the first time we're here, then alloc space
- * for new context and depart.
- */
- if (softc->pvt_ctx == NULL) {
- ctx = (struct cg6_cntxt *)
- kmem_zalloc(sizeof (struct cg6_cntxt), KM_SLEEP);
- ctx->pid = curpid;
- ctx->link = NULL;
- softc->pvt_ctx = ctx;
- return (ctx);
- }
-
- /*
- * Find existing context if one exists. We have a match if
- * we're the same process *and* there's not already a
- * mapping of this type assigned.
- */
- for (ctx = softc->pvt_ctx; ctx != NULL; ctx = ctx->link) {
- if (ctx->pid == curpid &&
- (maptype & ctx->flag & (CG6MAP_FBCTEC|CG6MAP_FB)) == 0)
- break;
- }
-
-
- /* no match, create a new one and add to softc list */
- if (ctx == NULL) {
- ctx = (struct cg6_cntxt *)
- kmem_zalloc(sizeof (struct cg6_cntxt), KM_SLEEP);
- ctx->pid = curpid;
- ctx->link = softc->pvt_ctx;
- softc->pvt_ctx = ctx;
- }
-
- DEBUGF(4, (CE_CONT, "ctx_map_insert: returning ctx=0x%x\n", ctx));
-
- return (ctx);
-}
-
-/*
- * getpid()
- *
- * Simple wrapper around process ID call to drv_getparm(9f).
- */
-static pid_t
-getpid()
-{
- pid_t mypid;
-
- if (drv_getparm(PPID, &mypid) == -1)
- return (0);
- return (mypid);
-}
-
-#define DEVMEMORY 1
-#define KERNELMEMORY 2
-
-/*ARGSUSED*/
-static int
-cg6_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len,
- size_t *maplen, uint_t model)
-{
- struct cg6_softc *softc = getsoftc(getminor(dev));
- dev_info_t *dip = softc->devi;
- ssize_t diff;
- int err = 0;
- caddr_t kvaddr = NULL;
- ddi_umem_cookie_t cookie = NULL;
- offset_t offset = 0;
- uint_t rnumber = 0;
- uint_t type = DEVMEMORY;
- size_t length = len;
- uint_t map_type = 0;
- uint_t ctxmap = 0;
- struct devmap_callback_ctl *callbackops = &cg6map_ops;
-
- DEBUGF(2, (CE_CONT, "cg6_devmap(%d), off=0x%x, len=%x, dhp=%x\n",
- getminor(dev), (uint_t)off, len, dhp));
-
- if ((diff = off - CG6_VADDR_COLOR) >= 0 && diff < softc->fbmappable) {
- if ((len + off) > (CG6_VADDR_COLOR + softc->fbmappable))
- length = CG6_VADDR_COLOR + softc->fbmappable - off;
- offset = CG6_ADDR_COLOR + diff;
- map_type = CG6MAP_FB;
- } else if ((diff = off - CG6_VADDR_FBC) >= 0 && diff < CG6_FBCTEC_SZ) {
- if ((len + off) > (CG6_VADDR_FBC + CG6_FBCTEC_SZ))
- length = (CG6_VADDR_FBC + CG6_FBCTEC_SZ) - off;
- offset = CG6_ADDR_FBC + diff;
- map_type = CG6MAP_FBCTEC;
- } else if ((diff = off - CG6_VADDR_CMAP) >= 0 && diff < CG6_CMAP_SZ) {
- if ((len + off) > (CG6_VADDR_CMAP + CG6_CMAP_SZ))
- length = (CG6_VADDR_CMAP + CG6_CMAP_SZ) - off;
- offset = CG6_ADDR_CMAP + diff;
- } else if ((diff = off - CG6_VADDR_FHC) >= 0 && diff < CG6_FHCTHC_SZ) {
- if ((len + off) > (CG6_VADDR_FHC + CG6_FHCTHC_SZ))
- length = (CG6_VADDR_FHC + CG6_FHCTHC_SZ) - off;
- offset = CG6_ADDR_FHC + diff;
- } else if ((diff = off - CG6_VADDR_ROM) >= 0 && diff < CG6_ROM_SZ) {
- if ((len + off) > (CG6_VADDR_ROM + CG6_ROM_SZ))
- length = (CG6_VADDR_ROM + CG6_ROM_SZ) - off;
- offset = softc->addr_rom + diff;
- } else if ((diff = off - CG6_VADDR_DHC) >= 0 && diff < CG6_DHC_SZ) {
- if ((len + off) > (CG6_VADDR_DHC + CG6_DHC_SZ))
- length = (CG6_VADDR_DHC + CG6_DHC_SZ) - off;
- offset = CG6_ADDR_DHC + diff;
- } else if ((diff = off - CG6_VADDR_ALT) >= 0 && diff < CG6_ALT_SZ) {
- if ((len + off) > (CG6_VADDR_ALT + CG6_ALT_SZ))
- length = (CG6_VADDR_ALT + CG6_ALT_SZ) - off;
- offset = CG6_ADDR_ALT + diff;
- } else if ((diff = off - CG6_VADDR_VRT) >= 0 && diff < CG6_VRT_SZ) {
- if ((len + off) > (CG6_VADDR_VRT + CG6_VRT_SZ))
- length = (CG6_VADDR_VRT + CG6_VRT_SZ) - off;
- type = KERNELMEMORY;
- if (softc->vrtpage != NULL)
- offset = diff;
- else
- kvaddr = (caddr_t)-1;
- cookie = softc->vrtcookie;
- } else if ((diff = off - CG3_MMAP_OFFSET) >= 0 &&
- diff < softc->fbmappable) {
- if ((len + off) > (CG3_MMAP_OFFSET + softc->fbmappable))
- length = CG3_MMAP_OFFSET + softc->fbmappable - off;
- offset = CG6_ADDR_COLOR + diff;
- } else if (off < CG6_VBASE) {
- if (softc->emulation == FBTYPE_SUN3COLOR) {
- if (off >= 0 && off < softc->fbmappable) {
- if ((len + off) > softc->fbmappable)
- length = softc->fbmappable - off;
- offset = CG6_ADDR_COLOR + diff;
- } else
- kvaddr = (caddr_t)-1;
- } else { /* softc->emulation == FBTYPE_SUN4COLOR */
- if (off >= 0 && off < softc->dummysize) {
- if ((len + off) > softc->dummysize)
- length = softc->dummysize - off;
- offset = CG6_ADDR_COLOR + diff;
- } else if ((diff = off - softc->dummysize) <
- softc->fbmappable) {
- if ((len + off) >
- (softc->dummysize + softc->fbmappable))
- length = softc->fbmappable - off;
- offset = CG6_ADDR_COLOR + diff;
- }
- }
- } else
- kvaddr = (caddr_t)-1;
-
- if (kvaddr == (caddr_t)-1) {
- DEBUGF(1, (CE_CONT, "cg6_devmap: no mapping off=0x%x, len=%x\n",
- (uint_t)off, len));
- return (-1);
- }
-
- DEBUGF(2, (CE_CONT, "cg6_devmap: offset=0x%x, kvaddr=%x, length=%x\n",
- (uint_t)offset, kvaddr, length));
-
- /*
- * LSC DFB BUG KLUDGE: DFB must always be mapped private on the buggy
- * (chip rev. 5) LSC chip. This is done to ensure that nobody ever
- * touches the framebuffer without the segment driver getting involved
- * to make sure the registers are idle. This involves taking a page
- * fault, invalidating all other process's mappings to the fb, (and
- * performing a context switch?)
- *
- * Under pixrects, which maps the chips and the FB all at once, the
- * entire mapping becomes a context. This won't hurt pixrects but
- * entails unnecessary context switching. Under other libraries such
- * as XGL, which maps the chips private and the FB shared, the FB
- * becomes part of the context. Programs which only map the FB will
- * also become contexts, but since they don't map the chips, there's
- * no context to switch.
- */
- ctxmap = (softc->chiprev == 5) ?
- (CG6MAP_FBCTEC|CG6MAP_FB) : CG6MAP_FBCTEC;
-
- /*
- * do context switching on the TEC and FBC registers.
- */
- if (map_type & ctxmap)
- callbackops = &cg6map_ops;
- else
- callbackops = NULL;
-
- if (type == DEVMEMORY) {
- if ((err = devmap_devmem_setup(dhp, dip, callbackops, rnumber,
- offset, length, PROT_ALL, DEVMAP_DEFAULTS,
- &endian_attr)) < 0)
- return (err);
- } else {
- if ((err = devmap_umem_setup(dhp, dip, callbackops, cookie,
- offset, length, PROT_ALL, DEVMAP_DEFAULTS,
- &endian_attr)) < 0)
- return (err);
- }
-
- *maplen = roundup(length, PAGESIZE);
- return (0);
-}