Re: Triton chipset & bridge optimizing

Gerard Roudier (groudier@iplus.fr)
Mon, 18 Mar 1996 23:38:19 +0000 (GMT)


Graham,

I have an Intel plato board (Neptune Chipset).
In order to show and to tune the chipset I have build a command tool.
As the ncrBsd2Linux driver, it was first for my own usage.
It seems that you have the same problem.

Here is the source code.
It's mix of "scanpci.c" by Robin Cutshaw and FreeBSD "pcisupport.c" by
Stefan Esser. (I only use excellent source code).
Compile the following source under Linux and run it.

------------------- CUT HERE --------------------------

/*
* compiling: [g]cc scanpci.c -o scanpci
* for SVR4 (not Solaris), UnixWare use:
* [g]cc -DSVR4 scanpci.c -o scanpci
* for DOS, watcom 9.5:
* wcc386p -zq -omaxet -7 -4s -s -w3 -d2 name.c
* and link with PharLap or other dos extender for exe
*
*/

#if defined(__SVR4)
#if !defined(SVR4)
#define SVR4
#endif
#endif

#include <stdio.h>
#include <sys/types.h>
#if defined(SVR4)
#if defined(sun)
#define __EXTENSIONS__
#endif
#include <sys/proc.h>
#include <sys/tss.h>
#if defined(NCR)
#define __STDC
#include <sys/sysi86.h>
#undef __STDC
#else
#include <sys/sysi86.h>
#endif
#if defined(__SUNPRO_C) || defined(sun) || defined(__sun)
#include <sys/psw.h>
#else
#include <sys/seg.h>
#endif
#include <sys/v86.h>
#endif
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__386BSD__)
#include <sys/file.h>
#include <machine/console.h>
#define GCCUSESGAS
#endif
#if defined(__bsdi__)
#include <sys/file.h>
#include <sys/ioctl.h>
#include <i386/isa/pcconsioctl.h>
#define GCCUSESGAS
#endif
#if defined(SCO)
#include <sys/console.h>
#include <sys/param.h>
#include <sys/immu.h>
#include <sys/region.h>
#include <sys/proc.h>
#include <sys/tss.h>
#include <sys/sysi86.h>
#include <sys/v86.h>
#endif
#if defined(Lynx_22)
#define GCCUSESGAS
#endif

#if defined(__WATCOMC__)

#include <stdlib.h>
void outl(unsigned port, unsigned data);
#pragma aux outl = "out dx, eax" parm [dx] [eax];
void outb(unsigned port, unsigned data);
#pragma aux outb = "out dx, al" parm [dx] [eax];
unsigned inl(unsigned port);
#pragma aux inl = "in eax, dx" parm [dx];
unsigned inb(unsigned port);
#pragma aux inb = "xor eax,eax" "in al, dx" parm [dx];

#else /* __WATCOMC__ */

#if defined(__GNUC__)

#if defined(GCCUSESGAS)
#define OUTB_GCC "outb %0,%1"
#define OUTL_GCC "outl %0,%1"
#define INB_GCC "inb %1,%0"
#define INL_GCC "inl %1,%0"
#else
#define OUTB_GCC "out%B0 (%1)"
#define OUTL_GCC "out%L0 (%1)"
#define INB_GCC "in%B0 (%1)"
#define INL_GCC "in%L0 (%1)"
#endif /* GCCUSESGAS */

static void outb(unsigned short port, unsigned char val) {
__asm__ __volatile__(OUTB_GCC : :"a" (val), "d" (port)); }
static void outl(unsigned short port, unsigned long val) {
__asm__ __volatile__(OUTL_GCC : :"a" (val), "d" (port)); }
static unsigned char inb(unsigned short port) { unsigned char ret;
__asm__ __volatile__(INB_GCC : "=a" (ret) : "d" (port)); return ret; }
static unsigned long inl(unsigned short port) { unsigned long ret;
__asm__ __volatile__(INL_GCC : "=a" (ret) : "d" (port)); return ret; }

#else /* __GNUC__ */

#if defined(__STDC__) && (__STDC__ == 1)
# if !defined(NCR)
# define asm __asm
# endif
#endif

#if defined(__SUNPRO_C)
/*
* This section is a gross hack in if you tell anyone that I wrote it,
* I'll deny it. :-)
* The leave/ret instructions are the big hack to leave %eax alone on return.
*/
unsigned char inb(int port) {
asm(" movl 8(%esp),%edx");
asm(" subl %eax,%eax");
asm(" inb (%dx)");
asm(" leave");
asm(" ret");
}

unsigned short inw(int port) {
asm(" movl 8(%esp),%edx");
asm(" subl %eax,%eax");
asm(" inw (%dx)");
asm(" leave");
asm(" ret");
}

unsigned long inl(int port) {
asm(" movl 8(%esp),%edx");
asm(" inl (%dx)");
asm(" leave");
asm(" ret");
}

void outb(int port, unsigned char value) {
asm(" movl 8(%esp),%edx");
asm(" movl 12(%esp),%eax");
asm(" outb (%dx)");
}

void outw(int port, unsigned short value) {
asm(" movl 8(%esp),%edx");
asm(" movl 12(%esp),%eax");
asm(" outw (%dx)");
}

void outl(int port, unsigned long value) {
asm(" movl 8(%esp),%edx");
asm(" movl 12(%esp),%eax");
asm(" outl (%dx)");
}
#else

#if defined(SVR4)
# if !defined(__USLC__)
# define __USLC__
# endif
#endif

#include <sys/inline.h>

#endif /* SUNPRO_C */

#endif /* __GNUC__ */
#endif /* __WATCOMC__ */

void enable_os_io();
void disable_os_io();

#define M_EQ 0 /* mask and return true if equal */
#define M_NE 1 /* mask and return true if not equal */
#define TRUE 2 /* don't read config, always true */

struct condmsg {
unsigned char port;
unsigned char mask;
unsigned char value;
char flags;
char *text;
};

static const struct condmsg set82434lx[] =
{
{ 0x00, 0x00, 0x00, TRUE, " memory clocks=" },
{ 0x57, 0xc0, 0xc0, M_EQ, "X-3-3-3 (50ns)" },
{ 0x58, 0x01, 0x00, M_EQ, ", no CAS-wait" },
{ 0x53, 0x08, 0x08, M_EQ, ", read around write"},
/*
{ 0x52, 0x21, 0x01, M_EQ, "3-2-2-2/4-2-2-2" },
{ 0x57, 0xc0, 0x40, M_EQ, "X-4-4-4/X-3-3-3 (60ns)" },
*/
{ 0x00, 0x00, 0x00, TRUE, "\n" },
/* end marker */
{ 0 }
};

static const struct condmsg conf82434lx[] =
{
{ 0x00, 0x00, 0x00, TRUE, "\tCPU: " },
{ 0x50, 0xe3, 0x82, M_EQ, "Pentium, 60MHz" },
{ 0x50, 0xe3, 0x83, M_EQ, "Pentium, 66MHz" },
{ 0x50, 0xe3, 0xa2, M_EQ, "Pentium, 90MHz" },
{ 0x50, 0xe3, 0xa3, M_EQ, "Pentium, 100MHz" },
{ 0x50, 0xc2, 0x82, M_NE, "(unknown)" },
{ 0x50, 0x04, 0x00, M_EQ, " (primary cache OFF)" },

{ 0x53, 0x01, 0x01, TRUE, ", CPU->Memory posting "},
{ 0x53, 0x01, 0x01, M_NE, "OFF" },
{ 0x53, 0x01, 0x01, M_EQ, "ON" },

{ 0x53, 0x08, 0x00, M_NE, ", read around write"},

{ 0x70, 0x04, 0x00, M_EQ, "\n\tWarning: Cache parity disabled!" },
{ 0x57, 0x20, 0x00, M_NE, "\n\tWarning: DRAM parity mask!" },
{ 0x57, 0x01, 0x00, M_EQ, "\n\tWarning: refresh OFF! " },

{ 0x00, 0x00, 0x00, TRUE, "\n\tCache: " },
{ 0x52, 0x01, 0x00, M_EQ, "None" },
{ 0x52, 0x81, 0x01, M_EQ, "" },
{ 0x52, 0xc1, 0x81, M_EQ, "256KB" },
{ 0x52, 0xc1, 0xc1, M_EQ, "512KB" },
{ 0x52, 0x03, 0x01, M_EQ, " writethrough" },
{ 0x52, 0x03, 0x03, M_EQ, " writeback" },

{ 0x52, 0x01, 0x01, M_EQ, ", cache clocks=" },
{ 0x52, 0x21, 0x01, M_EQ, "3-2-2-2/4-2-2-2" },
{ 0x52, 0x21, 0x21, M_EQ, "3-1-1-1" },

{ 0x52, 0x01, 0x01, M_EQ, "\n\tCache flags: " },
{ 0x52, 0x11, 0x11, M_EQ, " cache-all" },
{ 0x52, 0x09, 0x09, M_EQ, " byte-control" },
{ 0x52, 0x05, 0x05, M_EQ, " powersaver" },

{ 0x00, 0x00, 0x00, TRUE, "\n\tDRAM:" },
{ 0x57, 0x10, 0x00, M_EQ, " page mode" },

{ 0x00, 0x00, 0x00, TRUE, " memory clocks=" },
{ 0x57, 0xc0, 0x00, M_EQ, "X-4-4-4 (70ns)" },
{ 0x57, 0xc0, 0x40, M_EQ, "X-4-4-4/X-3-3-3 (60ns)" },
{ 0x57, 0xc0, 0x80, M_EQ, "???" },
{ 0x57, 0xc0, 0xc0, M_EQ, "X-3-3-3 (50ns)" },
{ 0x58, 0x02, 0x02, M_EQ, ", RAS-wait" },
{ 0x58, 0x01, 0x01, M_EQ, ", CAS-wait" },

{ 0x00, 0x00, 0x00, TRUE, "\n\tCPU->PCI: posting " },
{ 0x53, 0x02, 0x02, M_EQ, "ON" },
{ 0x53, 0x02, 0x00, M_EQ, "OFF" },
{ 0x00, 0x00, 0x00, TRUE, ", burst mode " },
{ 0x54, 0x02, 0x00, M_NE, "ON" },
{ 0x54, 0x02, 0x00, M_EQ, "OFF" },
{ 0x54, 0x04, 0x00, TRUE, ", PCI clocks=" },
{ 0x54, 0x04, 0x00, M_EQ, "2-2-2-2" },
{ 0x54, 0x04, 0x00, M_NE, "2-1-1-1" },
{ 0x00, 0x00, 0x00, TRUE, "\n\tPCI->Memory: posting " },
{ 0x54, 0x01, 0x00, M_NE, "ON" },
{ 0x54, 0x01, 0x00, M_EQ, "OFF" },

{ 0x57, 0x01, 0x01, M_EQ, "\n\tRefresh:" },
{ 0x57, 0x03, 0x03, M_EQ, " CAS#/RAS#(Hidden)" },
{ 0x57, 0x03, 0x01, M_EQ, " RAS#Only" },
{ 0x57, 0x05, 0x05, M_EQ, " BurstOf4" },

{ 0x00, 0x00, 0x00, TRUE, "\n" },

/* end marker */
{ 0 }
};

static char confread (int dev_num, int port)
{
unsigned long portw = port & ~3;
unsigned long ports = (port - portw) << 3;

unsigned long l = inl(0xC000 + portw);
return (l >> ports);
}

static void confwrite (int dev_num, int port, unsigned char value)
{
unsigned long portw = port & ~3;
unsigned long ports = (port - portw) << 3;

unsigned long l = inl(0xC000 + portw);

l &= (~(0xff << ports));
l |= (value << ports);

#if 1
outl(0xC000 + portw, l);
#endif
}

static void setconfig (int dev_num, const struct condmsg *tbl)
{
while (tbl->text) {
int cond = 0;
if (tbl->flags == TRUE) {
cond = 1;
} else {
unsigned char v = (unsigned char) confread(dev_num, tbl->port);
v &= (~tbl->mask);
v |= tbl->value;
confwrite(dev_num, tbl->port, v);
cond = 1;
}
if (cond) printf ("%s", tbl->text);
tbl++;
}
}

static void showconfig (int dev_num, const struct condmsg *tbl)
{
while (tbl->text) {
int cond = 0;
if (tbl->flags == TRUE) {
cond = 1;
} else {
unsigned char v = (unsigned char) confread(dev_num, tbl->port);
switch (tbl->flags) {
case M_EQ:
if ((v & tbl->mask) == tbl->value) cond = 1;
break;
case M_NE:
if ((v & tbl->mask) != tbl->value) cond = 1;
break;
}
}
if (cond) printf ("%s", tbl->text);
tbl++;
}
}

main(int argc, unsigned char *argv[])
{
unsigned long config_cmd;

if (argc != 1) {
printf("Usage: %s\n");
exit(1);
}
#if !defined(MSDOS)
if (getuid()) {
printf("This program must be run as root\n");
exit(1);
}
#endif

enable_os_io();

outb(0xCF8, 0xF1);
outb(0xCFA, 0x00); /* bus 0 for now */
#if 0
setconfig(0, set82434lx);
#endif
showconfig(0, conf82434lx);

outb(0xCF8, 0x00);

disable_os_io();
}

static int io_fd;

void
enable_os_io()
{
#if defined(SVR4) || defined(SCO)
#if defined(SI86IOPL)
sysi86(SI86IOPL, 3);
#else
sysi86(SI86V86, V86SC_IOPL, PS_IOPL);
#endif
#endif
#if defined(linux)
iopl(3);
#endif
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__386BSD__) || defined(__bsdi__)
if ((io_fd = open("/dev/console", O_RDWR, 0)) < 0) {
perror("/dev/console");
exit(1);
}
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__386BSD__)
if (ioctl(io_fd, KDENABIO, 0) < 0) {
perror("ioctl(KDENABIO)");
exit(1);
}
#endif
#if defined(__bsdi__)
if (ioctl(io_fd, PCCONENABIOPL, 0) < 0) {
perror("ioctl(PCCONENABIOPL)");
exit(1);
}
#endif
#endif
#if defined(MACH386)
if ((io_fd = open("/dev/iopl", O_RDWR, 0)) < 0) {
perror("/dev/iopl");
exit(1);
}
#endif
}

void
disable_os_io()
{
#if defined(SVR4) || defined(SCO)
#if defined(SI86IOPL)
sysi86(SI86IOPL, 0);
#else
sysi86(SI86V86, V86SC_IOPL, 0);
#endif
#endif
#if defined(linux)
iopl(0);
#endif
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__386BSD__)
if (ioctl(io_fd, KDDISABIO, 0) < 0) {
perror("ioctl(KDDISABIO)");
close(io_fd);
exit(1);
}
close(io_fd);
#endif
#if defined(__bsdi__)
if (ioctl(io_fd, PCCONDISABIOPL, 0) < 0) {
perror("ioctl(PCCONDISABIOPL)");
close(io_fd);
exit(1);
}
close(io_fd);
#endif
#if defined(MACH386)
close(io_fd);
#endif
}

--------------------- CUT HERE -------------------------

It s very easy to build an equivalent command tool for the Triton
Chipset, since the original sources are great.

Regards, Gerard.

On Mon, 18 Mar 1996, Graham Mitchell wrote:

> On 18 Mar 96 at 9:58, Joao Carlos Ventura wrote:
>
> <snip>
>
> > It does, but PCI bridge optimization only works with a few chipsets. And
> > as far as I remember the only one made by Intel that is supported is
> > Neptune, Triton's predecessor.
>
> It also works on Mercury chipset too (almost). This is an extract
> from dmesg.....
>
> pcibios_init : multiple entries, mail drew@colorado.edu
> pcibios_init : PCI BIOS revision 2.00 entry at 0xf3970
> Probing PCI hardware.
> PCI bridge optimization.
> Cache L2: Not supported.
> CPU-PCI posted write: on.
> CPU-Memory posted write: on.
> PCI-Memory posted write: on.
> PCI burst: on.
>
> There are 2 problems here...... The first is the multiple entries
> (tho nothing seems broken, and there is no reply from
> drew@colorado.edu - but no bounce yet either). The other problem is
> the L2 cache not supported. It IS on my machine 256k worth, so why
> does the kernel not think there is any.....? The board is an Intel
> Premiere/PCI 60Mhz Pentium with a Mercury chipset.
>
>
>
> Graham
> Ask not what you can do for your country,
> but what your government is doing to you
>
>