497 lines
11 KiB
C
497 lines
11 KiB
C
/*
|
|
* Copyright (c) 1988-89, Sun Microsystems Inc., Raleigh, North Carolina
|
|
*/
|
|
|
|
/* @(#)taac.c 1.1 92/07/30 */
|
|
|
|
#ifndef lint
|
|
static char sccs_id[]="@(#)taac.c 1.1 92/07/30 Copyr 1989 Sun Micro";
|
|
static char *ncaaid = "NCAA TAAC 1.1 opts = lock/pixrects/profiler";
|
|
#endif
|
|
|
|
/*
|
|
* TAAC-1 driver
|
|
*
|
|
* Rev Date Author Description
|
|
* 1.0 ?? Dec 1986 ??? Original
|
|
* ?.? ??????????? ??? Much time passes and changes are made.
|
|
* 2.1 27 Feb 1989 gfo add probe bypass for Sun3x/80 (Hydra)
|
|
* gfo remove conditional compile for Pegasus
|
|
* (use hard-code CPUid value of Pegasus machine)
|
|
* 2.2 14 Nov 1989 gfo "bump" rev level for install into SunOS 4.1
|
|
* 2.3 29 Nov 1989 gfo Remove dependencies to <taac1/taio.h>
|
|
*/
|
|
|
|
#include "taac.h"
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/buf.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/errno.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/vmmac.h>
|
|
#include <sys/user.h>
|
|
#include <sys/kernel.h>
|
|
#include <sys/map.h>
|
|
#include <sys/kmem_alloc.h>
|
|
|
|
#include <machine/mmu.h>
|
|
#include <machine/cpu.h>
|
|
#include <machine/pte.h>
|
|
|
|
#include <sundev/mbvar.h>
|
|
#include <sun/fbio.h>
|
|
|
|
/*
|
|
* The following defines were extracted from <mon/idprom.h> of SunOS
|
|
* 4.0.3 for Sun3x. Since this driver must support a number of cpu
|
|
* architectures and OS versions, not all of which use <mon/idprom.h>
|
|
* and some not fully defining all architecture ids in <mon/idprom.h>,
|
|
* it is best for now to include the needed defines here. These
|
|
* numbers do not change!
|
|
*/
|
|
|
|
#define IDM_SUN3_M25 0x12 /* Sun-3/50 */
|
|
#define IDM_SUN3_F 0x17 /* Sun-3/60 */
|
|
#define IDM_SUN3X_PEGASUS 0x41 /* Sun-3x/470/480 */
|
|
#define IDM_SUN3X_HYDRA 0x42 /* Sun-3x/80 */
|
|
#ifndef PGT_VME_D32
|
|
#define PGT_VME_D32 0xC000000 /* == VME_D32<<26 == 0x3<<26 */
|
|
#endif
|
|
|
|
|
|
/*
|
|
* This is a real crock but OS3 does make depend with egrep '^#include' which
|
|
* does not understand that these includes are def'ed out. If your compiling
|
|
* for OS3 delete the following 5 include files bracketed by 'ifdef _MAP_NEW.'
|
|
*
|
|
* 4.X include files
|
|
*/
|
|
|
|
#ifdef _MAP_NEW
|
|
|
|
/*
|
|
* These defines are extracted from /usr/include/taac1/taio.h and
|
|
* have been included here to avoid releasing "taio.h" and all its
|
|
* nested include files to the kernel. All these numbers are fixed!
|
|
*/
|
|
#define TA_PAGE0 0x0000
|
|
#define TA_PAGE1 0x2000
|
|
#define TA_PAGE2 0x4000
|
|
#define TA_PAGE3 0x6000
|
|
#define TA_PAGEBITS 0x6000
|
|
#define TA_TWODIM 0x1000
|
|
#define TIOCTEST _IOW(t, 1, int)
|
|
#define TIOCPROFON _IOW(t, 2, int)
|
|
#define TIOCPROFOFF _IOW(t, 3, caddr_t)
|
|
#define TIOCDEBUG _IOW(t, 4, int)
|
|
|
|
#include <vm/seg.h>
|
|
#include <machine/seg_kmem.h>
|
|
|
|
#include <pixrect/pixrect.h>
|
|
#include <pixrect/pr_impl_util.h>
|
|
#include <pixrect/memreg.h>
|
|
|
|
#else
|
|
|
|
/*
|
|
* 3.X include files
|
|
*/
|
|
|
|
/*
|
|
* These defines are extracted from /usr/include/taac1/taio.h and
|
|
* have been included here to avoid releasing "taio.h" and all its
|
|
* nested include files to the kernel. All these numbers are fixed!
|
|
*/
|
|
#define TA_PAGE0 0x0000
|
|
#define TA_PAGE1 0x2000
|
|
#define TA_PAGE2 0x4000
|
|
#define TA_PAGE3 0x6000
|
|
#define TA_PAGEBITS 0x6000
|
|
#define TA_TWODIM 0x1000
|
|
#define TIOCTEST _IOW(t, 1, int)
|
|
#define TIOCPROFON _IOW(t, 2, int)
|
|
#define TIOCPROFOFF _IOW(t, 3, caddr_t)
|
|
#define TIOCDEBUG _IOW(t, 4, int)
|
|
|
|
#include "/usr/include/pixrect/pixrect.h"
|
|
#include "/usr/include/pixrect/mem_rop_impl_util.h"
|
|
#include "/usr/include/pixrect/memreg.h"
|
|
#endif
|
|
|
|
#define TAAC_PROBE_SIZE (sizeof (long))
|
|
#define TAAC_TOTAL_SIZE (32*1024*1024) /* 32 Mb */
|
|
|
|
#define TAAC_SMR_MASK 0xffffff /* valid bits in SMR */
|
|
#define TAAC_SMR_RESET 0 /* reset code */
|
|
#define TAAC_SMR_INIT 1 /* initialization code */
|
|
|
|
#define TA_ISIZE 0x4000
|
|
|
|
#if NWIN > 0
|
|
/* SunWindows specific stuff */
|
|
struct pixrectops taac_ops = {
|
|
taac_rop,
|
|
taac_putcolormap,
|
|
taac_putattributes
|
|
};
|
|
#endif (NWIN > 0)
|
|
|
|
static int pagevals[] = { TA_PAGE0, 0, 0, 0, TA_PAGE1, 0, TA_PAGE2, TA_PAGE3 };
|
|
|
|
struct taac_softc {
|
|
int sc_debug; /* printf on/off */
|
|
unsigned sc_flag; /* the usual status */
|
|
/* locking */
|
|
int sc_uid; /* current uid for locking */
|
|
int sc_count; /* reference count for uid */
|
|
/* profiling */
|
|
int sc_offset; /* addr of data we want */
|
|
int sc_page; /* smr page value */
|
|
long sc_smrkmp; /* kernel map for smr */
|
|
long sc_kmp; /* kernel map for data */
|
|
unsigned short *sc_pbuf; /* profile trace buffe r */
|
|
int sc_pbufsize; /* size of the trace buffer */
|
|
unsigned *sc_smrp; /* pointer to smr */
|
|
unsigned *sc_datap; /* pointer to data page */
|
|
struct proc *sc_procp; /* traceing proc */
|
|
u_short *sc_pcdata; /* trace data */
|
|
/* pixrects */
|
|
caddr_t image; /* pointer to frame buffer */
|
|
int w, h; /* resolution */
|
|
int depth; /* bit planes available */
|
|
int size; /* frame buffer size (bytes) */
|
|
};
|
|
|
|
struct taac_softc taac_softc[NTAAC];
|
|
|
|
/* values for sc_flag
|
|
*/
|
|
#define TA_PROFON 0x1
|
|
|
|
int taacdebug = 0;
|
|
int taacprobe();
|
|
|
|
struct mb_device *taacinfo[NTAAC];
|
|
struct mb_driver taacdriver = {
|
|
taacprobe, 0, 0, 0, 0, 0,
|
|
TAAC_PROBE_SIZE, "taac", taacinfo, 0, 0, 0, 0
|
|
};
|
|
|
|
/*ARGSUSED*/
|
|
taacprobe(reg, unit)
|
|
caddr_t reg; int unit;
|
|
{
|
|
struct taac_softc *sc = &taac_softc[unit];
|
|
register long *smrp;
|
|
long smr;
|
|
long OK;
|
|
|
|
/* make sure we have a VME bus! */
|
|
switch (cpu) {
|
|
case IDM_SUN3_M25:
|
|
case IDM_SUN3_F:
|
|
case IDM_SUN3X_HYDRA:
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* init softc
|
|
*/
|
|
sc->sc_uid = -1;
|
|
sc->sc_count = 0;
|
|
sc->sc_smrkmp = -1;
|
|
sc->sc_kmp = -1;
|
|
sc->sc_smrp = NULL;
|
|
sc->sc_datap = NULL;
|
|
|
|
sc->h = 2048;
|
|
sc->w = 1024;
|
|
sc->depth = 8;
|
|
sc->size = sc->h * sc->w * sc->depth / sizeof (char);
|
|
|
|
/*
|
|
* Reset the TAAC by writing 0 to the SMR.
|
|
* XXX There should be a more sophisticated test here to
|
|
* determine that this is REALLY the TAAC.
|
|
*/
|
|
smrp = (long *) reg;
|
|
OK = pokel(smrp, (long) TAAC_SMR_RESET) ||
|
|
peekl(smrp, &smr) ||
|
|
(smr & TAAC_SMR_MASK) != 0 ||
|
|
(*smrp = TAAC_SMR_INIT,
|
|
(*smrp & TAAC_SMR_MASK) != TAAC_SMR_INIT) ?
|
|
0 : TAAC_PROBE_SIZE;
|
|
|
|
return (OK);
|
|
}
|
|
|
|
int taaclockenable = 1; /* patch to disable locking */
|
|
|
|
/*ARGSUSED*/
|
|
taacopen(dev, flag)
|
|
dev_t dev; int flag;
|
|
{
|
|
struct taac_softc *sc = &taac_softc[minor(dev)];
|
|
register struct mb_device *md;
|
|
|
|
if (minor(dev) >= NTAAC ||
|
|
(md = taacinfo[minor(dev)]) == 0 ||
|
|
md->md_alive == 0)
|
|
return (ENXIO);
|
|
|
|
if (taaclockenable){
|
|
if (sc->sc_count > 0){
|
|
if (u.u_uid != sc->sc_uid && u.u_uid != 0){
|
|
return (EBUSY);
|
|
} else {
|
|
sc->sc_count++;
|
|
}
|
|
} else {
|
|
sc->sc_uid = u.u_uid;
|
|
sc->sc_count++;
|
|
}
|
|
}
|
|
|
|
sc->sc_smrp = (unsigned *)taacinfo[minor(dev)]->md_addr;
|
|
|
|
if (taacdebug)
|
|
printf("taac0 (open): u: %d c: %d\n", sc->sc_uid, sc->sc_count);
|
|
|
|
return (0);
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
taacclose(dev, flag)
|
|
{
|
|
struct taac_softc *sc = &taac_softc[minor(dev)];
|
|
|
|
if (taacdebug)
|
|
printf("taac0 (close): u: %d c: %d\n", sc->sc_uid, sc->sc_count);
|
|
|
|
if (taaclockenable){
|
|
sc->sc_count = 0;
|
|
sc->sc_uid = -1;
|
|
}
|
|
|
|
if (sc->sc_flag & TA_PROFON){
|
|
sc->sc_flag &= ~(TA_PROFON);
|
|
|
|
if (sc->sc_kmp)
|
|
rmfree(kernelmap, (long)1, (u_long)sc->sc_kmp);
|
|
sc->sc_kmp = NULL;
|
|
|
|
if (sc->sc_pcdata)
|
|
kmem_free((caddr_t)sc->sc_pcdata, (u_int)TA_ISIZE * sizeof (short));
|
|
sc->sc_pcdata = NULL;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
#if defined(_MAP_NEW)
|
|
|
|
u_int hat_getkpfnum();
|
|
|
|
#endif
|
|
|
|
/*ARGSUSED*/
|
|
taacmmap(dev, off, prot)
|
|
dev_t dev; off_t off; int prot;
|
|
{
|
|
int addr;
|
|
|
|
if ((u_int) off >= TAAC_TOTAL_SIZE)
|
|
return (-1);
|
|
|
|
#if defined(_MAP_NEW)
|
|
addr = (int) hat_getkpfnum((addr_t)taacinfo[minor(dev)]->md_addr)
|
|
+ btop(off);
|
|
#else
|
|
addr = (getkpgmap(taacinfo[minor(dev)]->md_addr) & PG_PFNUM)
|
|
+ btop(off);
|
|
#endif
|
|
|
|
return (addr);
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
taacioctl(dev, cmd, data, flag)
|
|
dev_t dev; caddr_t data;
|
|
{
|
|
struct taac_softc *sc = &(taac_softc[minor(dev)]);
|
|
struct taac_softc *softc = &(taac_softc[minor(dev)]);
|
|
int i, pageval, error = 0;
|
|
|
|
switch (cmd){
|
|
case TIOCTEST:
|
|
if (taacdebug)
|
|
printf("taac0: ioctl test %x\n", *((int *)data));
|
|
break;
|
|
|
|
case TIOCPROFON:
|
|
if (taacdebug)
|
|
printf("taac0: ioctl prof on %x\n", *((int *)data));
|
|
|
|
if (sc->sc_flag & TA_PROFON)
|
|
return (EBUSY);
|
|
|
|
if ((sc->sc_pcdata =
|
|
(u_short *)kmem_alloc((u_int)TA_ISIZE * sizeof (short)))
|
|
== NULL)
|
|
return (ENOMEM); /* can't happen anyway, he said */
|
|
|
|
sc->sc_offset = *((int *)data) & 0x3fffff;
|
|
sc->sc_page = pagevals[*((int *)data) >> 27];
|
|
|
|
if ((sc->sc_kmp = rmalloc(kernelmap, (long)1)) == 0)
|
|
panic("taac: out of kernelmap for devices");
|
|
|
|
sc->sc_datap = (unsigned *)kmxtob(sc->sc_kmp);
|
|
|
|
#ifdef _MAP_NEW
|
|
pageval = hat_getkpfnum(taacinfo[0]->md_addr)
|
|
+ btop(sc->sc_offset + 0x1000000);
|
|
/*
|
|
* Pegasus use MC68030 memory management unit which does not
|
|
* use page table type bits.
|
|
*/
|
|
if ((cpu != IDM_SUN3X_PEGASUS))
|
|
pageval |= PGT_VME_D32;
|
|
|
|
segkmem_mapin(&kseg, (addr_t)sc->sc_datap, MMU_PAGESIZE,
|
|
(u_int)PROT_READ | PROT_WRITE, (u_int)pageval, 0);
|
|
#else
|
|
pageval = PGT_VME_D32 |
|
|
((getkpgmap(taacinfo[minor(dev)]->md_addr) & PG_PFNUM) +
|
|
btop(0x1000000 + sc->sc_offset));
|
|
sc->sc_offset &= 0x1fff;
|
|
mapin(&Usrptmap[sc->sc_kmp], btop(sc->sc_datap),
|
|
pageval, 1, PG_V|PG_KW);
|
|
#endif
|
|
|
|
sc->sc_flag |= TA_PROFON;
|
|
sc->sc_procp = u.u_procp;
|
|
|
|
for (i=0; i<TA_ISIZE; i++)
|
|
(sc->sc_pcdata)[i] = 0;
|
|
|
|
taactimeout(sc);
|
|
break;
|
|
|
|
case TIOCPROFOFF:
|
|
if (taacdebug)
|
|
printf("taac0: ioctl prof off %x\n", *((int *)data));
|
|
|
|
/*
|
|
* TODO: get our interupt priority up
|
|
*/
|
|
sc->sc_flag &= ~(TA_PROFON);
|
|
|
|
if (sc->sc_kmp)
|
|
rmfree(kernelmap, (long)1, (u_long)(sc->sc_kmp));
|
|
sc->sc_kmp = NULL;
|
|
|
|
if (copyout((caddr_t)(sc->sc_pcdata), *((caddr_t *)data),
|
|
TA_ISIZE * sizeof (short)))
|
|
error = EFAULT;
|
|
|
|
if (sc->sc_pcdata)
|
|
kmem_free((caddr_t)sc->sc_pcdata,
|
|
TA_ISIZE * sizeof (short));
|
|
sc->sc_pcdata = NULL;
|
|
|
|
break;
|
|
|
|
case TIOCDEBUG:
|
|
sc->sc_debug = *((int *)data);
|
|
break;
|
|
|
|
case FBIOGTYPE:
|
|
{
|
|
register struct fbtype *fb = (struct fbtype *) data;
|
|
|
|
/* fb->fb_type = FBTYPE_SUNTAAC; */
|
|
fb->fb_type = FBTYPE_NOTSUN3;
|
|
fb->fb_height = softc->h;
|
|
fb->fb_width = softc->w;
|
|
fb->fb_depth = softc->depth;
|
|
fb->fb_cmsize = 2 << softc->depth;
|
|
fb->fb_size = softc->size;
|
|
}
|
|
break;
|
|
|
|
#if NWIN > 0
|
|
|
|
case FBIOGPIXRECT:
|
|
((struct fbpixrect *) data)->fbpr_pixrect = &softc->pr;
|
|
|
|
softc->pr.pr_ops = &taac_ops;
|
|
softc->pr.pr_size.x = softc->w;
|
|
softc->pr.pr_size.y = softc->h;
|
|
softc->pr.pr_depth = softc->depth;
|
|
softc->pr.pr_data = (caddr_t) &softc->prd;
|
|
|
|
softc->prd.md_linebytes = mpr_linebytes(softc->w, 1);
|
|
softc->prd.md_image = (short *) softc->image;
|
|
softc->prd.md_offset.x = 0;
|
|
softc->prd.md_offset.y = 0;
|
|
softc->prd.md_primary = 0;
|
|
softc->prd.md_flags = MP_DISPLAY;
|
|
break;
|
|
|
|
#endif NWIN > 0
|
|
|
|
/*
|
|
* TODO: return hz
|
|
*/
|
|
default:
|
|
return (ENOTTY);
|
|
}
|
|
|
|
return (error);
|
|
}
|
|
|
|
taacread()
|
|
{
|
|
|
|
}
|
|
|
|
taacwrite()
|
|
{
|
|
|
|
}
|
|
|
|
taactimeout(sc)
|
|
struct taac_softc *sc;
|
|
{
|
|
unsigned oldsmr;
|
|
|
|
if (!sc->sc_flag & TA_PROFON)
|
|
return;
|
|
|
|
/*
|
|
s = spl7();
|
|
*/
|
|
|
|
oldsmr = *(sc->sc_smrp);
|
|
*(sc->sc_smrp) &= ~(TA_PAGEBITS | TA_TWODIM);
|
|
*(sc->sc_smrp) |= sc->sc_page;
|
|
|
|
(sc->sc_pcdata)[(*(sc->sc_datap)) & 0x3fff]++;
|
|
|
|
if (taacdebug)
|
|
printf("timeout: %x\n", (*(sc->sc_datap)) & 0x3fff);
|
|
|
|
*(sc->sc_smrp) = oldsmr;
|
|
|
|
/*
|
|
splx(s);
|
|
*/
|
|
|
|
timeout(taactimeout, (caddr_t)sc, 1);
|
|
|
|
return;
|
|
}
|