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

sig_pci_bus.c

/*
 * $Id: sig_pci_bus.c,v 1.68 2009-01-27 17:06:42 potyra Exp $
 *
 * Copyright (C) 2004-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.
 */

#include "config.h"
#include <sys/types.h>
#include <sys/mman.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fixme.h"

#include "glue-shm.h"

#include "sig_pci_bus.h"

int
sig_pci_bus_main_type_addr(
      struct sig_pci_bus_main *b,
      void *s,
      unsigned int type,
      uint32_t addr
)
{
      unsigned int nr;

      for (nr = 0; ; nr++) {
            int (*func)(void *, unsigned int, uint32_t);
            void *func_s;

            if (nr == b->member_count) {
                  /* Not found. */
                  return -1;
            }
            if (b->member[nr].s == s) {
                  /* Don't ask myself. */
                  continue;
            }
            func = b->member[nr].f->type_addr;
            func_s = b->member[nr].s;
            if (func
             && func(func_s, type, addr) == 0) {
                  return 0;
            }
      }
}

int
sig_pci_bus_main_read_data(
      struct sig_pci_bus_main *b,
      void *s,
      unsigned int bs,
      uint32_t *valp
)
{
      unsigned int nr;

      for (nr = 0; ; nr++) {
            int (*func)(void *, unsigned int, uint32_t *);
            void *func_s;

            if (nr == b->member_count) {
                  /* Not found. */
                  *valp = 0xffffffff;
                  return -1;
            }
            if (b->member[nr].s == s) {
                  /* Don't ask myself. */
                  continue;
            }
            func = b->member[nr].f->read_data;
            func_s = b->member[nr].s;
            if (func
             && func(func_s, bs, valp) == 0) {
                  return 0;
            }
      }
}

int
sig_pci_bus_main_write_data(
      struct sig_pci_bus_main *b,
      void *s,
      unsigned int bs,
      uint32_t val
)
{
      unsigned int nr;

      for (nr = 0; ; nr++) {
            int (*func)(void *, unsigned int, uint32_t);
            void *func_s;

            if (nr == b->member_count) {
                  /* Not found. */
                  return -1;
            }
            if (b->member[nr].s == s) {
                  /* Don't ask myself. */
                  continue;
            }
            func = b->member[nr].f->write_data;
            func_s = b->member[nr].s;
            if (func
             && func(func_s, bs, val) == 0) {
                  return 0;
            }
      }
}

int
sig_pci_bus_main_c0r(
      struct sig_pci_bus_main *b,
      void *s,
      uint32_t addr,
      unsigned int bs,
      uint32_t *valp
)
{
      int (*func)(void *, uint32_t, unsigned int, uint32_t *);
      unsigned int nr;

      assert((addr & 3) == 0);

      for (nr = 0; ; nr++) {
            if (nr == b->member_count) {
                  *valp = -1;
                  return 1;
            }

            if (! b->member[nr].f
             || b->member[nr].s == s) {
                  continue;
            }

            func = b->member[nr].f->c0r;
            if (func
             && func(b->member[nr].s, addr, bs, valp) == 0) {
                  return 0;
            }
      }
}

int
sig_pci_bus_main_c0w(
      struct sig_pci_bus_main *b,
      void *s,
      uint32_t addr,
      unsigned int bs,
      uint32_t val
)
{
      int (*func)(void *, uint32_t, unsigned int, uint32_t);
      unsigned int nr;

      assert((addr & 3) == 0);

      for (nr = 0; ; nr++) {
            if (nr == b->member_count) {
                  return 1;
            }

            if (! b->member[nr].f
             || b->member[nr].s == s) {
                  continue;
            }

            func = b->member[nr].f->c0w;
            if (func
             && func(b->member[nr].s, addr, bs, val) == 0) {
                  return 0;
            }
      }
}

int
sig_pci_bus_c1r(
      struct sig_pci_bus_main *b,
      void *s,
      uint32_t addr,
      unsigned int bs,
      uint32_t *valp
)
{
      int (*func)(void *, uint32_t, unsigned int, uint32_t *);
      unsigned int nr;

      assert((addr & 3) == 0);

      for (nr = 0; ; nr++) {
            if (nr == b->member_count) {
                  return 1;
            }

            if (! b->member[nr].f
             || b->member[nr].s == s) {
                  continue;
            }

            func = b->member[nr].f->c1r;
            if (func
             && func(b->member[nr].s, addr, bs, valp) == 0) {
                  return 0;
            }
      }
}

int
sig_pci_bus_c1w(
      struct sig_pci_bus_main *b,
      void *s,
      uint32_t addr,
      unsigned int bs,
      uint32_t val
)
{
      int (*func)(void *, uint32_t, unsigned int, uint32_t);
      unsigned int nr;

      assert((addr & 3) == 0);

      for (nr = 0; ; nr++) {
            if (nr == b->member_count) {
                  return 1;
            }

            if (! b->member[nr].f
             || b->member[nr].s == s) {
                  continue;
            }

            func = b->member[nr].f->c1w;
            if (func
             && func(b->member[nr].s, addr, bs, val) == 0) {
                  return 0;
            }
      }
}

static inline __attribute__((always_inline)) unsigned int
_sig_pci_bus_io_hash(uint32_t port, unsigned int bs)
{
      return port % SIG_PCI_BUS_HASH_SIZE;
}

static int
_sig_pci_bus_ior_lookup(
      struct sig_pci_bus_main *b,
      uint32_t port,
      unsigned int bs,
      int (**f)(void *s, uint32_t port, unsigned int bs, uint32_t *valp),
      void **s
)
{
      unsigned int hash;
      struct sig_pci_bus_main_ior *m;

      hash = _sig_pci_bus_io_hash(port, bs);

      for (m = b->ior_hash_first[hash]; ; m = m->hash_next) {
            if (! m) {
                  /* Not found. */
                  return 0;
            }
            if (m->port == port
             && m->bs == bs) {
                  /* Found. */
                  *f = m->f;
                  *s = m->s;
                  return 1;
            }
      }
}

static void
_sig_pci_bus_ior_add(
      struct sig_pci_bus_main *b,
      uint32_t port,
      unsigned int bs,
      int (*f)(void *s, uint32_t port, unsigned int bs, uint32_t *valp),
      void *s
)
{
      unsigned int hash;
      struct sig_pci_bus_main_ior *m;

      m = b->ior_lru_last;

      /* Remove from LRU list. */
      m->lru_prev->lru_next = 0;
      b->ior_lru_last = m->lru_prev;

      if (m->port != -1) {
            /* Remove from HASH list. */
            hash = _sig_pci_bus_io_hash(m->port, m->bs);
            if (m->hash_prev) {
                  m->hash_prev->hash_next = m->hash_next;
            } else {
                  b->ior_hash_first[hash] = m->hash_next;
            }
            if (m->hash_next) {
                  m->hash_next->hash_prev = m->hash_prev;
            } else {
                  b->ior_hash_last[hash] = m->hash_prev;
            }
      }

      /* Add new info. */
      m->port = port;
      m->bs = bs;
      m->f = f;
      m->s = s;

      /* Add to HASH list. */
      hash = _sig_pci_bus_io_hash(port, bs);
      m->hash_prev = 0;
      m->hash_next = b->ior_hash_first[hash];
      b->ior_hash_first[hash] = m;
      if (m->hash_next) {
            m->hash_next->hash_prev = m;
      } else {
            b->ior_hash_last[hash] = m;
      }

      /* Add to LRU list. */
      m->lru_prev = 0;
      m->lru_next = b->ior_lru_first;
      b->ior_lru_first = m;
      m->lru_next->lru_prev = m;
}

int
sig_pci_bus_ior_info(
      struct sig_pci_bus_main *b,
      void *s,
      uint32_t port,
      unsigned int bs,
      int (**cfp)(void *, uint32_t, unsigned int, uint32_t *),
      void **csp
)
{
      unsigned int nr;

      for (nr = 0; ; nr++) {
            int (*info_f)(void *, uint32_t, unsigned int,
                  int (**)(void *, uint32_t, unsigned int, uint32_t *),
                  void **);
            void *info_s;

            if (nr == b->member_count) {
                  /* No info found. */
                  return -1;
            }
            if (b->member[nr].s == s) {
                  /* Don't ask myself. */
                  continue;
            }
            info_f = b->member[nr].f->ior_info;
            info_s = b->member[nr].s;
            if (info_f
             && info_f(info_s, port, bs, cfp, csp) == 0) {
                  return 0;
            }
      }
}

void
sig_pci_bus_ior_info_flush(
      struct sig_pci_bus_main *b,
      void *s,
      uint32_t port,
      unsigned int bs
)
{
      unsigned int hash;
      struct sig_pci_bus_main_ior *m;

      hash = _sig_pci_bus_io_hash(port, bs);

      for (m = b->ior_hash_first[hash]; ; m = m->hash_next) {
            if (! m) {
                  /* Not found. */
                  return;
            }
            if (port == m->port
             && (bs == m->bs
              || bs == 0)) {
                  /* Found. */
                  /* Remove from LRU list. */
                  if (m->lru_prev) {
                        m->lru_prev->lru_next = m->lru_next;
                  } else {
                        b->ior_lru_first = m->lru_next;
                  }
                  if (m->lru_next) {
                        m->lru_next->lru_prev = m->lru_prev;
                  } else {
                        b->ior_lru_last = m->lru_prev;
                  }

                  /* Remove from HASH list. */
                  hash = _sig_pci_bus_io_hash(port, bs);
                  if (m->hash_prev) {
                        m->hash_prev->hash_next = m->hash_next;
                  } else {
                        b->ior_hash_first[hash] = m->hash_next;
                  }
                  if (m->hash_next) {
                        m->hash_next->hash_prev = m->hash_prev;
                  } else {
                        b->ior_hash_last[hash] = m->hash_prev;
                  }

                  /* Remove info. */
                  m->port = -1;
                  m->bs = -1;

                  /* Don't add empty entry to HASH list. */

                  /* Add to LRU list. */
                  m->lru_prev = b->ior_lru_last;
                  m->lru_next = 0;
                  m->lru_prev->lru_next = m;
                  b->ior_lru_last = m;
                  return;
            }
      }
}

int
sig_pci_bus_ior(
      struct sig_pci_bus_main *b,
      void *s,
      uint32_t port,
      unsigned int bs,
      uint32_t *valp
)
{
      int (*cf)(void *, uint32_t, unsigned int, uint32_t *);
      void *cs;
      unsigned int nr;

      assert((port & 3) == 0);

      if (_sig_pci_bus_ior_lookup(b, port, bs, &cf, &cs)) {
            (*cf)(cs, port, bs, valp);
            return 0;
      }

      if (sig_pci_bus_ior_info(b, s, port, bs, &cf, &cs) == 0) {
            _sig_pci_bus_ior_add(b, port, bs, cf, cs);
            cf(cs, port, bs, valp);
            return 0;
      }

      for (nr = 0; ; nr++) {
            if (nr == b->member_count) {
                  *valp = -1;
                  return 1;
            }

            if (! b->member[nr].f
             || b->member[nr].s == s) {
                  continue;
            }

            cf = b->member[nr].f->ior;
            cs = b->member[nr].s;
            if (cf
             && cf(cs, port, bs, valp) == 0) {
                  _sig_pci_bus_ior_add(b, port, bs, cf, cs);
                  return 0;
            }
      }
}

static int
_sig_pci_bus_iow_lookup(
      struct sig_pci_bus_main *b,
      uint32_t port,
      unsigned int bs,
      int (**f)(void *s, uint32_t port, unsigned int bs, uint32_t val),
      void **s
)
{
      unsigned int hash;
      struct sig_pci_bus_main_iow *m;

      hash = _sig_pci_bus_io_hash(port, bs);

      for (m = b->iow_hash_first[hash]; ; m = m->hash_next) {
            if (! m) {
                  /* Not found. */
                  return 0;
            }
            if (m->port == port
             && m->bs == bs) {
                  /* Found. */
                  *f = m->f;
                  *s = m->s;
                  return 1;
            }
      }
}

static void
_sig_pci_bus_iow_add(
      struct sig_pci_bus_main *b,
      uint32_t port,
      unsigned int bs,
      int (*f)(void *s, uint32_t port, unsigned int bs, uint32_t val),
      void *s
)
{
      unsigned int hash;
      struct sig_pci_bus_main_iow *m;

      m = b->iow_lru_last;

      /* Remove from LRU list. */
      m->lru_prev->lru_next = 0;
      b->iow_lru_last = m->lru_prev;

      if (m->port != -1) {
            /* Remove from HASH list. */
            hash = _sig_pci_bus_io_hash(m->port, m->bs);
            if (m->hash_prev) {
                  m->hash_prev->hash_next = m->hash_next;
            } else {
                  b->iow_hash_first[hash] = m->hash_next;
            }
            if (m->hash_next) {
                  m->hash_next->hash_prev = m->hash_prev;
            } else {
                  b->iow_hash_last[hash] = m->hash_prev;
            }
      }

      /* Add new info. */
      m->port = port;
      m->bs = bs;
      m->f = f;
      m->s = s;

      /* Add to HASH list. */
      hash = _sig_pci_bus_io_hash(port, bs);
      m->hash_prev = 0;
      m->hash_next = b->iow_hash_first[hash];
      b->iow_hash_first[hash] = m;
      if (m->hash_next) {
            m->hash_next->hash_prev = m;
      } else {
            b->iow_hash_last[hash] = m;
      }

      /* Add to LRU list. */
      m->lru_prev = 0;
      m->lru_next = b->iow_lru_first;
      b->iow_lru_first = m;
      m->lru_next->lru_prev = m;
}

int
sig_pci_bus_iow_info(
      struct sig_pci_bus_main *b,
      void *s,
      uint32_t port,
      unsigned int bs,
      int (**cfp)(void *, uint32_t, unsigned int, uint32_t),
      void **csp
)
{
      unsigned int nr;

      for (nr = 0; ; nr++) {
            int (*info_f)(void *, uint32_t, unsigned int,
                  int (**)(void *, uint32_t, unsigned int, uint32_t),
                  void **);
            void *info_s;

            if (nr == b->member_count) {
                  /* No info found. */
                  return -1;
            }
            if (b->member[nr].s == s) {
                  /* Don't ask myself. */
                  continue;
            }
            info_f = b->member[nr].f->iow_info;
            info_s = b->member[nr].s;
            if (info_f
             && info_f(info_s, port, bs, cfp, csp) == 0) {
                  return 0;
            }
      }
}

void
sig_pci_bus_iow_info_flush(
      struct sig_pci_bus_main *b,
      void *s,
      uint32_t port,
      unsigned int bs
)
{
      unsigned int hash;
      struct sig_pci_bus_main_iow *m;

      hash = _sig_pci_bus_io_hash(port, bs);

      for (m = b->iow_hash_first[hash]; ; m = m->hash_next) {
            if (! m) {
                  /* Not found. */
                  return;
            }
            if (port == m->port
             && (bs == m->bs
              || bs == 0)) {
                  /* Found. */
                  /* Remove from LRU list. */
                  if (m->lru_prev) {
                        m->lru_prev->lru_next = m->lru_next;
                  } else {
                        b->iow_lru_first = m->lru_next;
                  }
                  if (m->lru_next) {
                        m->lru_next->lru_prev = m->lru_prev;
                  } else {
                        b->iow_lru_last = m->lru_prev;
                  }

                  /* Remove from HASH list. */
                  hash = _sig_pci_bus_io_hash(port, bs);
                  if (m->hash_prev) {
                        m->hash_prev->hash_next = m->hash_next;
                  } else {
                        b->iow_hash_first[hash] = m->hash_next;
                  }
                  if (m->hash_next) {
                        m->hash_next->hash_prev = m->hash_prev;
                  } else {
                        b->iow_hash_last[hash] = m->hash_prev;
                  }

                  /* Remove info. */
                  m->port = -1;
                  m->bs = -1;

                  /* Don't add empty entry to HASH list. */

                  /* Add to LRU list. */
                  m->lru_prev = b->iow_lru_last;
                  m->lru_next = 0;
                  m->lru_prev->lru_next = m;
                  b->iow_lru_last = m;
                  return;
            }
      }
}

int
sig_pci_bus_iow(
      struct sig_pci_bus_main *b,
      void *s,
      uint32_t port,
      unsigned int bs,
      uint32_t val
)
{
      int (*cf)(void *, uint32_t, unsigned int, uint32_t);
      void *cs;
      unsigned int nr;

      assert((port & 3) == 0);

      if (_sig_pci_bus_iow_lookup(b, port, bs, &cf, &cs)) {
            cf(cs, port, bs, val);
            return 0;
      }

      if (sig_pci_bus_iow_info(b, s, port, bs, &cf, &cs) == 0) {
            _sig_pci_bus_iow_add(b, port, bs, cf, cs);
            cf(cs, port, bs, val);
            return 0;
      }

      for (nr = 0; ; nr++) {
            if (nr == b->member_count) {
                  return 1;
            }

            if (! b->member[nr].f
             || b->member[nr].s == s) {
                  continue;
            }

            cf = b->member[nr].f->iow;
            cs = b->member[nr].s;
            if (cf
             && cf(cs, port, bs, val) == 0) {
                  _sig_pci_bus_iow_add(b, port, bs, cf, cs);
                  return 0;
            }
      }
}

static inline unsigned int
_sig_pci_bus_map_hash(uint32_t addr)
{
      return (addr >> 12) & 0x3ff;
}

static inline __attribute__((always_inline)) struct sig_pci_bus_main_map *
_sig_pci_bus_map_lookup(
      struct sig_pci_bus_main *b,
      uint32_t addr
)
{
      unsigned int hash;
      struct sig_pci_bus_main_map *m;

      addr &= ~0xfff;

      hash = _sig_pci_bus_map_hash(addr);

      for (m = b->map_hash_first[hash]; ; m = m->hash_next) {
            if (! m) {
                  /*
                   * Not Found
                   */
                  return NULL;
            }
            if (m->addr == addr) {
                  /*
                   * Found
                   */
                  /* Don't update LRU list. */
                  /* Costs too much... */
                  return m;
            }
      }
}

static inline __attribute__((always_inline)) struct sig_pci_bus_main_map *
_sig_pci_bus_map_add(
      struct sig_pci_bus_main *b,
      uint32_t addr
)
{
      char *haddr_mr;
      char *haddr_mw;
      unsigned int hash;
      struct sig_pci_bus_main_map *m;

      addr &= ~0xfff;

      if (sig_pci_bus_map(b, b, addr, 0x1000, &haddr_mr, &haddr_mw) != 0) {
            haddr_mr = NULL;
            haddr_mw = NULL;
      }

      /* Get entry from LRU list. */
      m = b->map_lru_last;

      /* Remove from LRU list. */
      assert(m->lru_prev);
      m->lru_prev->lru_next = 0;
      b->map_lru_last = m->lru_prev;

      if (m->addr != -1) {
            /* Remove from HASH list. */
            hash = _sig_pci_bus_map_hash(m->addr & ~0xfff);
            if (m->hash_prev) {
                  m->hash_prev->hash_next = m->hash_next;
            } else {
                  b->map_hash_first[hash] = m->hash_next;
            }
            if (m->hash_next) {
                  m->hash_next->hash_prev = m->hash_prev;
            } else {
                  b->map_hash_last[hash] = m->hash_prev;
            }
      }

      /* Add new info. */
      m->addr = addr & ~0xfff;
      m->va_mr = (uint32_t *) haddr_mr;
      m->va_mw = (uint32_t *) haddr_mw;

      /* Add to HASH list. */
      hash = _sig_pci_bus_map_hash(addr & ~0xfff);
      m->hash_prev = 0;
      m->hash_next = b->map_hash_first[hash];
      b->map_hash_first[hash] = m;
      if (m->hash_next) {
            m->hash_next->hash_prev = m;
      } else {
            b->map_hash_last[hash] = m;
      }

      /* Add to LRU list. */
      m->lru_prev = 0;
      m->lru_next = b->map_lru_first;
      b->map_lru_first = m;
      m->lru_next->lru_prev = m;

      return m;
}

static void
_sig_pci_bus_map_flush(struct sig_pci_bus_main *b, uint32_t addr, uint32_t len)
{
      unsigned int hash;
      unsigned int i;
      struct sig_pci_bus_main_map *m;

      for (i = 0; i < sizeof(b->map) / sizeof(b->map[0]); i++) {
            m = &b->map[i];

            if (m->addr == -1
             || m->addr < addr
             || addr + len - 1 < m->addr) {
                  continue;
            }

            /* Remove from LRU list. */
            if (m->lru_prev) {
                  m->lru_prev->lru_next = m->lru_next;
            } else {
                  b->map_lru_first = m->lru_next;
            }
            if (m->lru_next) {
                  m->lru_next->lru_prev = m->lru_prev;
            } else {
                  b->map_lru_last = m->lru_prev;
            }

            /* Remove from HASH list. */
            hash = _sig_pci_bus_map_hash(m->addr);
            if (m->hash_prev) {
                  m->hash_prev->hash_next = m->hash_next;
            } else {
                  b->map_hash_first[hash] = m->hash_next;
            }
            if (m->hash_next) {
                  m->hash_next->hash_prev = m->hash_prev;
            } else {
                  b->map_hash_last[hash] = m->hash_prev;
            }

            /* Unmap page. */
            m->addr = -1;

            /* Don't add empty entry to HASH list. */

            /* Add to LRU list. */
            m->lru_prev = b->map_lru_last;
            m->lru_next = 0;
            m->lru_prev->lru_next = m;
            b->map_lru_last = m;
      }
}

int
sig_pci_bus_mr(
      struct sig_pci_bus_main *b,
      void *s,
      uint32_t pa,
      unsigned int bs,
      uint32_t *valp
)
{
      struct sig_pci_bus_main_map *m;
      uint32_t *va;
      int (*func)(void *, uint32_t, unsigned int, uint32_t *);
      unsigned int nr;

      m = _sig_pci_bus_map_lookup(b, pa);
      if (! m) {
            m = _sig_pci_bus_map_add(b, pa);
      }
      if (m->va_mr) {
            va = (uint32_t *) m->va_mr + ((pa & 0xffc) >> 2);

            /* No need to obey `bs'. */
            *valp = *va;

            return 0;
      }

      /*
       * Not mappable. Call function...
       */
      for (nr = 0; ; nr++) {
            if (nr == b->member_count) {
                  return -1;
            }
            if (! b->member[nr].f
             || b->member[nr].s == s) {
                  continue;
            }
            func = b->member[nr].f->mr;
            if (func
             && func(b->member[nr].s, pa, bs, valp) == 0) {
                  return 0;
            }
      }
}

int
sig_pci_bus_mw(
      struct sig_pci_bus_main *b,
      void *s,
      uint32_t pa,
      unsigned int bs,
      uint32_t val
)
{
      struct sig_pci_bus_main_map *m;
      uint32_t *va;
      int (*func)(void *, uint32_t, unsigned int, uint32_t);
      unsigned int nr;

      m = _sig_pci_bus_map_lookup(b, pa);
      if (! m) {
            m = _sig_pci_bus_map_add(b, pa);
      }
      if (m->va_mw) {
            va = (uint32_t *) m->va_mw + ((pa & 0xffc) >> 2);

            if (bs == 0xf) {
                  *va = val;
            } else {
                  if ((bs >> 0) & 1) {
                        *va &= ~(0xff << 0);
                        *va |= val & (0xff << 0);
                  }
                  if ((bs >> 1) & 1) {
                        *va &= ~(0xff << 8);
                        *va |= val & (0xff << 8);
                  }
                  if ((bs >> 2) & 1) {
                        *va &= ~(0xff << 16);
                        *va |= val & (0xff << 16);
                  }
                  if ((bs >> 3) & 1) {
                        *va &= ~(0xff << 24);
                        *va |= val & (0xff << 24);
                  }
            }
            return 0;
      }

      for (nr = 0; ; nr++) {
            if (nr == b->member_count) {
                  return -1;
            }
            if (! b->member[nr].f
             || b->member[nr].s == s) {
                  continue;
            }

            func = b->member[nr].f->mw;
            if (func
             && func(b->member[nr].s, pa, bs, val) == 0) {
                  return 0;
            }
      }
}

int
sig_pci_bus_map(
      struct sig_pci_bus_main *b,
      void *s,
      unsigned long pa,
      unsigned int len,
      char **haddr_mr_p,
      char **haddr_mw_p
)
{
      unsigned int nr;
      int (*func)(void *, unsigned long, unsigned int, char **, char **);

      for (nr = 0; ; nr++) {
            if (nr == b->member_count) {
                  return 1;
            }
            if (! b->member[nr].f
             || b->member[nr].s == s) {
                  continue;
            }
            func = b->member[nr].f->map;
            if (func != 0 && func(b->member[nr].s, pa, len,
                        haddr_mr_p, haddr_mw_p) == 0) {
                  return 0;
            }
      }
}

int
sig_pci_bus_inta_addr(
      struct sig_pci_bus_main *b,
      void *s
)
{
      unsigned int nr;
      int (*func)(void *);

      for (nr = 0; ; nr++) {
            if (nr == b->member_count) {
                  return 1;
            }
            if (! b->member[nr].f
             || b->member[nr].s == s) {
                  continue;
            }
            func = b->member[nr].f->inta_addr;
            if (func != 0 && func(b->member[nr].s) == 0) {
                  return 0;
            }
      }
}

int
sig_pci_bus_inta_data(
      struct sig_pci_bus_main *b,
      void *s,
      uint8_t *valp
)
{
      unsigned int nr;
      int (*func)(void *, uint8_t *);

      for (nr = 0; ; nr++) {
            if (nr == b->member_count) {
                  return 1;
            }
            if (! b->member[nr].f
             || b->member[nr].s == s) {
                  continue;
            }
            func = b->member[nr].f->inta_data;
            if (func != 0 && func(b->member[nr].s, valp) == 0) {
                  return 0;
            }
      }
}

int
sig_pci_bus_unmap(
      struct sig_pci_bus_main *b,
      void *s,
      unsigned long pa,
      unsigned long len
)
{
      unsigned int nr;
      int (*func)(void *, unsigned long, unsigned long);

      _sig_pci_bus_map_flush(b, pa, len);

      for (nr = 0; ; nr++) {
            if (nr == b->member_count) {
                  return 1;
            }
            if (! b->member[nr].f
             || b->member[nr].s == s) {
                  continue;
            }
            func = b->member[nr].f->unmap;
            if (func != 0 && func(b->member[nr].s, pa, len) == 0) {
                  return 0;
            }
      }
}

void
sig_pci_bus_main_connect(
      struct sig_pci_bus_main *b,
      void *s,
      const struct sig_pci_bus_main_funcs *f
)
{
      assert(b);
      assert(b->member_count < sizeof(b->member) / sizeof(b->member[0]));

      b->member[b->member_count].s = s;
      b->member[b->member_count].f = f;
      b->member_count++;
}

struct sig_pci_bus_main *
sig_pci_bus_main_init(const char *name, int nr)
{
      struct sig_pci_bus_main *b;
      struct sig_pci_bus_main_map *m;
      struct sig_pci_bus_main_ior *ior;
      struct sig_pci_bus_main_iow *iow;
      unsigned int i;

      b = shm_map(name, nr, sizeof(*b), 0);

      b->member_count = 0;

      b->map_lru_first = 0;
      b->map_lru_last = 0;
      for (i = 0; i < sizeof(b->map_hash_first) / sizeof(b->map_hash_first[0]); i++) {
            b->map_hash_first[i] = 0;
            b->map_hash_last[i] = 0;
      }
      for (i = 0; i < sizeof(b->map) / sizeof(b->map[0]); i++) {
            m = &b->map[i];
            m->addr = -1;
            m->va_mr = NULL;
            m->va_mw = NULL;

            /* Don't add empty entry to HASH list. */

            /* Add to LRU list. */
            m->lru_prev = b->map_lru_last;
            m->lru_next = 0;
            if (m->lru_prev) {
                  m->lru_prev->lru_next = m;
            } else {
                  b->map_lru_first = m;
            }
            b->map_lru_last = m;
      }

      b->ior_lru_first = 0;
      b->ior_lru_last = 0;
      for (i = 0; i < sizeof(b->ior_hash_first) / sizeof(b->ior_hash_first[0]); i++) {
            b->ior_hash_first[i] = 0;
            b->ior_hash_last[i] = 0;
      }
      for (i = 0; i < sizeof(b->ior) / sizeof(b->ior[0]); i++) {
            ior = &b->ior[i];
            ior->port = -1;
            ior->bs = -1;

            /* Don't add empty entry to HASH list. */

            /* Add to LRU list. */
            ior->lru_prev = b->ior_lru_last;
            ior->lru_next = 0;
            if (ior->lru_prev) {
                  ior->lru_prev->lru_next = ior;
            } else {
                  b->ior_lru_first = ior;
            }
            b->ior_lru_last = ior;
      }

      b->iow_lru_first = 0;
      b->iow_lru_last = 0;
      for (i = 0; i < sizeof(b->iow_hash_first) / sizeof(b->iow_hash_first[0]); i++) {
            b->iow_hash_first[i] = 0;
            b->iow_hash_last[i] = 0;
      }
      for (i = 0; i < sizeof(b->iow) / sizeof(b->iow[0]); i++) {
            iow = &b->iow[i];
            iow->port = -1;
            iow->bs = -1;

            /* Don't add empty entry to HASH list. */

            /* Add to LRU list. */
            iow->lru_prev = b->iow_lru_last;
            iow->lru_next = 0;
            if (iow->lru_prev) {
                  iow->lru_prev->lru_next = iow;
            } else {
                  b->iow_lru_first = iow;
            }
            b->iow_lru_last = iow;
      }

      return b;
}

int
sig_pci_bus_main_s0_type_addr(
      void *_f,
      unsigned int type,
      uint32_t addr
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_main_type_addr(f->s1, f, type, addr);
}

int
sig_pci_bus_main_s0_read_data(
      void *_f,
      unsigned int bs,
      uint32_t *valp
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_main_read_data(f->s1, f, bs, valp);
}

int
sig_pci_bus_main_s0_write_data(
      void *_f,
      unsigned int bs,
      uint32_t val
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_main_write_data(f->s1, f, bs, val);
}

int
sig_pci_bus_main_s0_c0r(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      uint32_t *valp
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_main_c0r(f->s1, f, addr, bs, valp);
}

int
sig_pci_bus_main_s0_c0w(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      uint32_t val
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_main_c0w(f->s1, f, addr, bs, val);
}

int
sig_pci_bus_main_s0_c1r(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      uint32_t *valp
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_c1r(f->s1, f, addr, bs, valp);
}

int
sig_pci_bus_main_s0_c1w(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      uint32_t val
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_c1w(f->s1, f, addr, bs, val);
}

int
sig_pci_bus_main_s0_ior(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      uint32_t *valp
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_ior(f->s1, f, addr, bs, valp);
}

int
sig_pci_bus_main_s0_iow(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      uint32_t val
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_iow(f->s1, f, addr, bs, val);
}

int
sig_pci_bus_main_s0_ior_info(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      int (**cfp)(void *, uint32_t, unsigned int, uint32_t *),
      void **csp
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_ior_info(f->s1, f, addr, bs, cfp, csp);
}

int
sig_pci_bus_main_s0_iow_info(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      int (**cfp)(void *, uint32_t, unsigned int, uint32_t),
      void **csp
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_iow_info(f->s1, f, addr, bs, cfp, csp);
}

void
sig_pci_bus_main_s0_ior_info_flush(
      void *_f,
      uint32_t port,
      unsigned int bs
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_ior_info_flush(f->s1, f, port, bs);
}

void
sig_pci_bus_main_s0_iow_info_flush(
      void *_f,
      uint32_t port,
      unsigned int bs
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_iow_info_flush(f->s1, f, port, bs);
}

int
sig_pci_bus_main_s0_mr(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      uint32_t *valp
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_mr(f->s1, f, addr, bs, valp);
}

int
sig_pci_bus_main_s0_mw(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      uint32_t val
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_mw(f->s1, f, addr, bs, val);
}

int
sig_pci_bus_main_s0_map(
      void *_f,
      unsigned long pa,
      unsigned int len,
      char **haddr_mr_p,
      char **haddr_mw_p
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_map(f->s1, f, pa, len, haddr_mr_p, haddr_mw_p);
}

int
sig_pci_bus_main_s0_inta_addr(
      void *_f
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_inta_addr(f->s1, f);
}

int
sig_pci_bus_main_s0_inta_data(
      void *_f,
      uint8_t *valp
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_inta_data(f->s1, f, valp);
}

int
sig_pci_bus_main_s0_unmap(
      void *_f,
      unsigned long pa,
      unsigned long len
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_unmap(f->s1, f, pa, len);
}

int
sig_pci_bus_main_s1_type_addr(
      void *_f,
      unsigned int type,
      uint32_t addr
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_main_type_addr(f->s0, f, type, addr);
}

int
sig_pci_bus_main_s1_read_data(
      void *_f,
      unsigned int bs,
      uint32_t *valp
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_main_read_data(f->s0, f, bs, valp);
}

int
sig_pci_bus_main_s1_write_data(
      void *_f,
      unsigned int bs,
      uint32_t val
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_main_write_data(f->s0, f, bs, val);
}

int
sig_pci_bus_main_s1_c0r(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      uint32_t *valp
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_main_c0r(f->s0, f, addr, bs, valp);
}

int
sig_pci_bus_main_s1_c0w(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      uint32_t val
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_main_c0w(f->s0, f, addr, bs, val);
}

int
sig_pci_bus_main_s1_c1r(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      uint32_t *valp
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_c1r(f->s0, f, addr, bs, valp);
}

int
sig_pci_bus_main_s1_c1w(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      uint32_t val
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_c1w(f->s0, f, addr, bs, val);
}

int
sig_pci_bus_main_s1_ior(
      void *_f,
      uint32_t port,
      unsigned int bs,
      uint32_t *valp
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_ior(f->s0, f, port, bs, valp);
}

int
sig_pci_bus_main_s1_iow(
      void *_f,
      uint32_t port,
      unsigned int bs,
      uint32_t val
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_iow(f->s0, f, port, bs, val);
}

int
sig_pci_bus_main_s1_ior_info(
      void *_f,
      uint32_t port,
      unsigned int bs,
      int (**cfp)(void *, uint32_t, unsigned int, uint32_t *),
      void **csp
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_ior_info(f->s0, f, port, bs, cfp, csp);
}

int
sig_pci_bus_main_s1_iow_info(
      void *_f,
      uint32_t port,
      unsigned int bs,
      int (**cfp)(void *, uint32_t, unsigned int, uint32_t),
      void **csp
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_iow_info(f->s0, f, port, bs, cfp, csp);
}

void
sig_pci_bus_main_s1_ior_info_flush(
      void *_f,
      uint32_t port,
      unsigned int bs
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_ior_info_flush(f->s0, f, port, bs);
}

void
sig_pci_bus_main_s1_iow_info_flush(
      void *_f,
      uint32_t port,
      unsigned int bs
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_iow_info_flush(f->s0, f, port, bs);
}

int
sig_pci_bus_main_s1_mr(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      uint32_t *valp
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_mr(f->s0, f, addr, bs, valp);
}

int
sig_pci_bus_main_s1_mw(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      uint32_t val
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_mw(f->s0, f, addr, bs, val);
}

int
sig_pci_bus_main_s1_map(
      void *_f,
      unsigned long pa,
      unsigned int len,
      char **haddr_mr_p,
      char **haddr_mw_p
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_map(f->s0, f, pa, len, haddr_mr_p, haddr_mw_p);
}

int
sig_pci_bus_main_s1_inta_addr(
      void *_f
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_inta_addr(f->s0, f);
}

int
sig_pci_bus_main_s1_inta_data(
      void *_f,
      uint8_t *valp
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_inta_data(f->s0, f, valp);
}

int
sig_pci_bus_main_s1_unmap(
      void *_f,
      unsigned long pa,
      unsigned long len
)
{
      struct sig_pci_bus_main_merge *f = (struct sig_pci_bus_main_merge *) _f;

      return sig_pci_bus_unmap(f->s0, f, pa, len);
}

struct sig_pci_bus_main_merge *
sig_pci_bus_main_merge(
      struct sig_pci_bus_main *s0,
      struct sig_pci_bus_main *s1
)
{
      static const struct sig_pci_bus_main_funcs s0_funcs = {
            .type_addr = sig_pci_bus_main_s0_type_addr,
            .read_data = sig_pci_bus_main_s0_read_data,
            .write_data = sig_pci_bus_main_s0_write_data,
            .c0r = sig_pci_bus_main_s0_c0r,
            .c0w = sig_pci_bus_main_s0_c0w,
            .c1r = sig_pci_bus_main_s0_c1r,
            .c1w = sig_pci_bus_main_s0_c1w,
            .ior_info = sig_pci_bus_main_s0_ior_info,
            .iow_info = sig_pci_bus_main_s0_iow_info,
            .ior = sig_pci_bus_main_s0_ior,
            .iow = sig_pci_bus_main_s0_iow,
            .mr = sig_pci_bus_main_s0_mr,
            .mw = sig_pci_bus_main_s0_mw,
            .map = sig_pci_bus_main_s0_map,
            .inta_addr = sig_pci_bus_main_s0_inta_addr,
            .inta_data = sig_pci_bus_main_s0_inta_data,
            .unmap = sig_pci_bus_main_s0_unmap,
      };
      static const struct sig_pci_bus_main_funcs s1_funcs = {
            .type_addr = sig_pci_bus_main_s1_type_addr,
            .read_data = sig_pci_bus_main_s1_read_data,
            .write_data = sig_pci_bus_main_s1_write_data,
            .c0r = sig_pci_bus_main_s1_c0r,
            .c0w = sig_pci_bus_main_s1_c0w,
            .c1r = sig_pci_bus_main_s1_c1r,
            .c1w = sig_pci_bus_main_s1_c1w,
            .ior_info = sig_pci_bus_main_s1_ior_info,
            .iow_info = sig_pci_bus_main_s1_iow_info,
            .ior = sig_pci_bus_main_s1_ior,
            .iow = sig_pci_bus_main_s1_iow,
            .mr = sig_pci_bus_main_s1_mr,
            .mw = sig_pci_bus_main_s1_mw,
            .map = sig_pci_bus_main_s1_map,
            .inta_addr = sig_pci_bus_main_s1_inta_addr,
            .inta_data = sig_pci_bus_main_s1_inta_data,
            .unmap = sig_pci_bus_main_s1_unmap,
      };
      struct sig_pci_bus_main_merge *m;

      m = malloc(sizeof(*m));
      assert(m);

      m->s0 = s0;
      sig_pci_bus_main_connect(s0, m, &s0_funcs);
      m->s1 = s1;
      sig_pci_bus_main_connect(s1, m, &s1_funcs);

      return m;
}

void
sig_pci_bus_main_split(struct sig_pci_bus_main_merge *m)
{
      fixme();
}

/* ----------------------------------------------------------------- */

int
sig_pci_bus_idsel_c0r(
      struct sig_pci_bus_idsel *b,
      void *s,
      uint32_t addr,
      unsigned int bs,
      uint32_t *valp
)
{
      unsigned int nr;
      int (*func)(void *, uint32_t, unsigned int, uint32_t *);

      assert((addr & 3) == 0);

      for (nr = 0; ; nr++) {
            if (nr == b->member_count) {
                  return 1;
            }
            if (! b->member[nr].f
             || b->member[nr].s == s) {
                  continue;
            }
            func = b->member[nr].f->c0r;
            if (func
             && func(b->member[nr].s, addr, bs, valp) == 0) {
                  return 0;
            }
      }
}

int
sig_pci_bus_idsel_c0w(
      struct sig_pci_bus_idsel *b,
      void *s,
      uint32_t addr,
      unsigned int bs,
      uint32_t val
)
{
      unsigned int nr;
      int (*func)(void *, uint32_t, unsigned int, uint32_t);

      assert((addr & 3) == 0);

      for (nr = 0; ; nr++) {
            if (nr == b->member_count) {
                  return 1;
            }
            if (! b->member[nr].f
             || b->member[nr].s == s) {
                  continue;
            }
            func = b->member[nr].f->c0w;
            if (func
             && func(b->member[nr].s, addr, bs, val) == 0) {
                  return 0;
            }
      }
}

void
sig_pci_bus_idsel_connect(
      struct sig_pci_bus_idsel *b,
      void *s,
      const struct sig_pci_bus_idsel_funcs *f
)
{
      assert(b);
      assert(b->member_count < sizeof(b->member) / sizeof(b->member[0]));

      b->member[b->member_count].s = s;
      b->member[b->member_count].f = f;
      b->member_count++;
}

struct sig_pci_bus_idsel *
sig_pci_bus_idsel_init(const char *name, int nr)
{
      struct sig_pci_bus_idsel *b;

      b = shm_map(name, nr, sizeof(*b), 0);

      b->member_count = 0;

      return b;
}

static int
sig_pci_bus_idsel_s0_c0r(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      uint32_t *valp
)
{
      struct sig_pci_bus_idsel_merge *f
                  = (struct sig_pci_bus_idsel_merge *) _f;

      return sig_pci_bus_idsel_c0r(f->s1, f, addr, bs, valp);
}

static int
sig_pci_bus_idsel_s0_c0w(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      uint32_t val
)
{
      struct sig_pci_bus_idsel_merge *f
                  = (struct sig_pci_bus_idsel_merge *) _f;

      return sig_pci_bus_idsel_c0w(f->s1, f, addr, bs, val);
}

static int
sig_pci_bus_idsel_s1_c0r(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      uint32_t *valp
)
{
      struct sig_pci_bus_idsel_merge *f
                  = (struct sig_pci_bus_idsel_merge *) _f;

      return sig_pci_bus_idsel_c0r(f->s0, f, addr, bs, valp);
}

static int
sig_pci_bus_idsel_s1_c0w(
      void *_f,
      uint32_t addr,
      unsigned int bs,
      uint32_t val
)
{
      struct sig_pci_bus_idsel_merge *f
                  = (struct sig_pci_bus_idsel_merge *) _f;

      return sig_pci_bus_idsel_c0w(f->s0, f, addr, bs, val);
}

struct sig_pci_bus_idsel_merge *
sig_pci_bus_idsel_merge(
      struct sig_pci_bus_idsel *s0,
      struct sig_pci_bus_idsel *s1
)
{
      static const struct sig_pci_bus_idsel_funcs s0_funcs = {
            .c0r = sig_pci_bus_idsel_s0_c0r,
            .c0w = sig_pci_bus_idsel_s0_c0w,
      };
      static const struct sig_pci_bus_idsel_funcs s1_funcs = {
            .c0r = sig_pci_bus_idsel_s1_c0r,
            .c0w = sig_pci_bus_idsel_s1_c0w,
      };
      struct sig_pci_bus_idsel_merge *m;

      m = malloc(sizeof(*m));
      assert(m);

      m->s0 = s0;
      sig_pci_bus_idsel_connect(s0, m, &s0_funcs);
      m->s1 = s1;
      sig_pci_bus_idsel_connect(s1, m, &s1_funcs);

      return m;
}

void
sig_pci_bus_idsel_split(struct sig_pci_bus_idsel_merge *m)
{
      fixme();
}

/* ----------------------------------------------------------------- */

struct sig_pci_bus *
sig_pci_bus_init(const char *name, unsigned int nr)
{
      char n[1000];
      struct sig_pci_bus *c;

      c = shm_map(name, nr, sizeof(*c), 0);
      c->type = SIG_GEN_PCI_BUS;

      sprintf(n, "%s-+5V", name);
      c->p5V = sig_boolean_init(n, nr);
      sprintf(n, "%s-+12V", name);
      c->p12V = sig_boolean_init(n, nr);
      sprintf(n, "%s--12V", name);
      c->m12V = sig_boolean_init(n, nr);

      sprintf(n, "%s-n_reset", name);
      c->n_reset = sig_boolean_init(n, nr);

      sprintf(n, "%s-idsel", name);
      c->idsel = sig_pci_bus_idsel_init(n, nr);
      sprintf(n, "%s-main", name);
      c->main = sig_pci_bus_main_init(n, nr);

      sprintf(n, "%s-intA", name);
      c->intA = sig_boolean_or_init(n, nr);
      sprintf(n, "%s-intB", name);
      c->intB = sig_boolean_or_init(n, nr);
      sprintf(n, "%s-intC", name);
      c->intC = sig_boolean_or_init(n, nr);
      sprintf(n, "%s-intD", name);
      c->intD = sig_boolean_or_init(n, nr);

      return c;
}

/* ----------------------------------------------------------------- */

void
sig_pci_bus_main_create(const char *name, int nr)
{
      shm_create(name, nr, sizeof(struct sig_pci_bus_main));
}

void
sig_pci_bus_main_destroy(const char *name, int nr)
{
      shm_destroy(name, nr);
}

/* ----------------------------------------------------------------- */

void
sig_pci_bus_idsel_create(const char *name, int nr)
{
      shm_create(name, nr, sizeof(struct sig_pci_bus_idsel));
}

void
sig_pci_bus_idsel_destroy(const char *name, int nr)
{
      shm_destroy(name, nr);
}

/* ----------------------------------------------------------------- */

void
sig_pci_bus_create(const char *name, unsigned int nr)
{
      char n[1000];

      shm_create(name, nr, sizeof(struct sig_pci_bus));

      sprintf(n, "%s-+5V", name);
      sig_boolean_create(n, nr);
      sprintf(n, "%s-+12V", name);
      sig_boolean_create(n, nr);
      sprintf(n, "%s--12V", name);
      sig_boolean_create(n, nr);

      sprintf(n, "%s-n_reset", name);
      sig_boolean_create(n, nr);

      sprintf(n, "%s-idsel", name);
      sig_pci_bus_idsel_create(n, nr);
      sprintf(n, "%s-main", name);
      sig_pci_bus_main_create(n, nr);

      sprintf(n, "%s-intA", name);
      sig_boolean_or_create(n, nr);
      sprintf(n, "%s-intB", name);
      sig_boolean_or_create(n, nr);
      sprintf(n, "%s-intC", name);
      sig_boolean_or_create(n, nr);
      sprintf(n, "%s-intD", name);
      sig_boolean_or_create(n, nr);
}

void
sig_pci_bus_destroy(const char *name, unsigned int nr)
{
      char n[1000];

      shm_destroy(name, nr);

      sprintf(n, "%s-+5V", name);
      sig_boolean_destroy(n, nr);
      sprintf(n, "%s-+12V", name);
      sig_boolean_destroy(n, nr);
      sprintf(n, "%s--12V", name);
      sig_boolean_destroy(n, nr);

      sprintf(n, "%s-n_reset", name);
      sig_boolean_destroy(n, nr);

      sprintf(n, "%s-idsel", name);
      sig_pci_bus_idsel_destroy(n, nr);
      sprintf(n, "%s-main", name);
      sig_pci_bus_main_destroy(n, nr);

      sprintf(n, "%s-intA", name);
      sig_boolean_or_destroy(n, nr);
      sprintf(n, "%s-intB", name);
      sig_boolean_or_destroy(n, nr);
      sprintf(n, "%s-intC", name);
      sig_boolean_or_destroy(n, nr);
      sprintf(n, "%s-intD", name);
      sig_boolean_or_destroy(n, nr);
}

Generated by  Doxygen 1.6.0   Back to index