Exemple #1
0
/*=========================================================================*\
| Function:                                                                 |
\*-------------------------------------------------------------------------*/
rtems_status_code m360_spi_init
(
/*-------------------------------------------------------------------------*\
| Purpose:                                                                  |
|   initialize the driver                                                   |
+---------------------------------------------------------------------------+
| Input Parameters:                                                         |
\*-------------------------------------------------------------------------*/
 rtems_libi2c_bus_t *bh                  /* bus specifier structure        */
)
/*-------------------------------------------------------------------------*\
| Return Value:                                                             |
|    o = ok or error code                                                   |
\*=========================================================================*/
{
  m360_spi_softc_t *softc_ptr = &(((m360_spi_desc_t *)(bh))->softc);
  rtems_status_code rc = RTEMS_SUCCESSFUL;

#if defined(DEBUG)
  printk("m360_spi_init called... ");
#endif
  /*
   * init HW registers:
   */
  /*
   * FIXME: set default mode in SPMODE
   */

  /*
   * allocate BDs (1x RX, 1x TX)
   */
  if (rc == RTEMS_SUCCESSFUL) {
    softc_ptr->rx_bd = M360AllocateBufferDescriptors (1);
    softc_ptr->tx_bd = M360AllocateBufferDescriptors (1);
    if ((softc_ptr->rx_bd == NULL) ||
	(softc_ptr->tx_bd == NULL)) {
      rc = RTEMS_NO_MEMORY;
    }
  }
  /*
   * set parameter RAM
   */
  m360.spip.rbase = (char *)softc_ptr->rx_bd - (char *)&m360;
  m360.spip.tbase = (char *)softc_ptr->tx_bd - (char *)&m360;
  m360.spip.rfcr  = M360_RFCR_MOT | M360_RFCR_DMA_SPACE;
  m360.spip.tfcr  = M360_RFCR_MOT | M360_RFCR_DMA_SPACE;
  m360.spip.mrblr = 2;

  /*
   * issue "InitRxTx" Command to CP
   */
  M360ExecuteRISC (M360_CR_OP_INIT_RX_TX | M360_CR_CHAN_SPI);

  /*
   * init interrupt stuff
   */
  if (rc == RTEMS_SUCCESSFUL) {
    m360_spi_install_irq_handler(softc_ptr,TRUE);
  }
  if (rc == RTEMS_SUCCESSFUL) {
    /*
     * set up ports
     * LINE      PAR  DIR  DAT
     * -----------------------
     * MOSI       1    1    x
     * MISO       1    1    x
     * CLK        1    1    x
     */

    /* set Port B Pin Assignment Register... */
    m360.pbpar =
      m360.pbpar
      | M360_PB_SPI_MISO_MSK
      | M360_PB_SPI_MOSI_MSK
      | M360_PB_SPI_CLK_MSK;

    /* set Port B Data Direction Register... */
    m360.pbdir =
      m360.pbdir
      | M360_PB_SPI_MISO_MSK
      | M360_PB_SPI_MOSI_MSK
      | M360_PB_SPI_CLK_MSK;
  }
  /*
   * mark, that we have initialized
   */
  if (rc == RTEMS_SUCCESSFUL) {
    softc_ptr->initialized = TRUE;
  }
#if defined(DEBUG)
  printk("... exit OK\r\n");
#endif
  return rc;
}
/*
 * Soak up buffer descriptors that have been sent
 * Note that a buffer descriptor can't be retired as soon as it becomes
 * ready.  The MC68360 Errata (May 96) says that, "If an Ethernet frame is
 *  made up of multiple buffers, the user should not reuse the first buffer
 * descriptor until the last buffer descriptor of the frame has had its
 * ready bit cleared by the CPM".
 */
static void
m360Enet_retire_tx_bd (struct scc_softc *sc)
{
	uint16_t         status;
	int i;
	int nRetired;
	struct mbuf *m, *n;
	int retries = 0;
	int saveStatus = 0;

	i = sc->txBdTail;
	nRetired = 0;
	while ((sc->txBdActiveCount != 0)
	   &&  (((status = (sc->txBdBase + i)->status) & M360_BD_READY) == 0)) {
		/*
		 * Check for errors which stop the transmitter.
		 */
		if (status & (M360_BD_LATE_COLLISION |
				M360_BD_RETRY_LIMIT |
				M360_BD_UNDERRUN)) {
			int j;

			if (status & M360_BD_LATE_COLLISION)
				sc->txLateCollision++;
			if (status & M360_BD_RETRY_LIMIT)
				sc->txRetryLimit++;
			if (status & M360_BD_UNDERRUN)
				sc->txUnderrun++;

			/*
			 * Reenable buffer descriptors
			 */
			j = sc->txBdTail;
			for (;;) {
				status = (sc->txBdBase + j)->status;
				if (status & M360_BD_READY)
					break;
				(sc->txBdBase + j)->status = M360_BD_READY |
					(status & (M360_BD_PAD |
						   M360_BD_WRAP |
						   M360_BD_INTERRUPT |
						   M360_BD_LAST |
						   M360_BD_TX_CRC));
				if (status & M360_BD_LAST)
					break;
				if (++j == sc->txBdCount)
					j = 0;
			}

			/*
			 * Move transmitter back to the first
			 * buffer descriptor in the frame.
			 */
			m360.scc1p._tbptr = m360.scc1p.tbase +
				sc->txBdTail * sizeof (m360BufferDescriptor_t);

			/*
			 * Restart the transmitter
			 */
			M360ExecuteRISC (M360_CR_OP_RESTART_TX | M360_CR_CHAN_SCC1);
			continue;
		}
		saveStatus |= status;
		retries += (status >> 2) & 0xF;
		nRetired++;
		if (status & M360_BD_LAST) {
			/*
			 * A full frame has been transmitted.
			 * Free all the associated buffer descriptors.
			 */
			if (saveStatus & M360_BD_DEFER)
				sc->txDeferred++;
			if (saveStatus & M360_BD_HEARTBEAT)
				sc->txHeartbeat++;
			if (saveStatus & M360_BD_CARRIER_LOST)
				sc->txLostCarrier++;
			saveStatus = 0;
			sc->txRetry += retries;
			retries = 0;
			sc->txBdActiveCount -= nRetired;
			while (nRetired) {
				nRetired--;
				m = sc->txMbuf[sc->txBdTail];
				MFREE (m, n);
				if (++sc->txBdTail == sc->txBdCount)
					sc->txBdTail = 0;
			}
		}
		if (++i == sc->txBdCount)
			i = 0;
	}
}
Exemple #3
0
static int
smc1Initialize (int major, int minor, void *arg)
{
  /*
   * Allocate buffer descriptors
   */
  smcRxBd = M360AllocateBufferDescriptors (1);
  smcTxBd = M360AllocateBufferDescriptors (1);

  /*
   * Configure port B pins to enable SMTXD1 and SMRXD1 pins
   */
  m360.pbpar |=  0xC0;
  m360.pbdir &= ~0xC0;
  m360.pbodr &= ~0xC0;

  /*
   * Set up BRG1 (9,600 baud)
   */
  m360.brgc1 = M360_BRG_RST;
  m360.brgc1 = smc1BRGC (console_baud_rate);

  /*
   * Put SMC1 in NMSI mode, connect SMC1 to BRG1
   */
  m360.simode |= M360_SI_SMC1_BRG1;

  /*
   * Set up SMC1 parameter RAM common to all protocols
   */
  m360.smc1p.rbase = (char *)smcRxBd - (char *)&m360;
  m360.smc1p.tbase = (char *)smcTxBd - (char *)&m360;
  m360.smc1p.rfcr = M360_RFCR_MOT | M360_RFCR_DMA_SPACE;
  m360.smc1p.tfcr = M360_TFCR_MOT | M360_TFCR_DMA_SPACE;
  if (m360_smc1_interrupt)
    m360.smc1p.mrblr = RXBUFSIZE;
  else
    m360.smc1p.mrblr = 1;

  /*
   * Set up SMC1 parameter RAM UART-specific parameters
   */
  m360.smc1p.un.uart.max_idl = 10;
  m360.smc1p.un.uart.brklen = 0;
  m360.smc1p.un.uart.brkec = 0;
  m360.smc1p.un.uart.brkcr = 0;

  /*
   * Set up the Receive Buffer Descriptor
   */
  smcRxBd->status = M360_BD_EMPTY | M360_BD_WRAP | M360_BD_INTERRUPT;
  smcRxBd->length = 0;
  smcRxBd->buffer = rxBuf;

  /*
   * Setup the Transmit Buffer Descriptor
   */
  smcTxBd->status = M360_BD_WRAP;

  /*
   * Set up SMC1 general and protocol-specific mode registers
   */
  m360.smc1.smce = ~0;  /* Clear any pending events */
  m360.smc1.smcm = 0;  /* Mask all interrupt/event sources */
  m360.smc1.smcmr = M360_SMCMR_CLEN(9) | M360_SMCMR_SM_UART;

  /*
   * Send "Init parameters" command
   */
  M360ExecuteRISC (M360_CR_OP_INIT_RX_TX | M360_CR_CHAN_SMC1);

  /*
   * Enable receiver and transmitter
   */
  m360.smc1.smcmr |= M360_SMCMR_TEN | M360_SMCMR_REN;

  if (m360_smc1_interrupt) {
  rtems_isr_entry old_handler;

  (void) rtems_interrupt_catch (smc1InterruptHandler,
            (m360.cicr & 0xE0) | 0x04,
            &old_handler);
  m360.smc1.smcm = 3;  /* Enable SMC1 TX and RX interrupts */
  m360.cimr |= 1UL << 4;  /* Enable SMC1 interrupts */
  }

  return 0;
}
/*
 * Initialize the ethernet hardware
 */
static void
m360Enet_initialize_hardware (struct scc_softc *sc)
{
	int i;
	unsigned char *hwaddr;
	rtems_status_code status;
	rtems_isr_entry old_handler;

	/*
	 * Configure port A CLK1, CLK2, TXD1 and RXD1 pins
	 */
	m360.papar |=  0x303;
	m360.padir &= ~0x303;
	m360.paodr &= ~0x303;

	/*
	 * Configure port C CTS1* and CD1* pins
	 */
	m360.pcpar &= ~0x30;
	m360.pcdir &= ~0x30;
	m360.pcso  |=  0x30;

	/*
	 * Connect CLK1 and CLK2 to SCC1
	 */
	m360.sicr &= ~0xFF;
	m360.sicr |= (5 << 3) | 4;

	/*
	 * Allocate mbuf pointers
	 */
	sc->rxMbuf = malloc (sc->rxBdCount * sizeof *sc->rxMbuf, M_MBUF, M_NOWAIT);
	sc->txMbuf = malloc (sc->txBdCount * sizeof *sc->txMbuf, M_MBUF, M_NOWAIT);
	if (!sc->rxMbuf || !sc->txMbuf)
		rtems_panic ("No memory for mbuf pointers");

	/*
	 * Set receiver and transmitter buffer descriptor bases
	 */
	sc->rxBdBase = M360AllocateBufferDescriptors(sc->rxBdCount);
	sc->txBdBase = M360AllocateBufferDescriptors(sc->txBdCount);
	m360.scc1p.rbase = (char *)sc->rxBdBase - (char *)&m360;
	m360.scc1p.tbase = (char *)sc->txBdBase - (char *)&m360;

	/*
	 * Send "Init parameters" command
	 */
	M360ExecuteRISC (M360_CR_OP_INIT_RX_TX | M360_CR_CHAN_SCC1);

	/*
	 * Set receive and transmit function codes
	 */
	m360.scc1p.rfcr = M360_RFCR_MOT | M360_RFCR_DMA_SPACE;
	m360.scc1p.tfcr = M360_TFCR_MOT | M360_TFCR_DMA_SPACE;

	/*
	 * Set maximum receive buffer length
	 */
	m360.scc1p.mrblr = RBUF_SIZE;

	/*
	 * Set CRC parameters
	 */
	m360.scc1p.un.ethernet.c_pres = 0xFFFFFFFF;
	m360.scc1p.un.ethernet.c_mask = 0xDEBB20E3;

	/*
	 * Clear diagnostic counters
	 */
	m360.scc1p.un.ethernet.crcec = 0;
	m360.scc1p.un.ethernet.alec = 0;
	m360.scc1p.un.ethernet.disfc = 0;

	/*
	 * Set pad value
	 */
	m360.scc1p.un.ethernet.pads = 0x8888;

	/*
	 * Set retry limit
	 */
	m360.scc1p.un.ethernet.ret_lim = 15;

	/*
	 * Set maximum and minimum frame length
	 */
	m360.scc1p.un.ethernet.mflr = 1518;
	m360.scc1p.un.ethernet.minflr = 64;
	m360.scc1p.un.ethernet.maxd1 = RBUF_SIZE;
	m360.scc1p.un.ethernet.maxd2 = RBUF_SIZE;

	/*
	 * Clear group address hash table
	 */
	m360.scc1p.un.ethernet.gaddr1 = 0;
	m360.scc1p.un.ethernet.gaddr2 = 0;
	m360.scc1p.un.ethernet.gaddr3 = 0;
	m360.scc1p.un.ethernet.gaddr4 = 0;

	/*
	 * Set our physical address
	 */
	hwaddr = sc->arpcom.ac_enaddr;
	m360.scc1p.un.ethernet.paddr_h = (hwaddr[5] << 8) | hwaddr[4];
	m360.scc1p.un.ethernet.paddr_m = (hwaddr[3] << 8) | hwaddr[2];
	m360.scc1p.un.ethernet.paddr_l = (hwaddr[1] << 8) | hwaddr[0];

	/*
	 * Aggressive retry
	 */
	m360.scc1p.un.ethernet.p_per = 0;

	/*
	 * Clear individual address hash table
	 */
	m360.scc1p.un.ethernet.iaddr1 = 0;
	m360.scc1p.un.ethernet.iaddr2 = 0;
	m360.scc1p.un.ethernet.iaddr3 = 0;
	m360.scc1p.un.ethernet.iaddr4 = 0;

	/*
	 * Set up receive buffer descriptors
	 */
	for (i = 0 ; i < sc->rxBdCount ; i++)
		(sc->rxBdBase + i)->status = 0;

	/*
	 * Set up transmit buffer descriptors
	 */
	for (i = 0 ; i < sc->txBdCount ; i++) {
		(sc->txBdBase + i)->status = 0;
		sc->txMbuf[i] = NULL;
	}
	sc->txBdHead = sc->txBdTail = 0;
	sc->txBdActiveCount = 0;

	/*
	 * Clear any outstanding events
	 */
	m360.scc1.scce = 0xFFFF;

	/*
	 * Set up interrupts
	 */
	status = rtems_interrupt_catch (m360Enet_interrupt_handler,
						(m360.cicr & 0xE0) | 0x1E,
						&old_handler);
	if (status != RTEMS_SUCCESSFUL)
		rtems_panic ("Can't attach M360 SCC1 interrupt handler: %s\n",
						rtems_status_text (status));
	m360.scc1.sccm = 0;	/* No interrupts unmasked till necessary */
	m360.cimr |= (1UL << 30);	/* Enable SCC1 interrupt */

	/*
	 * Set up General SCC Mode Register
	 * Ethernet configuration
	 */
	m360.scc1.gsmr_h = 0x0;
	m360.scc1.gsmr_l = 0x1088000c;

	/*
	 * Set up data synchronization register
	 * Ethernet synchronization pattern
	 */
	m360.scc1.dsr = 0xd555;

	/*
	 * Set up protocol-specific mode register
	 *	Heartbeat check
	 *	No force collision
	 *	Discard short frames
	 *	Individual address mode
	 *	Ethernet CRC
	 *	Not promisuous
	 *	Ignore/accept broadcast packets as specified
	 *	Normal backoff timer
	 *	No loopback
	 *	No input sample at end of frame
	 *	64-byte limit for late collision
	 *	Wait 22 bits before looking for start of frame delimiter
	 *	Disable full-duplex operation
	 */
	m360.scc1.psmr = 0x880A | (sc->acceptBroadcast ? 0 : 0x100);

	/*
	 * Enable the TENA (RTS1*) pin
	 */
#if (defined (M68360_ATLAS_HSB))
	m360.pbpar |= 0x1000;
	m360.pbdir |= 0x1000;
#else
	m360.pcpar |=  0x1;
	m360.pcdir &= ~0x1;
#endif
}
Exemple #5
0
/*
 * Initialize MC68360
 */
void _Init68360 (void)
{
  int i;
  rtems_isr_entry *vbr;
  unsigned long ramSize;

#if (defined (__mc68040__))
  volatile unsigned long *RamBase_p;

  RamBase_p = (volatile unsigned long *)&RamBase;

  /*
   *******************************************
   * Motorola 68040 and companion-mode 68360 *
   *******************************************
   */

  /*
   * Step 6: Is this a power-up reset?
   * For now we just ignore this and do *all* the steps
   * Someday we might want to:
   *  if (Hard, Loss of Clock, Power-up)
   *    Do all steps
   *  else if (Double bus fault, watchdog or soft reset)
   *    Skip to step 12
   *  else (must be a reset command)
   *    Skip to step 14
   */

  /*
   * Step 7: Deal with clock synthesizer
   * HARDWARE:
   *  Change if you're not using an external 25 MHz oscillator.
   */
  m360.clkocr = 0x83;  /* No more writes, full-power CLKO2 */
  m360.pllcr = 0xD000;  /* PLL, no writes, no prescale,
           no LPSTOP slowdown, PLL X1 */
  m360.cdvcr = 0x8000;  /* No more writes, no clock division */

  /*
   * Step 8: Initialize system protection
   *  Enable watchdog
   *  Watchdog causes system reset
   *  Next-to-slowest watchdog timeout (21 seconds with 25 MHz oscillator)
   *  Enable double bus fault monitor
   *  Enable bus monitor for external cycles
   *  1024 clocks for external timeout
   */
  m360.sypcr = 0xEC;

  /*
   * Step 9: Clear parameter RAM and reset communication processor module
   */
  for (i = 0 ; i < 192  ; i += sizeof (long)) {
    *((long *)((char *)&m360 + 0xC00 + i)) = 0;
    *((long *)((char *)&m360 + 0xD00 + i)) = 0;
    *((long *)((char *)&m360 + 0xE00 + i)) = 0;
    *((long *)((char *)&m360 + 0xF00 + i)) = 0;
  }
  M360ExecuteRISC (M360_CR_RST);

  /*
   * Step 10: Write PEPAR
   *  SINTOUT standard M68000 family interrupt level encoding
   *  CF1MODE=10 (BCLRO* output)
   *  No RAS1* double drive
   *  A31 - A28
   *  AMUX output
   *  CAS2* - CAS3*
   *  CAS0* - CAS1*
   *  CS7*
   *  AVEC*
   */
  m360.pepar = 0x3440;

  /*
   * Step 11: Remap Chip Select 0 (CS0*), set up GMR
   */
  /*
   * 512 addresses per DRAM page (256K DRAM chips)
   * 70 nsec DRAM
   * 180 nsec ROM (3 wait states)
   */
  m360.gmr = M360_GMR_RCNT(23) | M360_GMR_RFEN |
        M360_GMR_RCYC(0) | M360_GMR_PGS(1) |
        M360_GMR_DPS_32BIT | M360_GMR_NCS |
        M360_GMR_TSS40;
  m360.memc[0].br = (unsigned long)&_RomBase | M360_MEMC_BR_WP |
              M360_MEMC_BR_V;
  m360.memc[0].or = M360_MEMC_OR_WAITS(3) | M360_MEMC_OR_1MB |
            M360_MEMC_OR_32BIT;

  /*
   * Step 12: Initialize the system RAM
   */
  /*
   *  Set up option/base registers
   *    1M DRAM
   *    70 nsec DRAM
   *  Enable burst mode
   *  No parity checking
   *  Wait for chips to power up
   *  Perform 8 read cycles
   */
  ramSize = 1 * 1024 * 1024;
  m360.memc[1].or = M360_MEMC_OR_TCYC(0) |
          M360_MEMC_OR_1MB |
          M360_MEMC_OR_DRAM;
  m360.memc[1].br = (unsigned long)&RamBase |
          M360_MEMC_BR_BACK40 |
          M360_MEMC_BR_V;
  for (i = 0; i < 50000; i++)
    continue;
  for (i = 0; i < 8; ++i) {
    unsigned long rambase_value;
    rambase_value = *RamBase_p;
    (void) rambase_value; /* avoid set but not used warning */
  }

  /*
   * Step 13: Copy  the exception vector table to system RAM
   */
  m68k_get_vbr (vbr);
  for (i = 0; i < 256; ++i)
    M68Kvec[i] = vbr[i];
  m68k_set_vbr (M68Kvec);

  /*
   * Step 14: More system initialization
   * SDCR (Serial DMA configuration register)
   *  Enable SDMA during FREEZE
   *  Give SDMA priority over all interrupt handlers
   *  Set DMA arbiration level to 4
   * CICR (CPM interrupt configuration register):
   *  SCC1 requests at SCCa position
   *  SCC2 requests at SCCb position
   *  SCC3 requests at SCCc position
   *  SCC4 requests at SCCd position
   *  Interrupt request level 4
   *  Maintain original priority order
   *  Vector base 128
   *  SCCs priority grouped at top of table
   */
  m360.sdcr = M360_SDMA_SISM_7 | M360_SDMA_SAID_4;
  m360.cicr = (3 << 22) | (2 << 20) | (1 << 18) | (0 << 16) |
            (4 << 13) | (0x1F << 8) | (128);

  /*
   * Step 15: Set module configuration register
   *  Bus request MC68040 Arbitration ID 3
   *  Bus asynchronous timing mode (work around bug in Rev. B)
   *  Arbitration asynchronous timing mode
   *  Disable timers during FREEZE
   *  Disable bus monitor during FREEZE
   *  BCLRO* arbitration level 3
   *  No show cycles
   *  User/supervisor access
   *  Bus clear in arbitration ID level  3
   *  SIM60 interrupt sources higher priority than CPM
   */
  m360.mcr = 0x6000EC3F;

#elif (defined (M68360_ATLAS_HSB))
  /*
   ******************************************
   * Standalone Motorola 68360 -- ATLAS HSB *
   ******************************************
   */

  /*
   * Step 6: Is this a power-up reset?
   * For now we just ignore this and do *all* the steps
   * Someday we might want to:
   *  if (Hard, Loss of Clock, Power-up)
   *    Do all steps
   *  else if (Double bus fault, watchdog or soft reset)
   *    Skip to step 12
   *  else (must be a CPU32+ reset command)
   *    Skip to step 14
   */

  /*
   * Step 7: Deal with clock synthesizer
   * HARDWARE:
   *  Change if you're not using an external 25 MHz oscillator.
   */
  m360.clkocr = 0x8F;  /* No more writes, no clock outputs */
  m360.pllcr = 0xD000;  /* PLL, no writes, no prescale,
           no LPSTOP slowdown, PLL X1 */
  m360.cdvcr = 0x8000;  /* No more writes, no clock division */

  /*
   * Step 8: Initialize system protection
   *  Enable watchdog
   *  Watchdog causes system reset
   *  Next-to-slowest watchdog timeout (21 seconds with 25 MHz oscillator)
   *  Enable double bus fault monitor
   *  Enable bus monitor for external cycles
   *  1024 clocks for external timeout
   */
  m360.sypcr = 0xEC;

  /*
   * Step 9: Clear parameter RAM and reset communication processor module
   */
  for (i = 0 ; i < 192  ; i += sizeof (long)) {
    *((long *)((char *)&m360 + 0xC00 + i)) = 0;
    *((long *)((char *)&m360 + 0xD00 + i)) = 0;
    *((long *)((char *)&m360 + 0xE00 + i)) = 0;
    *((long *)((char *)&m360 + 0xF00 + i)) = 0;
  }
  M360ExecuteRISC (M360_CR_RST);

  /*
   * Step 10: Write PEPAR
   *  SINTOUT not used (CPU32+ mode)
   *  CF1MODE=00 (CONFIG1 input)
   *  RAS1* double drive
   *  WE0* - WE3*
   *  OE* output
   *  CAS2* - CAS3*
   *  CAS0* - CAS1*
   *  CS7*
   *  AVEC*
   * HARDWARE:
   *  Change if you are using a different memory configuration
   *  (static RAM, external address multiplexing, etc).
   */
  m360.pepar = 0x0180;

  /*
   * Step 11: Remap Chip Select 0 (CS0*), set up GMR
   */
  m360.gmr = M360_GMR_RCNT(12) | M360_GMR_RFEN |
        M360_GMR_RCYC(0) | M360_GMR_PGS(1) |
        M360_GMR_DPS_32BIT | M360_GMR_DWQ |
        M360_GMR_GAMX;
  m360.memc[0].br = (unsigned long)&_RomBase | M360_MEMC_BR_WP |
                M360_MEMC_BR_V;
  m360.memc[0].or = M360_MEMC_OR_WAITS(3) | M360_MEMC_OR_1MB |
              M360_MEMC_OR_8BIT;

  /*
   * Step 12: Initialize the system RAM
   */
  ramSize = 2 * 1024 * 1024;
  /* first bank 1MByte DRAM */
  m360.memc[1].or = M360_MEMC_OR_TCYC(2) | M360_MEMC_OR_1MB |
          M360_MEMC_OR_PGME | M360_MEMC_OR_DRAM;
  m360.memc[1].br = (unsigned long)&RamBase | M360_MEMC_BR_V;

  /* second bank 1MByte DRAM */
  m360.memc[2].or = M360_MEMC_OR_TCYC(2) | M360_MEMC_OR_1MB |
          M360_MEMC_OR_PGME | M360_MEMC_OR_DRAM;
  m360.memc[2].br = ((unsigned long)&RamBase + 0x100000) |
          M360_MEMC_BR_V;

  /* flash rom socket U6 on CS5 */
  m360.memc[5].br = (unsigned long)ATLASHSB_ROM_U6 | M360_MEMC_BR_WP |
                M360_MEMC_BR_V;
  m360.memc[5].or = M360_MEMC_OR_WAITS(2) | M360_MEMC_OR_512KB |
                M360_MEMC_OR_8BIT;

  /* CSRs on CS7 */
  m360.memc[7].or = M360_MEMC_OR_TCYC(4) | M360_MEMC_OR_64KB |
          M360_MEMC_OR_8BIT;
  m360.memc[7].br = ATLASHSB_ESR | 0x01;
  for (i = 0; i < 50000; i++)
    continue;
  for (i = 0; i < 8; ++i)
    *((volatile unsigned long *)(unsigned long)&RamBase);

  /*
   * Step 13: Copy  the exception vector table to system RAM
   */
  m68k_get_vbr (vbr);
  for (i = 0; i < 256; ++i)
    M68Kvec[i] = vbr[i];
  m68k_set_vbr (M68Kvec);

  /*
   * Step 14: More system initialization
   * SDCR (Serial DMA configuration register)
   *  Enable SDMA during FREEZE
   *  Give SDMA priority over all interrupt handlers
   *  Set DMA arbiration level to 4
   * CICR (CPM interrupt configuration register):
   *  SCC1 requests at SCCa position
   *  SCC2 requests at SCCb position
   *  SCC3 requests at SCCc position
   *  SCC4 requests at SCCd position
   *  Interrupt request level 4
   *  Maintain original priority order
   *  Vector base 128
   *  SCCs priority grouped at top of table
   */
  m360.sdcr = M360_SDMA_SISM_7 | M360_SDMA_SAID_4;
  m360.cicr = (3 << 22) | (2 << 20) | (1 << 18) | (0 << 16) |
            (4 << 13) | (0x1F << 8) | (128);

  /*
   * Step 15: Set module configuration register
   *  Disable timers during FREEZE
   *  Enable bus monitor during FREEZE
   *  BCLRO* arbitration level 3
   */

#elif defined(PGH360)
  /*
   * Step 6: Is this a power-up reset?
   * For now we just ignore this and do *all* the steps
   * Someday we might want to:
   *  if (Hard, Loss of Clock, Power-up)
   *    Do all steps
   *  else if (Double bus fault, watchdog or soft reset)
   *    Skip to step 12
   *  else (must be a CPU32+ reset command)
   *    Skip to step 14
   */

  /*
   * Step 7: Deal with clock synthesizer
   * HARDWARE:
   *  Change if you're not using an external 25 MHz oscillator.
   */
  m360.clkocr = 0x8e;  /* No more writes, CLKO1=1/3, CLKO2=off */
  /*
   * adjust crystal to average between 4.19 MHz and 4.00 MHz
   * reprogram pll
   */
  m360.pllcr = 0xA000+(24576000/((4000000+4194304)/2/128))-1;
          /* LPSTOP slowdown, PLL /128*??? */
  m360.cdvcr = 0x8000;  /* No more writes, no clock division */

  /*
   * Step 8: Initialize system protection
   *  Enable watchdog
   *  Watchdog causes system reset
   *  128 sec. watchdog timeout
   *  Enable double bus fault monitor
   *  Enable bus monitor external
   *  128 clocks for external timeout
   */
  m360.sypcr = 0xEF;
  /*
   * also initialize the SWP bit in PITR to 1
   */
  m360.pitr |= 0x0200;
  /*
   * and trigger SWSR twice to ensure, that interval starts right now
   */
  m360.swsr = 0x55;
  m360.swsr = 0xAA;
  m360.swsr = 0x55;
  m360.swsr = 0xAA;
  /*
   * Step 9: Clear parameter RAM and reset communication processor module
   */
  for (i = 0 ; i < 192  ; i += sizeof (long)) {
    *((long *)((char *)&m360 + 0xC00 + i)) = 0;
    *((long *)((char *)&m360 + 0xD00 + i)) = 0;
    *((long *)((char *)&m360 + 0xE00 + i)) = 0;
    *((long *)((char *)&m360 + 0xF00 + i)) = 0;
  }
  M360ExecuteRISC (M360_CR_RST);

  /*
   * Step 10: Write PEPAR
   *  SINTOUT not used (CPU32+ mode)
   *  CF1MODE=00 (CONFIG1 input)
   *  IPIPE1
   *  WE0-3
   *  OE* output
   *  CAS2* / CAS3*
   *  CAS0* / CAS1*
   *  CS7*
   *  AVEC*
   * HARDWARE:
   *  Change if you are using a different memory configuration
   *  (static RAM, external address multiplexing, etc).
   */
  m360.pepar = 0x0080;
  /*
   * Step 11: Remap Chip Select 0 (CS0*), set up GMR
   *  no DRAM support
   * HARDWARE:
   *  Change if you are using a different memory configuration
   */
  m360.gmr = M360_GMR_RCNT(23) | M360_GMR_RFEN      | M360_GMR_RCYC(0) |
       M360_GMR_PGS(6)   | M360_GMR_DPS_32BIT | M360_GMR_DWQ     |
             M360_GMR_GAMX;

  m360.memc[0].br = (unsigned long)&_RomBase | M360_MEMC_BR_WP |
              M360_MEMC_BR_V;
  m360.memc[0].or = M360_MEMC_OR_WAITS(3) | M360_MEMC_OR_512KB |
              M360_MEMC_OR_8BIT;

  /*
   * Step 12: Initialize the system RAM
   *  Set up option/base registers
   *    16 MB DRAM
   *    1 wait state
   * HARDWARE:
   *  Change if you are using a different memory configuration
   *      NOTE: no Page mode possible for EDO RAMs (?)
   */
  ramSize = 16 * 1024 * 1024;
  m360.memc[7].or = M360_MEMC_OR_TCYC(1)  | M360_MEMC_OR_16MB |
        M360_MEMC_OR_FCMC(0)  | /* M360_MEMC_OR_PGME | */
                          M360_MEMC_OR_32BIT    | M360_MEMC_OR_DRAM;
  m360.memc[7].br = (unsigned long)&RamBase | M360_MEMC_BR_V;

  /*
   * FIXME: here we should wait for 8 refresh cycles...
   */
  /*
   * Step 12a: test the ram, if wanted
   * FIXME: when do we call this?
   * -> only during firmware execution
   * -> perform intesive test only on request
   * -> ensure, that results are stored properly
   */
#if 0 /* FIXME: activate RAM tests again */
  {
    void *ram_base, *ram_end, *code_loc;
    extern char ramtest_start,ramtest_end;
    ram_base = &ramtest_start;
    ram_end  = &ramtest_end;
    code_loc = (void *)ramtest_exec;
    if ((ram_base < ram_end) &&
      !((ram_base <= code_loc) && (code_loc < ram_end))) {
      ramtest_exec(ram_base,ram_end);
    }
  }
#endif
  /*
   * Step 13: Copy  the exception vector table to system RAM
   */
  m68k_get_vbr (vbr);
  for (i = 0; i < 256; ++i)
    M68Kvec[i] = vbr[i];
  m68k_set_vbr (M68Kvec);

  /*
   * Step 14: More system initialization
   * SDCR (Serial DMA configuration register)
   *  Disable SDMA during FREEZE
   *  Give SDMA priority over all interrupt handlers
   *  Set DMA arbiration level to 4
   * CICR (CPM interrupt configuration register):
   *  SCC1 requests at SCCa position
   *  SCC2 requests at SCCb position
   *  SCC3 requests at SCCc position
   *  SCC4 requests at SCCd position
   *  Interrupt request level 4
   *  Maintain original priority order
   *  Vector base 128
   *  SCCs priority grouped at top of table
   */
  m360.sdcr = M360_SDMA_SISM_7 | M360_SDMA_SAID_4;
  m360.cicr = (3 << 22) | (2 << 20) | (1 << 18) | (0 << 16) |
            (4 << 13) | (0x1F << 8) | (128);

  /*
   * Step 15: Set module configuration register
   *  Disable timers during FREEZE
   *  Enable bus monitor during FREEZE
   *  BCLRO* arbitration level 3
   *  No show cycles
   *  User/supervisor access
   *  Bus clear interupt service level 7
   *  SIM60 interrupt sources higher priority than CPM
   */
  m360.mcr = 0x4C7F;

#elif (defined (GEN68360_WITH_SRAM))
   /*
    ***************************************************
    * Generic Standalone Motorola 68360               *
    *           As described in MC68360 User's Manual *
    * But uses SRAM instead of DRAM                   *
    *  CS0* - 512kx8 flash memory                     *
    *  CS1* - 512kx32 static RAM                      *
    *  CS2* - 512kx32 static RAM                      *
    ***************************************************
    */

   /*
    * Step 7: Deal with clock synthesizer
    * HARDWARE:
    * Change if you're not using an external oscillator which
    * oscillates at the system clock rate.
    */
   m360.clkocr = 0x8F;     /* No more writes, no clock outputs */
   m360.pllcr = 0xD000;    /* PLL, no writes, no prescale,
                              no LPSTOP slowdown, PLL X1 */
   m360.cdvcr = 0x8000;    /* No more writes, no clock division */

   /*
    * Step 8: Initialize system protection
    * Enable watchdog
    * Watchdog causes system reset
    * Next-to-slowest watchdog timeout (21 seconds with 25 MHz oscillator)
    * Enable double bus fault monitor
    * Enable bus monitor for external cycles
    * 1024 clocks for external timeout
    */
    m360.sypcr = 0xEC;

   /*
    * Step 9: Clear parameter RAM and reset communication processor module
    */
   for (i = 0 ; i < 192  ; i += sizeof (long)) {
      *((long *)((char *)&m360 + 0xC00 + i)) = 0;
      *((long *)((char *)&m360 + 0xD00 + i)) = 0;
      *((long *)((char *)&m360 + 0xE00 + i)) = 0;
      *((long *)((char *)&m360 + 0xF00 + i)) = 0;
   }
   M360ExecuteRISC (M360_CR_RST);

   /*
    * Step 10: Write PEPAR
    * SINTOUT not used (CPU32+ mode)
    * CF1MODE=00 (CONFIG1 input)
    * IPIPE1*
    * WE0* - WE3*
    * OE* output
    * CAS2* - CAS3*
    * CAS0* - CAS1*
    * CS7*
    * AVEC*
    * HARDWARE:
    * Change if you are using a different memory configuration
    * (static RAM, external address multiplexing, etc).
    */
   m360.pepar = 0x0080;

   /*
    * Step 11: Set up GMR
    *
    */
   m360.gmr = 0x0;

   /*
    * Step 11a: Remap 512Kx8 flash memory on CS0*
    * 2 wait states
    * Make it read-only for now
    */
   m360.memc[0].br = (unsigned long)&_RomBase | M360_MEMC_BR_WP |
                                                   M360_MEMC_BR_V;
   m360.memc[0].or = M360_MEMC_OR_WAITS(2) | M360_MEMC_OR_512KB |
                                                   M360_MEMC_OR_8BIT;
   /*
    * Step 12: Set up main memory
    * 512Kx32 SRAM on CS1*
    * 512Kx32 SRAM on CS2*
    * 0 wait states
    */
   ramSize = 4 * 1024 * 1024;
   m360.memc[1].br = (unsigned long)&RamBase | M360_MEMC_BR_V;
   m360.memc[1].or = M360_MEMC_OR_WAITS(0) | M360_MEMC_OR_2MB |
                                                   M360_MEMC_OR_32BIT;
   m360.memc[2].br = ((unsigned long)&RamBase + 0x200000) | M360_MEMC_BR_V;
   m360.memc[2].or = M360_MEMC_OR_WAITS(0) | M360_MEMC_OR_2MB |
                                                   M360_MEMC_OR_32BIT;
   /*
    * Step 13: Copy  the exception vector table to system RAM
    */
   m68k_get_vbr (vbr);
   for (i = 0; i < 256; ++i)
           M68Kvec[i] = vbr[i];
   m68k_set_vbr (M68Kvec);

   /*
    * Step 14: More system initialization
    * SDCR (Serial DMA configuration register)
    * Enable SDMA during FREEZE
    * Give SDMA priority over all interrupt handlers
    * Set DMA arbiration level to 4
    * CICR (CPM interrupt configuration register):
    * SCC1 requests at SCCa position
    * SCC2 requests at SCCb position
    * SCC3 requests at SCCc position
    * SCC4 requests at SCCd position
    * Interrupt request level 4
    * Maintain original priority order
    * Vector base 128
    * SCCs priority grouped at top of table
    */
   m360.sdcr = M360_SDMA_SISM_7 | M360_SDMA_SAID_4;
   m360.cicr = (3 << 22) | (2 << 20) | (1 << 18) | (0 << 16) |
                  (4 << 13) | (0x1F << 8) | (128);

   /*
    * Step 15: Set module configuration register
    * Disable timers during FREEZE
    * Enable bus monitor during FREEZE
    * BCLRO* arbitration level 3
    * No show cycles
    * User/supervisor access
    * Bus clear interrupt service level 7
    * SIM60 interrupt sources higher priority than CPM
    */
   m360.mcr = 0x4C7F;

#else
  volatile unsigned long *RamBase_p;

  RamBase_p = (volatile unsigned long *)&RamBase;
  /*
   ***************************************************
   * Generic Standalone Motorola 68360               *
   *           As described in MC68360 User's Manual *
   *           Atlas ACE360                          *
   ***************************************************
   */

  /*
   * Step 6: Is this a power-up reset?
   * For now we just ignore this and do *all* the steps
   * Someday we might want to:
   *  if (Hard, Loss of Clock, Power-up)
   *    Do all steps
   *  else if (Double bus fault, watchdog or soft reset)
   *    Skip to step 12
   *  else (must be a CPU32+ reset command)
   *    Skip to step 14
   */

  /*
   * Step 7: Deal with clock synthesizer
   * HARDWARE:
   *  Change if you're not using an external 25 MHz oscillator.
   */
  m360.clkocr = 0x8F;  /* No more writes, no clock outputs */
  m360.pllcr = 0xD000;  /* PLL, no writes, no prescale,
           no LPSTOP slowdown, PLL X1 */
  m360.cdvcr = 0x8000;  /* No more writes, no clock division */

  /*
   * Step 8: Initialize system protection
   *  Enable watchdog
   *  Watchdog causes system reset
   *  Next-to-slowest watchdog timeout (21 seconds with 25 MHz oscillator)
   *  Enable double bus fault monitor
   *  Enable bus monitor for external cycles
   *  1024 clocks for external timeout
   */
  m360.sypcr = 0xEC;

  /*
   * Step 9: Clear parameter RAM and reset communication processor module
   */
  for (i = 0 ; i < 192  ; i += sizeof (long)) {
    *((long *)((char *)&m360 + 0xC00 + i)) = 0;
    *((long *)((char *)&m360 + 0xD00 + i)) = 0;
    *((long *)((char *)&m360 + 0xE00 + i)) = 0;
    *((long *)((char *)&m360 + 0xF00 + i)) = 0;
  }
  M360ExecuteRISC (M360_CR_RST);

  /*
   * Step 10: Write PEPAR
   *  SINTOUT not used (CPU32+ mode)
   *  CF1MODE=00 (CONFIG1 input)
   *  RAS1* double drive
   *  WE0* - WE3*
   *  OE* output
   *  CAS2* - CAS3*
   *  CAS0* - CAS1*
   *  CS7*
   *  AVEC*
   * HARDWARE:
   *  Change if you are using a different memory configuration
   *  (static RAM, external address multiplexing, etc).
   */
  m360.pepar = 0x0180;

  /*
   * Step 11: Remap Chip Select 0 (CS0*), set up GMR
   *  32-bit DRAM
   *  Internal DRAM address multiplexing
   *  60 nsec DRAM
   *  180 nsec ROM (3 wait states)
   *  15.36 usec DRAM refresh interval
   *  The DRAM page size selection is not modified since this
   *  startup code may be running in a bootstrap PROM or in
   *  a program downloaded by the bootstrap PROM.
   */
  m360.gmr = (m360.gmr & 0x001C0000) | M360_GMR_RCNT(23) |
          M360_GMR_RFEN | M360_GMR_RCYC(0) |
          M360_GMR_DPS_32BIT | M360_GMR_NCS |
          M360_GMR_GAMX;
  m360.memc[0].br = (unsigned long)&_RomBase | M360_MEMC_BR_WP |
                M360_MEMC_BR_V;
  m360.memc[0].or = M360_MEMC_OR_WAITS(3) | M360_MEMC_OR_1MB |
              M360_MEMC_OR_8BIT;

  /*
   * Step 12: Initialize the system RAM
   * Do this only if the DRAM has not already been set up
   */
  if ((m360.memc[1].br & M360_MEMC_BR_V) == 0) {
    /*
     * Set up GMR DRAM page size, option and  base registers
     *  Assume 16Mbytes of DRAM
     *  60 nsec DRAM
     */
    m360.gmr = (m360.gmr & ~0x001C0000) | M360_GMR_PGS(5);
    m360.memc[1].or = M360_MEMC_OR_TCYC(0) |
            M360_MEMC_OR_16MB |
            M360_MEMC_OR_DRAM;
    m360.memc[1].br = (unsigned long)&RamBase | M360_MEMC_BR_V;

    /*
     * Wait for chips to power up
     *  Perform 8 read cycles
     */
    for (i = 0; i < 50000; i++)
      continue;
    for (i = 0; i < 8; ++i)
      *RamBase_p;

    /*
     * Determine memory size (1, 4, or 16 Mbytes)
     * Set GMR DRAM page size appropriately.
     * The OR is left at 16 Mbytes.  The bootstrap PROM places its
     * .data and .bss segments at the top of the 16 Mbyte space.
     * A 1 Mbyte or 4 Mbyte DRAM will show up several times in
     * the memory map, but will work with the same bootstrap PROM.
     */
    *(volatile char *)&RamBase = 0;
    *((volatile char *)&RamBase+0x00C01800) = 1;
    if (*(volatile char *)&RamBase) {
      m360.gmr = (m360.gmr & ~0x001C0000) | M360_GMR_PGS(1);
    }
    else {
      *((volatile char *)&RamBase+0x00801000) = 1;
      if (*(volatile char *)&RamBase) {
        m360.gmr = (m360.gmr & ~0x001C0000) | M360_GMR_PGS(3);
      }
    }

    /*
     * Enable parity checking
     */
    m360.memc[1].br |= M360_MEMC_BR_PAREN;
  }
  switch (m360.gmr & 0x001C0000) {
  default:    ramSize =  4 * 1024 * 1024;  break;
  case M360_GMR_PGS(1):  ramSize =  1 * 1024 * 1024;  break;
  case M360_GMR_PGS(3):  ramSize =  4 * 1024 * 1024;  break;
  case M360_GMR_PGS(5):  ramSize = 16 * 1024 * 1024;  break;
  }

  /*
   * Step 13: Copy  the exception vector table to system RAM
   */
  m68k_get_vbr (vbr);
  for (i = 0; i < 256; ++i)
    M68Kvec[i] = vbr[i];
  m68k_set_vbr (M68Kvec);

  /*
   * Step 14: More system initialization
   * SDCR (Serial DMA configuration register)
   *  Enable SDMA during FREEZE
   *  Give SDMA priority over all interrupt handlers
   *  Set DMA arbiration level to 4
   * CICR (CPM interrupt configuration register):
   *  SCC1 requests at SCCa position
   *  SCC2 requests at SCCb position
   *  SCC3 requests at SCCc position
   *  SCC4 requests at SCCd position
   *  Interrupt request level 4
   *  Maintain original priority order
   *  Vector base 128
   *  SCCs priority grouped at top of table
   */
  m360.sdcr = M360_SDMA_SISM_7 | M360_SDMA_SAID_4;
  m360.cicr = (3 << 22) | (2 << 20) | (1 << 18) | (0 << 16) |
            (4 << 13) | (0x1F << 8) | (128);

  /*
   * Step 15: Set module configuration register
   *  Disable timers during FREEZE
   *  Enable bus monitor during FREEZE
   *  BCLRO* arbitration level 3
   *  No show cycles
   *  User/supervisor access
   *  Bus clear interrupt service level 7
   *  SIM60 interrupt sources higher priority than CPM
   */
  m360.mcr = 0x4C7F;
#endif

  /*
   * Copy data, clear BSS, switch stacks and call main()
   * Must pass ramSize as argument since the data/bss segment
   * may be overwritten.
   */
  _CopyDataClearBSSAndStart (ramSize);
}