1
0
Files
2022-09-29 17:59:04 +03:00

1600 lines
44 KiB
C

#ident "lib/libsk/graphics/EXPRESS/gr2_init.c: $Revision: 1.66 $"
/*
* gr2_init.c - initialization functions for EXPRESS graphics
*/
#include "sys/sbd.h"
#include "sys/param.h"
#include "arcs/hinv.h"
#include "sys/gr2hw.h"
#include "sys/sema.h"
#include "sys/gr2.h"
#include "sys/cpu.h"
#include "sys/immu.h"
#include "vidtim.h"
#include "sys/gr2_if.h"
#include "mc.out.h"
#include "arcshqucout.h"
#include "arcsgeucout.h"
#include "cursor.h"
#include <libsc.h>
#include <libsk.h>
#if defined(IP19) || defined(IP21) || defined(IP25)
#include <sys/EVEREST/everest.h>
#include <sys/EVEREST/evconfig.h>
#include <sys/EVEREST/io4.h>
#include <sys/EVEREST/dang.h>
int tport_window=-1, tport_adap=-1;
int dang_inited = 0;
volatile long long *dang_ptr=(long long *)NULL;
static void *everest_dang_init(int , int, int);
static int find_dang(int, int *, int *);
#endif
#if defined(IP19)
static volatile struct _expPipeEntryRec *wg = (volatile struct _expPipeEntryRec *)EV_WGINPUT_BASE;
#define FIFO(x,y) wg[(x)].pipeUnion.l = (y)
#define FLUSHBUS() wg[0xff].pipeUnion.l = 0
#elif defined(IP21)
#define EVEN_OFFSET 0
#define FLUSH_OFFSET 4
static volatile union _expPipeEntryRec *wg = (volatile union _expPipeEntryRec *)EV_WGINPUT_BASE;
#define FIFO(x,y) { wg[EVEN_OFFSET].i = (x); wg[EVEN_OFFSET].i = (y); }
#define FLUSHBUS() wg[FLUSH_OFFSET].i = 0
#elif defined(IP25)
static volatile union _expPipeEntryRec *wg = (volatile union _expPipeEntryRec *)EV_WGINPUT_BASE;
#define FIFO(x,y) { wg[0].i = (x); wg[0].i = (y); }
#define FLUSHBUS() load_double((long long *)&dang_ptr[DANG_UPPER_GIO_ADDR])
#else
#define FIFO(x,y) base->fifo[(x)] = (y)
#define FLUSHBUS() *((volatile int *)PHYS_TO_K1(0x1fc00000))
#endif
extern unsigned char vc1_ptr_bits[];
extern unsigned char vc1_ptr_ol_bits[];
#if defined (FLAT_PANEL)
#include "sys/fpanel.h"
#endif /* FLAT_PANEL */
#define GR2_VR_TIMEOUT 20000
#define GR2_TIMEOUT_XMAP 10
extern struct tp_fncs gr2_tp_fncs;
#if IP22
int is_indyelan(void);
#endif
#if IP22 || IP26 || IP28
#define MAXGR2 2
#else
#define MAXGR2 1
#endif
struct gr2_info gr2_ginfo[MAXGR2];
#if defined(IP19) || defined(IP21) || defined(IP25)
struct gr2_hw *expr[] = {
(struct gr2_hw *)NULL, /* XXX need to create a page(s) to map the EXPRESS in GIO space */
(struct gr2_hw *)NULL
};
#else
struct gr2_hw *expr[] = {
(struct gr2_hw*)PHYS_TO_K1(GR2_BASE_PHYS),
#if IP22 || IP26 || IP28
(struct gr2_hw*)PHYS_TO_K1(GR2_BASE1_PHYS),
#endif /* IP22 || IP26 || IP28 */
(struct gr2_hw*)NULL
};
#endif
void Gr2TpMapcolor(void *,int,int,int,int);
extern COMPONENT montmpl; /* defined in gfx.c */
/******************************************************************************
*
* Check to see if a private bus GR2 type board is there.
*
* Returns:
* 0: board not found
* 1: found board, part of info struct filled in
*
*****************************************************************************/
int Gr2Probe(struct gr2_hw *hw)
{
if (badaddr(&hw->hq.mystery,4) || hw->hq.mystery != 0xdeadbeef) {
#if defined(IP19) || defined(IP21) || defined(IP25)
/* Clean up since we probably have a DANG timeout */
store_double((long long *)&dang_ptr[DANG_CLR_TIMEOUT], (long long)1); /*Clear timeout */
#endif
return 0;
}
else {
return 1;
}
}
static void Gr2InitInfo(struct gr2_hw *hw, struct gr2_info *info)
{
int vma, vmb, vmc;
int GR2version, VBversion;
GR2version = ~(hw->bdvers.rd0) & 0xf;
if (!GR2version) /* Gr2 board not found */
return;
else
{
info->BoardType = GR2_TYPE_GR2;
/* We found a board */
strncpy(info->gfx_info.name, GFX_NAME_GR2, GFX_INFO_NAME_SIZE);
info->gfx_info.length = sizeof(struct gr2_info);
/* Board rev. number */
info->GfxBoardRev = GR2version;
/* Video Backend Board rev. number */
if (GR2version < 4) {
VBversion = (~(hw->bdvers.rd2) & 0xc) >> 2;
} else {
VBversion = ~(hw->bdvers.rd1) & 0x3;
}
if (!VBversion) { /* Video Backend Board not found */
return;
}
info->VidBckEndRev = VBversion;
if (GR2version < 4) {
/* Zbuffer option installed */
if ((hw->bdvers.rd1 & 0xc) == 0xc)
info->Zbuffer = 0;
else
info->Zbuffer = 1;
vma = vmb = vmc = 0;
/* 8-bit vs 24-bit planes */
if ((hw->bdvers.rd3 & 0x3) != 0x3)
vma = 1;
if ((hw->bdvers.rd3 & 0xc) != 0xc)
vmb = 1;
if ((hw->bdvers.rd3 & 0x30) != 0x30)
vmc = 1;
/* XXXCheck if VRAMs are skipping any slots or
* not installed in order
*/
if (vma && vmb && vmc)
info->Bitplanes = 24;
else if (vma && vmb)
info->Bitplanes = 16; /* Not supportted */
else
info->Bitplanes = 8;
info->MonitorType = ((hw->bdvers.rd2 & 0x3) << 1) | (hw->bdvers.rd1 & 0x1);
} else {
if ((hw->bdvers.rd1 & 0x20) >> 5)
info->Zbuffer = 1;
else
info->Zbuffer = 0;
if ((hw->bdvers.rd1 & 0x10) >> 4)
info->Bitplanes = 24;
else
info->Bitplanes = 8;
info->MonitorType = (hw->bdvers.rd0 & 0xf0) >> 4;
}
/* Only 1 option for EXPRESS */
info->Auxplanes = 4;
info->Wids = 4;
if (info->MonitorType == 6)
{
/* We don't support this configuration */
info->gfx_info.xpmax = 1024;
info->gfx_info.ypmax = 768;
/* We don't support this configuration */
} else {
info->gfx_info.xpmax = 1280;
info->gfx_info.ypmax = 1024;
}
}
}
struct gr2_info *
getGr2Info(void *hw)
{
struct gr2_hw *express;
int i;
for (i = 0, express=expr[0]; express != 0; express=expr[++i]) {
if ((void *)express == hw)
return(&gr2_ginfo[i]);
}
return(0);
}
unsigned char clk107B[] = {
0xc4,0x0f,0x15,0x20,0x30,0x4c,0x50,0x60,
0x70,0x80,0x91,0xa5,0xb6,0xd1,0xe0,0xf0,0xc4};
/******************************************************************************
*
* Set up configuration register and start the clock.
*
*****************************************************************************/
unsigned char PLLclk132[] = {0x00,0x00,0x00,0x04,0x05,0x04,0x06};
unsigned char PLLclk107[] = {0x00,0x10,0x00,0x15,0x18,0x01,0x0F};
static void
Gr2StartClock(register struct gr2_hw *base, struct gr2_info *info)
{
register int i,j;
register unsigned char PLLbyte, *PLLclk = NULL;
if (info->GfxBoardRev < 4) {
if ((info->MonitorType & 0x7) == 1) { /* 72 HZ */
/* Select the 132 MHz crystal*/
base->bdvers.rd0 = 0x2;
} else if ((info->MonitorType & 0x7) != 6) { /* 60 HZ */
/* Select the 107.352 MHz crystal*/
base->bdvers.rd0 = 0x1;
}
/* Reset the VC1 chip
* Must give VC1 time to reset. Don't put this right before
* taking the VC1 out of reset
*/
base->bdvers.rd1 = 0x00;
/*
* Must always initialize programmable clock, even if not being used,
* else will run at max speed, and may affect system.
*/
if ((info->MonitorType & 0x7) != 6) { /* 1280 x 1024 */
for (i=0; i<sizeof(clk107B); i++)
base->clock.write = clk107B[i];
}
/* Take the VC1 out of reset and set configuration register
*in expanded backend mode
*/
base->bdvers.rd1 = 0x40;
} else { /* ultra, dual-head boards */
base->bdvers.rd0 = 0x47;
if ((info->MonitorType & 0x7) == 1) /* 72 HZ */
PLLclk = PLLclk132;
else if ((info->MonitorType & 0x7) != 6) /* 60 HZ */
PLLclk = PLLclk107;
if (PLLclk) {
for (i=0; i<7; i++) {
PLLbyte = PLLclk[i];
for (j=0;j<8;j++) {
if ((j == 7) && (i== 6))
base->clock.write = (PLLbyte & 0x1) | 0x2;
else
base->clock.write = PLLbyte & 0x1;
PLLbyte = PLLbyte >> 1;
}
}
}
base->bdvers.rd1 = 0x00;
DELAY(3);
base->bdvers.rd1 = 0x1;
}
}
static void Gr2DacInit(register struct gr2_bt457_dac *dac)
{
register int i;
dac->addr = GR2_DAC_READMASK;
dac->cmd2 = 0x0; /* Turn off DAC*/
dac->addr = GR2_DAC_BLINKMASK;
dac->cmd2 = 0;
dac->addr = GR2_DAC_CMD;
dac->cmd2 = GR2_DAC_5TO1MUX|GR2_DAC_RAMENBL|GR2_DAC_OL0ENBL;
dac->addr = GR2_DAC_TEST;
dac->cmd2 = 0;
/* Identity gamma ramp */
dac->addr = 0;
for (i = 0; i < GR2_DAC_NGAMMAENT; i++)
dac->paltram = i;
/* overlay color palette initialization */
dac->addr = 0;
for (i = 0; i < GR2_DAC_NOVLMAPENT; i++)
dac->ovrlay = i;
}
static void Gr2LoadVC1SRAM(
register struct gr2_hw *base, /* base address in K1 seg */
unsigned short *data,
unsigned int addr,
unsigned int length)
{
register int i;
base->vc1.addrhi = addr >> 8;
base->vc1.addrlo = addr & 0x00ff;
for (i = 0; i < length; i++)
base->vc1.sram = data[i];
}
/*
* The first section of XMAP initialization.
*/
static void
Gr2XMAPInit(
register struct gr2_hw *base, /* board base address in K1 seg */
struct gr2_info *info)
{
int pix_mode, pd_mode, pix_pg;
/*
* Initialize mode registers
*/
/* Init XMAP to 8 bit color index mode
* IMPT: Need to set color mode for textport bringup.
*/
base->xmapall.addrlo = 0;
base->xmapall.addrhi = 0;
/* Only the mode registers of DID 0(default) is initalized */
pix_mode = 2; /* 8-bit color index, buffer 0 */
pd_mode = 0;
pix_pg = 16; /* DID 0 only */
base->xmapall.mode = (((pix_pg<<3) | pix_mode) << 24) | (pd_mode<<16);
/*
* Initialize misc. registers
* XXX X server should write this when we get ext. fifo
*/
base->xmapall.addrlo = 0;
base->xmapall.addrhi = 0;
base->xmapall.misc = 0x0; /* red component of blackout value */
base->xmapall.misc = 0x0; /* green component of blackout value */
base->xmapall.misc = 0x0; /* blue component of blackout value */
/* color index GR2_CURSCMAP_BASE+1 will be used as normal cursor color
* for initialization
*/
base->xmapall.misc = 14; /* pgreg */
base->xmapall.misc = 0; /* cu_reg */
#if defined (FLAT_PANEL)
/*
* If we're using the flat panel display,
* enable output to the video connector.
*/
if (info->MonitorType == MONITORID_CORONA ||
info->MonitorType == MONITORID_ICHIBAN) {
base->xmap[0].fifostatus = 0xf;
base->xmap[1].fifostatus = 0xc;
base->xmap[2].fifostatus = 0xd;
base->xmap[3].fifostatus = 0xe;
base->xmap[4].fifostatus = 0xf;
i2cPanelOn();
}
#endif /* FLAT_PANEL */
}
/*Initialize hq2 internal registers */
static void Gr2HQ2RegInit(struct gr2_hw *base, struct gr2_info *info)
{
int i;
info->GEs = 1;
for (i=1; i<8; i++) {
/* Probing whether we have 1 or 4 or 8 GE's installed */
base->ge[i].ram0[0] = 0x1f1f1f1f;
base->ge[i].ram0[31] = 0x2e2e2e2e;
base->ge[i].ram0[63] = 0x3d3d3d3d;
base->ge[i].ram0[95] = 0x4c4c4c4c;
base->ge[i].ram0[127] = 0x5b5b5b5b;
if (base->ge[i].ram0[0] == 0x1f1f1f1f &&
base->ge[i].ram0[31] == 0x2e2e2e2e &&
base->ge[i].ram0[63] == 0x3d3d3d3d &&
base->ge[i].ram0[95] == 0x4c4c4c4c &&
base->ge[i].ram0[127] == 0x5b5b5b5b)
info->GEs = i+1;
}
/*
* configure numge register, including fast ShRAM buffer for ultra
*/
if (info->GEs == 8) {
base->hq.numge = HQ2_FASTSHRAMCNT_4 | info->GEs;
} else {
base->hq.numge = info->GEs;
}
base->hq.refresh = 0x10;
base->hq.fifo_full_timeout = 100;
/* Need to be finalized */
base->hq.fifo_empty_timeout = 10;
base->hq.fifo_full = 40;
/* No using it */
base->hq.fifo_empty = 1;
}
/******************************************************************************
*
* Probe all chip revisions.
*
*****************************************************************************/
static void Gr2ProbeChipRev(struct gr2_hw *base, struct gr2_info *info)
{
/* HQ2 rev. number */
info->HQ2Rev = base->hq.version >> 23;
/* GE7 rev. number */
base->ge[0].ram0[0xFD] = 0;
info->GE7Rev = (base->ge[0].ram0[0xFD] & 0xff) >> 5;
/* VC1 rev. number */
base->vc1.addrhi = 5 >> 8;
base->vc1.addrlo = 5 & 0x00ff;
info->VC1Rev = base->vc1.testreg & 0x7;
}
static void Gr2RegisterInit(struct gr2_hw *base, struct gr2_info *info)
{
register didnum;
register i;
unsigned short frtableDID[1024];
unsigned short ltableDID[8];
register ysize = info->gfx_info.ypmax; /* display resolution;
* XXX Shouldn't be hardcoded
*/
#define NPIX_NormMon 1279 /* Must be between 1276-1279, so VC1 will use
same DID # as previous pixel*/
/**********************************************************************
* Init CPU graphics registers
*********************************************************************/
#if IP20
/* clear vertical retrace interrupt */
*((volatile unchar*)PHYS_TO_K1(PORT_CONFIG)) &= ~PCON_CLEARVRI;
flushbus();
*((volatile unchar*)PHYS_TO_K1(PORT_CONFIG)) |= PCON_CLEARVRI;
#elif IP22
/* clear vertical retrace interrupt */
if (is_ioc1()) {
/* XXX - The IOC1 chip has fixed this hardware kludge and this code
* should be changed.
*/
/* INDY with Elan Board */
if(is_indyelan()) {
*((volatile int *)PHYS_TO_K1(HPC3_GEN_CONTROL)) &= ~0x1;
flushbus();
*((volatile int *)PHYS_TO_K1(HPC3_GEN_CONTROL)) |= 0x00000001;
}
}
else {
*((volatile unchar*)PHYS_TO_K1(PORT_CONFIG)) &=
~(PCON_CLR_SG_RETRACE_N|PCON_CLR_S0_RETRACE_N);
flushbus();
*((volatile unchar*)PHYS_TO_K1(PORT_CONFIG)) |=
(PCON_CLR_SG_RETRACE_N|PCON_CLR_S0_RETRACE_N);
}
#elif IP26 || IP28
*((volatile unchar*)PHYS_TO_K1(PORT_CONFIG)) &=
~(PCON_CLR_SG_RETRACE_N|PCON_CLR_S0_RETRACE_N);
flushbus();
*((volatile unchar*)PHYS_TO_K1(PORT_CONFIG)) |=
(PCON_CLR_SG_RETRACE_N|PCON_CLR_S0_RETRACE_N);
#endif
/**********************************************************************
* Init DACs
*********************************************************************/
Gr2DacInit(&base->reddac);
Gr2DacInit(&base->grndac);
Gr2DacInit(&base->bluedac);
/**********************************************************************
* Init VC1
*********************************************************************/
/*
* Disable interrupt to VC1, blackout the display.
* GR2_VC1_INTERRUPT
* Don't use macro.
*/
base->vc1.sysctl = 0x1;
/*
* Load video timing table
* Timing table for cursor to move
* from off screen on the left,
* to 1023
* On older (GR2version < 4) systems
* there are 3 bits of monitor id, one newer there are 4, and
* on IndyElan, we have cleverly used bit 7 to indicate a
* flat panel display is present. Hence the multi-labeled cases
* in the switch below.
*/
switch(info->MonitorType)
{
/* 72HZ Monitor */
case 1: /* Mitsubishi 19" monitor, or Sony 19" 72HZ only */
case 9:
Gr2LoadVC1SRAM(base, (unsigned short *)ltableH72, GR2_VIDTIM_LST_BASE,
sizeof(ltableH72)/sizeof(short));
Gr2LoadVC1SRAM(base, (unsigned short *)frtableH72, GR2_VIDTIM_FRMT_BASE,
sizeof(frtableH72)/sizeof(short));
Gr2LoadVC1SRAM(base, (unsigned short *)ltableH72_400,
GR2_VIDTIM_CURSLST_BASE, sizeof(ltableH72_400)/sizeof(short));
Gr2LoadVC1SRAM(base, (unsigned short *)frtableH72_400,
GR2_VIDTIM_CURSFRMT_BASE, sizeof(frtableH72_400)/sizeof(short));
break;
case 6:
case 14:
break;
#if defined (FLAT_PANEL)
case MONITORID_CORONA:
/* low-res flat panel display */
/* Since the flat panel is low-res we
only need 1 timing table (no vc1 cursor
bug to work around in this case) */
Gr2LoadVC1SRAM(base, (unsigned short *)ltableFP, GR2_VIDTIM_LST_BASE,
sizeof(ltableFP)/sizeof(short));
Gr2LoadVC1SRAM(base, (unsigned short *)frtableFP, GR2_VIDTIM_FRMT_BASE,
sizeof(frtableFP)/sizeof(short));
break;
case MONITORID_ICHIBAN : /* hi-res flat panel display */
Gr2LoadVC1SRAM(base, (unsigned short *)ltableIchiban,
GR2_VIDTIM_LST_BASE,
sizeof(ltableIchiban)/sizeof(short));
Gr2LoadVC1SRAM(base, (unsigned short *)frtableIchiban,
GR2_VIDTIM_FRMT_BASE,
sizeof(frtableIchiban)/sizeof(short));
Gr2LoadVC1SRAM(base, (unsigned short *)ltableIchiban_400,
GR2_VIDTIM_CURSLST_BASE,
sizeof(ltableIchiban_400)/sizeof(short));
Gr2LoadVC1SRAM(base, (unsigned short *)frtableIchiban_400,
GR2_VIDTIM_CURSFRMT_BASE,
sizeof(frtableIchiban_400)/sizeof(short));
break;
#endif /* FLAT_PANEL */
default:
Gr2LoadVC1SRAM(base, (unsigned short*)ltableH60, GR2_VIDTIM_LST_BASE,
sizeof(ltableH60)/sizeof(short));
Gr2LoadVC1SRAM(base, (unsigned short*)frtableH60,
GR2_VIDTIM_FRMT_BASE,
sizeof(frtableH60)/sizeof(short));
/* Timing table for cursor to move
* from 1024,
* to offscreen on the right.
*
* Line table is loaded at 0x400 in VC1 SRAM.
*/
Gr2LoadVC1SRAM(base, (unsigned short*)ltableH60_400,
GR2_VIDTIM_CURSLST_BASE,
sizeof(ltableH60_400)/sizeof(short));
Gr2LoadVC1SRAM(base, (unsigned short*)frtableH60_400,
GR2_VIDTIM_CURSFRMT_BASE,
sizeof(frtableH60_400)/sizeof(short));
break;
}
/*
* Load DID table
*/
/*XXX found out where defines the X,Y resolution */
/*XXX REPLACE 1023 later */
/*XXX Need modify, if VC1 supports line repeat count */
for (i = 0; i < ysize - 1; i++)
frtableDID[i] = GR2_DID_LST_BASE;
/* HACK, bug in VC1. 4 dummy DID needed. */
frtableDID[i] = GR2_DID_LST_BASE + 4;
for (didnum = 0; didnum < 1; didnum++) {
ltableDID[didnum*8] = 1;
ltableDID[didnum*8+1] = didnum; /* Same DID for whole line */
/*
* HACK, bug in VC1. 4 dummy DID with the previous scanline
* entry needed at the end of LST.
*/
ltableDID[didnum*8+2] = ltableDID[didnum*8] + 4;
ltableDID[didnum*8+3] = ltableDID[didnum*8+1];
for (i = 4; i <= 7; i++)
ltableDID[(didnum*8)+i] = 0;
}
Gr2LoadVC1SRAM(base, ltableDID, GR2_DID_LST_BASE, sizeof(ltableDID));
Gr2LoadVC1SRAM(base, frtableDID, GR2_DID_FRMT_BASE, ysize);
/* Load entry pointer of the video timing table */
base->vc1.addrhi = (GR2_VID_EP >> 8) & 0xff;
base->vc1.addrlo = GR2_VID_EP & 0xff;
if (info->gfx_info.xpmax > 1025)
base->vc1.cmd0 = GR2_VIDTIM_CURSFRMT_BASE;
else
base->vc1.cmd0 = GR2_VIDTIM_FRMT_BASE;
/* Load GR2_VID_ENAB */
base->vc1.addrhi = (GR2_VID_ENAB >> 8) & 0xff;
base->vc1.addrlo = GR2_VID_ENAB & 0xff;
/* Always write in pair of bytes, even only 1 byte data is needed */
base->vc1.cmd0 = 0;
/* Load registers of DID table */
base->vc1.addrhi = (GR2_DID_EP >> 8) & 0xff;
base->vc1.addrlo = GR2_DID_EP & 0xff;
base->vc1.cmd0 = GR2_DID_FRMT_BASE;
base->vc1.cmd0 = GR2_DID_FRMT_BASE +
(unsigned short)(ysize*sizeof(short));
base->vc1.cmd0 = ((NPIX_NormMon / 5) << 8) | (NPIX_NormMon % 5);
/* Load black out control registers */
base->vc1.addrhi = (GR2_BLKOUT_EVEN >> 8) & 0xff;
base->vc1.addrlo = GR2_BLKOUT_EVEN & 0xff;
base->vc1.cmd0 = 0; /* index 0 of the color map */
{
unsigned short buf[128];
bzero(buf, sizeof(buf));
for (i = 0; i < 16; i++) {
buf[i*2] = (vc1_ptr_bits[i*2] << 8)
| vc1_ptr_bits[i*2+1];
}
for (i = 0; i < 16; i++) {
buf[64+i*2] = (vc1_ptr_ol_bits[i*2] << 8)
| vc1_ptr_ol_bits[i*2+1];
}
Gr2LoadVC1SRAM(base, buf, GR2_CURSOR0_BASE,
sizeof(buf)/sizeof(short));
base->vc1.addrhi = GR2_CUR_EP >> 8;
base->vc1.addrlo = GR2_CUR_EP & 0xff;
base->vc1.cmd0 = GR2_CURSOR0_BASE; /* CUR_EP */
base->vc1.cmd0 = 0x000; /* CUR_XL */
base->vc1.cmd0 = 0x000; /* CUR_XY */
base->vc1.cmd0 = 0x000; /* normal cursor mode */
}
/* Enable VC1, cursor function and display, DID display
* GR2_VC1_VC1 | GR2_VC1_DID | GR2_VC1_CURSOR| GR2_VC1_CURSOR_DISPLAY
* Don't use macro.
*/
base->vc1.sysctl = GR2_VC1_VC1 | GR2_VC1_DID
| GR2_VC1_CURSOR | GR2_VC1_CURSOR_DISPLAY;
/**********************************************************************
* Init XMAPs
*********************************************************************/
Gr2XMAPInit(base, info);
/**********************************************************************
* Init other misc. regs.
*********************************************************************/
Gr2HQ2RegInit(base, info);
Gr2ProbeChipRev(base, info);
}
/*
* Textport and diagnostic compiled in microcode. Allows a standalone
* executable to contain its own microcode.
*/
/*****************************************************************************
* Set up the textport microcode.
*****************************************************************************/
extern int _prom;
static mcout_t *Gr2TpHQUcodeSetup(void)
{
mcout_t *hqptr = (mcout_t *)(hq_ucode_str.hq_ucode);
if (!_prom) /* cannot write to prom .data! */
#if IP20
strcpy(hqptr->version, "IP20/GR2 PROM HQ Microcode\n");
#elif IP22
strcpy(hqptr->version, "IP22/GR2 PROM HQ Microcode\n");
#elif IP19
strcpy(hqptr->version, "IP19/GR2 PROM HQ Microcode\n");
#elif IP21
strcpy(hqptr->version, "IP21/GR2 PROM HQ Microcode\n");
#elif IP25
strcpy(hqptr->version, "IP25/GR2 PROM HQ Microcode\n");
#elif IP26
strcpy(hqptr->version, "IP26/GR2 PROM HQ Microcode\n");
#elif IP28
strcpy(hqptr->version, "IP28/GR2 PROM HQ Microcode\n");
#endif
return hqptr;
}
static mcout_t *Gr2TpGEUcodeSetup(void)
{
mcout_t *geptr = (mcout_t *)(ge_ucode_str.ge_ucode);
if (!_prom) /* cannot write to prom .data! */
#if IP20
strcpy(geptr->version, "IP20/GR2 PROM GE Microcode\n");
#elif IP22
strcpy(geptr->version, "IP22/GR2 PROM GE Microcode\n");
#elif IP19
strcpy(geptr->version, "IP19/GR2 PROM GE Microcode\n");
#elif IP21
strcpy(geptr->version, "IP21/GR2 PROM GE Microcode\n");
#elif IP25
strcpy(geptr->version, "IP25/GR2 PROM GE Microcode\n");
#elif IP26
strcpy(geptr->version, "IP26/GR2 PROM GE Microcode\n");
#elif IP28
strcpy(geptr->version, "IP28/GR2 PROM GE Microcode\n");
#endif
return geptr;
}
static int Gr2DownloadHQ2(struct gr2_hw *base, mcout_t *hq_ucode)
{
HQ_RECORD *baseptr;
unsigned short *code_start;
int record_count, i,error;
if(hq_ucode == 0)
return 0;
#ifdef DEBUG
/* In case, f_magic is incorrect, you'll be able to see what ucode is
* being loaded.
*/
printf("Magic : %x\n", hq_ucode->f_magic);
printf("Version : %s", hq_ucode->version);
printf("Date : %s", hq_ucode->date);
printf("Path : %s\n", hq_ucode->path);
printf("Length : %d bytes per microword => %d bit control word\n",
hq_ucode->length, hq_ucode->length * 8);
#endif
if (hq_ucode->f_magic != HQ2_MAGIC) {
return 0;
}
/* Load HQ2 attribute jump table */
for (i = 0; i < 16; i++) {
base->hq.attrjmp[i] = hq_ucode->data[i];
}
code_start = (unsigned short *)
((__psunsigned_t)hq_ucode + hq_ucode->f_codeoff);
record_count = 0;
while (1) {
baseptr = (HQ_RECORD*)code_start;
if (baseptr->address == 0xffff)
break;
base->hqucode[baseptr->address]
= (baseptr->ucode[0] << 16) | baseptr->ucode[1];
code_start += (hq_ucode->length + 6)/sizeof(short);
record_count++;
}
code_start = (unsigned short *)
((__psunsigned_t)hq_ucode + hq_ucode->f_codeoff);
error = 0;
while (1) {
baseptr = (HQ_RECORD*)code_start;
if (baseptr->address == 0xffff)
break;
if (((baseptr->ucode[0] << 16)
| baseptr->ucode[1]) != base->hqucode[baseptr->address]) {
#ifdef DEBUG
printf("ERROR in hq ucode **** Address -> %x expected -> %x actual -> %x\n",
baseptr->address,
base->hqucode[baseptr->address],
((baseptr->ucode[0]<<16) | baseptr->ucode[1]));
#endif
error++;
}
code_start += (hq_ucode->length + 6)/sizeof(short);
}
if (error) {
#ifdef DEBUG
printf("%d errors were detected in hq_ucode\n", error);
#endif
return 0;
} else {
#ifdef DEBUG
printf("Download was successful no errors detected.....\n");
printf("%d Microcode Records Downloaded..\n\n", record_count);
#endif
return 1;
}
}
#define GE7URAM_SIZE 64*1024
static int Gr2DownloadGE7(struct gr2_hw *base, mcout_t *ge_ucode)
{
GE_RECORD *baseptr;
unsigned short *code_start;
int record_count, i, error, sherror;
if(ge_ucode == 0)
return 0;
#ifdef DEBUG
/* In case, f_magic is incorrect, you'll be able to see what ucode is
* being loaded.
*/
printf("Magic : %x\n", ge_ucode->f_magic);
printf("Version : %s", ge_ucode->version);
printf("Date : %s", ge_ucode->date);
printf("Path : %s\n", ge_ucode->path);
printf("Length : %d bytes per microword => %d bit control word\n",
ge_ucode->length, ge_ucode->length * 8);
#endif
if (ge_ucode->f_magic != GE7_MAGIC) {
return 0;
}
for (i = 0; i < 512; i++)
base->shram[CONSTMEM + i] = ge_ucode->data[i];
sherror = 0;
for (i = 0; i < 512; i++) {
if( base->shram[CONSTMEM + i] != ge_ucode->data[i]) {
printf("ERROR in loading constants**** Shram Location -> %x expected -> %x actual -> %x\n",
CONSTMEM + i, ge_ucode->data[i], base->shram[CONSTMEM + i]);
sherror++;
}
}
#ifdef DEBUG
if (sherror)
printf("%d errors were detected in shram constants\n",sherror);
#endif
/* Clear GE ucode ram with zeros to workaround ucode/RAM initialization
* problem.
*/
for (i=0; i< GE7URAM_SIZE;i++)
{
base->hq.gepc = i;
base->ge[0].ram0[0xf8] = 0x0;
base->ge[0].ram0[0xf9] = 0x0;
base->ge[0].ram0[0xfa] = 0x0;
base->ge[0].ram0[0xfb] = 0x0;
base->hq.ge7loaducode = 0x0;
}
code_start = (unsigned short *)
((__psunsigned_t)ge_ucode + ge_ucode->f_codeoff);
record_count = 0;
while (1) {
baseptr = (GE_RECORD*)code_start;
if (baseptr->address == 0xffff)
break;
base->hq.gepc = baseptr->address;
base->ge[0].ram0[0xf8]
= (baseptr->ucode[8] << 16 ) | baseptr->ucode[9];
base->ge[0].ram0[0xf9]
= (baseptr->ucode[6] << 16 ) | baseptr->ucode[7];
base->ge[0].ram0[0xfa]
= (baseptr->ucode[4] << 16 ) | baseptr->ucode[5];
base->ge[0].ram0[0xfb]
= (baseptr->ucode[2] << 16 ) | baseptr->ucode[3];
base->hq.ge7loaducode
= (baseptr->ucode[0] << 16 ) | baseptr->ucode[1];
code_start += (ge_ucode->length + 6)/sizeof(short);
record_count++;
}
code_start = (unsigned short *)
((__psunsigned_t)ge_ucode + ge_ucode->f_codeoff);
error = 0;
while (1) {
baseptr = (GE_RECORD*)code_start;
if (baseptr->address == 0xffff)
break;
base->hq.gepc = baseptr->address;
if ((base->hq.ge7loaducode & 0x3dfffff)
!= (((baseptr->ucode[0] << 16)
| baseptr->ucode[1]) & 0x3dfffff)) {
#ifdef DEBUG
printf("ERROR: ge7ucodeload [25:0] to HQ, offset 0x%x\n",baseptr->address);
printf("\texpected 0x%x, returned 0x%x\n",(((baseptr->ucode[0] << 16 ) | baseptr->ucode[1]) & 0x3dfffff), (base->hq.ge7loaducode & 0x3dfffff));
#endif
error++;
}
if (base->ge[0].ram0[0xf8]
!= ((baseptr->ucode[8] << 16) | baseptr->ucode[9])) {
#ifdef DEBUG
printf("ERROR: Bits[31:0] GE7ucode, offset 0x%x\n",
baseptr->address);
printf("\texpected 0x%x, returned 0x%x\n",
((baseptr->ucode[8] << 16 ) | baseptr->ucode[9]), base->ge[0].ram0[0xf8]);
#endif
error++;
}
if (base->ge[0].ram0[0xf9]
!= ((baseptr->ucode[6] << 16) | baseptr->ucode[7])) {
#ifdef DEBUG
printf("ERROR: Bits [63:32] GE7ucode, offset 0x%x\n",
baseptr->address);
printf("\texpected 0x%x, returned 0x%x\n",
((baseptr->ucode[6] << 16 ) | baseptr->ucode[7]), base->ge[0].ram0[0xf9]);
#endif
error++;
}
if (base->ge[0].ram0[0xfa]
!= ((baseptr->ucode[4] << 16 ) | baseptr->ucode[5])) {
#ifdef DEBUG
printf("ERROR: Bits [95:64] GE7ucode, offset 0x%x\n",
baseptr->address);
printf("\texpected 0x%x, returned 0x%x\n",
((baseptr->ucode[4] << 16) | baseptr->ucode[5]),base->ge[0].ram0[0xfa]);
#endif
error++;
}
if ((base->ge[0].ram0[0xfb] & 0x7f)
!= (((baseptr->ucode[2] << 16) | baseptr->ucode[3]) & 0x7f)) {
#ifdef DEBUG
printf("ERROR: Bits [102:96] GE7ucode, offset 0x%x\n",
baseptr->address);
printf("\texpected 0x%x, returned 0x%x\n",
(((baseptr->ucode[2] << 16) | baseptr->ucode[3]) & 0x7f),(base->ge[0].ram0[0xfb] & 0x7f));
#endif
error++;
}
code_start += (ge_ucode->length + 6)/sizeof(short);
}
#ifdef DEBUG
if (error)
printf("%d errors were detected in ge_ucode\n", error);
else {
printf("GE7 ucode download was successful -- no errors detected\n");
printf("%d Microcode Records Downloaded...\n", record_count);
}
#endif
return 1;
}
static int Gr2TpSetup(struct gr2_hw *base, struct gr2_info *info)
{
if (Gr2DownloadHQ2(base,Gr2TpHQUcodeSetup()) == 0) {
base->shram[TP_PROBE_ID] = 0;
return -1;
}
if (Gr2DownloadGE7(base,Gr2TpGEUcodeSetup()) == 0) {
base->shram[TP_PROBE_ID] = 0;
return -1;
}
/* Set GE pc to 0 */
base->hq.gepc = 0;
/* Unstall HQ and GE */
base->hq.unstall = 0;
switch(info->GfxBoardRev) {
case 0:
case 1:
case 2:
case 3:
FIFO(PUC_INIT,0);
break;
case 4:
case 9:
case 10:
case 11:
FIFO(PUC_INIT,1);
break;
case 5:
case 6:
case 7:
case 8:
default:
FIFO(PUC_INIT,2);
break;
}
FLUSHBUS(); /* make sure init completes */
DELAY(9);
base->shram[TP_PROBE_ID] = UCODE_TP;
return 0;
}
static void Gr2SetCursorColor(struct gr2_hw *hw,
int fr, int fg, int fb, int br, int bg, int bb)
{
Gr2TpMapcolor(hw, GR2_CURSCMAP_BASE-4096 + 1, fr, fg, fb);
Gr2TpMapcolor(hw, GR2_CURSCMAP_BASE-4096 + 2, br, bg, bb);
}
static void Gr2Init(struct gr2_hw *hw, struct gr2_info *info)
{
/* must reset the graphics board in case ucode is running
*/
#if IP22
unsigned char mask;
if(is_fullhouse()) {
mask = (hw == (struct gr2_hw *)PHYS_TO_K1(GR2_BASE_PHYS)) ?
PCON_SG_RESET_N :
PCON_S0_RESET_N ;
*(volatile unsigned char *)PHYS_TO_K1(PORT_CONFIG) &= ~mask;
flushbus();
DELAY(5);
*(volatile unsigned char *)PHYS_TO_K1(PORT_CONFIG) |= mask;
flushbus();
} else if(is_indyelan()) { /* Indy Elan Graphics */
*(volatile unsigned int *)PHYS_TO_K1(CPU_CONFIG) &= ~CONFIG_GRRESET;
flushbus();
DELAY(5);
*(volatile unsigned int *)PHYS_TO_K1(CPU_CONFIG) |= CONFIG_GRRESET;
flushbus();
}
#elif defined(IP26) || defined(IP28)
unsigned char mask;
mask = (hw == (struct gr2_hw *)PHYS_TO_K1(GR2_BASE_PHYS)) ?
PCON_SG_RESET_N :
PCON_S0_RESET_N ;
*(volatile unsigned char *)PHYS_TO_K1(PORT_CONFIG) &= ~mask;
flushbus();
DELAY(5);
*(volatile unsigned char *)PHYS_TO_K1(PORT_CONFIG) |= mask;
flushbus();
#elif defined(IP19) || defined(IP21) || defined(IP25)
store_double((long long *)&dang_ptr[DANG_GIORESET],(long long)0);
DELAY(10);
store_double((long long *)&dang_ptr[DANG_GIORESET],(long long)1);
#else
*(volatile unsigned int *)PHYS_TO_K1(CPU_CONFIG) &= ~CONFIG_GRRESET;
flushbus();
DELAY(5);
*(volatile unsigned int *)PHYS_TO_K1(CPU_CONFIG) |= CONFIG_GRRESET;
flushbus();
#endif
Gr2InitInfo(hw, info);
/*
* Start the clock and set up the configuration
*/
Gr2StartClock(hw, info);
#if defined (FLAT_PANEL)
{
int panel = 0xdeadbeef;
/*
* No video support, check for flat panel. If
* we find one, we'll use it as the display.
*/
if ( gr2_i2cProbe(hw) && i2cSetup() &&
i2cPanelID(&panel) &&
(panel == PANEL_XGA_MITSUBISHI ||
panel == PANEL_EWS_MITSUBISHI))
{
unsigned char *PLLclk, PLLbyte;
int i,j;
i2cPanelOff(); /* reduct flash! */
switch (panel) {
case PANEL_EWS_MITSUBISHI :
info->MonitorType = MONITORID_ICHIBAN;
info->gfx_info.xpmax = 1280;
info->gfx_info.ypmax = 1024;
PLLclk = PLLclkIchiban;
break;
case PANEL_XGA_MITSUBISHI :
info->MonitorType = MONITORID_CORONA;
info->gfx_info.xpmax = 1025;
info->gfx_info.ypmax = 768;
PLLclk = PLLclkFP;
#if IP22 || IP26 || IP28
/* The Indigo2 logo does not
fit on the small screen */
if (is_fullhouse())
logoOff();
#endif
break;
}
/* Re-program clock to flat panel clock */
hw->bdvers.rd0 = 0x47;
for (i=0; i<7; i++) {
PLLbyte = PLLclk[i];
for (j=0;j<8;j++) {
if ((j == 7) && (i== 6))
hw->clock.write = (PLLbyte & 0x1) | 0x2;
else
hw->clock.write = PLLbyte & 0x1;
PLLbyte = PLLbyte >> 1;
}
}
hw->bdvers.rd1 = 0x00;
DELAY(3);
hw->bdvers.rd1 = 0x1;
}
}
#endif /* FLAT_PANEL */
/*
* Initialize registers. Screen will be blanked.
*/
Gr2RegisterInit(hw, info);
/* download ucode (tport & diag) */
Gr2TpSetup(hw,info);
/* init cursor color */
Gr2SetCursorColor(hw, 0xff, 0, 0, 0xff, 0xff, 0xff);
}
int
Gr2ProbeAll(char *base[])
{
struct gr2_hw *express;
int i, bd = 0;
/* Init all express boards, but use first found as default.
*/
for (i = 0, express=expr[0]; express != 0; express=expr[++i]) {
if (Gr2Probe(express)) {
Gr2Init(express, &gr2_ginfo[i]);
base[bd++] = (char *)express;
}
}
return bd;
}
/*
* Probe routine set by .cf file and used by the textport. The tp calls
* with fncs=0, and we return the base of the next EXPRESS board. If fncs
* is != 0, we return the functions for the graphics board at base.
*/
void *
gr2_probe(struct tp_fncs **fncs)
{
static char *base[MAXGR2+1];
static int i;
#if defined(IP19) || defined(IP21) || defined(IP25)
int slot;
void *gio_va; /* Virtual address of GIO 0x1f000000 */
#endif
if (fncs) {
*fncs = &gr2_tp_fncs;
i = 0;
return 0;
}
#if defined(IP19) || defined(IP21) || defined(IP25)
/* In an IP19 or IP21 Everest chassis.
* Look for the presence of DANG chip, figure out the Ibus
* slot and Ibus adapter number.
*/
if (!dang_inited) {
if ((slot = find_dang(0,&tport_window,&tport_adap)) == -1) {
/* Can't find the DANG chip, assume no gr2 present */
return 0;
}
else {
dang_ptr = (volatile long long *)SWIN_BASE(tport_window,tport_adap);
}
/* Initialise the DANG chip in the given slot, window, and adapter
* number. Allocate a virtual page that maps onto the EXPRESS
* area within the GIO.
*/
gio_va = everest_dang_init(slot,tport_window,tport_adap);
expr[0] = (struct gr2_hw *)gio_va;
dang_inited = 1;
}
#endif
/* allow looping to get multiple heads */
if (i == 0) {
bzero(base,sizeof(base));
Gr2ProbeAll(base);
}
if (i >= MAXGR2+1)
return 0;
return (void *)base[i++];
}
/*
* Re-probe for EXPRESS graphics boards and add them to the hardware config
*/
int
gr2_install(COMPONENT *root)
{
char idbuf[44]; /* max is "SGI-GR2-XZ missing bitplanes missing Z" */
COMPONENT *tmp, gr2tmpl;
struct gr2_info *pinfo;
struct gr2_hw **pexpr;
extern int gfxboard;
int i;
#if defined(IP19) || defined(IP21) || defined(IP25)
void *gio_va; /* Virtual address of GIO 0x1f000000 */
int slot;
if (!dang_inited) {
if ((slot = find_dang(0,&tport_window,&tport_adap)) == -1) {
/* Can't find the DANG chip, assume no gr2 present */
return 0;
}
else {
dang_ptr = (volatile long long *)SWIN_BASE(tport_window,tport_adap);
}
/* Initialise the DANG chip in the given slot, window, and adapter
* number. Allocate a virtual page that maps onto the EXPRESS
* area within the GIO.
*/
gio_va = everest_dang_init(slot,tport_window,tport_adap);
expr[0] = (struct gr2_hw *)gio_va;
dang_inited = 1;
}
#endif
gr2tmpl.Class = ControllerClass;
gr2tmpl.Type = DisplayController;
gr2tmpl.Flags = ConsoleOut|Output;
gr2tmpl.Version = SGI_ARCS_VERS;
gr2tmpl.Revision = SGI_ARCS_REV;
gr2tmpl.Key = 0;
gr2tmpl.AffinityMask = 0x01;
gr2tmpl.ConfigurationDataSize = 0;
gr2tmpl.Identifier = idbuf;
for(i=0, pexpr=expr; *pexpr != 0; pexpr++,i++) {
if (Gr2Probe(*pexpr)) {
char *ext;
pinfo = &gr2_ginfo[i];
/* Info is not initialized make sure we kill
* lingering magic number, then probe enough
* to figure out board type.
*/
if (pinfo->GEs == 0) {
(*pexpr)->shram[TP_PROBE_ID] = 0;
Gr2InitInfo(*pexpr,pinfo);
Gr2HQ2RegInit(*pexpr,pinfo);
}
/* figure out GR2 config:
* Ultra - 8 GE, 24 bit, with Z
* Elan - 4 GE, 24 bit, with Z
* XZ - 2 GE, 24 bit, with Z
* XS24 - 1 GE, 24 bit, opt Z
* XSM - 4 GE, 8 bit, no Z (ala Siemens)
* XS - 1 GE, 8 bit, opt Z
*/
#if IP20
strcpy(gr2tmpl.Identifier,"SGI-GR2");
#else
switch(pinfo->GfxBoardRev) {
case 0:
case 1:
case 2:
case 3:
strcpy(gr2tmpl.Identifier,"SGI-GR2");
break;
case 4:
strcpy(gr2tmpl.Identifier,"SGI-GR3");
break;
case 9:
case 10:
case 11:
strcpy(gr2tmpl.Identifier,"SGI-GR5");
break;
case 5:
case 6:
case 7:
case 8:
default:
strcpy(gr2tmpl.Identifier,"SGI-GU1");
break;
}
#endif
switch (pinfo->GEs) {
case 8:
ext = "-Extreme";
break;
case 4:
if (pinfo->Bitplanes == 24) {
ext = "-Elan";
#if defined(IP22)
if(is_indyelan())
ext = "-XZ";
#endif
switch (pinfo->GfxBoardRev) {
case 9:
case 10:
case 11:
ext = "-XZ";
break;
default:
break;
}
}
else
ext = "-XSM";
break;
case 2:
ext = "-XZ";
if (pinfo->Bitplanes != 24) {
strcat(gr2tmpl.Identifier,ext);
ext = " missing bitplanes";
}
if (pinfo->Zbuffer == 0) {
strcat(gr2tmpl.Identifier,ext);
ext = " missing Z";
}
break;
case 1: /* 1 GE */
if (pinfo->Bitplanes == 24)
ext = "-XS24";
else
ext = "-XS";
if (pinfo->Zbuffer) {
strcat(gr2tmpl.Identifier,ext);
ext = "Z";
}
break;
default:
ext = " unknown GE configuration";
break;
}
strcat(gr2tmpl.Identifier, ext);
gr2tmpl.IdentifierLength = strlen(gr2tmpl.Identifier);
tmp = AddChild(root, &gr2tmpl, (void*)NULL);
if (tmp == (COMPONENT*)NULL)
cpu_acpanic("gr2");
tmp->Key = gfxboard++;
RegisterDriverStrategy(tmp, _gfx_strat);
if (pinfo->MonitorType != 7) {
tmp = AddChild(tmp, &montmpl, (void*)NULL);
if (tmp == (COMPONENT*)NULL)
cpu_acpanic("monitor");
}
}
}
return (1);
}
#if defined(IP19) || defined(IP21) || defined(IP25)
#ifdef IP19
/* This routine maps virtual address 0xf0000000 to 0xf0ffffff to
* first 16Mb of the given pfn.
*
* Returns:
* virtual address of a 16Mb page that maps onto the given pfn.
*/
static void
*alloc_gfxspace(int pfn)
{
__psunsigned_t va;
int old_pgmask;
union pte_int {
pte_t pte;
int x;
} pteevn, pteodd;
#define IOMAP_TLBPAGEMASK 0x1ffe000
va = (unsigned)0xf0000000;
pteevn.x = (((pfn) << 6) | (2 << 3) | (1 << 2) | (1 << 1) | 1);
pteodd.x = 0;
old_pgmask = get_pgmask();
set_pgmask(IOMAP_TLBPAGEMASK);
tlbwired(0,0,(caddr_t)va,pteevn.x,pteodd.x); /* Use entry 0 only, it is reserved for graphics */
set_pgmask(old_pgmask);
return((void *)va);
}
#endif /* IP19 */
/*
* Given a logical DANG number, find the physical slot
* number of the IO4 attached to the given DANG, and return
* the window number as well as the adapter number that is
* associated with the given DANG chip.
*
* Returns:
* -1 Can't find the given DANG.
* Physical slot number of the IO4 connected to the given DANG
*/
static int
find_dang(int dangnum, int *window, int *adapter)
{
evcfginfo_t *cfginfo = EVCFGINFO;
evbrdinfo_t *brd;
int slot;
int dang_found = 0;
int adap;
/*
* Start from the highest physical slot number. The convention
* is that the first DANG is attached to the IO4 located
* at the highest physical slot. The last DANG is attached
* to the IO4 at the lowest physical slot.
*/
for ( slot=EV_MAX_SLOTS ; slot-- ; ) {
brd = &(cfginfo->ecfg_board[slot]);
if ( (brd->eb_type & (EVCLASS_MASK|EVTYPE_MASK)) == EVTYPE_IO4
&& (brd->eb_enabled)
) {
/* Found an IO4 board and it is enabled.
* Now look at all the adapters in the IO4, and look
* for the DANG chip.
*/
for (adap=1; adap<=7; adap++) { /* adapter numbers from 1 to 7 */
if (brd->eb_un.ebun_io.eb_ioas[adap].ioa_type == IO4_ADAP_DANG) {
if (dang_found == dangnum) {
/* This is the DANG we are looking for */
*window = brd->eb_un.ebun_io.eb_winnum;
*adapter = adap;
return(slot);
}
else {
/* We found a DANG, but it
* isn't the DANG we are looking for, try again.
*/
dang_found++;
}
}
}
}
}
return -1;
}
/*
* Do various initialisation.
* Set up all the DANG registers.
* Allocate a virtual page to map to the EXPRESS area on the GIO.
* Set up the write gatherer so that writes to it get dumped to the DANG.
*
* Returns:
* virtual address of GIO address 0x1f000000 (where EXPRESS sits).
*/
static void
*everest_dang_init(int slot,int window,int adapter)
{
volatile long long reg;
int io_config_reg;
void *va;
#if defined(IP19)
/* running in 32bit mode, with 4KB page size */
va = alloc_gfxspace(LWIN_PFN(window,adapter)+(0x3000000>>12));
#elif defined(IP21) || defined(IP25)
/* running in 64bit mode, with 16KB page size */
va = (void *)(((long long)(LWIN_PFN(window,adapter)) << 12) + 0x9000000003000000);
#endif
/* Clear all DANG errors */
reg = load_double((long long *)&dang_ptr[DANG_PIO_ERR_CLR]);
reg = load_double((long long *)&dang_ptr[DANG_DMAM_ERR_CLR]);
reg = load_double((long long *)&dang_ptr[DANG_DMAS_ERR_CLR]);
reg = load_double((long long *)&dang_ptr[DANG_DMAM_COMPLETE_CLR]);
/* Set up GIO address registers */
store_double((long long *)&dang_ptr[DANG_UPPER_GIO_ADDR],(long long)7);
store_double((long long *)&dang_ptr[DANG_MIDDLE_GIO_ADDR],(long long)0);
/* Set up interrupt registers */
store_double((long long *)&dang_ptr[DANG_INTR_BREAK],(long long)4); /*Make DANG stop sending to GIO when GIO interrupts the dang */
/* All interrupt registers default to have interrupts disabled */
/* Set up FIFO registers */
store_double((long long *)&dang_ptr[DANG_WG_LOWATER],(long long)32);
store_double((long long *)&dang_ptr[DANG_WG_HIWATER],(long long)1024);
store_double((long long *)&dang_ptr[DANG_WG_FULL], (long long)0xfff);
/* For now allow user process to access entire GR2 FIFO space */
store_double((long long *)&dang_ptr[DANG_WG_PRIV_LOADDR], (long long)0); /* 5 bits */
store_double((long long *)&dang_ptr[DANG_WG_PRIV_HIADDR], (long long)0x1f); /* 5 bits */
store_double((long long *)&dang_ptr[DANG_WG_GIO_UPPER],(long long)0xf82); /* Upper 15 bits of 0x1f040000 */
store_double((long long *)&dang_ptr[DANG_WG_GIO_STREAM], (long long)0x1f040000); /* GIO addr for streaming mode (32bits) */
store_double((long long *)&dang_ptr[DANG_GIO64], (long long)0); /* GIO 32 */
store_double((long long *)&dang_ptr[DANG_MAX_GIO_TIMEOUT],(long long)1000000); /* 500K GIO clocks */
/* Setup the IO4 configuration register since we use the Write Gatherer */
io_config_reg = (int)IO4_GETCONF_REG(slot, 2);
io_config_reg |= (0x10101 << adapter);
IO4_SETCONF_REG(slot,2,io_config_reg);
/* Set up write gatherer */
#if defined(IP19)
store_double((long long *)EV_WGCNTRL,(long long)2); /* Big endian, disabled */
store_double((long long *)EV_WGCLEAR,(long long)0); /* Clear WG */
reg = (long long)(LWIN_PFN(window,adapter));
reg <<= 12;
reg |= (cpuid() << 8) | (1 << 15);
store_double((long long *)EV_WGDST,reg); /* Set up destination */
store_double((long long *)EV_WGCNTRL,(long long)3); /* Big endian, enabled */
#elif defined(IP21)
reg = (long long)(LWIN_PFN(window,adapter));
reg <<= 12;
reg |= (cpuid() << 8) | (1 << 15);
store_double((long long *)EV_WGDST,reg); /* Set up destination */
#elif defined(IP25)
reg = (long long)(LWIN_PFN(window,adapter));
reg <<= 12;
reg |= (cpuid() << 8) | (1 << 15);
store_double((long long *)EV_GRDST,reg); /* Set up destination */
#endif
return(va);
}
#endif