-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

  I pasted the source from the file in this e-mail, so you can all tell
me I am crazy when I am wrong.  This ALL came from a GPLed package.  I
am also attaching the tgz this came out of.  Basically it's the src.rpm
output.  Also, I did an md5sum on the test.rom and the same rom image
from the rpm, and they were an exact match.  So using the switch I
mentioned when I sent out my correction was able to grab the rom image
perfectly.  Now the trick is getting the rom writable, and low and
behold I find a jarrell_rom_jumper.c file with the linux bios source
package for this version of linux bios.

( This is the second time I have sent this e-mail, the first one held
because it exceeded the 2mb limit.  So I am not re-attaching it, we will
have to find another method or the moderator will have to release it.)

 Please let me know if this helps, and thanx in advance.

Joshua McDowell


#define _GNU_SOURCE
#include <getopt.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/io.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include "./freebios2/src/include/boot/linuxbios_tables.h"

#define PACKED __attribute__((packed))

#define cli() __asm__ __volatile__ ("cli" : : : "memory")
#define sti() __asm__ __volatile__ ("sti" : : : "memory")

typedef uint32_t device_t;

#define FLOPPY_DEVICE      0
#define COM1_DEVICE        2
#define COM2_DEVICE        3
#define CWC_DEVICE         4
#define KBC_DEVICE         5
#define CIR_DEVICE         6
#define GPIO_DEVICE        7
#define FMC_DEVICE         9
#define WATCHDOG_DEVICE  0xa
#define XBUS_DEVICE      0xf
#define RTC_DEVICE      0x10
#define HMC_DEVICE      0x14

#define DEVICE_MAP (\
        (1<<0)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<9)|\
        (1<<0xa)|(1<<0xf)|(1<<0x10)|(1<<0x14))

#define PNP_BASE_PORT 0x2e

#define PNP_DEV(PORT, FUNC) (((PORT) << 8) | (FUNC))

#define PNP_IDX_IO0  0x60
#define PNP_IDX_IO1  0x62
#define PNP_IDX_IO2  0x64
#define PNP_IDX_IO3  0x66
#define PNP_IDX_IRQ0 0x70
#define PNP_IDX_IRQ1 0x72
#define PNP_IDX_DRQ0 0x74
#define PNP_IDX_DRQ1 0x75



static void enter_pnp(device_t dev)
{
        unsigned port = dev >> 8;
        unsigned device = dev & 0xff;
        /* Enter pnp mode  */
        /* noop */
        /* Set the logical device */
        outb(0x07, port);
        outb(device, port +1);
}

static void exit_pnp(device_t dev)
{
        /* noop */
}


/* I enter and exit pnp config mode with every access
 * so when I read an invalid address and potentially
 * mess up the state machine, the state machine gets
 * reset.
 */
static void pnp_write_config(device_t dev, uint8_t reg, uint8_t value)
{
        unsigned port = dev >> 8;
        cli();
        enter_pnp(dev);
        outb(reg, port);
        outb(value, port + 1);
        exit_pnp(dev);
        sti();
}

static uint8_t pnp_read_config(device_t dev, uint8_t reg)
{
        unsigned port = dev >> 8;
        uint8_t result;
        cli();
        enter_pnp(dev);
        outb(reg, port);
        result = inb(port +1);
        exit_pnp(dev);
        sti();
        return result;
}

static void pnp_set_enable(device_t dev, int enable)
{
        pnp_write_config(dev, 0x30, enable?0x1:0x0);
}

static int  pnp_read_enable(device_t dev)
{
        return pnp_read_config(dev, 0x30);
}

static uint16_t pnp_read_iobase(device_t dev, unsigned index)
{
        uint16_t iobase;
        iobase =  pnp_read_config(dev, index) << 8;
        iobase |= pnp_read_config(dev, index + 1);
        return iobase;
}

static uint8_t pnp_read_irq(device_t dev, unsigned index)
{
        return pnp_read_config(dev, index);
}

static uint8_t pnp_read_drq(device_t dev, unsigned index)
{
        return pnp_read_config(dev, index);
}

static void pnp_print_config(device_t dev, FILE *fp)
{
        unsigned device = dev & 0xff;
        int i;
        fprintf(fp, "Resource configuration for device: 0x%02x\n", device);
        fprintf(fp, "Enabled: 0x%02x\n", pnp_read_enable(dev));
        fprintf(fp, "iobase0: 0x%04x  iobase1: 0x%04x  iobase2: 0x%04x
iobase3: 0x%04x\n",
                pnp_read_iobase(dev, PNP_IDX_IO0),
                pnp_read_iobase(dev, PNP_IDX_IO1),
                pnp_read_iobase(dev, PNP_IDX_IO2),
                pnp_read_iobase(dev, PNP_IDX_IO3));
        fprintf(fp, "irq0: %2d  irq1: %2d  drq: %d\n",
                pnp_read_irq(dev, PNP_IDX_IRQ0),
                pnp_read_irq(dev, PNP_IDX_IRQ1),
                pnp_read_drq(dev, PNP_IDX_DRQ0));
        for(i = 0x00; i < 256; i++) {
                unsigned char byte;
                byte = pnp_read_config(dev, i);
                if ((i & 0xf) == 0) {
                        fprintf(fp, "%02x: ", i);
                }
                fprintf(fp, "%02x ", byte);
                if ((i & 0xf) == 0xf) {
                        fprintf(fp, "\n");
                }
        }
        fprintf(fp, "\n");
}



/*
 * Functions for accessing PCI configuration space with type 1 accesses
 */



#define PCI_DEV(BUS, DEV, FN) ( \
        (((BUS) & 0xFF) << 16) | \
        (((DEV) & 0x1f) << 11) | \
        (((FN)  & 0x7) << 8))

#define PCI_ID(VENDOR_ID, DEVICE_ID) \
        ((((DEVICE_ID) & 0xFFFF) << 16) | ((VENDOR_ID) & 0xFFFF))


#define CONFIG_CMD(dev, where) (0x80000000 | dev | (where & ~3))


static uint8_t pci_read_config8(device_t dev, int where)
{
        outl(CONFIG_CMD(dev,where), 0xCF8);
        return inb(0xCFC + (where&3));
}

static uint16_t pci_read_config16(device_t dev, int where)
{
        outl(CONFIG_CMD(dev,where), 0xCF8);
        return inw(0xCFC + (where&2));
}

static uint32_t pci_read_config32(device_t dev, int where)
{
        outl(CONFIG_CMD(dev,where), 0xCF8);
        return inl(0xCFC);
}

static void pci_write_config8(device_t dev, int where, uint8_t value)
{
        outl(CONFIG_CMD(dev,where), 0xCF8);
        outb(value, 0xCFC + (where&3));
}

static void pci_write_config16(device_t dev, int where, uint16_t value)
{
        outl(CONFIG_CMD(dev,where), 0xCF8);
        outw(value, 0xCFC + (where&2));
}

static void pci_write_config32(device_t dev, int where, uint32_t value)
{
        outl(CONFIG_CMD(dev,where), 0xCF8);
        outl(value, 0xCFC);
}

#undef CONFIG_CMD

#define PCI_DEV_INVALID (0xffffffffU)
static device_t pci_locate_device(unsigned pci_id, device_t dev)
{
        for(; dev <= PCI_DEV(255, 31, 7); dev += PCI_DEV(0,0,1)) {
                unsigned int id;
                id = pci_read_config32(dev, 0);
                if (id == pci_id) {
                        return dev;
                }
        }
        return PCI_DEV_INVALID;
}

void udelay(int useconds)
{
        struct timeval tv;
        tv.tv_sec = 0;
        tv.tv_usec = useconds;
        select(0, 0, 0, 0, &tv);
}

/*
  jumper pin 1 -> sio_bios_sel (pin 52)
  jumper pin 2 -> (xbus_r_a20 to ROM) (ich5r pin r2 LDRQ1_N/GPI41)
  jumper pin 3 -> pull down resistor
*/

static void die(char *format, ...)
{
        va_list args;
        va_start(args, format);
        vfprintf(stderr, format, args);
        va_end(args);
        exit(1);
}

#define J_DISCONNECTED 0
#define J_1TO2         1
#define J_2TO3         2


void print_jumper_state(int state, FILE *fp)
{
        if (state == J_DISCONNECTED) {
                fprintf(fp, "High     -- disconnected");
        }
        else if (state == J_1TO2) {
                fprintf(fp, "Toggling -- 1 to 2");
        }
        else if (state == J_2TO3) {
                fprintf(fp, "Low      -- 2 to 3");
        }
        else {
                die("Impossible Jumper state\n");
        }
}

int main(int argc, char*argv[])
{
        device_t ich5r;
        device_t nsc87427;
        uint32_t gpio_base;
        uint32_t gpio_use_sel2, gp_lvl2;
        uint32_t gp_lvl2_lo, gp_lvl2_hi;
        uint16_t xbus_base;
        uint8_t  xbimm, xbbsl;
        FILE *fp;
        int expected_jumper_state, jumper_state;
        int i;


        expected_jumper_state = J_2TO3;

        if (iopl(3) != 0) {
                die("iopl failed!\n");
        }

        /* Find the ich5r */
        ich5r = pci_locate_device(PCI_ID(0x8086,0x24d0), 0);
        if (ich5r == PCI_DEV_INVALID) {
                fprintf(stderr, "Could not find southbridge\n");
        }
        /* Find the gpio bar/base D31:F0 0x58-0x5b */
        gpio_base = pci_read_config32(ich5r, 0x58);
        gpio_base &= ~1;
#if 0
        fprintf(stdout, "gpio_base: %08x\n", gpio_base);
#endif
        if (gpio_base == 0) {
                die("gpio_base is not set!\n");
        }
        /* Ensure the gpio line is properly setup */
        gpio_use_sel2 = inl(gpio_base + 0x30);
#if 0
        fprintf(stdout, "gpio_use_sel2: %08x\n",
                gpio_use_sel2);
#endif
        if ((gpio_use_sel2 & (1 << (41 - 32 ))) == 0) {
                die("gpio not configured to read high rom address line\n");
        }
#if 0
        /* Read the rom address line */
        gp_lvl2 = inl(gpio_base + 0x38);
        fprintf(stdout, "gp_lvl2: %08x 41=%d\n",
                gp_lvl2, (gp_lvl2 & (1 << (41 - 32)))?1:0 );
#endif

        /* Get the superio device */
        nsc87427 = PNP_DEV(PNP_BASE_PORT, XBUS_DEVICE);


        /* Get the xbus base address */
        xbus_base = pnp_read_iobase(nsc87427, PNP_IDX_IO0);
        if (xbus_base == 0) {
                die("xbus_base is not set!\n");
        }

        /* Clear the protections bits... */
        for(i = 0; i < 32; i++) {
                outb(((i & 0xf) << 4) | 0, xbus_base + 0x13 + (i >> 4));
        }

        /* Copy the current xbus high bit confiugration */
        xbimm = pnp_read_config(nsc87427, 0xfe);
        xbbsl = pnp_read_config(nsc87427, 0xff);

        /* Disable toggling */
        pnp_write_config(nsc87427, 0xff, xbbsl & 0x7f);

        /* Force the bit high */
        pnp_write_config(nsc87427, 0xfe, xbimm & 0x7f);

        /* Read the rom address line */
        gp_lvl2_lo = !!(inl(gpio_base + 0x38) & (1 << (41 - 32)));
#if 0
        fprintf(stdout, "41=%d\n", gp_lvl2_lo);
#endif

        /* Force the bit low */
        pnp_write_config(nsc87427, 0xfe, xbimm | 0x80);

        /* Read the rom address line */
        gp_lvl2_hi = !!(inl(gpio_base + 0x38) & (1 << (41 - 32)));
#if 0
        fprintf(stdout, "41=%d\n", gp_lvl2_hi);
#endif

        /* Restore the xbus high bit configuration */
        pnp_write_config(nsc87427, 0xfe, xbimm);
        pnp_write_config(nsc87427, 0xff, xbbsl);

        /* Record the jumper state */
        jumper_state = -1;
        /* Report the jumper state */
        if (gp_lvl2_hi != gp_lvl2_lo) {
                jumper_state = J_1TO2; /* Because it toggles */
        }
        else if (gp_lvl2_lo == 0) {
                jumper_state = J_2TO3; /* Because it is stuck low */
        }
        else {
                jumper_state = J_DISCONNECTED; /* Becuase it is stuck high */
        }

#if 0
        /* Print the device registers */
        pnp_print_config(nsc87427, stdout);

        /* Get the xbus base address */
        xbus_base = pnp_read_iobase(nsc87427, PNP_IDX_IO0);
        if (xbus_base == 0) {
                die("xbus_base is not set!\n");
        }
        /* Dump the xbus io mapped registers */
        for(i = 0; i <= 0x16; i++) {
                unsigned value;
                value = inb(xbus_base + i);
                fprintf(stdout, "%02x ", value);
        }
        fprintf(stdout, "\n");

        /* Dump the protection bits... */
        for(i = 0; i < 32; i++) {
                unsigned value;
                outb(((i & 0xf) << 4) | (1 << 3), xbus_base + 0x13 + (i >> 4));
                value = inb(xbus_base + 0x13 + (i >> 4));
                fprintf(stdout, "%02x ", value);
                if (((i+1) & 0xf) == 0) {
                        fprintf(stdout, "\n");
                }
        }

#endif
        /* Report the jumper state */
        fp = stdout;
        fprintf(fp, "Current jumper state: ");
        print_jumper_state(jumper_state, fp);
        fprintf(fp, "\n");
        if (expected_jumper_state != jumper_state) {
                fprintf(fp, "Expected:             ");
                print_jumper_state(expected_jumper_state, fp);
                fprintf(fp, "\n");
                exit(1);
        }
        return 0;
}

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkoU7WwACgkQDiqOyViXQA5f/ACdHMZG5qnh6iUu7rNiPTFdMI3u
8IwAn0TOaFA89AnKQtVmIB00Y3gb9NaN
=c4uN
-----END PGP SIGNATURE-----

-- 
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to