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

chip_plx_9052.c

/*
 * $Id: chip_plx_9052.c,v 1.48 2009-02-03 15:41:46 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.
 */

#include <assert.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "glue-log.h"
#include "glue-main.h"
#include "glue-shm.h"
#include "umutil.h"

#include "chip_plx_9052.h"

#define COMP "chip_plx_9052"

struct cpssp {

      /* config_space
       * Vendor ID:                       00 .. 01
       * Device ID:                       02 .. 03
       * Command:                   04 .. 05
       * Status:                    06 .. 07
       * Revision ID:                     08          
       * Class Code:                      09 .. 0b
       * C. Line Size:              0c          
       * Lat. Timer:                      0d          
       * Header Type:               0e          
       * Build in S. Test:                0f          
       * Base Address 0:                  10 .. 13
       * Base Address 1:                  14 .. 17
       * Base Address 2:                  18 .. 1b
       * Base Address 3:                  1c .. 1f
       * Base Address 4:                  20 .. 23
       * Base Address 5:                  24 .. 27
       * Cardbus I. Structure:            28 .. 2b
       * Subsystem ID:              2c .. 2d
       * Subsystem Vendor ID:             2e .. 2f
       * Exp. ROM Base Address:           30 .. 33
       * Reserved:                        34 .. 37
       * Reserved:                        38 .. 3b
       * Interrupt:                       3c          
       * Interrupt Pin:             3d          
       * Min. Grant:                      3e          
       * Max. Latency:              3f          
       */

      uint32_t ClassCode, BaseAddr0, BaseAddr1, BaseAddr2, BaseAddr3, BaseAddr4;
      uint32_t BaseAddr5, CardbusInfraStruct, ExpRomBaseAddr;
      uint16_t VendorID, DeviceID, Command, Status, SubsystemID, SubsystemVendorID;
      uint8_t RevisionID, CacheLineSize, LatencyTimer, HeaderType, BiSt, Interrupt, InterruptPin, MinGrant, MaxLatency;
      
      /* Local configuration register
       * Local Address Space 0 Range:           00 .. 03
       * Local Address Space 1 Range:           04 .. 07
       * Local Address Space 2 Range:           08 .. 0b
       * Local Address Space 3 Range:           0c .. 0f
       * Exp. Rom Range:                  10 .. 13
       * Loc. Addr.Sp. 0 Local Base:            14 .. 17
       * Loc. Addr.Sp. 1 Local Base:            18 .. 1b
       * Loc. Addr.Sp. 2 Local Base:            1c .. 1f
       * Loc. Addr.Sp. 3 Local Base:            20 .. 23
       * Exp. Rom Local Base:             24 .. 27
       * Loc. Addr.Sp. 0 Bus Reg. Descr.: 28 .. 2b
       * Loc. Addr.Sp. 1 Bus Reg. Descr.: 2c .. 2f
       * Loc. Addr.Sp. 2 Bus Reg. Descr.: 30 .. 33
       * Loc. Addr.Sp. 3 Bus Reg. Descr.: 34 .. 37
       * Exp. Rom Bus Reg. Descr.:        38 .. 3b
       * Chip Select 0 Base Address:            3c .. 3f
       * Chip Select 1 Base Address:            40 .. 43
       * Chip Select 2 Base Address:            44 .. 47
       * Chip Select 3 Base Address:            48 .. 4b
       * Interrupt Control/Status:        4c .. 4f
       * U I/O, Dir.Slave Resp., Ser.Eepr.      50 .. 53
       */
      
      uint32_t LAddrSp0Range, LAddrSp1Range, LAddrSp2Range, LAddrSp3Range, ExpRomRange;
      uint32_t LAddrSp0Base, LAddrSp1Base, LAddrSp2Base, LAddrSp3Base, ExpRomBase;
      uint32_t LAddrSp0BusRegionDescr, LAddrSp1BusRegionDescr, LAddrSp2BusRegionDescr, LAddrSp3BusRegionDescr;
      uint32_t ExpRomBusRegionDescr, ChipSel0BaseAddr, ChipSel1BaseAddr, ChipSel2BaseAddr, ChipSel3BaseAddr;
      uint32_t IntContrStat, UserIO;
      
      uint32_t LAddrSp0_size, LAddrSp1_size, LAddrSp2_size, LAddrSp3_size, ExpRom_size;

      uint32_t ChipSel0_mask;
      uint32_t ChipSel1_mask;
      uint32_t ChipSel2_mask;
      uint32_t ChipSel3_mask;
      
      uint16_t rom[64];
      
      /*
       * Signals pci bus
       */
      
      struct sig_boolean_or *port_intA;
      
      /*
       * Signals internal local bus
       */
      
       struct sig_cs *port_cs0;
       struct sig_cs *port_cs1;
       struct sig_cs *port_cs2;
       struct sig_cs *port_cs3;

      /*
       * State
       */
      
      unsigned int nr;
      unsigned int state_power;
};

/* Debugging stuff */
#define WARNINGS 0x0
#define DEBUGMASK 0x00

/* Add the following values together to select which debug messages you want */
#define DEBUG_CONFSPACE 0x0001
#define DEBUG_IO        0x0002
#define DEBUG_OTHER           0x0004
 
/* Debugging */
#if (DEBUGMASK > 0)
#define TRACE(lvl, fmt, arg...) \
      if ((lvl & DEBUGMASK)) { \
            char tmplog[2]; \
            tmplog[0] = '-'; \
            tmplog[1] = 0; \
            faum_log(FAUM_LOG_DEBUG, "plx_9052", \
             tmplog, "[ %04x  ] " fmt , \
             lvl, arg); \
      }
#else
#define TRACE(lvl, fmt, arg...) while(0) { } /* ; */
#endif /* DEBUGMASK > 0 */

// bit no in PCI Status register
#define STB_TARGETABORT 11
#define STB_SYSTEMERROR 14
#define STB_PARITYERROR 15


// clear status bit
static void
chip_plx_9052_clrstb(unsigned int status_bit)
{
      // Fixme: -> fill me :-)
      fprintf(stderr, "%s called (status bit=%d)\n", __FUNCTION__,
                  status_bit);
}

static void
chip_plx_9052_setvalfromeeprom(void *_css)
{
      struct cpssp *cpssp = (struct cpssp *) _css;
      uint16_t *rom = cpssp->rom;
                  
      // a real chip checks if the start bit is 0 to detect the presence of an eeprom
      // here we check if we have a pointer != 0 to the rom
       if ( ! rom ) return;
      
      // if the eeprom is present the chip checks if the 1st 48 bits are not all 1 afterwards it continues reading
      if (rom[0] != 0xffff
       || rom[1] != 0xffff
       || rom[2] != 0xffff) {
            /*
             * EEPROM maybe valid => overwrite default values with
             * values from EEPROM.
             */
            cpssp->DeviceID = rom[0];
            cpssp->VendorID = rom[1];
            cpssp->ClassCode = rom[2] << 16; 
            cpssp->ClassCode |= rom[3] << 0;
            cpssp->SubsystemID = rom[4];
            cpssp->SubsystemVendorID = rom[5];
            cpssp->MaxLatency = (uint8_t)(rom[6] >> 8);
            cpssp->MinGrant = (uint8_t)(rom[7] >> 0);
            cpssp->InterruptPin = (uint8_t)(rom[7] >> 8);
            cpssp->Interrupt = (uint8_t)(rom[7] >> 0);
            cpssp->LAddrSp0Range = ( rom[8] & 0x0fff ) << 16;
            cpssp->LAddrSp0Range |= rom[9] << 0;
            cpssp->LAddrSp1Range = ( rom[10] & 0x0fff ) << 16;
            cpssp->LAddrSp1Range |= rom[11] << 0;
            cpssp->LAddrSp2Range = ( rom[12] & 0x0fff ) << 16;
            cpssp->LAddrSp2Range |= rom[13] << 0;
            cpssp->LAddrSp3Range = ( rom[14] & 0x0fff ) << 16;
            cpssp->LAddrSp3Range |= rom[15] << 0;
            cpssp->ExpRomRange = rom[16] << 16;
            cpssp->ExpRomRange |= rom[17] << 0;
            cpssp->LAddrSp0Base = rom[18] << 16;
            cpssp->LAddrSp0Base |= rom[19] << 0;
            cpssp->LAddrSp1Base = rom[20] << 16;
            cpssp->LAddrSp1Base |= rom[21] << 0;
            cpssp->LAddrSp2Base = rom[22] << 16;
            cpssp->LAddrSp2Base |= rom[23] << 0;
            cpssp->LAddrSp3Base = rom[24] << 16;
            cpssp->LAddrSp3Base |= rom[25] << 0;
            cpssp->ExpRomBase = rom[26] << 16;
            cpssp->ExpRomBase |= rom[27] << 0;
            cpssp->LAddrSp0BusRegionDescr = rom[28] << 16;
            cpssp->LAddrSp0BusRegionDescr |= rom[29] << 0;
            cpssp->LAddrSp1BusRegionDescr = rom[30] << 16;
            cpssp->LAddrSp1BusRegionDescr |= rom[31] << 0;
            cpssp->LAddrSp2BusRegionDescr = rom[32] << 16;
            cpssp->LAddrSp2BusRegionDescr |= rom[33] << 0;
            cpssp->LAddrSp3BusRegionDescr = rom[34] << 16;
            cpssp->LAddrSp3BusRegionDescr |= rom[35] << 0;
            cpssp->ExpRomBusRegionDescr = rom[36] << 16;
            cpssp->ExpRomBusRegionDescr |= rom[37] << 0;
            cpssp->ChipSel0BaseAddr = rom[38] << 16;
            cpssp->ChipSel0BaseAddr |= rom[39] << 0;
            cpssp->ChipSel1BaseAddr = rom[40] << 16;
            cpssp->ChipSel1BaseAddr |= rom[41] << 0;
            cpssp->ChipSel2BaseAddr = rom[42] << 16;
            cpssp->ChipSel2BaseAddr |= rom[43] << 0;
            cpssp->ChipSel3BaseAddr = rom[44] << 16;
            cpssp->ChipSel3BaseAddr |= rom[45] << 0;
            cpssp->IntContrStat = rom[46] << 16;
            cpssp->IntContrStat |= rom[47] << 0;
            cpssp->UserIO = rom[48] << 16;
            cpssp->UserIO |= rom[49] << 0;
      } 
}
      
static void
chip_plx_9052_power_set(void *_css, unsigned int val)
{
      ((struct cpssp *)_css)->state_power = val;
}

static uint32_t
_calc_chip_sel_mask(uint32_t base)
{
      int i;
      uint32_t res;

      base &= ~1;
      i = 0;
      res = 1;
      while (i < 31 && (base & 1) == 0) {
            res <<= 1;
            res |= 1;
            base >>= 1;
            i++;
      }

      return ~res;
}

static void
chip_plx_9052_n_reset_set(void *_css, unsigned int val)
{
      struct cpssp *cpssp = (struct cpssp *) _css;
      
      /* 
       * according to the 9052 manual initialisation is done during power-on.
       * the pci RST signal resets the default values of the 9052 internal register
       */
      
      /* 
       * Default values config space:                 
       * Vendor ID:                       0x10b5
       * Device ID:                       0x9050
       * Command:                   0x0
       * Status:                    0x280 (Bit 7,9: 1 / 0-6,10-15: 0)
       * Revision ID:                     0x2
       * Class Code:                      0x06 0x80 0x00
       * C. Line Size:              0x0
       * Lat. Timer:                      0x0
       * Header Type:               0x0
       * Build in S. Test:                0x0
       * Base Address 0:                  0x0
       * Base Address 1:                  0x1
       * Base Address 2:                  0x0
       * Base Address 3:                  0x0
       * Base Address 4:                  0x0
       * Base Address 5:                  0x0
       * Subsystem ID:              0x0
       * Subsystem Vendor ID:             0x0
       * Exp. ROM Base Address:           0x0
       * Reserved:                        0x0
       * Reserved:                        0x0
       * Interrupt:                       0x0
       * Interrupt Pin:             0x1 (INTA)
       * Min. Grant:                      0x0         
       * Max. Latency:              0x0
       */
       
      cpssp->VendorID = 0x10b5;
      cpssp->DeviceID = 0x9050;
      cpssp->Command = 0x0;
      cpssp->Status = 0x280; // 0x1010000000
      cpssp->RevisionID = 0x2;
      cpssp->ClassCode = 0x06800000;
      cpssp->CacheLineSize = 0x0;
      cpssp->LatencyTimer = 0x0;
      cpssp->HeaderType = 0x0;
      cpssp->BiSt = 0x0;
      cpssp->BaseAddr0 = 0x0;
      cpssp->BaseAddr1 = 0x1;
      cpssp->BaseAddr2 = 0x0;
      cpssp->BaseAddr3 = 0x0;
      cpssp->BaseAddr4 = 0x0;
      cpssp->BaseAddr5 = 0x0;
      cpssp->CardbusInfraStruct = 0x0;
      cpssp->SubsystemID = 0x0;
      cpssp->SubsystemVendorID = 0x0;
      cpssp->ExpRomBaseAddr = 0x0;
      cpssp->Interrupt = 0x0;
      cpssp->InterruptPin = 0x1;
      cpssp->MinGrant = 0x0;
      cpssp->MaxLatency = 0x0;
      
      /* Default values local configuration register:
       * Local Address Space 0 Range:           0x0ff00000
       * Local Address Space 1 Range:           0x0
       * Local Address Space 2 Range:           0x0
       * Local Address Space 3 Range:           0x0
       * Exp. Rom Range:                  0x0fff0000
       * Loc. Addr.Sp. 0 Local Base:            0x0
       * Loc. Addr.Sp. 1 Local Base:            0x0
       * Loc. Addr.Sp. 2 Local Base:            0x0
       * Loc. Addr.Sp. 3 Local Base:            0x0
       * Exp. Rom Local Base:             0x00100000
       * Loc. Addr.Sp. 0 Bus Reg. Descr.: 0x00800000
       * Loc. Addr.Sp. 1 Bus Reg. Descr.: 0x00800000
       * Loc. Addr.Sp. 2 Bus Reg. Descr.: 0x00800000
       * Loc. Addr.Sp. 3 Bus Reg. Descr.: 0x00800000
       * Exp. Rom Bus Reg. Descr.:        0x00800000
       * Chip Select 0 Base Address:            0x0
       * Chip Select 1 Base Address:            0x0
       * Chip Select 2 Base Address:            0x0
       * Chip Select 3 Base Address:            0x0
       * Interrupt Control/Status:        0x0
       * U I/O, Dir.Slave Resp., Ser.Eepr.      0x00200000
       */

      cpssp->LAddrSp0Range = 0x0ff00000;
      cpssp->LAddrSp1Range = 0x0;
      cpssp->LAddrSp2Range = 0x0;
      cpssp->LAddrSp3Range = 0x0;
      cpssp->ExpRomRange = 0x0fff0000;
      cpssp->LAddrSp0Base = 0x0;
      cpssp->LAddrSp1Base = 0x0;
      cpssp->LAddrSp2Base = 0x0;
      cpssp->LAddrSp3Base = 0x0;
      cpssp->ExpRomBase = 0x00100000;
      cpssp->LAddrSp0BusRegionDescr = 0x00800000;
      cpssp->LAddrSp1BusRegionDescr = 0x00800000;
      cpssp->LAddrSp2BusRegionDescr = 0x00800000;
      cpssp->LAddrSp3BusRegionDescr = 0x00800000;
      cpssp->ExpRomBusRegionDescr = 0x00800000;
      cpssp->ChipSel0BaseAddr = 0x0;
      cpssp->ChipSel1BaseAddr = 0x0;
      cpssp->ChipSel2BaseAddr = 0x0;
      cpssp->ChipSel3BaseAddr = 0x0;
      cpssp->IntContrStat = 0x0;
      cpssp->UserIO = 0x00200000;

      /* check if rom is present
       * and if present and not empty
       * load values from rom
       */    
      chip_plx_9052_setvalfromeeprom(_css);

      /*
       * these values are needed in ioread/write so we calculate them once
       * if changed later, we have to update these values 
       */
      cpssp->BaseAddr2 = cpssp->LAddrSp0Range & 0x1;
      cpssp->BaseAddr3 = cpssp->LAddrSp1Range & 0x1;
      cpssp->BaseAddr4 = cpssp->LAddrSp2Range & 0x1;
      cpssp->BaseAddr5 = cpssp->LAddrSp3Range & 0x1;

      cpssp->LAddrSp0_size = 1 + ~( (cpssp->LAddrSp0Range | 0xf0000000) & ~( (cpssp->LAddrSp0Range & 0x1) ? 0x00000003 : 0x0000000f ) );
      cpssp->LAddrSp1_size = 1 + ~( (cpssp->LAddrSp1Range | 0xf0000000) & ~( (cpssp->LAddrSp1Range & 0x1) ? 0x00000003 : 0x0000000f ) );
      cpssp->LAddrSp2_size = 1 + ~( (cpssp->LAddrSp2Range | 0xf0000000) & ~( (cpssp->LAddrSp2Range & 0x1) ? 0x00000003 : 0x0000000f ) );
      cpssp->LAddrSp3_size = 1 + ~( (cpssp->LAddrSp3Range | 0xf0000000) & ~( (cpssp->LAddrSp3Range & 0x1) ? 0x00000003 : 0x0000000f ) );

      cpssp->ChipSel0_mask = _calc_chip_sel_mask(cpssp->ChipSel0BaseAddr);
      cpssp->ChipSel1_mask = _calc_chip_sel_mask(cpssp->ChipSel1BaseAddr);
      cpssp->ChipSel3_mask = _calc_chip_sel_mask(cpssp->ChipSel2BaseAddr);
      cpssp->ChipSel3_mask = _calc_chip_sel_mask(cpssp->ChipSel3BaseAddr);

      TRACE(DEBUG_OTHER, "chip_plx_9052 resetted. LAddrSp0_size=%x, LAddrSp1_size=%x\n",cpssp->LAddrSp0_size,cpssp->LAddrSp1_size); 
}

static uint32_t
_calc_mask(unsigned int bs)
{
      uint32_t mask = 0x0;
      
      // bs -> 0001 0011 0111 1111  -> 1. byte
      if ((bs >> 0) & 1) mask |= 0xff << 0;
      // bs -> 0010 0011 0110 0111 1110 1111 -> 2. byte
      if ((bs >> 1) & 1) mask |= 0xff << 8;
      // bs -> 0100 0110 0111 1100 1110 1111 -> 3. byte
      if ((bs >> 2) & 1) mask |= 0xff << 16;
      // bs -> 1000 1100 1110 1111 -> 4. byte
      if ((bs >> 3) & 1) mask |= 0xff << 24;

      return mask;      
}

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

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

      if ((addr >> 8) & 7) {
            return 1;
      }
      addr &= 0xff;

      /* compute mask for byte select */
      mask = _calc_mask(bs);

      *valp = 0x0;

      switch (addr) {
            case 0x00 ... 0x03: // matches DeviceID, VendorID
                  *valp = cpssp->DeviceID << 16;
                  *valp |= cpssp->VendorID << 0; 
                  TRACE(DEBUG_CONFSPACE,"CSPAVE READ (DeviceID, VendorID) addr: %02x, val: %08x\n",addr, *valp);
                  break;
            case 0x04 ... 0x07: // matches Status, Command
                  *valp |= cpssp->Status << 16;
                  *valp |= cpssp->Command << 0;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE READ (Status, Command) addr: %02x, val: %08x\n",addr, *valp);
                  break;
            case 0x08 ... 0x0b: // matches ClassCode, RevisionID
                  *valp = cpssp->ClassCode;
                  *valp |= cpssp->RevisionID << 0;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE READ (ClassCode, RevisionID) addr: %02x, val: %08x\n",addr, *valp);
                  break;
            case 0x0c ... 0x0f: // matches BiSt, HeaderType, LatencyTimer, CacheLineSize
                  *valp = cpssp->BiSt << 24;
                  *valp |= cpssp->HeaderType << 16;
                  *valp |= cpssp->LatencyTimer << 8;
                  *valp |= cpssp->CacheLineSize << 0;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE READ (BiSt, HeaderType, LatencyTimer, CacheLineSize) addr: %02x, val: %08x\n",addr, *valp);
                  break;
            case 0x10 ... 0x13: // matches BaseAddr0
                  *valp = cpssp->BaseAddr0;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE READ (BaseAddr0) addr: %02x, val: %08x\n",addr, *valp);
                  break;
            case 0x14 ... 0x17: // matches BaseAddr1
                  *valp = cpssp->BaseAddr1;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE READ (BaseAddr1) addr: %02x, val: %08x\n",addr, *valp);
                  break;
            case 0x18 ... 0x1b: // matches BaseAddr2
                  *valp = cpssp->BaseAddr2;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE READ (BaseAddr2) addr: %02x, val: %08x\n",addr, *valp);
                  break;
            case 0x1c ... 0x1f: // matches BaseAddr3
                  *valp = cpssp->BaseAddr3;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE READ (BaseAddr3) addr: %02x, val: %08x\n",addr, *valp);
                  break;
            case 0x20 ... 0x23: // matches BaseAddr4
                  *valp = cpssp->BaseAddr4;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE READ (BaseAddr4) addr: %02x, val: %08x\n",addr, *valp);
                  break;
            case 0x24 ... 0x27: // matches BaseAddr5
                  *valp = cpssp->BaseAddr5;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE READ (BaseAddr5) addr: %02x, val: %08x\n",addr, *valp);
                  break;
            case 0x28 ... 0x2b: // matches CardbusInfraStruct
                  *valp = cpssp->CardbusInfraStruct;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE READ (CardbusInfraStruct) addr: %02x, val: %08x\n",addr, *valp);
                  break;
            case 0x2c ... 0x2f: // matches SubsystemID, SubsystemVendorID 
                  *valp = cpssp->SubsystemID << 16;
                  *valp |= cpssp->SubsystemVendorID << 0;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE READ (SubsystemID, SubsystemVendorID) addr: %02x, val: %08x\n",addr, *valp);
                  break;
            case 0x30 ... 0x33: // matches PCI Expansion Rom BaseAddr
                  *valp = cpssp->ExpRomBaseAddr;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE READ (PCI Expansion Rom BaseAddr) addr: %02x, val: %08x\n",addr, *valp);
                  break;
            //Fixme:are the default values for reserved fields 1 or 0 ?
            case 0x34 ... 0x37: // Reserved
                  TRACE(DEBUG_CONFSPACE,"CSPAVE READ (Reserved1) addr: %02x, val: %08x\n",addr, *valp);
                  break;
            case 0x38 ... 0x3b: // Reserved
                  TRACE(DEBUG_CONFSPACE,"CSPAVE READ (Reserved2) addr: %02x, val: %08x\n",addr, *valp);
                  break;
            case 0x3c ... 0x3f: // matches MaxLatency, MinGrant, InterruptPin, Interrupt
                  *valp = cpssp->MaxLatency << 24;
                  *valp |= cpssp->MinGrant << 16;
                  *valp |= cpssp->InterruptPin << 8;
                  *valp |= cpssp->Interrupt << 0;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE READ (MaxLatency, MinGrant, InterruptPin, Interrupt) addr: %02x, val: %08x\n",addr, *valp);
                  break;
            default:
                  TRACE(DEBUG_CONFSPACE,"UNKNOW CSPAVE READ: addr: %02x, val: %08x\n",addr, *valp);
                  break;
      }

      *valp &= mask;

      TRACE(DEBUG_CONFSPACE, 
            "---> CSPACE READ COMPLETE: Addr: %02x Value: %08x BS: %0x, Mask: %x\n",
            addr, *valp, bs, mask);

      return 0;
}

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

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

      if ((addr >> 8) & 7) {
            return 1;
      }
      addr &= 0xff;

      /* compute mask for byte select */
      mask = _calc_mask(bs);
      oval = 0x0;

      switch (addr) {
            case 0x00 ... 0x03: // matches VendorID, DeviceID
#if ( DEBUGMASK & DEBUG_CONFSPACE )
                  oval = cpssp->DeviceID << 16;
                  oval |= cpssp->VendorID << 0;
#endif 
                  TRACE(DEBUG_CONFSPACE,"CSPAVE WRITE (VendorID, DeviceID) addr: %02x, oval: %0x8, val: %08x\n",addr, oval, val);
                  // readonly
                  break;
            case 0x04 ... 0x07: // matches Command, Status
                  oval = cpssp->Status << 16;
                  oval |= cpssp->Command << 0;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE WRITE (Command, Status) addr: %02x, oval: %08x, val: %08x\n",addr, oval, val);
                  // Command register: bit 2 - 5, 7, 9 - 15 readonly
                  // Status register: bit 0 - 10, 12, 13 readonly
                  // -> mask  0x143
                  // Status register: bit 11,14,15 are writeable, but writing of 1 causes clearing the bit
                  // -> ~mask must be modified to keep the readonly and the bits that can only be cleared
                  oval &= ( ~mask | 0xfffffebc );
                  oval |= (( val & mask ) & 0x143 );
                  // Status register: check if some clearable bits are 1
                  if ( val >> 27 & 0x1 ) chip_plx_9052_clrstb(STB_TARGETABORT);
                  if ( val >> 30 & 0x1 ) chip_plx_9052_clrstb(STB_SYSTEMERROR);
                  if ( val >> 31 & 0x1 ) chip_plx_9052_clrstb(STB_PARITYERROR);
                  cpssp->Command = oval >> 0;
                  break;
            case 0x08 ... 0x0b: // matches RevisionID, ClassCode
#if ( DEBUGMASK & DEBUG_CONFSPACE )
                  oval = cpssp->ClassCode;
                  oval |= cpssp->RevisionID << 0;
#endif 
                  TRACE(DEBUG_CONFSPACE,"CSPAVE WRITE (RevisionID, ClassCode) addr: %02x, oval: %08x, val: %08x\n",addr, oval, val);
                  // readonly
                  break;
            case 0x0c ... 0x0f: // matches CacheLineSize, LatencyTimer, HeaderType, BiSt
                  oval = cpssp->BiSt << 24;
                  oval |= cpssp->HeaderType << 16;
                  oval |= cpssp->LatencyTimer << 8;
                  oval |= cpssp->CacheLineSize << 0;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE WRITE (CacheLineSize, LatencyTimer, HeaderType, BiSt) addr: %02x, oval: %08x, val: %08x\n",addr, oval, val);
                  // Latency-Timer bit 0 - 7 readonly
                  // HeaderType bit 0 - 7 readonly
                  // BiSt bit 0 - 7 readonly
                  // -> mask 0x000000ff
                  oval &= ( ~mask | 0xffffff00 );
                  oval |= (( val & mask ) & 0x000000ff );
                  cpssp->CacheLineSize = oval >> 0;
                  break;
            case 0x10 ... 0x13: // matches BaseAddr0
                  // Request 128 Byte memory space
                  oval = cpssp->BaseAddr0;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE WRITE (BaseAddr0) addr: %02x, oval: %08x, val: %08x\n",addr, oval, val);
                  // bit 0 - 6 are hardwired to 0 -> mask 0xffffff80 -> 128 Byte
                  oval &= ~mask;
                  oval |= (( val & mask ) & 0xffffff80 );
                  cpssp->BaseAddr0 = oval;
                  break;
            case 0x14 ... 0x17: // matches BaseAddr1
                  // Request 128 Byte IO space
                  oval = cpssp->BaseAddr1;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE WRITE (BaseAddr1) addr: %02x, oval: %08x, val: %08x\n",addr, oval, val);
                  // bit 0 hardwired to 1, 1 - 6 hardwired to 0 -> mask 0xFFFFFF81
                  oval &= ( ~mask | 0x1 );
                  oval |= (( val & mask ) & 0xffffff81 );
                  cpssp->BaseAddr1 = oval;
                  break;
            case 0x18 ... 0x1b: // matches BaseAddr2
                  oval = cpssp->BaseAddr2;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE WRITE (BaseAddr2) addr: %02x, oval: %08x, val: %08x\n",addr, oval, val);
                  // bit 0 readonly 
                  if ( cpssp->LAddrSp0Range & 0x1 ) {
                        // bit 0 = 1 -> register maps into i/o space
                        // bit 1 readonly
                        oval &= ( ~mask | 0x3 ); 
                        } else {
                        // bit 0 = 0 -> register maps into memory
                        // bit 1 - 3 readonly
                        // -> mask 0xfffffff0
                        oval &= ( ~mask | 0xf );
                        }
                  oval |= (( val & mask ) & ( 0xf0 << 24 | cpssp->LAddrSp0Range ) );
                  cpssp->BaseAddr2 = oval;
                  break;
            case 0x1c ... 0x1f: // matches BaseAddr3
                  oval = cpssp->BaseAddr3;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE WRITE (BaseAddr3) addr: %02x, oval: %08x, val: %08x\n",addr, oval, val);
                  // bit 0 readonly
                  if ( cpssp->LAddrSp1Range & 0x1 ) {
                        // bit 0 = 1 -> register maps into i/o space
                        // bit 1 readonly
                        oval &= ( ~mask | 0x3 );
                        } else {
                        // bit 0 = 0 -> register maps into memory
                        // bit 1 - 3 readonly
                        // -> mask 0xfffffff0
                        oval &= ( ~mask | 0xf );
                        }
                  oval |= (( val & mask ) & ( 0xf0 << 24 | cpssp->LAddrSp1Range ) );
                  cpssp->BaseAddr3 = oval;
                  break;
            case 0x20 ... 0x23: // matches BaseAddr4
                  oval = cpssp->BaseAddr4;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE WRITE (BaseAddr4) addr: %02x, val: %08x\n",addr, val);
                  // bit 0 readonly
                  if ( cpssp->LAddrSp2Range & 0x1 ) {
                        // bit 0 = 1 -> register maps into i/o space
                        // bit 1 readonly
                        oval &= ( ~mask | 0x3 );
                        } else {
                        // bit 0 = 0 -> register maps into memory
                        // bit 1 - 3 readonly
                        // -> mask 0xfffffff0
                        oval &= ( ~mask | 0xf );
                        }
                  oval |= (( val & mask ) & ( 0xf0 << 24 | cpssp->LAddrSp2Range ) );
                  cpssp->BaseAddr4 = oval;
                  break;
            case 0x24 ... 0x27: // matches BaseAddr5
                  oval = cpssp->BaseAddr5;
                  TRACE(DEBUG_CONFSPACE,"CSPAVE WRITE (BaseAddr5) addr: %02x, val: %08x\n",addr, val);
                  // bit 0 readonly
                  if ( cpssp->LAddrSp3Range & 0x1 ) {
                        // bit 0 = 1 -> register maps into i/o space
                        // bit 1 readonly
                        oval &= ( ~mask | 0x3 );
                  } else {
                        // bit 0 = 0 -> register maps into memory
                        // bit 1 - 3 readonly
                        // -> mask 0xfffffff0
                        oval &= ( ~mask | 0xf );
                  }
                  oval |= (( val & mask ) & ( 0xf0 << 24 | cpssp->LAddrSp2Range ) );
                  cpssp->BaseAddr5 = oval;
                  break;
            case 0x28 ... 0x2b: // matches CardbusInfraStruct
#if ( DEBUGMASK & DEBUG_CONFSPACE )
                  oval = cpssp->CardbusInfraStruct;
#endif
                  TRACE(DEBUG_CONFSPACE,"CSPAVE WRITE (CardbusInfraStruct) addr: %02x, val: %08x\n",addr, val);
                  // readonly
                  break;
            case 0x30 ... 0x33: // matches SubsystemVendorID, SubsystemID
#if ( DEBUGMASK & DEBUG_CONFSPACE )
                  oval = cpssp->SubsystemID << 16;
                  oval |= cpssp->SubsystemVendorID << 0;
#endif
                  TRACE(DEBUG_CONFSPACE,"CSPAVE WRITE (SubsystemVendorID, SubsystemID) addr: %02x, val: %08x\n",addr, val);
                  // readonly
                  break;
            case 0x34 ... 0x37: // matches reserved space 1
#if ( DEBUGMASK & DEBUG_CONFSPACE )
                  oval = 0xffffffff;
#endif
                  TRACE(DEBUG_CONFSPACE,"CSPAVE WRITE (Reserved1) addr: %02x, oval: %08x, val: %08x\n",addr, oval, val);
                  // Reserved
                  break;
            case 0x38 ... 0x3b: // matches reserved space 2
#if ( DEBUGMASK & DEBUG_CONFSPACE )
                  oval = 0xffffffff;
#endif
                  TRACE(DEBUG_CONFSPACE,"CSPAVE WRITE (Reserved2) addr: %02x, oval: %08x, val: %08x\n",addr, oval, val);
                  // Reserved
                  break;
            case 0x3c ... 0x3f: // matches Interrupt, InterruptPin, MinGrant, MaxLatency
#if ( DEBUGMASK & DEBUG_CONFSPACE )
                  oval = cpssp->MaxLatency << 24;
                  oval |= cpssp->MinGrant << 16;
                  oval |= cpssp->InterruptPin << 8;
#endif
                  oval |= cpssp->Interrupt << 0; 
                  TRACE(DEBUG_CONFSPACE,"CSPAVE WRITE (Interrupt, InterruptPin, MinGrant, MaxLatency) addr: %02x, val: %08x\n",addr, val);
                  // MaxLatency: readonly
                  // MinGrant: readonly
                  // InterruptPin: readonly
                  // Interrupt: writeable
                  oval &= ( ~mask | 0xffffff00 );
                  oval |= (( val & mask ) & 0x000000ff );
                  cpssp->Interrupt = oval >> 0;
                  break;
            default:
                  TRACE(DEBUG_CONFSPACE,"UNKNOW CSPAVE WRITE: addr: %02x, val: %08x\n",addr, val);
                  break;
      }

      TRACE(DEBUG_CONFSPACE, 
            "---> CSPACE WRITE COMPLETE: Addr: %02x Value: %08x BS: %0x\n",
            addr, oval, bs);

      return 0;
}

/*
 * possible Bus Modes:
 * 8, 16, 32 Bit multiplexed or non-multiplexed mode
 * 8 or 16 bit ISA mode
 */

static uint8_t
_local_readb(void *_css, uint32_t port, unsigned int cs)
{
      struct cpssp *cpssp = (struct cpssp *) _css;
      uint8_t val8;
      
      val8 = 0x0;
      
      TRACE(DEBUG_IO,"IO READ -> _local_readb -> port: %08x, cs: %d\n",port ,cs);
      
      switch (cs) {
            case 0:
                  // cs0
                  sig_cs_readb(cpssp->port_cs0, cpssp, &val8, port);
                  break;
            case 1:
                  // cs1
                  sig_cs_readb(cpssp->port_cs1, cpssp, &val8, port);
                  break;
            case 2:
                  // cs2
                  sig_cs_readb(cpssp->port_cs2, cpssp, &val8, port);
                  break;
            case 3:
                  // cs3
                  sig_cs_readb(cpssp->port_cs3, cpssp, &val8, port);
                  break;
            default:
                  assert(0);
                  break;
      }

      return val8;
}

static uint16_t
_local_readw(void *_css, uint32_t port, unsigned int cs)
{
      uint16_t val16;
      
      val16 = 0xbeef;
      
      return val16;
}

static uint32_t
_local_readl(void *_css, uint32_t port, unsigned int cs)
{
      uint32_t val32;
      
      val32 = 0xbeefbeef;
      
      return val32;
}

static unsigned int
_local_cs(struct cpssp * cpssp, uint32_t laddr)
{
      if ((cpssp->ChipSel0BaseAddr & 1)
            && (cpssp->ChipSel0_mask & laddr) == (cpssp->ChipSel0_mask & cpssp->ChipSel0BaseAddr)) {
            return 0;
      } else if ((cpssp->ChipSel1BaseAddr & 1)
                  && (cpssp->ChipSel1_mask & laddr) == (cpssp->ChipSel1_mask & cpssp->ChipSel1BaseAddr)) {
            return 1;
      } else if ((cpssp->ChipSel2BaseAddr & 1)
                  && (cpssp->ChipSel2_mask & laddr) == (cpssp->ChipSel2_mask & cpssp->ChipSel2BaseAddr)) {
            return 2;
      } else if ((cpssp->ChipSel3BaseAddr & 1) &&
                  (cpssp->ChipSel3_mask & laddr) == (cpssp->ChipSel3_mask & cpssp->ChipSel3BaseAddr)) {
            return 3;
      } else {
            /* FIXME what to do if no CS fits? */
            return 0;
      }
}

static int
chip_plx_9052_ior(void *_css, uint32_t addr, unsigned int bs, uint32_t *valp)
{
      struct cpssp *cpssp = (struct cpssp *) _css;
      uint32_t port, mask;
      unsigned int cs;
      unsigned int bw;

      // card IO enabled?
      if ( (cpssp->Command & 0x1) == 0 ) {
            TRACE(DEBUG_IO,"IO READ before enabled: cmd-reg: %08x\n",cpssp->Command);
            return -1;
      } else {
            TRACE(DEBUG_IO,"IO READ addr: %08x\n",addr);
      }
      
      mask = _calc_mask(bs);
      
      /*
       * FIXME: baseaddr0 & baseaddr1 are configureable, 
       * but this is not supported for pc platform, maybe implemented later
       * here baseaddr1 is used as io space
       */
      uint32_t baseaddr1 = ( cpssp->BaseAddr1 & 0xfffffffc );
      
      // if address range are io ports -> baseddr<n> is calculated otherwise 0x0
      uint32_t baseaddr2 = ( cpssp->BaseAddr2 & 0x1 ) ? ( cpssp->BaseAddr2 & 0xfffffffe ) : 0x0;
      uint32_t baseaddr3 = ( cpssp->BaseAddr3 & 0x1 ) ? ( cpssp->BaseAddr3 & 0xfffffffe ) : 0x0;
      uint32_t baseaddr4 = ( cpssp->BaseAddr4 & 0x1 ) ? ( cpssp->BaseAddr4 & 0xfffffffe ) : 0x0;
      uint32_t baseaddr5 = ( cpssp->BaseAddr5 & 0x1 ) ? ( cpssp->BaseAddr5 & 0xfffffffe ) : 0x0;
      
      /* 
       * since the 9052 is configureable through its rom, 
       * we have io access to the local configuration registers
       * and we have to check if any of the 4 local address space are io space
       */ 
      
      TRACE(DEBUG_IO,"IO READ baseaddr1: %08x\n",baseaddr1);
      TRACE(DEBUG_IO,"IO READ baseaddr2: %08x\n",baseaddr2);
      TRACE(DEBUG_IO,"IO READ baseaddr3: %08x\n",baseaddr3);
      TRACE(DEBUG_IO,"IO READ baseaddr4: %08x\n",baseaddr4);
      TRACE(DEBUG_IO,"IO READ baseaddr5: %08x\n",baseaddr5);

      // baseaddr0 is always mapped to memory, so we don´t check it here

      if ( baseaddr1 <= addr && addr < ( baseaddr1 + 0x80 ) ) {
            // io access to local configuration register
            
            TRACE(DEBUG_IO,"IO READ local config. registers addr: %08x, val:",addr);
            port = addr - baseaddr1;

            *valp = 0x0;

            switch (port) {
            case 0x00 ... 0x03: // matches Local Address Space 0 Range
                  *valp = cpssp->LAddrSp0Range;
                  break;
            case 0x04 ... 0x07: // matches Local Address Space 1 Range
                  *valp = cpssp->LAddrSp1Range;
                  break;
            case 0x08 ... 0x0b: // matches Local Address Space 2 Range
                  *valp = cpssp->LAddrSp2Range;
                  break;
            case 0x0c ... 0x0f: // matches Local Address Space 3 Range
                  *valp = cpssp->LAddrSp3Range;
                  break;
            case 0x10 ... 0x13: // matches Expansion Rom Range
                  *valp = cpssp->ExpRomRange;
                  break;
            case 0x14 ... 0x17: // matches Local Address Space 0 Local Base Address (Remap)
                  *valp = cpssp->LAddrSp0Base;
                  break;
            case 0x18 ... 0x1b: // matches Local Address Space 1 Local Base Address (Remap)
                  *valp = cpssp->LAddrSp1Base;
                  break;
            case 0x1c ... 0x1f: // matches Local Address Space 2 Local Base Address (Remap)
                  *valp = cpssp->LAddrSp2Base;
                  break;
            case 0x20 ... 0x23: // matches Local Address Space 3 Local Base Address (Remap)
                  *valp = cpssp->LAddrSp3Base;
                  break;
            case 0x24 ... 0x27: // matches Expansion Rom Local Base Address (Remap)
                  *valp = cpssp->ExpRomBase;
                  break;
            case 0x28 ... 0x2b: // matches Local Address Space 0 Bus Region Descriptors
                  *valp = cpssp->LAddrSp0BusRegionDescr;
                  break;
            case 0x2c ... 0x2f: // matches Local Address Space 1 Bus Region Descriptors
                  *valp = cpssp->LAddrSp1BusRegionDescr;
                  break;
            case 0x30 ... 0x33: // matches Local Address Space 2 Bus Region Descriptors
                  *valp = cpssp->LAddrSp2BusRegionDescr;
                  break;
            case 0x34 ... 0x37: // matches Local Address Space 3 Bus Region Descriptors
                  *valp = cpssp->LAddrSp3BusRegionDescr;
                  break;
            case 0x38 ... 0x3b: // matches Expansion Rom Bus Region Descriptors
                  *valp = cpssp->ExpRomBusRegionDescr;
                  break;
            case 0x3c ... 0x3f: // matches Chip Select 0 Base Address
                  *valp = cpssp->ChipSel0BaseAddr;
                  break;
            case 0x40 ... 0x43: // matches Chip Select 1 Base Address
                  *valp = cpssp->ChipSel1BaseAddr;
                  break;
            case 0x44 ... 0x47: // matches Chip Select 2 Base Address
                  *valp = cpssp->ChipSel2BaseAddr;
                  break;
            case 0x48 ... 0x4b: // matches Chip Select 3 Base Address
                  *valp = cpssp->ChipSel3BaseAddr;
                  break;
            case 0x4c ... 0x4f: // matches Interrupt Control / Status
                  *valp = cpssp->IntContrStat;
                  break;
            case 0x50 ... 0x53: // matches User I/O, Direct Slave Response, Serial Eeprom and Initialisation Control
                  *valp = cpssp->UserIO;  
                  break;
            case 0x54 ... 0x7f: // FIXME: is here something ?
                  break;
            default: // this should be never reached
                  return -1;
                  break;
            }
            
            *valp &= mask;
            
            TRACE(DEBUG_IO,"%08x\n",*valp);
            
            return 0;
            
      } else if ( baseaddr2 && baseaddr2 <= addr && addr < baseaddr2 + cpssp->LAddrSp0_size ) {
            // io access to local address space 0
            
            TRACE(DEBUG_IO,"IO READ local addr. space0 addr: %08x\n",addr);
            port = addr - baseaddr2;
            cs = _local_cs(cpssp, port);

            *valp = 0x0;
            
            /* check bus mode -> LAddrSp0BusRegionDescr bit 23,22 defines the bus width
             * 00 -> 8 bit
             * 01 -> 16 bit
             * 10 -> 32 bit
             * 11 -> reserved
             */
             bw = ( cpssp->LAddrSp0BusRegionDescr & 0x00c00000 ) >> 21;
            // and call appropirate function with cpssp, port, bs & address space no
            if ( bw == 0x0 ) {
                  // 8 bit bus width
                  // Fixme: Big Endian Support
                  if (( bs >> 0 ) & 1 ) {
                        *valp |= _local_readb(_css, port, cs) << 0;
                  }
                  if (( bs >> 1 ) & 1 ) {
                        *valp |= _local_readb(_css, port+1 ,cs) << 8;
                  }
                  if (( bs >> 2 ) & 1 ) {
                        *valp |= _local_readb(_css, port+2, cs) << 16;
                  }
                  if (( bs >> 3 ) & 1 ) {
                        *valp |= _local_readb(_css, port+3, cs) << 24;
                  }
            } else if ( bw == 0x1 ) {
                  // 16 bit bus width
                  // FIXME: write me!
                  TRACE(DEBUG_IO,"IO READ local addr. space0 16 bit bus width is not implemented: %08x\n",bw);
                  assert(0);
                  *valp = _local_readw(cpssp, port, cs);
            } else if ( bw == 0x2 ) {
                  // 32 bit bus width
                  // FIXME: write me
                  TRACE(DEBUG_IO,"IO READ local addr. space0 32 bit bus width is not implemented: %08x\n",bw);
                  assert(0);
                  *valp = _local_readl(cpssp, port, cs);
            } else {
                  TRACE(DEBUG_IO,"IO READ local addr. space0 wrong bus width: %08x\n",bw);
                  *valp = 0x0;
                  // FIXME: better use assert(0); ?
            }
            
            return 0;
            
      } else if ( baseaddr3 && baseaddr3 <= addr && addr < baseaddr3 + cpssp->LAddrSp1_size ) {
            // io access to local address space 1
            
            TRACE(DEBUG_IO,"IO READ local addr. space1 addr: %08x\n",addr);
            port = addr - baseaddr3;
            cs = _local_cs(cpssp, port);

            /* check bus mode -> LAddrSp1BusRegionDescr bit 23,22 defines the bus width
             * 00 -> 8 bit
             * 01 -> 16 bit
             * 10 -> 32 bit
             * 11 -> reserved
             */
             bw = ( cpssp->LAddrSp1BusRegionDescr & 0x00c00000 ) >> 21;
            // and call apropiate function with cpssp, port, bs & address space no
            if ( bw == 0x0 ) {
                  // 8 bit bus width
                  // Fixme: Big Endian Support
                  if (( bs >> 0 ) & 1 ) {
                        *valp |= _local_readb(_css, port, cs) << 0;
                  }
                  if (( bs >> 1 ) & 1 ) {
                        *valp |= _local_readb(_css, port+1, cs) << 8;
                  }
                  if (( bs >> 2 ) & 1 ) {
                        *valp |= _local_readb(_css, port+2, cs) << 16;
                  }
                  if (( bs >> 3 ) & 1 ) {
                        *valp |= _local_readb(_css, port+3, cs) << 24;
                  }
            } else if ( bw == 0x1 ) {
                  // 16 bit bus width
                  TRACE(DEBUG_IO,"IO READ local addr. space1 16 bit bus width is not implemented: %08x\n",bw);
                  assert(0);
                  // *valp = _local_readw(cpssp, port, bs, cs);
            } else if ( bw == 0x2 ) {
                  // 32 bit bus width
                  TRACE(DEBUG_IO,"IO READ local addr. space1 32 bit bus width is not implemented: %08x\n",bw);
                  assert(0);
                  // *valp = _local_readlw(cpssp, port, bs, cs);
            } else {
                  TRACE(DEBUG_IO,"IO READ local addr. space1 wrong bus width: %08x\n",bw);
                  *valp = 0x0;
                  // FIXME: better use assert(0); ?
            }
            
            return 0;
            
      } else if ( baseaddr4 && baseaddr4 <= addr && addr < baseaddr4 + cpssp->LAddrSp2_size ) {
            // io access to local address space 2
            
            TRACE(DEBUG_IO,"IO READ local addr. space2 addr: %08x\n",addr);
            port = addr - baseaddr4;
            cs = _local_cs(cpssp, port);

            /* check bus mode -> LAddrSp2BusRegionDescr bit 23,22 defines the bus width
             * 00 -> 8 bit
             * 01 -> 16 bit
             * 10 -> 32 bit
             * 11 -> reserved
             */
             bw = ( cpssp->LAddrSp2BusRegionDescr & 0x00c00000 ) >> 21;
            // and call apropiate function with cpssp, port, bs & address space no
            if ( bw == 0x0 ) {
                  // 8 bit bus width
                  // Fixme: Big Endian Support
                  if (( bs >> 0 ) & 1 ) {
                        *valp |= _local_readb(_css, port, cs) << 0;
                  }
                  if (( bs >> 1 ) & 1 ) {
                        *valp |= _local_readb(_css, port+1, cs) << 8;
                  }
                  if (( bs >> 2 ) & 1 ) {
                        *valp |= _local_readb(_css, port+2, cs) << 16;
                  }
                  if (( bs >> 3 ) & 1 ) {
                        *valp |= _local_readb(_css, port+3, cs) << 24;
                  }
            } else if ( bw == 0x1 ) {
                  // 16 bit bus width
                  TRACE(DEBUG_IO,"IO READ local addr. space2 16 bit bus width is not implemented: %08x\n",bw);
                  assert(0);
                  // *valp = _local_readw(cpssp, port, bs, cs);
            } else if ( bw == 0x2 ) {
                  // 32 bit bus width
                  TRACE(DEBUG_IO,"IO READ local addr. space2 32 bit bus width is not implemented: %08x\n",bw);
                  assert(0);
                  // *valp = _local_readlw(cpssp, port, bs, cs);
            } else {
                  TRACE(DEBUG_IO,"IO READ local addr. space2 wrong bus width: %08x\n",bw);
                  *valp = 0x0;
                  // FIXME: better use assert(0); ?
            }
            
            return 0;
            
      } else if ( baseaddr5 && baseaddr5 <= addr && addr < baseaddr5 + cpssp->LAddrSp3_size ) {
            // io access to local address space 3
            
            TRACE(DEBUG_IO,"IO READ local addr. space3 addr: %08x\n",addr);
            port = addr - baseaddr5;
            cs = _local_cs(cpssp, port);

            /* check bus mode -> LAddrSp3BusRegionDescr bit 23,22 defines the bus width
             * 00 -> 8 bit
             * 01 -> 16 bit
             * 10 -> 32 bit
             * 11 -> reserved
             */
             bw = ( cpssp->LAddrSp3BusRegionDescr & 0x00c00000 ) >> 21;
            // and call apropiate function with cpssp, port, bs & address space no
            if ( bw == 0x0 ) {
                  // 8 bit bus width
                  // Fixme: Big Endian Support
                  if (( bs >> 0 ) & 1 ) {
                        *valp |= _local_readb(_css, port, cs) << 0;
                  }
                  if (( bs >> 1 ) & 1 ) {
                        *valp |= _local_readb(_css, port+1, cs) << 8;
                  }
                  if (( bs >> 2 ) & 1 ) {
                        *valp |= _local_readb(_css, port+2, cs) << 16;
                  }
                  if (( bs >> 3 ) & 1 ) {
                        *valp |= _local_readb(_css, port+3, cs) << 24;
                  }
            } else if ( bw == 0x1 ) {
                  // 16 bit bus width
                  TRACE(DEBUG_IO,"IO READ local addr. space3 16 bit bus width is not implemented: %08x\n",bw);
                  assert(0);
                  // *valp = _local_readw(cpssp, port, bs, cs);
            } else if ( bw == 0x2 ) {
                  // 32 bit bus width
                  TRACE(DEBUG_IO,"IO READ local addr. space3 32 bit bus width is not implemented: %08x\n",bw);
                  assert(0);
                  // *valp = _local_readlw(cpssp, port, bs, cs);
            } else {
                  TRACE(DEBUG_IO,"IO READ local addr. space3 wrong bus width: %08x\n",bw);
                  *valp = 0x0;
                  // FIXME: better use assert(0); ?
            }
            
            return 0;
            
      } else // we are not responsible for this address
            return -1;
      
      // dummy, never reached
      return -1;
}


/*
 * possible Bus Modes:
 * 8, 16, 32 Bit multiplexed or non-multiplexed mode
 * 8 or 16 bit ISA mode
 */

static int
_local_writeb(void *_css, uint8_t val8, uint32_t port, unsigned int cs)
{
      struct cpssp *cpssp = (struct cpssp *) _css;
      
      TRACE(DEBUG_IO,"IO WRITE -> _local_writeb -> port: %08x, cs: %d\n",port ,cs);
      
      switch (cs) {
            case 0:
                  // cs0
                  sig_cs_writeb(cpssp->port_cs0, cpssp, val8, port);
                  break;
            case 1:
                  // cs1
                  sig_cs_writeb(cpssp->port_cs1, cpssp, val8, port);
                  break;
            case 2:
                  // cs2
                  sig_cs_writeb(cpssp->port_cs2, cpssp, val8, port);
                  break;
            case 3:
                  // cs3
                  sig_cs_writeb(cpssp->port_cs3, cpssp, val8, port);
                  break;
            default:
                  assert(0);
                  break;
      }

      return 0;
}

static int
chip_plx_9052_iow(void *_css, uint32_t addr, unsigned int bs, uint32_t val)
{
      struct cpssp *cpssp = (struct cpssp *) _css;
      uint32_t port, mask, oval;
      unsigned int cs;
      unsigned int bw;
      
      /* card IO enabled? */
      if ( (cpssp->Command & 0x1) == 0 ) {
            TRACE(DEBUG_IO,"IO WRITE before enabled: cmd-reg: %08x\n",cpssp->Command);
            return -1;
      }
      
      /*
       * FIXME: baseaddr0 & baseaddr1 are configureable, 
       * but this is not supported for pc platform, maybe implemented later
       */
      
      uint32_t baseaddr1 = ( cpssp->BaseAddr1 & 0xfffffffc );
      
      // if address range are io ports -> baseddr<n> is calculated otherwise 0x0
      uint32_t baseaddr2 = ( cpssp->BaseAddr2 & 0x1 ) ? ( cpssp->BaseAddr2 & 0xfffffffe ) : 0x0;
      uint32_t baseaddr3 = ( cpssp->BaseAddr3 & 0x1 ) ? ( cpssp->BaseAddr3 & 0xfffffffe ) : 0x0;
      uint32_t baseaddr4 = ( cpssp->BaseAddr4 & 0x1 ) ? ( cpssp->BaseAddr4 & 0xfffffffe ) : 0x0;
      uint32_t baseaddr5 = ( cpssp->BaseAddr5 & 0x1 ) ? ( cpssp->BaseAddr5 & 0xfffffffe ) : 0x0;
      
      // baseaddr0 is always mapped to memory, so we don´t check it here
      
      if ( baseaddr1 <= addr && addr < ( baseaddr1 + 0x80 ) ) {
            // io access to local configuration register
            TRACE(DEBUG_IO,"IO WRITE local config. register addr: %08x, val:%08x\n",addr, val);
            port = addr - baseaddr1;
            
            oval = 0x0;
            mask = _calc_mask(bs);
            
            switch (port) {
            case 0x00 ... 0x03: // matches Local Address Space 0 Range
                  // bit 28 - 31 readonly -> 0xf0 << 24
                  oval = cpssp->LAddrSp0Range;
                  oval &= ( ~mask | 0xf0000000 );
                  oval |= (( val & mask ) & 0x0fffffff );
                  cpssp->LAddrSp0Range = oval;
                  // recalculating BaseAddr2 & LAddrSp0_size
                  cpssp->BaseAddr2 = cpssp->LAddrSp0Range & 0x1;              
                  cpssp->LAddrSp0_size = 1 + ~( (cpssp->LAddrSp0Range | 0xf0000000) & ~( (cpssp->LAddrSp0Range & 0x1) ? 0x00000003 : 0x0000000f ) );
                  break;
            case 0x04 ... 0x07: // matches Local Address Space 1 Range
                  // bit 28 - 31 readonly -> 0xf0 << 24
                  oval = cpssp->LAddrSp1Range;
                  oval &= ( ~mask | 0xf0000000 );
                  oval |= (( val & mask ) & 0x0fffffff );
                  cpssp->LAddrSp1Range = oval;
                  // recalculating BaseAddr3 & LAddrSp1_size
                  cpssp->BaseAddr3 = cpssp->LAddrSp1Range & 0x1;
                  cpssp->LAddrSp1_size = 1 + ~( (cpssp->LAddrSp1Range | 0xf0000000) & ~( (cpssp->LAddrSp1Range & 0x1) ? 0x00000003 : 0x0000000f ) );
                  break;
            case 0x08 ... 0x0b: // matches Local Address Space 2 Range
                  // bit 28 - 31 readonly -> 0xf0 << 24
                  oval = cpssp->LAddrSp2Range;
                  oval &= ( ~mask | 0xf0000000 );
                  oval |= (( val & mask ) & 0x0fffffff );
                  cpssp->LAddrSp2Range = oval;
                  // recalculating BaseAddr4 & LAddrSp2_size
                  cpssp->BaseAddr4 = cpssp->LAddrSp2Range & 0x1;
                  cpssp->LAddrSp2_size = 1 + ~( (cpssp->LAddrSp2Range | 0xf0000000) & ~( (cpssp->LAddrSp2Range & 0x1) ? 0x00000003 : 0x0000000f ) );
                  break;
            case 0x0c ... 0x0f: // matches Local Address Space 3 Range
                  // bit 28 - 31 readonly -> 0xf0 << 24
                  oval = cpssp->LAddrSp3Range;
                  oval &= ( ~mask | 0xf0000000 );
                  oval |= (( val & mask ) & 0x0fffffff );
                  cpssp->LAddrSp3Range = oval;
                  // recalculating BaseAddr5 & LAddrSp3_size
                  cpssp->BaseAddr5 = cpssp->LAddrSp3Range & 0x1;
                  cpssp->LAddrSp3_size = 1 + ~( (cpssp->LAddrSp3Range | 0xf0000000) & ~( (cpssp->LAddrSp3Range & 0x1) ? 0x00000003 : 0x0000000f ) );
                  break;
            case 0x10 ... 0x13: // matches Expansion Rom Range
                  // bit 0 - 10 readonly -> 0x7ff
                  oval = cpssp->ExpRomRange;
                  oval &= ( ~mask | 0x7ff );
                  oval |= ((val & mask ) & 0xfffff800 );
                  cpssp->ExpRomRange = oval;
                  break;
            case 0x14 ... 0x17: // matches Local Address Space 0 Local Base Address (Remap)
                  // bit 1, 28 - 31 readonly -> 0xf0000001
                  oval = cpssp->LAddrSp0Base;
                  oval &= ( ~mask | 0xf0000001 );
                  oval |= (( val & mask ) & 0x0ffffffe );
                  cpssp->LAddrSp0Base = oval;
                  break;
            case 0x18 ... 0x1b: // matches Local Address Space 1 Local Base Address (Remap)
                  // bit 1, 28 - 31 readonly -> 0xf0000001
                  oval = cpssp->LAddrSp1Base;
                  oval &= ( ~mask | 0xf0000001 );
                  oval |= (( val & mask ) & 0x0ffffffe );
                  cpssp->LAddrSp1Base = oval;
                  break;
            case 0x1c ... 0x1f: // matches Local Address Space 2 Local Base Address (Remap)
                  // bit 1, 28 - 31 readonly -> 0xf0000001
                  oval = cpssp->LAddrSp2Base;
                  oval &= ( ~mask | 0xf0000001 );
                  oval |= (( val & mask ) & 0x0ffffffe );
                  cpssp->LAddrSp2Base = oval;
                  break;
            case 0x20 ... 0x23: // matches Local Address Space 3 Local Base Address (Remap)
                  // bit 1, 28 - 31 readonly -> 0xf0000001
                  oval = cpssp->LAddrSp3Base;
                  oval &= ( ~mask | 0xf0000001 );
                  oval |= (( val & mask ) & 0x0ffffffe );
                  cpssp->LAddrSp3Base = oval;
                  break;
            case 0x24 ... 0x27: // matches Expansion Rom Local Base Address (Remap)
                  // bit 0 - 10, 28 - 31 readonly -> 0xf00007ff
                  oval = cpssp->ExpRomBase;
                  oval &= ( ~mask | 0xf00007ff );
                  oval |= ((val & mask ) & 0x0ffff800 );
                  cpssp->ExpRomBase = oval;
                  break;
            case 0x28 ... 0x2b: // matches Local Address Space 0 Bus Region Descriptors
                  oval = cpssp->LAddrSp0BusRegionDescr;
                  oval &= ~mask;
                  oval |= ( val & mask );
                  cpssp->LAddrSp0BusRegionDescr = oval;
                  break;
            case 0x2c ... 0x2f: // matches Local Address Space 1 Bus Region Descriptors
                  oval = cpssp->LAddrSp1BusRegionDescr;
                  oval &= ~mask;
                  oval |= ( val & mask );
                  cpssp->LAddrSp1BusRegionDescr = oval;
                  break;
            case 0x30 ... 0x33: // matches Local Address Space 2 Bus Region Descriptors
                  oval = cpssp->LAddrSp2BusRegionDescr;
                  oval &= ~mask;
                  oval |= ( val & mask );
                  cpssp->LAddrSp2BusRegionDescr = oval;
                  break;
            case 0x34 ... 0x37: // matches Local Address Space 3 Bus Region Descriptors
                  oval = cpssp->LAddrSp3BusRegionDescr;
                  oval &= ~mask;
                  oval |= ( val & mask );
                  cpssp->LAddrSp3BusRegionDescr = oval;
                  break;
            case 0x38 ... 0x3b: // matches Expansion Rom Bus Region Descriptors
                  oval = cpssp->ExpRomBusRegionDescr;
                  oval &= ~mask;
                  oval |= ( val & mask );
                  cpssp->ExpRomBusRegionDescr = oval;
                  break;
            case 0x3c ... 0x3f: // matches Chip Select 0 Base Address
                  // bit 28 - 31 readonly -> 0xf0 << 24
                  oval = cpssp->ChipSel0BaseAddr;
                  oval &= ( ~mask | 0xf0000000 );
                  oval |= (( val & mask ) & 0x0fffffff );
                  cpssp->ChipSel0BaseAddr = oval;
                  cpssp->ChipSel0_mask = _calc_chip_sel_mask(oval);
                  break;
            case 0x40 ... 0x43: // matches Chip Select 1 Base Address
                  // bit 28 - 31 readonly -> 0xf0 << 24
                  oval = cpssp->ChipSel1BaseAddr;
                  oval &= ( ~mask | 0xf0000000 );
                  oval |= (( val & mask ) & 0x0fffffff );
                  cpssp->ChipSel1BaseAddr = oval;
                  cpssp->ChipSel1_mask = _calc_chip_sel_mask(oval);
                  break;
            case 0x44 ... 0x47: // matches Chip Select 2 Base Address
                  // bit 28 - 31 readonly -> 0xf0 << 24
                  oval = cpssp->ChipSel2BaseAddr;
                  oval &= ( ~mask | 0xf0000000 );
                  oval |= (( val & mask ) & 0x0fffffff );
                  cpssp->ChipSel2BaseAddr = oval;
                  cpssp->ChipSel2_mask = _calc_chip_sel_mask(oval);
                  break;
            case 0x48 ... 0x4b: // matches Chip Select 3 Base Address
                  // bit 28 - 31 readonly -> 0xf0 << 24
                  oval = cpssp->ChipSel3BaseAddr;
                  oval &= ( ~mask | 0xf0000000 );
                  oval |= (( val & mask ) & 0x0fffffff );
                  cpssp->ChipSel3BaseAddr = oval;
                  cpssp->ChipSel3_mask = _calc_chip_sel_mask(oval);
                  break;
            case 0x4c ... 0x4f: // matches Interrupt Control / Status
                  // bit 2, 5, 12 - 31 readonly -> 0xfffff024
                  oval = cpssp->IntContrStat;
                  oval &= ( ~mask | 0xfffff024 );
                  oval |= (( val & mask ) & 0x00000fdb );
                  cpssp->IntContrStat = oval;
                  break;
            case 0x50 ... 0x53: // matches User I/O, Direct Slave Response, Serial Eeprom and Initialisation Control
                  // bit 27,28,31 readonly -> 0x98 << 24
                  oval = cpssp->UserIO;
                  oval &= ( ~mask | 0x98000000 );
                  oval |= (( val & mask ) & 0x67ffffff );
                  cpssp->UserIO = oval;   
                  break;
            case 0x54 ... 0x7f: // FIXME: is here something ?
                  break;
            default: // this should be never reached
                  return -1;
                  break;
            }
                        
            return 0;

      } else if ( baseaddr2 && baseaddr2 <= addr && addr < baseaddr2 + cpssp->LAddrSp0_size ) {
            // io access to local address space 0
            TRACE(DEBUG_IO,"IO WRITE local addr. space0 addr: %08x, val:%08x\n",addr, val);
            port = addr - baseaddr2;
            cs = _local_cs(cpssp, port);
            
            /* check bus mode -> LAddrSp0BusRegionDescr bit 23,22 defines the bus width
             * 00 -> 8 bit
             * 01 -> 16 bit
             * 10 -> 32 bit
             * 11 -> reserved
             */
             bw = ( cpssp->LAddrSp0BusRegionDescr & 0x00c00000 ) >> 21;
            // and call apropiate function with cpssp, port, bs & address space no
            
            if ( bw == 0x0 ) {
                  // 8 bit bus width
                  // Fixme: Big Endian Support
                  if (( bs >> 0 ) & 1 ) {
                        _local_writeb(_css, ((uint8_t) (val >>  0)), port, cs);
                  }
                  if (( bs >> 1 ) & 1 ) {
                        _local_writeb(_css, ((uint8_t) (val >>  8)), port+1, cs);
                  }
                  if (( bs >> 2 ) & 1 ) {
                        _local_writeb(_css, ((uint8_t) (val >> 16)), port+2, cs);
                  }
                  if (( bs >> 3 ) & 1 ) {
                        _local_writeb(_css, ((uint8_t) (val >> 24)), port+3, cs);
                  }
            } else if ( bw == 0x1 ) {
                  // 16 bit bus width
                  // FIXME: write me!
                  TRACE(DEBUG_IO,"IO WRITE local addr. space0 16 bit bus width is not implemented: %08x\n",bw);
                  assert(0);
            } else if ( bw == 0x2 ) {
                  // 32 bit bus width
                  // FIXME: write me
                  TRACE(DEBUG_IO,"IO WRITE local addr. space0 32 bit bus width is not implemented: %08x\n",bw);
                  assert(0);
            } else {
                  TRACE(DEBUG_IO,"IO WRITE local addr. space0 wrong bus width: %08x\n",bw);
                  // FIXME: better use assert(0); ?
            }
            
            return 0;
      } else if ( baseaddr3 && baseaddr3 <= addr && addr < baseaddr3 + cpssp->LAddrSp1_size ) {
            // io access to local address space 1
            TRACE(DEBUG_IO,"IO WRITE local addr. space1 addr: %08x, val:%08x\n",addr, val);
            port = addr - baseaddr3;
            cs = _local_cs(cpssp, port);
            
            /* check bus mode -> LAddrSp1BusRegionDescr bit 23,22 defines the bus width
             * 00 -> 8 bit
             * 01 -> 16 bit
             * 10 -> 32 bit
             * 11 -> reserved
             */
             bw = ( cpssp->LAddrSp1BusRegionDescr & 0x00c00000 ) >> 21;
            // and call apropiate function with cpssp, port, bs & address space no
            
            if ( bw == 0x0 ) {
                  // 8 bit bus width
                  // FIXME: write me!
            } else if ( bw == 0x1 ) {
                  // 16 bit bus width
                  // FIXME: write me!
                  TRACE(DEBUG_IO,"IO WRITE local addr. space1 16 bit bus width is not implemented: %08x\n",bw);
                  assert(0);
            } else if ( bw == 0x2 ) {
                  // 32 bit bus width
                  // FIXME: write me
                  TRACE(DEBUG_IO,"IO WRITE local addr. space1 32 bit bus width is not implemented: %08x\n",bw);
                  assert(0);
            } else {
                  TRACE(DEBUG_IO,"IO WRITE local addr. space1 wrong bus width: %08x\n",bw);
                  // FIXME: better use assert(0); ?
            }
            
            return 0;
      } else if ( baseaddr4 && baseaddr4 <= addr && addr < baseaddr4 + cpssp->LAddrSp2_size ) {
            // io access to local address space 2
            TRACE(DEBUG_IO,"IO WRITE local addr. space2 addr: %08x, val:%08x\n",addr, val);
            port = addr - baseaddr4;
            cs = _local_cs(cpssp, port);
            
            /* check bus mode -> LAddrSp2BusRegionDescr bit 23,22 defines the bus width
             * 00 -> 8 bit
             * 01 -> 16 bit
             * 10 -> 32 bit
             * 11 -> reserved
             */
             bw = ( cpssp->LAddrSp2BusRegionDescr & 0x00c00000 ) >> 21;
            // and call apropiate function with cpssp, port, bs & address space no
            
            if ( bw == 0x0 ) {
                  // 8 bit bus width
                  // FIXME: write me!
            } else if ( bw == 0x1 ) {
                  // 16 bit bus width
                  // FIXME: write me!
                  TRACE(DEBUG_IO,"IO WRITE local addr. space2 16 bit bus width is not implemented: %08x\n",bw);
                  assert(0);
            } else if ( bw == 0x2 ) {
                  // 32 bit bus width
                  // FIXME: write me
                  TRACE(DEBUG_IO,"IO WRITE local addr. space2 32 bit bus width is not implemented: %08x\n",bw);
                  assert(0);
            } else {
                  TRACE(DEBUG_IO,"IO WRITE local addr. space2 wrong bus width: %08x\n",bw);
                  // FIXME: better use assert(0); ?
            }
            
            return 0;
      } else if ( baseaddr5 && baseaddr5 <= addr && addr < baseaddr5 + cpssp->LAddrSp3_size ) {
            // io access to local address space 3
            TRACE(DEBUG_IO,"IO WRITE local addr. space3 addr: %08x, val:%08x\n",addr, val);
            port = addr - baseaddr5;
            cs = _local_cs(cpssp, port);
            
            /* check bus mode -> LAddrSp3BusRegionDescr bit 23,22 defines the bus width
             * 00 -> 8 bit
             * 01 -> 16 bit
             * 10 -> 32 bit
             * 11 -> reserved
             */
             bw = ( cpssp->LAddrSp3BusRegionDescr & 0x00c00000 ) >> 21;
            // and call apropiate function with cpssp, port, bs & address space no
            
            if ( bw == 0x0 ) {
                  // 8 bit bus width
                  // FIXME: write me!
            } else if ( bw == 0x1 ) {
                  // 16 bit bus width
                  // FIXME: write me!
                  TRACE(DEBUG_IO,"IO WRITE local addr. space3 16 bit bus width is not implemented: %08x\n",bw);
                  assert(0);
            } else if ( bw == 0x2 ) {
                  // 32 bit bus width
                  // FIXME: write me
                  TRACE(DEBUG_IO,"IO WRITE local addr. space3 32 bit bus width is not implemented: %08x\n",bw);
                  assert(0);
            } else {
                  TRACE(DEBUG_IO,"IO WRITE local addr. space3 wrong bus width: %08x\n",bw);
                  // FIXME: better use assert(0); ?
            }
            
            return 0;
      } else 
            return -1;

      // dummy, never reached
      return -1;
}

#if 0 /* Not used */
static int
chip_plx_9052_mr(void *_css, uint32_t addr, unsigned int bs, uint32_t *valp)
{
      fprintf(stderr, "%s called (addr=%08x, bs=%x)\n", __FUNCTION__,
                  (unsigned int) addr, bs);
      return -1;
}

static int
chip_plx_9052_mw(void *_css, uint32_t addr, unsigned int bs, uint32_t val)
{
      fprintf(stderr, "%s called (addr=%08x, bs=%x, val=%08x)\n",
            __FUNCTION__, (unsigned int) addr, bs, (unsigned int) val);
      return -1;
}
#endif

void
chip_plx_9052_init(
      unsigned int nr,
      struct sig_boolean *port_power,
      struct sig_boolean *port_reset_hash_,
      struct sig_pci_bus_idsel *port_idsel,
      struct sig_pci_bus_main *port_pci_bus,
      struct sig_boolean_or *port_intA,
      struct sig_cs *port_cs0,
      struct sig_cs *port_cs1,
      struct sig_cs *port_cs2,
      struct sig_cs *port_cs3
)
{
      static const struct sig_boolean_funcs power_funcs = {
            .set = chip_plx_9052_power_set,
      };
      static const struct sig_boolean_funcs reset_hash__funcs = {
            .set = chip_plx_9052_n_reset_set,
      };
      static const struct sig_pci_bus_idsel_funcs idsel_funcs = {
            .c0r = chip_plx_9052_c0r,
            .c0w = chip_plx_9052_c0w,
      };
      static const struct sig_pci_bus_main_funcs pci_bus_funcs = {
            .ior = chip_plx_9052_ior,
            .iow = chip_plx_9052_iow,
#if 0 /* Not used */
            .mr = chip_plx_9052_mr,
            .mw = chip_plx_9052_mw,
            .map = chip_plx_9052_map,
#endif
      };
      struct cpssp *cpssp;

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

      /* Out */
      cpssp->port_intA = port_intA;
      sig_boolean_or_connect_out(port_intA, cpssp, 0);

      /* Call */
      sig_pci_bus_idsel_connect(port_idsel, cpssp, &idsel_funcs);

      sig_pci_bus_main_connect(port_pci_bus, cpssp, &pci_bus_funcs);

      cpssp->port_cs0 = port_cs0;

      cpssp->port_cs1 = port_cs1;

      cpssp->port_cs2 = port_cs2;

      cpssp->port_cs3 = port_cs3;

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

      sig_boolean_connect_in(port_reset_hash_, cpssp, &reset_hash__funcs);

}

unsigned int
chip_plx_9052_create(const char *img)
{
      static unsigned int nr = 0;
      struct cpssp *cpssp;
      const char *path;
      int fd;
      int ret;
       
      shm_create(COMP, nr, sizeof(*cpssp));
      cpssp = shm_map(COMP, nr, sizeof(*cpssp), 0);

      path = buildpath(ROMDIR, img);
      fd = open(path, O_RDONLY);
      assert(0 <= fd);

      ret = read(fd, cpssp->rom, sizeof(cpssp->rom));
      assert(0 <= ret);
      assert(ret == sizeof(cpssp->rom));

      ret = close(fd);
      assert(0 <= ret);

      shm_unmap(cpssp, sizeof(*cpssp));

      return nr++;
}

void
chip_plx_9052_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