示例#1
0
static uint32_t pci_scan(
  uint32_t           handle,
  pci_scan_helper_t  helper,
  void               *arg
)
{
  uint32_t vendor;
  uint8_t  bus;
  uint8_t  dev;
  uint8_t  fun;
  uint8_t  hd;

  bus = PCIB_DEVSIG_BUS(  (unsigned long)handle );
  dev = PCIB_DEVSIG_DEV(  (unsigned long)handle );
  fun = PCIB_DEVSIG_FUNC( (unsigned long)handle );

  hd = fun > 0 ? PCI_MAX_FUNCTIONS : 1;

  for (; bus<pci_bus_count(); bus++, dev=0) {
    for (; dev<PCI_MAX_DEVICES; dev++, fun=0) {
      for (; fun<hd; fun++) {
        /*
         * The last devfn id/slot is special; must skip it
         */
        if ((PCI_MAX_DEVICES-1 == dev) && (PCI_MAX_FUNCTIONS-1 == fun) )
          break;

        (void)pci_read_config_dword(bus, dev, 0, PCI_VENDOR_ID, &vendor);
        if (PCI_INVALID_VENDORDEVICEID == vendor)
          continue;

        if ( fun == 0 ) {
          pci_read_config_byte(bus,dev, 0,  PCI_HEADER_TYPE, &hd);
          hd = (hd & PCI_HEADER_TYPE_MULTI_FUNCTION ? PCI_MAX_FUNCTIONS : 1);
        }

        (void)pci_read_config_dword(bus, dev, fun, PCI_VENDOR_ID, &vendor);
        if (PCI_INVALID_VENDORDEVICEID == vendor)
          continue;
        #ifdef PCI_DEBUG
          fprintf(
            stderr,
            "pci_scan: found 0x%08" PRIx32 " at %d/x%02x/%d\n", vendor, bus, dev, fun
          );
        #endif
        if ( (*helper)(bus, dev, fun, arg) > 0 ) {
          if ( ++fun >= hd ) {
            fun = 0;
            if ( ++dev >= PCI_MAX_DEVICES ) {
              dev = 0;
              bus++;
            }
          }
          return PCIB_DEVSIG_MAKE(bus,dev,fun);
        }
      }
    }
  }
  return 0;
}
示例#2
0
void pci_list_devices( void )
{
   uint32_t d;
   unsigned char bus,dev,fun,hd;

  printk(
    "BUS:SLOT:FUN  VENDOR-DEV_ID: COMMAND STATUS BASE_ADDR0 "
    "BASE_ADDR1 IRQ_PIN -> IRQ_LINE\n"
  );
  for (bus=0 ; bus<pci_bus_count(); bus++) {
    for (dev=0 ; dev<PCI_MAX_DEVICES; dev++) {
      for (fun=0 ; fun<PCI_MAX_FUNCTIONS; fun++) {
        /*
         * The last devfn id/slot is special; must skip it
         */
        if (PCI_MAX_DEVICES-1==dev && PCI_MAX_FUNCTIONS-1 == fun)
          break;

        (void) pci_read_config_dword(bus,dev,0,PCI_VENDOR_ID,&d);
        if (PCI_INVALID_VENDORDEVICEID == d)
          continue;

        if ( 0 == fun ) {
          pci_read_config_byte(bus,dev,0, PCI_HEADER_TYPE, &hd);
          hd = (hd & PCI_HEADER_TYPE_MULTI_FUNCTION ? PCI_MAX_FUNCTIONS : 1);
        }

        (void)pci_read_config_dword(bus,dev,fun,PCI_VENDOR_ID,&d);
        if (PCI_INVALID_VENDORDEVICEID == d)
          continue;
        print_device_config( bus, dev, fun );
      }
    }
  }
}
示例#3
0
文件: main_pci.c 项目: AoLaD/rtems
static int pci_summary(void)
{
	char *str;
	char *cfglib_strs[5] = {"NONE", "AUTO", "STATIC", "READ", "PERIPHERAL"};

	if (pci_system_type == PCI_SYSTEM_HOST)
		str = "HOST";
	else if (pci_system_type == PCI_SYSTEM_PERIPHERAL)
		str = "PERIPHERAL";
	else
		str = "UNKNOWN / UNINITIALIZED";
	printf(" SYSTEM:            %s\n", str);

	if (pci_config_lib_type > PCI_CONFIG_LIB_PERIPHERAL) {
		puts(" Bad configuration library");
		return 1;
	}
	printf(" CFG LIBRARY:       %s\n", cfglib_strs[pci_config_lib_type]);
	printf(" NO. PCI BUSES:     %d buses\n", pci_bus_count());
	printf(" PCI ENDIAN:        %s\n", pci_endian ? "Big" : "Little");
#if (CPU_LITTLE_ENDIAN == TRUE)
	puts(" MACHINE ENDIAN:    Little");
#else
	puts(" MACHINE ENDIAN:    Big");
#endif

	return 0;
}
示例#4
0
/* This is a very ugly hack. I don't want to change the shared
 * code to support multiple hoses so we hide everything under
 * the hood with horrible kludges for now. Sorry.
 */
void
BSP_pci_initialize(void)
{

#if 0	/* These values are already set up for the shared/pci.c code      */
{
extern pci_config_access_functions pci_indirect_functions;
        /* by means of the PCI_CONFIG_ADDR/PCI_CONFIG_DATA macros (bsp.h) */
	BSP_pci_configuration.pci_config_addr = hoses[0].pci_config_addr;
	BSP_pci_configuration.pci_config_data = hoses[0].pci_config_data;
	BSP_pci_configuration.pci_functions   = &pci_indirect_functions;
}
#endif
	/* initialize the first hose */
	/* scan hose 0 and sets the maximum bus number */
	pci_initialize();
	/* remember the boundary */
	BSP_pci_hose1_bus_base = pci_bus_count();
	/* so far, so good -- now comes the cludgy part: */
	/* hack/reset the bus count */
	ucMaxPCIBus = 0;
	/* scan hose 1 */
	BSP_pci_configuration.pci_config_addr = hoses[1].pci_config_addr;
	BSP_pci_configuration.pci_config_data = hoses[1].pci_config_data;
	pci_initialize();
	/* check for overflow of an unsigned char */
	if ( BSP_pci_hose1_bus_base + pci_bus_count() > 255 ) {
		BSP_panic("Too many PCI busses in the system");
	}
	/* readjust total number */
	ucMaxPCIBus+=BSP_pci_hose1_bus_base;

	/* install new access functions that can hide the hoses */
	BSP_pci_configuration.pci_config_addr = (volatile unsigned char *)0xdeadbeef;
	BSP_pci_configuration.pci_config_data = (volatile unsigned char *)0xdeadbeef;
	BSP_pci_configuration.pci_functions   = &pci_hosed_indirect_functions;
}
示例#5
0
文件: pci.c 项目: 0871087123/rtems
static int FindPCIbridge( int mybus, struct pcibridge *pb )
{
  int          pbus, pslot;
  uint8_t      bussec, buspri;
  uint16_t     devid, vendorid, dclass;

  for(pbus=0; pbus< pci_bus_count(); pbus++) {
    for(pslot=0; pslot< PCI_MAX_DEVICES; pslot++) {
      pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &devid);
      if ( devid == 0xffff ) continue;

      pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &vendorid);
      if ( vendorid == 0xffff ) continue;

      pci_read_config_word(pbus, pslot, 0, PCI_CLASS_DEVICE, &dclass);

      if ( dclass == PCI_CLASS_BRIDGE_PCI ) {
        pci_read_config_byte(pbus, pslot, 0, PCI_PRIMARY_BUS,    &buspri);
        pci_read_config_byte(pbus, pslot, 0, PCI_SECONDARY_BUS,  &bussec);

#ifdef SHOW_PCI_SETTING
         printk("pci : Found bridge at %d:0x%02x, mybus %d, pribus %d, secbus %d ",
                 pbus, pslot, mybus, buspri, bussec );
#endif
         if ( bussec == mybus ) {
#ifdef SHOW_PCI_SETTING
           printk("match\n");
#endif
           /* found our nearest bridge going towards the root */
           pb->bus = pbus;
           pb->slot = pslot;

           return 0;
        }
#ifdef SHOW_PCI_SETTING
         printk("no match\n");
#endif
      }

     }
   }
   return -1;
}
int pci_for_each(int (*func)(pci_dev_t, void*), void *arg)
{
	uint32_t id;
	uint8_t hd;
	int bus, dev, fun, result, fail;
	int maxbus = pci_bus_count();
	pci_dev_t pcidev;

	for (bus = 0; bus < maxbus ; bus++) {
		for (dev = 0; dev < PCI_MAX_DEVICES; dev++) {
			pcidev = PCI_DEV(bus, dev, 0);

			for (fun = 0; fun < PCI_MAX_FUNCTIONS; fun++, pcidev++) {
				fail = pci_cfg_r32(pcidev, PCI_VENDOR_ID, &id);
				if (fail || (0xffffffff == id) || (0 == id)) {
					if (fun == 0)
						break;
					else
						continue;
				}

				DBG("pcibus_for_each: found 0x%08lx at"
				    " %d/%d/%d\n", id, bus, dev, fun);
				result = func(pcidev, arg);
				if (result != 0)
					return result; /* Stopped */

				/* Stop if not a multi-function device */
				if (fun == 0) {
					pci_cfg_r8(pcidev, PCI_HEADER_TYPE,
							&hd);
					if ((hd & PCI_MULTI_FUNCTION) == 0)
						break;
				}
			}
		}
	}

	return 0; /* scanned all */
}
示例#7
0
void bsp_start( void )
{
#ifdef CONF_VPD
  int i;
#endif
#ifdef SHOW_LCR1_REGISTER
  unsigned l1cr;
#endif
#ifdef SHOW_LCR2_REGISTER
  unsigned l2cr;
#endif
#ifdef SHOW_LCR3_REGISTER
  unsigned l3cr;
#endif
  uintptr_t intrStackStart;
  uintptr_t intrStackSize;
  ppc_cpu_id_t myCpu;
  ppc_cpu_revision_t myCpuRevision;
  Triv121PgTbl  pt=0;

  /* Till Straumann: 4/2005
   * Need to map the system registers early, so we can printk...
   * (otherwise we silently die)
   */
  /*
   * Kate Feng : PCI 0 domain memory space, want to leave room for the VME window
   */
  setdbat(2, PCI0_MEM_BASE, PCI0_MEM_BASE, 0x10000000, IO_PAGE);

  /* Till Straumann: 2004
   * map the PCI 0, 1 Domain I/O space, GT64260B registers
   * and the reserved area so that the size is the power of 2.
   * 2009 : map the entire 256 M space
   *
   */
  setdbat(3,PCI0_IO_BASE, PCI0_IO_BASE, 0x10000000, IO_PAGE);


  /*
   * Get CPU identification dynamically. Note that the get_ppc_cpu_type() function
   * store the result in global variables so that it can be used latter...
   */
  myCpu   = get_ppc_cpu_type();
  myCpuRevision = get_ppc_cpu_revision();

#ifdef SHOW_LCR1_REGISTER
  l1cr = get_L1CR();
  printk("Initial L1CR value = %x\n", l1cr);
#endif

  /*
   * Initialize the interrupt related settings.
   */
  intrStackStart = (uintptr_t) __rtems_end;
  intrStackSize = rtems_configuration_get_interrupt_stack_size();

  /*
   * Initialize default raw exception handlers.
   */
  ppc_exc_initialize(
    PPC_INTERRUPT_DISABLE_MASK_DEFAULT,
    intrStackStart,
    intrStackSize
  );

  /*
   * Init MMU block address translation to enable hardware
   * access
   * More PCI1 memory mapping to be done after BSP_pgtbl_activate.
   */
  printk("-----------------------------------------\n");
  printk("Welcome to %s on MVME5500-0163\n", _RTEMS_version );
  printk("-----------------------------------------\n");

  BSP_mem_size         =  probeMemoryEnd();

  /* TODO: calculate the BSP_bus_frequency using the REF_CLK bit
   *       of System Status  register
   */
  /* rtems_bsp_delay_in_bus_cycles are defined in registers.h */
  BSP_bus_frequency      = 133333333;
  BSP_processor_frequency    = 1000000000;
  /* P94 : 7455 clocks the TB/DECR at 1/4 of the system bus clock frequency */
  BSP_time_base_divisor      = 4000;

  /* Maybe not setup yet becuase of the warning message */
  /* Allocate and set up the page table mappings
   * This is only available on >604 CPUs.
   *
   * NOTE: This setup routine may modify the available memory
   *       size. It is essential to call it before
   *       calculating the workspace etc.
   */
  pt = BSP_pgtbl_setup(&BSP_mem_size);
  if (!pt)
     printk("WARNING: unable to setup page tables.\n");

  printk("Now BSP_mem_size = 0x%x\n",BSP_mem_size);

  /* P94 : 7455 TB/DECR is clocked by the system bus clock frequency */

  bsp_clicks_per_usec    = BSP_bus_frequency/(BSP_time_base_divisor * 1000);

  /*
   * Initalize RTEMS IRQ system
   */
   BSP_rtems_irq_mng_init(0);

#ifdef SHOW_LCR2_REGISTER
  l2cr = get_L2CR();
  printk("Initial L2CR value = %x\n", l2cr);
#endif

#ifdef SHOW_LCR3_REGISTER
  /* L3CR needs DEC int. handler installed for bsp_delay()*/
  l3cr = get_L3CR();
  printk("Initial L3CR value = %x\n", l3cr);
#endif


  /* Activate the page table mappings only after
   * initializing interrupts because the irq_mng_init()
   * routine needs to modify the text
   */
  if (pt) {
#ifdef SHOW_MORE_INIT_SETTINGS
    printk("Page table setup finished; will activate it NOW...\n");
#endif
    BSP_pgtbl_activate(pt);
  }
  /* Read Configuration Vital Product Data (VPD) */
  if ( I2Cread_eeprom(0xa8, 4,2, &ConfVPD_buff[0], 150))
     printk("I2Cread_eeprom() error \n");
  else {
#ifdef CONF_VPD
    printk("\n");
    for (i=0; i<150; i++) {
      printk("%2x ", ConfVPD_buff[i]);
      if ((i % 20)==0 ) printk("\n");
    }
    printk("\n");
#endif
  }

  /*
   * PCI 1 domain memory space
   */
  setdbat(1, PCI1_MEM_BASE, PCI1_MEM_BASE, 0x10000000, IO_PAGE);


#ifdef SHOW_MORE_INIT_SETTINGS
  printk("Going to start PCI buses scanning and initialization\n");
#endif
  pci_initialize();
#ifdef SHOW_MORE_INIT_SETTINGS
  printk("Number of PCI buses found is : %d\n", pci_bus_count());
#endif

  /* Install our own exception handler (needs PCI) */
  globalExceptHdl = BSP_exceptionHandler;

  /* clear hostbridge errors. MCP signal is not used on the MVME5500
   * PCI config space scanning code will trip otherwise :-(
   */
  _BSP_clear_hostbridge_errors(0, 1 /*quiet*/);

#ifdef SHOW_MORE_INIT_SETTINGS
  printk("MSR %x \n", _read_MSR());
  printk("Exit from bspstart\n");
#endif

}
示例#8
0
文件: pci.c 项目: 0871087123/rtems
void FixupPCI( const struct _int_map *bspmap, int (*swizzler)(int,int) )
{
  unsigned char        cvalue;
  uint16_t             devid;
  int                  ismatch, i, j, pbus, pslot, pfun, int_pin, int_name, nfuns;

  /*
   * If the device has a non-zero INTERRUPT_PIN, assign a bsp-specific
   * INTERRUPT_NAME if one isn't already in place.  Then, drivers can
   * trivially use INTERRUPT_NAME to hook up with devices.
   */

  for (pbus=0; pbus< pci_bus_count(); pbus++) {
	for (pslot=0; pslot< PCI_MAX_DEVICES; pslot++) {
	  pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &devid);
	  if ( devid == 0xffff ) continue;

	  /* got a device */
	  pci_read_config_byte(pbus, pslot, 0, PCI_HEADER_TYPE, &cvalue);
	  nfuns = cvalue & PCI_HEADER_TYPE_MULTI_FUNCTION ? PCI_MAX_FUNCTIONS : 1;

	  for (pfun=0; pfun< nfuns; pfun++) {
		pci_read_config_word(pbus, pslot, pfun, PCI_DEVICE_ID, &devid);
		if( devid == 0xffff ) continue;

		pci_read_config_byte( pbus, pslot, pfun, PCI_INTERRUPT_PIN, &cvalue);
		int_pin = cvalue;

		pci_read_config_byte( pbus, pslot, pfun, PCI_INTERRUPT_LINE, &cvalue);
		int_name = cvalue;

		/* printk("pci : device %d:0x%02x:%i devid %04x, intpin %d, intline  %d\n",
		   pbus, pslot, pfun, devid, int_pin, int_name ); */

#ifdef SHOW_PCI_SETTING
		{
		  unsigned short cmd,stat;
		  unsigned char  lat, seclat, csize;

		  pci_read_config_word(pbus,pslot,pfun,PCI_COMMAND, &cmd );
		  pci_read_config_word(pbus,pslot,pfun,PCI_STATUS, &stat );
		  pci_read_config_byte(pbus,pslot,pfun,PCI_LATENCY_TIMER, &lat );
		  pci_read_config_byte(pbus,pslot,pfun,PCI_SEC_LATENCY_TIMER, &seclat );
		  pci_read_config_byte(pbus,pslot,pfun,PCI_CACHE_LINE_SIZE, &csize );


		  printk("pci : device %d:0x%02x:%d  cmd %04X, stat %04X, latency %d, "
			  " sec_latency %d, clsize %d\n", pbus, pslot, pfun, cmd, stat,
			  lat, seclat, csize);
		}
#endif

		if ( int_pin > 0 ) {
		  ismatch = 0;

		  /*
		   * first run thru the bspmap table and see if we have an
		   * explicit configuration
		   */
		  for (i=0; bspmap[i].bus > -1; i++) {
			if ( bspmap[i].bus == pbus && bspmap[i].slot == pslot ) {
			  ismatch = -1;
			  /* we have a record in the table that gives specific
			   * pins and interrupts for devices in this slot */
			  if ( int_name == 255 ) {
				/* find the vector associated with whatever pin the
				 * device gives us
				 */
				for ( int_name=-1, j=0; bspmap[i].pin_route[j].pin > -1; j++ ) {
				  if ( bspmap[i].pin_route[j].pin == int_pin ) {
					int_name = bspmap[i].pin_route[j].int_name[0];
					break;
				  }
				}
				if ( int_name == -1 ) {
				  printk("pci : Unable to resolve device %d:0x%02x:%d w/ swizzled int "
					  "pin %i to an interrupt_line.\n", pbus, pslot, pfun, int_pin );
				} else {
				  PRINT_MSG();
				  pci_write_config_byte( pbus,pslot,pfun,
					  PCI_INTERRUPT_LINE,(cvalue= int_name, cvalue));
				}
			  } else {
				test_intname( &bspmap[i],pbus,pslot,pfun,int_pin,int_name);
			  }
			  break;
			}
		  }

		  if ( !ismatch ) {
			/*
			 * no match, which means we're on a bus someplace.  Work
			 * backwards from it to one of our defined busses,
			 * swizzling thru each bridge on the way.
			 */

			/* keep pbus, pslot pointed to the device being
			 * configured while we track down the bridges using
			 * tbus,tslot.  We keep searching the routing table because
			 * we may end up finding our bridge in it
			 */

			int tbus= pbus, tslot= pslot;

			for (;;) {
			  for (i=0; bspmap[i].bus > -1; i++) {
				if ( bspmap[i].bus == tbus &&
					(bspmap[i].slot == tslot || bspmap[i].slot == -1) ) {
				  ismatch = -1;
				  /* found a record for this bus, so swizzle the
				   * int_pin which we then use to find the
				   * interrupt_name.
				   */

				  if ( int_name == 255 ) {
					/*
					 * FIXME.  I can't believe this little hack
					 * is right.  It does not yield an error in
					 * convienently simple situations.
					 */
					if ( tbus ) int_pin = (*swizzler)(tslot,int_pin);

					/*
					 * int_pin points to the interrupt channel
					 * this card ends up delivering interrupts
					 * on.  Find the int_name servicing it.
					 */
					for (int_name=-1, j=0; bspmap[i].pin_route[j].pin > -1; j++){
					  if ( bspmap[i].pin_route[j].pin == int_pin ) {
						int_name = bspmap[i].pin_route[j].int_name[0];
						break;
					  }
					}

					if ( int_name == -1 ) {
					  printk("pci : Unable to resolve device %d:0x%02x:%d w/ swizzled "
						  "int pin %i to an interrupt_line.\n",
						  pbus, pslot, pfun, int_pin );
					} else {
					  PRINT_MSG();
					  pci_write_config_byte(pbus,pslot,pfun,
						  PCI_INTERRUPT_LINE,(cvalue=int_name, cvalue));
					}
				  } else {
					test_intname(&bspmap[i],pbus,pslot,pfun,int_pin,int_name);
				  }
				  goto donesearch;
				}
			  }

			  if ( !ismatch ) {
				struct pcibridge   pb;

				/*
				 * Haven't found our bus in the int map, so work
				 * upwards thru the bridges till we find it.
				 */

				if ( FindPCIbridge( tbus, &pb )== 0 ) {
				  int_pin = (*swizzler)(tslot,int_pin);

				  /* our next bridge up is on pb.bus, pb.slot- now
				   * instead of pointing to the device we're
				   * trying to configure, we move from bridge to
				   * bridge.
				   */

				  tbus = pb.bus;
				  tslot = pb.slot;
				} else {
				  printk("pci : No bridge from bus %i towards root found\n",
					  tbus );
				  goto donesearch;
				}
			  }
			}
		  }
donesearch:

		  if ( !ismatch && int_pin != 0 && int_name == 255 ) {
			printk("pci : Unable to match device %d:0x%02x:%d with an int "
				"routing table entry\n", pbus, pslot, pfun  );
		  }
		}
	  }
	}
  }
}
示例#9
0
void BSP_motload_pci_fixup(void)
{
uint32_t	b0,b1,r0,r1,lim,dis;

	/* MotLoad on the mvme5500 and mvme6100 configures the PCI
	 * busses nicely, i.e., the values read from the memory address
	 * space BARs by means of PCI config cycles directly reflect the
	 * CPU memory map. Thus, the presence of two hoses is already hidden.
	 *
	 * Unfortunately, all PCI I/O addresses are 'zero-based' i.e.,
	 * a hose-specific base address would have to be added to
	 * the values read from config space.
	 *
	 * We fix this here so I/O BARs also reflect the CPU memory map.
	 *
	 * Furthermore, the mvme5500 uses
	 *    f000.0000
	 *  ..f07f.ffff  for PCI-0 / hose0
	 *
	 *  and
	 *
	 *    f080.0000
	 *  ..f0ff.0000  for PCI-1 / hose 0
	 *
	 *  whereas the mvme6100 does it the other way round...
	 */

	b0 = in_le32( (volatile unsigned*)(BSP_MV64x60_BASE + GT_PCI0_IO_Low_Decode) );
	b1 = in_le32( (volatile unsigned*)(BSP_MV64x60_BASE + GT_PCI1_IO_Low_Decode) );

	r0 = in_le32( (volatile unsigned*)(BSP_MV64x60_BASE + GT_PCI0_IO_Remap) );
	r1 = in_le32( (volatile unsigned*)(BSP_MV64x60_BASE + GT_PCI1_IO_Remap) );

	switch ( BSP_getDiscoveryVersion(0) ) {
		case MV_64360:
			/* In case of the MV64360 the 'limit' is actually a 'size'!
			 * Disable by setting special bits in the 'BAR disable reg'.
			 */
			dis = in_le32( (volatile unsigned*)(BSP_MV64x60_BASE + MV_64360_BASE_ADDR_DISBL) );
			/* disable PCI0 I/O and PCI1 I/O */
			out_le32( (volatile unsigned*)(BSP_MV64x60_BASE + MV_64360_BASE_ADDR_DISBL), dis | (1<<9) | (1<<14) );
			/* remap busses on hose 0; if the remap register was already set, assume
			 * that someone else [such as the bootloader] already performed the fixup
			 */
			if ( (b0 & 0xffff) && 0 == (r0 & 0xffff) ) {
				rtems_pci_io_remap( 0, BSP_pci_hose1_bus_base, (b0 & 0xffff)<<16 );
				out_le32( (volatile unsigned*)(BSP_MV64x60_BASE + GT_PCI0_IO_Remap), (b0 & 0xffff) );
			}

			/* remap busses on hose 1 */
			if ( (b1 & 0xffff) && 0 == (r1 & 0xffff) ) {
				rtems_pci_io_remap( BSP_pci_hose1_bus_base, pci_bus_count(), (b1 & 0xffff)<<16 );
				out_le32( (volatile unsigned*)(BSP_MV64x60_BASE + GT_PCI1_IO_Remap), (b1 & 0xffff) );
			}

			/* re-enable */
			out_le32( (volatile unsigned*)(BSP_MV64x60_BASE + MV_64360_BASE_ADDR_DISBL), dis );
		break;

		case GT_64260_A:
		case GT_64260_B:
			
			if ( (b0 & 0xfff) && 0 == (r0 & 0xfff) ) { /* base are only 12 bits */
				/* switch window off by setting the limit < base */
				lim = in_le32( (volatile unsigned*)(BSP_MV64x60_BASE + GT_PCI0_IO_High_Decode) );
				out_le32( (volatile unsigned*)(BSP_MV64x60_BASE + GT_PCI0_IO_High_Decode), 0 );
				/* remap busses on hose 0 */
				rtems_pci_io_remap( 0, BSP_pci_hose1_bus_base, (b0 & 0xfff)<<20 );

				/* BTW: it seems that writing the base register also copies the
				 * value into the 'remap' register automatically (??)
				 */
				out_le32( (volatile unsigned*)(BSP_MV64x60_BASE + GT_PCI0_IO_Remap), (b0 & 0xfff) );

				/* re-enable */
				out_le32( (volatile unsigned*)(BSP_MV64x60_BASE + GT_PCI0_IO_High_Decode), lim );
			}

			if ( (b1 & 0xfff) && 0 == (r1 & 0xfff) ) { /* base are only 12 bits */
				/* switch window off by setting the limit < base */
				lim = in_le32( (volatile unsigned*)(BSP_MV64x60_BASE + GT_PCI1_IO_High_Decode) );
				out_le32( (volatile unsigned*)(BSP_MV64x60_BASE + GT_PCI1_IO_High_Decode), 0 );

				/* remap busses on hose 1 */
				rtems_pci_io_remap( BSP_pci_hose1_bus_base, pci_bus_count(), (b1 & 0xfff)<<20 );

				out_le32( (volatile unsigned*)(BSP_MV64x60_BASE + GT_PCI1_IO_Remap), (b1 & 0xfff) );

				/* re-enable */
				out_le32( (volatile unsigned*)(BSP_MV64x60_BASE + GT_PCI1_IO_High_Decode), lim );
			}
		break;

		default:
			BSP_panic("Unknown discovery version; switch in file: "__FILE__" not implemented (yet)");
		break; /* never get here */
	}

	/* Fixup the IRQ lines; the mvme6100 maps them nicely into our scheme, i.e., GPP
	 * interrupts start at 64 upwards
	 *
	 * The mvme5500 is apparently initialized differently :-(. GPP interrupts start at 0
	 * Since all PCI interrupts are wired to GPP we simply check for a value < 64 and
	 * reprogram the interrupt line register.
	 */
	BSP_pciScan(0, fixup_irq_line, 0);
}
示例#10
0
void VIA_isa_bridge_interrupts_setup(void)
{
  pci_isa_bridge_device pci_dev;
  uint32_t temp;
  unsigned char tmp;
  unsigned char maxBus;
  unsigned found = 0;

  maxBus = pci_bus_count();
  pci_dev.function 	= 0; /* Assumes the bidge is the first function */

  for (pci_dev.bus = 0; pci_dev.bus < maxBus; pci_dev.bus++) {
#ifdef SCAN_PCI_PRINT
    printk("isa_bridge_interrupts_setup: Scanning bus %d\n", pci_dev.bus);
#endif
    for (pci_dev.device = 0; pci_dev.device < PCI_MAX_DEVICES; pci_dev.device++) {
#ifdef SCAN_PCI_PRINT
      printk("isa_bridge_interrupts_setup: Scanning device %d\n", pci_dev.device);
#endif
      pci_read_config_dword(pci_dev.bus, pci_dev.device,  pci_dev.function,
			       PCI_VENDOR_ID, &temp);
#ifdef SCAN_PCI_PRINT
      printk("Vendor/device = %x\n", temp);
#endif
      if ((temp == (((unsigned short) PCI_VENDOR_ID_VIA) | (PCI_DEVICE_ID_VIA_82C586_0 << 16)))
	 ) {
	bridge = pci_dev;
	via_82c586 = &bridge;
#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
	/*
	 * Should print : bus = 0, device = 11, function = 0 on a MCP750.
	 */
	printk("Via PCI/ISA bridge found at bus = %d, device = %d, function = %d\n",
	       via_82c586->bus,
	       via_82c586->device,
	       via_82c586->function);
#endif
	found = 1;
	goto loop_exit;

      }
    }
  }
loop_exit:
  if (!found) BSP_panic("VIA_82C586 PCI/ISA bridge not found!n");

  tmp = inb(0x810);
  if  ( !(tmp & 0x2)) {
#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
    printk("This is a second generation MCP750 board\n");
    printk("We must reprogram the PCI/ISA bridge...\n");
#endif
    pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
			 0x47,  &tmp);
#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
    printk(" PCI ISA bridge control2 = %x\n", (unsigned) tmp);
#endif
    /*
     * Enable 4D0/4D1 ISA interrupt level/edge config registers
     */
    tmp |= 0x20;
    pci_write_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
			  0x47, tmp);
    /*
     * Now program the ISA interrupt edge/level
     */
    tmp = ELCRS_INT9_LVL | ELCRS_INT10_LVL | ELCRS_INT11_LVL;
    outb(tmp, ISA8259_S_ELCR);
    tmp = ELCRM_INT5_LVL;
    outb(tmp, ISA8259_M_ELCR);;
    /*
     * Set the Interrupt inputs to non-inverting level interrupt
     */
    pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
			    0x54, &tmp);
#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
    printk(" PCI ISA bridge PCI/IRQ Edge/Level Select = %x\n", (unsigned) tmp);
#endif
    tmp = 0;
    pci_write_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
			  0x54, tmp);
  }
  else {
#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
    printk("This is a first generation MCP750 board\n");
    printk("We just show the actual value used by PCI/ISA bridge\n");
#endif
    pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
			 0x47,  &tmp);
#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
    printk(" PCI ISA bridge control2 = %x\n", (unsigned) tmp);
#endif
    /*
     * Show the Interrupt inputs inverting/non-inverting level status
     */
    pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
			 0x54, &tmp);
#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
    printk(" PCI ISA bridge PCI/IRQ Edge/Level Select = %x\n", (unsigned) tmp);
#endif
  }
}
示例#11
0
文件: bspstart.c 项目: epicsdeb/rtems
void bsp_start( void )
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;
#if !defined(mvme2100)
  unsigned l2cr;
#endif
  uintptr_t intrStackStart;
  uintptr_t intrStackSize;
  ppc_cpu_id_t myCpu;
  ppc_cpu_revision_t myCpuRevision;
  prep_t boardManufacturer;
  motorolaBoard myBoard;
  Triv121PgTbl	pt=0;

  /*
   * Get CPU identification dynamically. Note that the get_ppc_cpu_type()
   * function store the result in global variables so that it can be used
   * later...
   */
  myCpu 	= get_ppc_cpu_type();
  myCpuRevision = get_ppc_cpu_revision();

  /*
   * Init MMU block address translation to enable hardware access
   */

#if !defined(mvme2100)
  /*
   * PC legacy IO space used for inb/outb and all PC compatible hardware
   */
  setdbat(1, _IO_BASE, _IO_BASE, 0x10000000, IO_PAGE);
#endif

  /*
   * PCI devices memory area. Needed to access OpenPIC features
   * provided by the Raven
   *
   * T. Straumann: give more PCI address space
   */
  setdbat(2, PCI_MEM_BASE+PCI_MEM_WIN0, PCI_MEM_BASE+PCI_MEM_WIN0, 0x10000000, IO_PAGE);

  /*
   * Must have acces to open pic PCI ACK registers provided by the RAVEN
   */
  setdbat(3, 0xf0000000, 0xf0000000, 0x10000000, IO_PAGE);

#if defined(mvme2100)
  /* Need 0xfec00000 mapped for this */
  EUMBBAR = get_eumbbar();
#endif

  /*
   * enables L1 Cache. Note that the L1_caches_enables() codes checks for
   * relevant CPU type so that the reason why there is no use of myCpu...
   */
  L1_caches_enables();

#if !defined(mvme2100)
  /*
   * Enable L2 Cache. Note that the set_L2CR(L2CR) codes checks for
   * relevant CPU type (mpc750)...
   */
  l2cr = get_L2CR();
#ifdef SHOW_LCR2_REGISTER
  printk("Initial L2CR value = %x\n", l2cr);
#endif
  if ( (! (l2cr & 0x80000000)) && ((int) l2cr == -1))
    set_L2CR(0xb9A14000);
#endif

  /*
   * Initialize the interrupt related settings.
   */
  intrStackStart = (uintptr_t) __rtems_end;
  intrStackSize = rtems_configuration_get_interrupt_stack_size();

  /*
   * Initialize default raw exception handlers.
   */
  sc = ppc_exc_initialize(
    PPC_INTERRUPT_DISABLE_MASK_DEFAULT,
    intrStackStart,
    intrStackSize
  );
  if (sc != RTEMS_SUCCESSFUL) {
    BSP_panic("cannot initialize exceptions");
  }

  select_console(CONSOLE_LOG);

  /*
   * We check that the keyboard is present and immediately
   * select the serial console if not.
   */
#if defined(BSP_KBD_IOBASE)
  { int err;
    err = kbdreset();
    if (err) select_console(CONSOLE_SERIAL);
  }
#else
  select_console(CONSOLE_SERIAL);
#endif

  boardManufacturer   =  checkPrepBoardType(&residualCopy);
  if (boardManufacturer != PREP_Motorola) {
    printk("Unsupported hardware vendor\n");
    while (1);
  }
  myBoard = getMotorolaBoard();

  printk("-----------------------------------------\n");
  printk("Welcome to %s on %s\n", _RTEMS_version,
                                    motorolaBoardToString(myBoard));
  printk("-----------------------------------------\n");
#ifdef SHOW_MORE_INIT_SETTINGS
  printk("Residuals are located at %x\n", (unsigned) &residualCopy);
  printk("Additionnal boot options are %s\n", loaderParam);
  printk("Initial system stack at %x\n",stack);
  printk("Software IRQ stack starts at %x with size %u\n", intrStackStart, intrStackSize);
  printk("-----------------------------------------\n");
#endif

#ifdef TEST_RETURN_TO_PPCBUG
  printk("Hit <Enter> to return to PPCBUG monitor\n");
  printk("When Finished hit GO. It should print <Back from monitor>\n");
  debug_getc();
  _return_to_ppcbug();
  printk("Back from monitor\n");
  _return_to_ppcbug();
#endif /* TEST_RETURN_TO_PPCBUG  */

#ifdef SHOW_MORE_INIT_SETTINGS
  printk("Going to start PCI buses scanning and initialization\n");
#endif

  pci_initialize();
  {
    const struct _int_map *bspmap  = motorolaIntMap(currentBoard);
    if( bspmap ) {
       printk("pci : Configuring interrupt routing for '%s'\n",
          motorolaBoardToString(currentBoard));
       FixupPCI(bspmap, motorolaIntSwizzle(currentBoard));
    }
    else
       printk("pci : Interrupt routing not available for this bsp\n");
 }

#ifdef SHOW_MORE_INIT_SETTINGS
  printk("Number of PCI buses found is : %d\n", pci_bus_count());
#endif
#ifdef TEST_RAW_EXCEPTION_CODE
  printk("Testing exception handling Part 1\n");
  /*
   * Cause a software exception
   */
  __asm__ __volatile ("sc");
  /*
   * Check we can still catch exceptions and return coorectly.
   */
  printk("Testing exception handling Part 2\n");
  __asm__ __volatile ("sc");

  /*
   * Somehow doing the above seems to clobber SPRG0 on the mvme2100.  The
   * interrupt disable mask is stored in SPRG0. Is this a problem?
   */
  ppc_interrupt_set_disable_mask( PPC_INTERRUPT_DISABLE_MASK_DEFAULT);

#endif

/* See above */

  BSP_mem_size            = residualCopy.TotalMemory;
  BSP_bus_frequency       = residualCopy.VitalProductData.ProcessorBusHz;
  BSP_processor_frequency = residualCopy.VitalProductData.ProcessorHz;
  BSP_time_base_divisor   = (residualCopy.VitalProductData.TimeBaseDivisor?
                    residualCopy.VitalProductData.TimeBaseDivisor : 4000);

  /* clear hostbridge errors but leave MCP disabled -
   * PCI config space scanning code will trip otherwise :-(
   */
  _BSP_clear_hostbridge_errors(0 /* enableMCP */, 0/*quiet*/);

  /* Allocate and set up the page table mappings
   * This is only available on >604 CPUs.
   *
   * NOTE: This setup routine may modify the available memory
   *       size. It is essential to call it before
   *       calculating the workspace etc.
   */
  pt = BSP_pgtbl_setup(&BSP_mem_size);

  if (!pt || TRIV121_MAP_SUCCESS != triv121PgTblMap(
            pt, TRIV121_121_VSID, 0xfeff0000, 1,
            TRIV121_ATTR_IO_PAGE, TRIV121_PP_RW_PAGE)) {
	printk("WARNING: unable to setup page tables VME "
               "bridge must share PCI space\n");
  }

  /*
   *  initialize the device driver parameters
   */
  bsp_clicks_per_usec 	 = BSP_bus_frequency/(BSP_time_base_divisor * 1000);

  /*
   * Initalize RTEMS IRQ system
   */
  BSP_rtems_irq_mng_init(0);

  /* Activate the page table mappings only after
   * initializing interrupts because the irq_mng_init()
   * routine needs to modify the text
   */
  if (pt) {
#ifdef  SHOW_MORE_INIT_SETTINGS
    printk("Page table setup finished; will activate it NOW...\n");
#endif
    BSP_pgtbl_activate(pt);
    /* finally, switch off DBAT3 */
    setdbat(3, 0, 0, 0, 0);
  }

#if defined(DEBUG_BATS)
  ShowBATS();
#endif

#ifdef SHOW_MORE_INIT_SETTINGS
  printk("Exit from bspstart\n");
#endif
}