Patches by Pantelis Antoniou, 16 Apr 2004:
- add support for a new version of an Intracom board and fix
  various other things on others.
- add verify support to the crc32 command (define
  CONFIG_CRC32_VERIFY to enable it)
- fix FEC driver for MPC8xx systems:
  1. fix compilation problems for boards that use dynamic
     allocation of DPRAM
  2. shut down FEC after network transfers
- HUSH parser fixes:
  1. A new test command was added. This is a simplified version of
     the one in the bourne shell.
  2. A new exit command was added which terminates the current
     executing script.
  3. Fixed handing of $? (exit code of last executed command)
diff --git a/cpu/mpc8xx/fec.c b/cpu/mpc8xx/fec.c
index b7603da..6d1b178 100644
--- a/cpu/mpc8xx/fec.c
+++ b/cpu/mpc8xx/fec.c
@@ -60,22 +60,22 @@
 {
 	int ether_index;
 	int fecp_offset;
-	int bd_offset;
 	int phy_addr;
 	int actual_phy_addr;
+	int initialized;
 }
 	ether_fcc_info[] = {
 #if defined(CONFIG_ETHER_ON_FEC1)
 	{
 		0,
 		offsetof(immap_t, im_cpm.cp_fec1),
-		CPM_FEC_BASE,
 #if defined(CONFIG_FEC1_PHY)
 		CONFIG_FEC1_PHY,
 #else
 		-1,	/* discover */
 #endif
 		-1,
+		0,
 
 	},
 #endif
@@ -83,13 +83,13 @@
 	{
 		1,
 		offsetof(immap_t, im_cpm.cp_fec2),
-		CPM_FEC_BASE + 0x50,
 #if defined(CONFIG_FEC2_PHY)
 		CONFIG_FEC2_PHY,
 #else
 		-1,
 #endif
 		-1,
+		0,
 	},
 #endif
 };
@@ -383,6 +383,11 @@
 	 */
 	fecp->fec_mii_speed = ((bd->bi_intfreq + 4999999) / 5000000) << 1;
 
+#if defined(CONFIG_NETTA) || defined(CONFIG_NETPHONE)
+	/* our PHYs are the limit at 2.5 MHz */
+	fecp->fec_mii_speed <<= 1;
+#endif
+
 #if defined(CONFIG_DUET) && defined(WANT_MII)
 	/* use MDC for MII */
 	immr->im_ioport.iop_pdpar |=  0x0080;
@@ -695,6 +700,14 @@
 		efis->actual_phy_addr = efis->phy_addr;
 	}
 #if defined(CONFIG_MII) && defined(CONFIG_RMII)
+
+	/* the MII interface is connected to FEC1
+	   so for the miiphy_xxx function to work we must 
+	   call mii_init since fec_halt messes the thing up */
+
+	if (efis->ether_index != 0)
+		mii_init();
+
 	/*
 	 * adapt the RMII speed to the speed of the phy
 	 */
@@ -719,25 +732,43 @@
 	/* And last, try to fill Rx Buffer Descriptors */
 	fecp->fec_r_des_active = 0x01000000;	/* Descriptor polling active    */
 
+	efis->initialized = 1;
+
 	return 1;
 }
 
 
 static void fec_halt(struct eth_device* dev)
 {
-#if 0
-	volatile immap_t *immr = (immap_t *)CFG_IMMR;
-	immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-#endif
-}
+	struct ether_fcc_info_s *efis = dev->priv;
+	volatile fec_t *fecp = (volatile fec_t *)(CFG_IMMR + efis->fecp_offset);
+	int i;
 
-#if 0
-void restart(void)
-{
-	volatile immap_t *immr = (immap_t *)CFG_IMMR;
-	immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+	/* avoid halt if initialized; mii gets stuck otherwise */
+	if (!efis->initialized)
+		return;
+
+	/* Whack a reset.
+	 * A delay is required between a reset of the FEC block and
+	 * initialization of other FEC registers because the reset takes
+	 * some time to complete. If you don't delay, subsequent writes
+	 * to FEC registers might get killed by the reset routine which is
+	 * still in progress.
+	 */
+
+	fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET;
+	for (i = 0;
+	     (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);
+	     ++i) {
+		udelay (1);
+	}
+	if (i == FEC_RESET_DELAY) {
+		printf ("FEC_RESET_DELAY timeout\n");
+		return;
+	}
+
+	efis->initialized = 0;
 }
-#endif
 
 #if defined(CFG_DISCOVER_PHY) || defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
 
@@ -781,14 +812,20 @@
 {
 	uint mii_reply;
 	volatile fec_t	*ep;
+	int cnt;
 
 	ep = &(((immap_t *)CFG_IMMR)->im_cpm.cp_fec);
 
 	ep->fec_mii_data = mii_cmd;	/* command to phy */
 
 	/* wait for mii complete */
-	while (!(ep->fec_ievent & FEC_ENET_MII))
-		;	/* spin until done */
+	cnt = 0;
+	while (!(ep->fec_ievent & FEC_ENET_MII)) {
+		if (++cnt > 1000) {
+			printf("mii_send STUCK!\n");
+			break;
+		}
+	}
 	mii_reply = ep->fec_mii_data;		/* result from phy */
 	ep->fec_ievent = FEC_ENET_MII;		/* clear MII complete */
 #if 0
@@ -870,8 +907,6 @@
 
 #if (defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)) && !defined(CONFIG_BITBANGMII)
 
-static int mii_init_done = 0;
-
 /****************************************************************************
  * mii_init -- Initialize the MII for MII command without ethernet
  * This function is a subset of eth_init
@@ -883,10 +918,6 @@
 	volatile fec_t *fecp = &(immr->im_cpm.cp_fec);
 	int i, j;
 
-	if (mii_init_done != 0) {
-		return;
-	}
-
 	for (j = 0; j < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); j++) {
 
 	/* Whack a reset.
@@ -924,8 +955,6 @@
 	 */
 	fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN;
 	}
-
-	mii_init_done = 1;
 }
 
 /*****************************************************************************