Logo Search packages:      
Sourcecode: faumachine version File versions  Download package

chip_intel_82443BX.c

/*
 * $Id: chip_intel_82443BX.c,v 1.193 2009-01-28 12:59:18 potyra Exp $
 *
 * Copyright (C) 2003-2009 FAUmachine Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

/*
 * This is an implementation of the host controller of the
 * Intel 440BX chipset.
 */

#define DEBUG_SMRAM     0
#define DEBUG_CHIPSET   0

#include "config.h"
#include <inttypes.h>

#include <assert.h>
#include "fixme.h"
#include <stdio.h>
#include <string.h>

#include "glue-log.h"
#include "glue-shm.h"
#include "pci.h"  /* Should go away - FIXME VOSSI */

#include "chip_intel_82443BX.h"

#define COMP "chip_intel_82443BX"

enum chip_intel_82443BX_orig {
      ORIG_HOST_BUS,
      ORIG_PCI_BUS,
};

struct cpssp {
      /*
       * Config
       */

      /*
       * Signals
       */
      struct sig_host_bus_main *port_host_bus;
      struct sig_pci_bus_main *port_pci_bus;
      struct sig_pci_bus_idsel *port_idsel;
      struct sig_agp_bus_main *port_agp_bus;
      struct sig_pci_bus_idsel *port_gidsel;
      struct sig_cs *sig_mem_cs[8];

      /*
       * State
       */
      uint32_t confsp[64];

      enum chip_intel_82443BX_region {
            REGION_NONE,

            REGION_PM2_CTL,
            REGION_CONFADD,
            REGION_CONFDATA,

            REGION_MEM0,
            REGION_MEM1,
            REGION_MEM2,
            REGION_MEM3,
            REGION_MEM4,
            REGION_MEM5,
            REGION_MEM6,
            REGION_MEM7,

            REGION_PCI,
      } selected;
      uint32_t selected_addr;

      uint32_t confadd; /* Currently addressed device/register */
};

/* ----------------------------------------------------------------- */
/* Built-In Functions                                                */
/* ----------------------------------------------------------------- */

/*
 * FIXME:
 * This (optional, for ACPI) register is used to disable both
 * the PCI and AGP arbiters in the 82443BX to prevent any
 * external bus masters from acquiring the PCI or AGP bus.
 */
static int
chip_intel_82443BX_pm2_ctl_read(
      struct cpssp *cpssp,
      unsigned int bs,
      uint32_t *datap
)
{
      if ((bs >> 2) & 1) {
            fprintf(stderr, "WARNING: 82443BX (Power Management): "
                  "reading from unimplemented PM2_CTL register\n");
            *datap &= ~(0xff << 16);
            *datap |= 0x00 << 16;
            return 0;
      } else {
            return -1;
      }
}

static int
chip_intel_82443BX_pm2_ctl_write(
      struct cpssp *cpssp,
      unsigned int bs,
      uint32_t data
)
{
      if ((bs >> 2) & 1) {
            data >>= 16;
            data &= 0xff;

            fprintf(stderr, "WARNING: 82443BX (Power Management): "
                  "writing 0x%02x%s to unimplemented PM2_CTL "
                  "register\n", data, (data & ~0x01) ? " (reserved bits!)" : "");
            return 0;
      } else {
            return -1;
      }
}

static int
chip_intel_82443BX_confadd_read(
      struct cpssp *cpssp,
      unsigned int bs,
      uint32_t *datap
)
{
      if (bs == 0xf) {
            *datap = cpssp->confadd;
            return 0;
      } else {
            return -1;
      }
}

static int
chip_intel_82443BX_confadd_write(
      struct cpssp *cpssp,
      unsigned int bs,
      uint32_t data
)
{
      if (bs == 0xf) {
            uint32_t odata;

            data &= ~(1 << 30); /* Clear reserved bits. */
            data &= ~(1 << 29);
            data &= ~(1 << 28);
            data &= ~(1 << 27);
            data &= ~(1 << 26);
            data &= ~(1 << 25);
            data &= ~(1 << 24);
            data &= ~(1 <<  1);
            data &= ~(1 <<  0);

            odata = cpssp->confadd;
            cpssp->confadd = data;

            if (((odata >> 31) & 1) != ((data >> 31) & 1)) {
                  sig_host_bus_ior_info_flush(cpssp->port_host_bus, cpssp,
                              0x0cfc, 0);
                  sig_host_bus_iow_info_flush(cpssp->port_host_bus, cpssp,
                              0x0cfc, 0);
            }
            return 0;
      } else {
            return -1;
      }
}

static enum chip_intel_82443BX_region
chip_intel_82443BX__region(
      struct cpssp *cpssp,
      enum chip_intel_82443BX_orig orig,
      unsigned int type,
      unsigned int smm,
      uint32_t addr
)
{
      enum chip_intel_82443BX_region region;

      switch (type) {
      case SIG_HOST_BUS_IOR:
      case SIG_HOST_BUS_IOW:
            if (addr == 0x0020
             && ((pci_getconfigb(cpssp->confsp, 0x7A) >> 6) & 1)) {
                  /*
                   * "When bit 6 of the PMCR is set to `1', the ACPI
                   * Register [...] is enabled. When bit 6 is set to
                   * `0', I/O accesses to location 0022h are forwarded
                   * to PCI or AGP"
                   * (3-4, 82443BX datasheet)
                   */
                  region = REGION_PM2_CTL;

            } else if (addr == 0x0cf8) {
                  region = REGION_CONFADD;

            } else if (addr == 0x0cfc
                  && ((cpssp->confadd >> 31) & 1)) {
                  region = REGION_CONFDATA;

            } else {
                  region = REGION_PCI;
            }
            break;

      case SIG_HOST_BUS_MR:
      case SIG_HOST_BUS_MW: {
            unsigned int rw;

            if ((addr >> 23) < pci_getconfigb(cpssp->confsp, 0x60)) {
                  region = REGION_MEM0;
            } else if ((addr >> 23) < pci_getconfigb(cpssp->confsp, 0x61)) {
                  region = REGION_MEM1;
            } else if ((addr >> 23) < pci_getconfigb(cpssp->confsp, 0x62)) {
                  region = REGION_MEM2;
            } else if ((addr >> 23) < pci_getconfigb(cpssp->confsp, 0x63)) {
                  region = REGION_MEM3;
            } else if ((addr >> 23) < pci_getconfigb(cpssp->confsp, 0x64)) {
                  region = REGION_MEM4;
            } else if ((addr >> 23) < pci_getconfigb(cpssp->confsp, 0x65)) {
                  region = REGION_MEM5;
            } else if ((addr >> 23) < pci_getconfigb(cpssp->confsp, 0x66)) {
                  region = REGION_MEM6;
            } else if ((addr >> 23) < pci_getconfigb(cpssp->confsp, 0x67)) {
                  region = REGION_MEM7;
            } else {
                  region = REGION_PCI;
            }

            if (/* 0x00000000 <= addr && */ addr < 0x000a0000) {
                  /*
                   * Low memory.
                   */
                  rw = 3;

            } else if (0x000a0000 <= addr && addr < 0x000c0000) {
                  /*
                   * VGA hole / SMRAM
                   */
                  unsigned int n;

                  n = pci_getconfigb(cpssp->confsp, 0x72); /*SMRAM Control*/
                  if ((n & (1 << 3) /* G_SMRAME */)
                   && (smm || ((n & (1 << 6) /* D_OPEN */)))) {
                        /* SMRAM */
                        rw = 3;
                  } else {
                        /* VGA Hole */
                        rw = 0;
                  }

            } else if (0x000c0000 <= addr && addr < 0x000c4000) {
                  rw = pci_getconfigb(cpssp->confsp, 0x5a) & 0xf;

            } else if (0x000c4000 <= addr && addr < 0x000c8000) {
                  rw = pci_getconfigb(cpssp->confsp, 0x5a) >> 4;

            } else if (0x000c8000 <= addr && addr < 0x000cc000) {
                  rw = pci_getconfigb(cpssp->confsp, 0x5b) & 0xf;

            } else if (0x000cc000 <= addr && addr < 0x000d0000) {
                  rw = pci_getconfigb(cpssp->confsp, 0x5b) >> 4;

            } else if (0x000d0000 <= addr && addr < 0x000d4000) {
                  rw = pci_getconfigb(cpssp->confsp, 0x5c) & 0xf;

            } else if (0x000d4000 <= addr && addr < 0x000d8000) {
                  rw = pci_getconfigb(cpssp->confsp, 0x5c) >> 4;

            } else if (0x000d8000 <= addr && addr < 0x000dc000) {
                  rw = pci_getconfigb(cpssp->confsp, 0x5d) & 0xf;

            } else if (0x000dc000 <= addr && addr < 0x000e0000) {
                  rw = pci_getconfigb(cpssp->confsp, 0x5d) >> 4;

            } else if (0x000e0000 <= addr && addr < 0x000e4000) {
                  rw = pci_getconfigb(cpssp->confsp, 0x5e) & 0xf;

            } else if (0x000e4000 <= addr && addr < 0x000e8000) {
                  rw = pci_getconfigb(cpssp->confsp, 0x5e) >> 4;

            } else if (0x000e8000 <= addr && addr < 0x000ec000) {
                  rw = pci_getconfigb(cpssp->confsp, 0x5f) & 0xf;

            } else if (0x000ec000 <= addr && addr < 0x000f0000) {
                  rw = pci_getconfigb(cpssp->confsp, 0x5f) >> 4;

            } else if (0x000f0000 <= addr && addr < 0x00100000) {
                  /*
                   * BIOS Area configured by PAM register 0x59.
                   */
                  rw = pci_getconfigb(cpssp->confsp, 0x59) >> 4;

            } else {
                  /*
                   * High memory.
                   */
                  rw = 3;
            }

            if ((type == SIG_HOST_BUS_MR && ! (rw & 1))
             || (type == SIG_HOST_BUS_MW && ! (rw & 2))) {
                  region = REGION_PCI;
            }

            break;
          }
      default:
            assert(0); /* Cannot happen. */
      }

      if (orig == ORIG_PCI_BUS
       && region == REGION_PCI) {
            region = REGION_NONE;
      }

      return region;
}

static int
chip_intel_82443BX_type_addr(
      void *_css,
      enum chip_intel_82443BX_orig orig,
      unsigned int type,
      uint32_t addr
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      cpssp->selected = chip_intel_82443BX__region(cpssp, orig, type, 0, addr);
      switch (cpssp->selected) {
      case REGION_NONE:
            /* Do nothing... */
            return -1;

      case REGION_MEM0 ... REGION_MEM7:
            cpssp->selected_addr = addr;
            return 0;

      case REGION_PM2_CTL:
      case REGION_CONFADD:
            (void) sig_pci_bus_main_type_addr(
                        cpssp->port_pci_bus, cpssp,
                        type, addr);
            return 0; /* Might be wrong - FIXME */

      case REGION_PCI:
            return sig_pci_bus_main_type_addr(
                        cpssp->port_pci_bus, cpssp,
                        type, addr);

      case REGION_CONFDATA:
            if (((cpssp->confadd >> 16) & 0xff) == 0x00) {
                  /* Config Space Type 0 */
                  uint32_t bus;
                  uint32_t dev;
                  uint32_t reg;

                  bus = (cpssp->confadd >> 16) & 0xff;
                  dev = (cpssp->confadd >> 11) & 0x1f;
                  reg = (cpssp->confadd >>  0) & 0x7fc;

                  if (dev < 32 - 11) {
                        dev = 1 << (11 + dev);
                  } else {
                        dev = 0;
                  }

                  (void) sig_pci_bus_main_type_addr(
                              cpssp->port_pci_bus, (void *) 0,
                              type == SIG_HOST_BUS_IOR
                                    ? SIG_PCI_BUS_C0R 
                                    : SIG_PCI_BUS_C0W,
                              dev | reg);
                  return 0;

            } else {
                  /* Config Space Type 1 */
                  (void) sig_pci_bus_main_type_addr(
                              cpssp->port_pci_bus, (void *) 0,
                              type == SIG_HOST_BUS_IOR
                                    ? SIG_PCI_BUS_C1R 
                                    : SIG_PCI_BUS_C1W,
                              cpssp->confadd & ~3);
                  return 0;
            }
      default:
            assert(0); /* Cannot happen. */
      }
}

static int
chip_intel_82443BX_read_data(
      void *_css,
      unsigned int bs,
      uint32_t *datap
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;
      int ret;

      switch (cpssp->selected) {
      case REGION_NONE:
            ret = -1;
            break;

      case REGION_MEM0 ... REGION_MEM7:
            ret = sig_cs_read(
                        cpssp->sig_mem_cs[cpssp->selected - REGION_MEM0],
                        cpssp,
                        cpssp->selected_addr, bs, datap);
            break;

      case REGION_PM2_CTL:
      case REGION_CONFADD:
      case REGION_CONFDATA:
      case REGION_PCI:
            ret = sig_pci_bus_main_read_data(
                        cpssp->port_pci_bus, (void *) 0,
                        bs, datap);
            break;

      default:
            assert(0); /* Cannot happen. */
      }

      switch (cpssp->selected) {
      case REGION_PM2_CTL:
            ret &= chip_intel_82443BX_pm2_ctl_read(cpssp, bs, datap);
            break;

      case REGION_CONFADD:
            ret &= chip_intel_82443BX_confadd_read(cpssp, bs, datap);
            break;

      default:
            break;
      }

      return ret;
}

static int
chip_intel_82443BX_write_data(
      void *_css,
      unsigned int bs,
      uint32_t data
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;
      int ret;

      switch (cpssp->selected) {
      case REGION_NONE:
            ret = -1;
            break;

      case REGION_MEM0 ... REGION_MEM7:
            ret = sig_cs_write(
                        cpssp->sig_mem_cs[cpssp->selected - REGION_MEM0],
                        cpssp,
                        cpssp->selected_addr, bs, data);
            break;

      case REGION_PM2_CTL:
      case REGION_CONFADD:
      case REGION_CONFDATA:
      case REGION_PCI:
            ret = sig_pci_bus_main_write_data(
                        cpssp->port_pci_bus, (void *) 0,
                        bs, data);
            break;

      default:
            assert(0); /* Cannot happen. */
      }

      switch (cpssp->selected) {
      case REGION_PM2_CTL:
            ret &= chip_intel_82443BX_pm2_ctl_write(cpssp, bs, data);
            break;

      case REGION_CONFADD:
            ret &= chip_intel_82443BX_confadd_write(cpssp, bs, data);
            break;

      default:
            break;
      }

      return ret;
}

static int
chip_intel_82443BX_ior(
      void *_css,
      uint32_t port,
      unsigned int bs,
      uint32_t *valp
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      switch (chip_intel_82443BX__region(cpssp,
                        ORIG_HOST_BUS, SIG_HOST_BUS_IOR, 0, port)) {
      case REGION_NONE:
            return -1;

      case REGION_PM2_CTL:
            return sig_pci_bus_ior(cpssp->port_pci_bus, cpssp,
                        port, bs, valp)
                 & chip_intel_82443BX_pm2_ctl_read(cpssp, bs, valp);

      case REGION_CONFADD:
            return sig_pci_bus_ior(cpssp->port_pci_bus, cpssp,
                        port, bs, valp)
                 & chip_intel_82443BX_confadd_read(cpssp, bs, valp);
      
      case REGION_CONFDATA: {
            /*
             * Configuration Data Register
             */
            uint32_t bus;
            uint32_t dev;
            uint32_t addr;

            bus = (cpssp->confadd >> 16) & 0xff;
            dev = (cpssp->confadd >> 11) & 0x1f;

            if (bus == 0) {
                  /* Generate Type 0 configuration cycle. */
                  
                  addr = cpssp->confadd & 0x7fc;
                  
                  if (dev < 21) {
                        return sig_pci_bus_main_c0r(
                                    cpssp->port_pci_bus,
                                    (void *) 0, /* FIXME */
                                    (1 << (11 + dev)) | addr,
                                    bs, valp);
                  } else {
                        *valp = 0xffffffff;
                        return 0;
                  }
            } else {
                  /* Generate Type 1 configuration cycle. */
                  
                  addr = cpssp->confadd & ~3;
                  
                  return sig_pci_bus_c1r(cpssp->port_pci_bus,
                                    cpssp, addr, bs, valp);
            }
          }
      case REGION_PCI:
            /*
             * Forward to PCI bus.
             */
            return sig_pci_bus_ior(cpssp->port_pci_bus, cpssp,
                        port, bs, valp);

      default:
            assert(0); /* Cannot happen. */
      }
}

static int
chip_intel_82443BX_iow(
      void *_css,
      uint32_t port,
      unsigned int bs,
      uint32_t val
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      switch (chip_intel_82443BX__region(cpssp,
                        ORIG_HOST_BUS, SIG_HOST_BUS_IOW, 0, port)) {
      case REGION_NONE:
            return -1;

      case REGION_PM2_CTL:
            return sig_pci_bus_iow(cpssp->port_pci_bus, cpssp,
                        port, bs, val)
                 & chip_intel_82443BX_pm2_ctl_write(cpssp, bs, val);

      case REGION_CONFADD:
            return sig_pci_bus_iow(cpssp->port_pci_bus, cpssp,
                        port, bs, val)
                 & chip_intel_82443BX_confadd_write(cpssp, bs, val);

      case REGION_CONFDATA: {
            /*
             * Configuration Data Register
             */
            uint32_t bus;
            uint32_t dev;
            uint32_t addr;

            bus = (cpssp->confadd >> 16) & 0xff;
            dev = (cpssp->confadd >> 11) & 0x1f;

            if (bus == 0) {
                  /* Generate Type 0 configuration cycle. */
                  addr = cpssp->confadd & 0x7fc;
                  
                  if (dev < 21) {
                        return sig_pci_bus_main_c0w(
                                    cpssp->port_pci_bus,
                                    (void *) 0, /* FIXME */
                                    (1 << (11 + dev)) | addr,
                                    bs, val);
                  } else {
                        return 0;
                  }
            } else {
                  /* Generate Type 1 configuration cycle. */
                  addr = cpssp->confadd & ~3;
                  
                  return sig_pci_bus_c1w(cpssp->port_pci_bus,
                                    cpssp, addr, bs, val);
            }
          }
      case REGION_PCI:
            /*
             * Forward to PCI bus.
             */
            return sig_pci_bus_iow(cpssp->port_pci_bus, cpssp,
                        port, bs, val);

      default:
            assert(0); /* Cannot happen. */
      }
}

static int
chip_intel_82443BX_ior_info(
      struct cpssp *cpssp,
      enum chip_intel_82443BX_orig orig,
      uint32_t port,
      unsigned int bs,
      int (**cf)(void *, uint32_t, unsigned int, uint32_t *),
      void **cs
)
{
      switch (chip_intel_82443BX__region(cpssp, orig, SIG_HOST_BUS_IOR, 0, port)) {
      case REGION_PM2_CTL:
      case REGION_CONFADD:
      case REGION_CONFDATA:
            *cf = chip_intel_82443BX_ior;
            *cs = cpssp;
            return 0;
      case REGION_PCI:
            return sig_pci_bus_ior_info(cpssp->port_pci_bus, cpssp,
                        port, bs, cf, cs);
      default:
            assert(0); /* Cannot happen. */
      }
}

static int
chip_intel_82443BX_iow_info(
      struct cpssp *cpssp,
      enum chip_intel_82443BX_orig orig,
      uint32_t port,
      unsigned int bs,
      int (**cf)(void *, uint32_t, unsigned int, uint32_t),
      void **cs
)
{
      switch (chip_intel_82443BX__region(cpssp, orig, SIG_HOST_BUS_IOW, 0, port)) {
      case REGION_PM2_CTL:
      case REGION_CONFADD:
      case REGION_CONFDATA:
            *cf = chip_intel_82443BX_iow;
            *cs = cpssp;
            return 0;
      case REGION_PCI:
            return sig_pci_bus_iow_info(cpssp->port_pci_bus, cpssp,
                        port, bs, cf, cs);
      default:
            assert(0); /* Cannot happen. */
      }
}

static int
chip_intel_82443BX_mem_read(
      void *_css,
      enum chip_intel_82443BX_orig orig,
      unsigned int smm,
      uint32_t addr,
      unsigned int bs,
      uint32_t *valp
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      cpssp->selected = chip_intel_82443BX__region(cpssp, orig,
                  SIG_HOST_BUS_MR, smm, addr);
      cpssp->selected_addr = addr;

      switch (cpssp->selected) {
      case REGION_NONE:
            return -1;

      case REGION_MEM0 ... REGION_MEM7:
            return sig_cs_read(cpssp->sig_mem_cs[cpssp->selected - REGION_MEM0],
                        cpssp, cpssp->selected_addr, bs, valp);
      case REGION_PCI:
            return sig_pci_bus_mr(cpssp->port_pci_bus, cpssp,
                        cpssp->selected_addr, bs, valp);
      default:
            assert(0); /* Cannot happen. */
      }
}

static int
chip_intel_82443BX_mem_write(
      void *_css,
      enum chip_intel_82443BX_orig orig,
      unsigned int smm,
      uint32_t addr,
      unsigned int bs,
      uint32_t val
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      cpssp->selected = chip_intel_82443BX__region(cpssp,
                  orig, SIG_HOST_BUS_MW, smm, addr);
      cpssp->selected_addr = addr;

      switch (cpssp->selected) {
      case REGION_NONE:
            return -1;

      case REGION_MEM0 ... REGION_MEM7:
            return sig_cs_write(cpssp->sig_mem_cs[cpssp->selected - REGION_MEM0],
                        cpssp, cpssp->selected_addr, bs, val);
      case REGION_PCI:
            return sig_pci_bus_mw(cpssp->port_pci_bus, cpssp,
                        cpssp->selected_addr, bs, val);
      default:
            assert(0); /* Cannot happen. */
      }
}

static int
chip_intel_82443BX_map(
      void *_css,
      enum chip_intel_82443BX_orig orig,
      unsigned int smm,
      unsigned long addr,
      unsigned int len,
      char **haddr_mr_p,
      char **haddr_mw_p
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;
      enum chip_intel_82443BX_region region;
      char *haddr_dummy;
      int ret;

      region = chip_intel_82443BX__region(cpssp, orig, SIG_HOST_BUS_MR, smm, addr);
      switch (region) {
      case REGION_NONE:
            ret = 1;
            break;

      case REGION_MEM0 ... REGION_MEM7:
            /* Forward to memory. */
            ret = sig_cs_map(cpssp->sig_mem_cs[region - REGION_MEM0],
                        cpssp, addr, len, haddr_mr_p, &haddr_dummy);
            break;

      case REGION_PCI:
            /* Forward to PCI bus. */
            ret = sig_pci_bus_map(cpssp->port_pci_bus, cpssp, addr, len,
                        haddr_mr_p, &haddr_dummy);
            break;

      default:
            assert(0); /* Cannot happen. */
      }
      if (ret != 0) {
            *haddr_mr_p = NULL;
      }

      region = chip_intel_82443BX__region(cpssp, orig, SIG_HOST_BUS_MW, smm, addr);
      switch (region) {
      case REGION_NONE:
            ret = -1;
            break;

      case REGION_MEM0 ... REGION_MEM7:
            /* Forward to memory. */
            ret = sig_cs_map(cpssp->sig_mem_cs[region - REGION_MEM0],
                        cpssp, addr, len, &haddr_dummy, haddr_mw_p);
            break;

      case REGION_PCI:
            /* Forward to PCI bus. */
            ret = sig_pci_bus_map(cpssp->port_pci_bus, cpssp, addr, len,
                        &haddr_dummy, haddr_mw_p);
            break;

      default:
            assert(0); /* Cannot happen. */
      }
      if (ret != 0) {
            *haddr_mw_p = NULL;
      }

      return 0;
}

/* ----------------------------------------------------------------- */
/* Host Bus Interface                                                */
/* ----------------------------------------------------------------- */

static int
chip_intel_82443BX_host_bus_type_addr(
      void *_css,
      unsigned int type,
      uint32_t addr
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      return chip_intel_82443BX_type_addr(cpssp, ORIG_HOST_BUS, type, addr);
}

static int
chip_intel_82443BX_host_bus_read_data(
      void *_css,
      unsigned int bs,
      uint32_t *valp
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      return chip_intel_82443BX_read_data(cpssp, bs, valp);
}

static int
chip_intel_82443BX_host_bus_write_data(
      void *_css,
      unsigned int bs,
      uint32_t val
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      return chip_intel_82443BX_write_data(cpssp, bs, val);
}

static int
chip_intel_82443BX_host_bus_ior(
      void *_css,
      uint32_t port,
      unsigned int bs,
      uint32_t *valp
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      return chip_intel_82443BX_ior(cpssp, port, bs, valp);
}

static int
chip_intel_82443BX_host_bus_iow(
      void *_css,
      uint32_t port,
      unsigned int bs,
      uint32_t val
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      return chip_intel_82443BX_iow(cpssp, port, bs, val);
}

static int
chip_intel_82443BX_host_bus_ior_info(
      void *_css,
      uint32_t port,
      unsigned int bs,
      int (**cf)(void *, uint32_t, unsigned int, uint32_t *),
      void **cs
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      return chip_intel_82443BX_ior_info(cpssp, ORIG_HOST_BUS, port, bs, cf, cs);
}

static int
chip_intel_82443BX_host_bus_iow_info(
      void *_css,
      uint32_t port,
      unsigned int bs,
      int (**cf)(void *, uint32_t, unsigned int, uint32_t),
      void **cs
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      return chip_intel_82443BX_iow_info(cpssp, ORIG_HOST_BUS, port, bs, cf, cs);
}

static int
chip_intel_82443BX_host_bus_inta_addr(
      void *_css
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      return sig_pci_bus_inta_addr(cpssp->port_pci_bus, cpssp);
}

static int
chip_intel_82443BX_host_bus_inta_data(
      void *_css,
      uint8_t *valp
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      return sig_pci_bus_inta_data(cpssp->port_pci_bus, cpssp, valp);
}

static int
chip_intel_82443BX_host_bus_mr(
      void *_css,
      unsigned int smm,
      uint32_t addr,
      unsigned int bs,
      uint32_t *valp
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      return chip_intel_82443BX_mem_read(cpssp, ORIG_HOST_BUS,
                  smm, addr, bs, valp);
}

static int
chip_intel_82443BX_host_bus_mw(
      void *_css,
      unsigned int smm,
      uint32_t addr,
      unsigned int bs,
      uint32_t val
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      return chip_intel_82443BX_mem_write(cpssp, ORIG_HOST_BUS,
                  smm, addr, bs, val);
}

static int
chip_intel_82443BX_host_bus_map(
      void *_css,
      unsigned int smm,
      unsigned long pa,
      unsigned int len,
      char **haddr_mr_p,
      char **haddr_mw_p,
      char **haddr_mx_p
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      if (chip_intel_82443BX_map(cpssp, ORIG_HOST_BUS,
                  smm, pa, len, haddr_mr_p, haddr_mw_p) == 0) {
            *haddr_mx_p = *haddr_mr_p;
            return 0;
      }
      if (sig_pci_bus_map(cpssp->port_pci_bus, cpssp,
                  pa, len, haddr_mr_p, haddr_mw_p) == 0) {
            *haddr_mx_p = *haddr_mr_p;
            return 0;
      }
      return 1;
}

/* ----------------------------------------------------------------- */
/* MEM Bus Interface                                                 */
/* ----------------------------------------------------------------- */

static int
chip_intel_82443BX_memX_unmap(void *_css, unsigned long pa, unsigned long len)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      /* Should unmap interval [pa, pa + len) only - FIXME VOSSI */
      sig_host_bus_unmap(cpssp->port_host_bus, cpssp, 0, 1024*1024*1024);
      sig_pci_bus_unmap(cpssp->port_pci_bus, cpssp, 0, 1024*1024*1024);

      return 0;
}

/* ----------------------------------------------------------------- */
/* PCI Bus Interface                                                 */
/* ----------------------------------------------------------------- */

static int
chip_intel_82443BX_pci_bus_mr(
      void *_css,
      uint32_t addr,
      unsigned int bs,
      uint32_t *valp
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      return chip_intel_82443BX_mem_read(cpssp, ORIG_PCI_BUS,
                  0, addr, bs, valp);
}

static int
chip_intel_82443BX_pci_bus_mw(
      void *_css,
      uint32_t addr,
      unsigned int bs,
      uint32_t val
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      return chip_intel_82443BX_mem_write(cpssp, ORIG_PCI_BUS,
                  0, addr, bs, val);
}

static int
chip_intel_82443BX_pci_bus_map(
      void *_css,
      unsigned long pa,
      unsigned int len,
      char **haddr_mr_p,
      char **haddr_mw_p
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;
      char *haddr_mx;

      if (chip_intel_82443BX_map(cpssp, ORIG_PCI_BUS,
                  0, pa, len, haddr_mr_p, haddr_mw_p) == 0)
            return 0;
      if (sig_host_bus_map(cpssp->port_host_bus, cpssp,
                  0, pa, len, haddr_mr_p, haddr_mw_p, &haddr_mx) == 0) {
            return 0;
      }
      return 1;
}

static int
chip_intel_82443BX_pci_bus_unmap(
      void *_css,
      unsigned long pa,
      unsigned long len
)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      sig_host_bus_unmap(cpssp->port_host_bus, cpssp, pa, len);

      return 1;
}

/* ----------------------------------------------------------------- */
/* Config Space Interface                                            */
/* ----------------------------------------------------------------- */

/*
 * This are helper functions - all config spaces writes, no matter if they
 * are byte, word or long accesses, get mapped to this.
 */
static void
_chip_intel_82443BX_pci_bus_cwriteb(
      struct cpssp *cpssp,
      unsigned char addr,
      unsigned char val
)
{
      unsigned char oldval;

      switch (addr) {
      case 0x00 ... 0x3f:
            /*
             * Writing to reserved config space registers *below* 0x40
             * is allowed. Value written is discarded.
             */
            /* Nothing to do... */
            break;

            /* NBX Configuration Register */
            /* 3-16 */
      case 0x50: /* Bit 7-0 */
            val &= 0xec; /* Mask "reserved" bits */
            pci_setconfigb(cpssp->confsp, addr, val);
            break;
      case 0x51: /* Bit 15-8 */
            val &= 0xbf; /* Mask "reserved" bits */
            pci_setconfigb(cpssp->confsp, addr, val);
            break;
      case 0x52: /* Bit 23-16 */
            val &= 0x07; /* Mask "reserved" bits */
            pci_setconfigb(cpssp->confsp, addr, val);
            break;
      case 0x53: /* Bit 31-24 */
            pci_setconfigb(cpssp->confsp, addr, val);
            break;

            /* DRAM Control Register */
            /* 3-19 */
      case 0x57:
            /* Just remember settings. Not used by simulation. */
            val &= 0x3f;
            pci_setconfigb(cpssp->confsp, addr, val);
            break;

            /* DRAM Timing Register */
            /* 3-20 */
      case 0x58:
            /* Just remember settings. Not used by simulation. */
            val &= 0x3; /* Mask "reserved" bits */
            pci_setconfigb(cpssp->confsp, addr, val);
            break;

            /* Programmable Attribute Map Register */
            /* 3-20 */
      case 0x59:
            val &= 0x30; /* Mask "reserved" bits */

            oldval = pci_getconfigb(cpssp->confsp, addr);
            if (val != oldval) {
                  pci_setconfigb(cpssp->confsp, addr, val);
                  sig_host_bus_unmap(cpssp->port_host_bus, cpssp,
                              0x000f0000, 0x00010000);
                  sig_pci_bus_unmap(cpssp->port_pci_bus, cpssp,
                              0x000f0000, 0x00010000);

                  if (DEBUG_CHIPSET) {
                        faum_log(FAUM_LOG_DEBUG, "82443BX", "", \
                               "Changed PAM register 0x%x to 0x%x\n",
                              addr, val);
                  }
            }
            break;

            /* Programmable Attribute Map Registers */
            /* 3-20 */
      case 0x5a ... 0x5f:
            val &= 0x33; /* Mask "reserved" bits */

            oldval = pci_getconfigb(cpssp->confsp, addr);
            if (val != oldval) {
                  pci_setconfigb(cpssp->confsp, addr, val);
                  sig_host_bus_unmap(cpssp->port_host_bus, cpssp,
                              0x000c0000 + (addr - 0x5a) * 0x8000, 0x8000);
                  sig_pci_bus_unmap(cpssp->port_pci_bus, cpssp,
                              0x000c0000 + (addr - 0x5a) * 0x8000, 0x8000);
                  if (DEBUG_CHIPSET) {
                        faum_log(FAUM_LOG_DEBUG, "82443BX", "", \
                               "Changed PAM register 0x%x to 0x%x\n",
                              addr, val);
                  }
            }
            break;

            /* DRAM Row Boundary Register */
            /* 3-22 */
      case 0x60 ... 0x67:
            oldval = pci_getconfigb(cpssp->confsp, addr);
            pci_setconfigb(cpssp->confsp, addr, val);
            if (val != oldval) {
                  sig_host_bus_unmap(cpssp->port_host_bus, cpssp,
                              0x00000000, 0x40000000);
                  sig_pci_bus_unmap(cpssp->port_pci_bus, cpssp,
                              0x00000000, 0x40000000);
            }
            break;

            /* Fixed DRAM Hole Control Register */
            /* 3-24 */
      case 0x68:
            val &= 0xc0; /* Mask "reserved" bits. */
            if (val != 0) {
                  /* FIXME */
                  fixme();
            }
            pci_setconfigb(cpssp->confsp, addr, val);
            break;

            /* Memory Buffer Strength Control Register */
            /* 3-25 */
      case 0x69 ... 0x6e:
            /* Just remember settings. Not used by simulation. */
            pci_setconfigb(cpssp->confsp, addr, val);
            break;

            /* System Management RAM Control Register */
            /* 3-28 */
      case 0x72:
            val &= 0x78; /* mask "reserved" bit 7 and readonly bits 2:0 */
            val |= 0x02; /* bits 2:0 hardwired to '010' */
            oldval = pci_getconfigb(cpssp->confsp, addr);
            if (oldval & (1 << 4) /* D_LCK */) {
                  /* if D_LCK is set, D_OPEN can't be set any more;
                   * D_LCK can only be cleared by a power-on reset */
                  val &= ~(1 << 6); /* D_OPEN */
                  val |= (1 << 4); /* D_LCK */
            }
            if (val != oldval) {
                  if (DEBUG_SMRAM) {
                        faum_log(FAUM_LOG_DEBUG, "82443BX", "",
                              "Writing 0x%02x to SMRAM "
                              "Control (was 0x%02x)\n", val, oldval);
                  }

                  pci_setconfigb(cpssp->confsp, addr, val);
                  /* SMRAM mapping may have changed */
                  sig_host_bus_unmap(cpssp->port_host_bus, cpssp,
                              0x000a0000, 0x00020000);
                  sig_pci_bus_unmap(cpssp->port_pci_bus, cpssp,
                              0x000a0000, 0x00020000);
            }
            break;
            
            /* Extended System Management RAM Control Register */
            /* 3-29 */
      case 0x73:
            goto unimplemented;

            /* SDRAM Row Page Size Register */
            /* 3-30 */
      case 0x74 ... 0x75:
            goto unimplemented;

            /* SDRAM Control Register */
            /* 3-30 */
      case 0x76 ... 0x77:
            goto unimplemented;

            /* Paging Policy Register */
            /* 3-32 */
      case 0x78 ... 0x79:
            goto unimplemented;

            /* Power Management Control Register */
            /* 3-33 */
      case 0x7A:
            val &= ~0x02; /* Bit 1 is read only */
            pci_setconfigb(cpssp->confsp, addr, val);

            sig_host_bus_ior_info_flush(cpssp->port_host_bus, cpssp,
                        0x0020, 1 << 2);
            sig_host_bus_iow_info_flush(cpssp->port_host_bus, cpssp,
                        0x0020, 1 << 2);
            break;

            /* Suspend CBR Refresh Rate Register */
            /* 3-34 */
      case 0x7b ... 0x7c:
            goto unimplemented;

            /* Error Address Pointer Register */
            /* 3-35 */
      case 0x80 ... 0x83:
            goto unimplemented;

            /* Error Command Register */
            /* 3-36 */
      case 0x90:
            /* Just remember settings. Not used by simulation. */
            pci_setconfigb(cpssp->confsp, addr, val);
            break;

            /* Error Status Register */
            /* 3-37 */
      case 0x91 ... 0x92:
            /* As we don't set any error bits we don't need to
             * reset them... */
            break;

            /* AGP Capability Identifier Register */
            /* 3-38 */
      case 0xa0 ... 0xa3:
            goto unimplemented;

            /* AGP Status Register */
            /* 3-38 */
      case 0xa4 ... 0xa7:
            goto unimplemented;

            /* AGP Command Register */
            /* 3-39 */
      case 0xa8 ... 0xab:
            goto unimplemented;

            /* AGP Control Register */
            /* 3-40 */
      case 0xb0 ... 0xb3:
            goto unimplemented;

            /* Aperture Size Register */
            /* 3-41 */
      case 0xb4:
            val &= 0x3f; /* Masking "reserved" bits. */
            pci_setconfigb(cpssp->confsp, addr, val);
            break;

            /* Aperture Translation Table Base Register */
            /* 3-41 */
      case 0xb8 ... 0xbb:
            goto unimplemented;

            /* Memory Buffer Frequency Select Register */
            /* 3-42 */
      case 0xca ... 0xcc:
            goto unimplemented;

            /* BIOS Scratch Pad Register */
            /* 3-44 */
      case 0xd0 ... 0xd7:
            goto unimplemented;

            /* DRAM Write Thermal Throttling Control Register */
            /* 3-44 */
            /* Just remember settings. Not used by simulation. */
      case 0xe0: /* Bit 7-0 */
      case 0xe1: /* Bit 15-8 */
      case 0xe2: /* Bit 23-16 */
      case 0xe3: /* Bit 31-24 */
      case 0xe4: /* Bit 39-32 */
            if (! ((pci_getconfigb(cpssp->confsp, 0xe7) >> 7) & 1)) {
                  pci_setconfigb(cpssp->confsp, addr, val);
            }
            break;
      case 0xe5: /* Bit 47-40 */
            if (! ((pci_getconfigb(cpssp->confsp, 0xe7) >> 7) & 1)) {
                  val &= 0x3f; /* Masking "reserved" bits. */
                  pci_setconfigb(cpssp->confsp, addr, val);
            }
            break;
      case 0xe6: /* Bit 55-48 */
            /* All bits "reserved". */
            break;
      case 0xe7: /* Bit 63-56 */
            if (! ((pci_getconfigb(cpssp->confsp, 0xe7) >> 7) & 1)) {
                  val &= 0x80; /* Masking "reserved" bits. */
                  pci_setconfigb(cpssp->confsp, addr, val);
            }
            break;

            /* DRAM Read Thermal Throttling Control Register */
            /* 3-46 */
            /* Just remember settings. Not used by simulation. */
      case 0xe8: /* Bit 7-0 */
      case 0xe9: /* Bit 15-8 */
      case 0xea: /* Bit 23-16 */
      case 0xeb: /* Bit 31-24 */
      case 0xec: /* Bit 39-32 */
            if (! ((pci_getconfigb(cpssp->confsp, 0xe7) >> 7) & 1)) {
                  pci_setconfigb(cpssp->confsp, addr, val);
            }
            break;
      case 0xed: /* Bit 47-40 */
            if (! ((pci_getconfigb(cpssp->confsp, 0xe7) >> 7) & 1)) {
                  val &= 0x3f; /* Masking "reserved" bits. */
                  pci_setconfigb(cpssp->confsp, addr, val);
            }
            break;
      case 0xee: /* Bit 55-48 */
      case 0xef: /* Bit 63-56 */
            /* All bits "reserved". */
            break;

            /* Buffer Control Register */
            /* 3-47 */
      case 0xf0 ... 0xf1:
            goto unimplemented;

      unimplemented:;
            faum_log(FAUM_LOG_WARNING, "82443BX (Host Controller)", "",
                        "Writing 0x%02x to unimplemented register 0x%02x.\n",
                        val, addr);
            break;

      default:
            faum_log(FAUM_LOG_WARNING, "82443BX (Host Controller)", "",
                        "Writing 0x%02x to reserved register 0x%02x.\n",
                        val, addr);
            break;
      }
}

static int
chip_intel_82443BX_c0w(void *_css, uint32_t addr, unsigned int bs, uint32_t val)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      if ((addr >> 11) & 1) {
            /* Host/PCI Bridge */
            if ((bs >> 0) & 1) {
                  _chip_intel_82443BX_pci_bus_cwriteb(cpssp,
                        (addr + 0) & 0xff, (val >>  0) & 0xff);
            }
            if ((bs >> 1) & 1) {
                  _chip_intel_82443BX_pci_bus_cwriteb(cpssp,
                        (addr + 1) & 0xff, (val >>  8) & 0xff);
            }
            if ((bs >> 2) & 1) {
                  _chip_intel_82443BX_pci_bus_cwriteb(cpssp,
                        (addr + 2) & 0xff, (val >>  16) & 0xff);
            }
            if ((bs >> 3) & 1) {
                  _chip_intel_82443BX_pci_bus_cwriteb(cpssp,
                        (addr + 3) & 0xff, (val >>  24) & 0xff);
            }
            return 0;

      } else if ((addr >> 12) & 1) {
            /* AGP - FIXME VOSSI */
            return -1;

      } else {
            return -1;
      }
}

static int
chip_intel_82443BX_c0r(void *_css, uint32_t addr, unsigned int bs, uint32_t *valp)
{
      struct cpssp *cpssp = (struct cpssp *) _css;

      if ((addr >> 11) & 1) {
            /* Host/PCI Bridge */
            if ((bs >> 0) & 1) {
                  *valp &= ~(0xff << 0);
                  *valp |= pci_getconfigb(cpssp->confsp,
                              (addr + 0) & 0xff) << 0;
            }
            if ((bs >> 1) & 1) {
                  *valp &= ~(0xff << 8);
                  *valp |= pci_getconfigb(cpssp->confsp,
                              (addr + 1) & 0xff) << 8;
            }
            if ((bs >> 2) & 1) {
                  *valp &= ~(0xff << 16);
                  *valp |= pci_getconfigb(cpssp->confsp,
                              (addr + 2) & 0xff) << 16;
            }
            if ((bs >> 3) & 1) {
                  *valp &= ~(0xff << 24);
                  *valp |= pci_getconfigb(cpssp->confsp,
                              (addr + 3) & 0xff) << 24;
            }
            return 0;

      } else if ((addr >> 12) & 1) {
            /* AGP - FIXME VOSSI */
            return -1;

      } else {
            return -1;
      }
}

static void
chip_intel_82443BX_power_set(void *_css, unsigned int val)
{
      /* FIXME */
}

static void
chip_intel_82443BX_n_reset_set(void *_css, unsigned int n_val)
{
      struct cpssp *cpssp = (struct cpssp *) _css;
      int i;

      /* Set PAM to default */
      for (i = 0x59; i < 0x5f; i++) {
            pci_setconfigb(cpssp->confsp, i, 0x00);
      }
      for (i = 0x60; i < 0x68; i++) {
            pci_setconfigb(cpssp->confsp, i, 0x01);
      }
      /* SMRAM register defaults to 0x02 on reset */
      pci_setconfigb(cpssp->confsp, 0x72, 0x02);
}

/* ----------------------------------------------------------------- */
/* Init Function                                                     */
/* ----------------------------------------------------------------- */

void
chip_intel_82443BX_init(
      unsigned int nr,
      struct sig_boolean *port_power,
      struct sig_boolean *port_reset_hash_,
      struct sig_host_bus_main *port_host_bus,
      struct sig_cs *port_mem_cs0,
      struct sig_cs *port_mem_cs1,
      struct sig_cs *port_mem_cs2,
      struct sig_cs *port_mem_cs3,
      struct sig_cs *port_mem_cs4,
      struct sig_cs *port_mem_cs5,
      struct sig_cs *port_mem_cs6,
      struct sig_cs *port_mem_cs7,
      struct sig_mem_bus_main *port_mem,
      struct sig_pci_bus_main *port_pci_bus,
      struct sig_pci_bus_idsel *port_idsel,
      struct sig_agp_bus_main *port_agp_bus,
      struct sig_pci_bus_idsel *port_gidsel
)
{
      static const struct sig_boolean_funcs power_funcs = {
            .set = chip_intel_82443BX_power_set,
      };
      static const struct sig_boolean_funcs reset_hash__funcs = {
            .set = chip_intel_82443BX_n_reset_set,
      };
      static const struct sig_host_bus_main_funcs host_bus_funcs = {
            .type_addr =      chip_intel_82443BX_host_bus_type_addr,
            .read_data =      chip_intel_82443BX_host_bus_read_data,
            .write_data =     chip_intel_82443BX_host_bus_write_data,

            .ior =            chip_intel_82443BX_host_bus_ior,
            .iow =            chip_intel_82443BX_host_bus_iow,

            .ior_info = chip_intel_82443BX_host_bus_ior_info,
            .iow_info = chip_intel_82443BX_host_bus_iow_info,

            .mr =       chip_intel_82443BX_host_bus_mr,
            .mw =       chip_intel_82443BX_host_bus_mw,
            .map =            chip_intel_82443BX_host_bus_map,

            .inta_addr =      chip_intel_82443BX_host_bus_inta_addr,
            .inta_data =      chip_intel_82443BX_host_bus_inta_data,

#if 0 /* Not used yet. */
            .unmap =    chip_intel_82443BX_host_bus_unmap,
#endif
      };
      static const struct sig_cs_funcs mem_cs0_funcs = {
            .unmap =    chip_intel_82443BX_memX_unmap,
      };
      static const struct sig_cs_funcs mem_cs1_funcs = {
            .unmap =    chip_intel_82443BX_memX_unmap,
      };
      static const struct sig_cs_funcs mem_cs2_funcs = {
            .unmap =    chip_intel_82443BX_memX_unmap,
      };
      static const struct sig_cs_funcs mem_cs3_funcs = {
            .unmap =    chip_intel_82443BX_memX_unmap,
      };
      static const struct sig_cs_funcs mem_cs4_funcs = {
            .unmap =    chip_intel_82443BX_memX_unmap,
      };
      static const struct sig_cs_funcs mem_cs5_funcs = {
            .unmap =    chip_intel_82443BX_memX_unmap,
      };
      static const struct sig_cs_funcs mem_cs6_funcs = {
            .unmap =    chip_intel_82443BX_memX_unmap,
      };
      static const struct sig_cs_funcs mem_cs7_funcs = {
            .unmap =    chip_intel_82443BX_memX_unmap,
      };
      static const struct sig_pci_bus_main_funcs pci_bus_funcs = {
            .mr =       chip_intel_82443BX_pci_bus_mr,
            .mw =       chip_intel_82443BX_pci_bus_mw,
            .map =            chip_intel_82443BX_pci_bus_map,

#if 0 /* Not used yet. */
            .ack =            chip_intel_82443BX_pci_bus_ack,
#endif

            .unmap =    chip_intel_82443BX_pci_bus_unmap,
      };
      static const struct sig_pci_bus_idsel_funcs idsel_funcs = {
            .c0r =            chip_intel_82443BX_c0r,
            .c0w =            chip_intel_82443BX_c0w,
      };
      struct cpssp *cpssp;

      cpssp = shm_map(COMP, nr, sizeof(*cpssp), 0);

      /* Out */
      /* Call */
      cpssp->port_host_bus = port_host_bus;
      sig_host_bus_main_connect(port_host_bus, cpssp, &host_bus_funcs);

      cpssp->sig_mem_cs[0] = port_mem_cs0;
      sig_cs_connect(port_mem_cs0, cpssp, &mem_cs0_funcs);

      cpssp->sig_mem_cs[1] = port_mem_cs1;
      sig_cs_connect(port_mem_cs1, cpssp, &mem_cs1_funcs);

      cpssp->sig_mem_cs[2] = port_mem_cs2;
      sig_cs_connect(port_mem_cs2, cpssp, &mem_cs2_funcs);

      cpssp->sig_mem_cs[3] = port_mem_cs3;
      sig_cs_connect(port_mem_cs3, cpssp, &mem_cs3_funcs);

      cpssp->sig_mem_cs[4] = port_mem_cs4;
      sig_cs_connect(port_mem_cs4, cpssp, &mem_cs4_funcs);

      cpssp->sig_mem_cs[5] = port_mem_cs5;
      sig_cs_connect(port_mem_cs5, cpssp, &mem_cs5_funcs);

      cpssp->sig_mem_cs[6] = port_mem_cs6;
      sig_cs_connect(port_mem_cs6, cpssp, &mem_cs6_funcs);

      cpssp->sig_mem_cs[7] = port_mem_cs7;
      sig_cs_connect(port_mem_cs7, cpssp, &mem_cs7_funcs);

      cpssp->port_pci_bus = port_pci_bus;
      sig_pci_bus_main_connect(port_pci_bus, cpssp, &pci_bus_funcs);

      cpssp->port_idsel = port_idsel;
      sig_pci_bus_idsel_connect(port_idsel, cpssp, &idsel_funcs);

      cpssp->port_agp_bus = port_agp_bus;
      /* FIXME */

      cpssp->port_gidsel = port_gidsel;
      /* FIXME */

      /* In */
      sig_boolean_connect_in(port_power, cpssp, &power_funcs);

      sig_boolean_connect_in(port_reset_hash_, cpssp, &reset_hash__funcs);

}

unsigned int
chip_intel_82443BX_create(void)
{
      static unsigned int nr = 0;
      struct cpssp *cpssp;

      shm_create(COMP, nr, sizeof(*cpssp));
      cpssp = shm_map(COMP, nr, sizeof(*cpssp), 0);

      /* initialize PCI config space */
      memset(cpssp->confsp, 0, 0x100);
      pci_setconfigw(cpssp->confsp, PCI_VENDOR_ID, PCI_VENDOR_ID_INTEL);
      /* Set device ID for BX chipset with AGP disabled */
      pci_setconfigw(cpssp->confsp, PCI_DEVICE_ID, 0x7192);
      pci_setconfigw(cpssp->confsp, PCI_COMMAND, 0x0006);
      pci_setconfigw(cpssp->confsp, PCI_STATUS, 0x2210);
      pci_setconfigb(cpssp->confsp, PCI_REVISION_ID, 0x02);
      pci_setconfigw(cpssp->confsp, PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_HOST);
      pci_setconfigb(cpssp->confsp, PCI_LATENCY_TIMER, 0x40);
      pci_setconfigl(cpssp->confsp, PCI_BASE_ADDRESS_0, 0x00000008);

      shm_unmap(cpssp, sizeof(*cpssp));

      return nr++;
}

void
chip_intel_82443BX_destroy(unsigned int nr)
{
      struct cpssp *cpssp;

      cpssp = shm_map(COMP, nr, sizeof(*cpssp), 0);

      shm_unmap(cpssp, sizeof(*cpssp));
      shm_destroy(COMP, nr);
}

Generated by  Doxygen 1.6.0   Back to index