changeset 435:a6484a9a16c6

Improve generalized support for MPC/QUICC based platforms
author gthomas
date Mon, 25 Nov 2002 23:20:50 +0000
parents c4fa19c99259
children f44d40e6cdd3
files packages/devs/eth/powerpc/mbx/current/ChangeLog packages/devs/eth/powerpc/mbx/current/cdl/mbx_eth_drivers.cdl packages/devs/eth/powerpc/mbx/current/include/mbx_eth.inl packages/devs/eth/powerpc/quicc/current/ChangeLog packages/devs/eth/powerpc/quicc/current/src/if_quicc.c packages/devs/eth/powerpc/quicc/current/src/quicc_eth.h packages/hal/powerpc/mbx/current/ChangeLog packages/hal/powerpc/mbx/current/cdl/hal_powerpc_mbx.cdl packages/hal/powerpc/mpc8xx/current/ChangeLog packages/hal/powerpc/mpc8xx/current/include/var_regs.h packages/hal/powerpc/quicc/current/ChangeLog packages/hal/powerpc/quicc/current/cdl/hal_powerpc_quicc.cdl packages/hal/powerpc/quicc/current/include/ppc8xx.h packages/hal/powerpc/quicc/current/src/quicc_smc1.c packages/hal/powerpc/ts1000/current/ChangeLog packages/hal/powerpc/ts1000/current/cdl/hal_powerpc_ts1000.cdl packages/hal/powerpc/ts1000/current/src/ts1000.S packages/hal/powerpc/viper/current/ChangeLog packages/hal/powerpc/viper/current/cdl/hal_powerpc_viper.cdl packages/hal/powerpc/viper/current/src/viper.S
diffstat 20 files changed, 704 insertions(+), 322 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/packages/devs/eth/powerpc/mbx/current/ChangeLog
@@ -0,0 +1,44 @@
+2002-11-25  Gary Thomas  <gthomas@ecoscentric.com>
+
+	* include/mbx_eth.inl: 
+	* cdl/mbx_eth_drivers.cdl: New package - platform specifics for
+	Motorola MBX (PowerPC 860) board.
+
+//===========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2002 Gary Thomas
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
+	
+	
+
new file mode 100644
--- /dev/null
+++ b/packages/devs/eth/powerpc/mbx/current/cdl/mbx_eth_drivers.cdl
@@ -0,0 +1,69 @@
+#====================================================================
+#
+#      mbx_eth_drivers.cdl
+#
+#      Hardware specifics for Motorola MBX ethernet
+#
+#====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+## Copyright (C) 2002 Gary Thomas
+##
+## eCos is free software; you can redistribute it and/or modify it under
+## the terms of the GNU General Public License as published by the Free
+## Software Foundation; either version 2 or (at your option) any later version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+## WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License along
+## with eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+## at http://sources.redhat.com/ecos/ecos-license/
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):      gthomas, hmt
+# Original data:  gthomas
+# Contributors:   gthomas
+# Date:           2001-02-14
+#
+#####DESCRIPTIONEND####
+#
+#====================================================================
+
+cdl_package CYGPKG_DEVS_ETH_POWERPC_MBX {
+    display       "Motorola MBX (MPC8xxT) ethernet support"
+    description   "Hardware specifics for Motorola MBX ethernet"
+
+    parent        CYGPKG_IO_ETH_DRIVERS
+    active_if	  CYGPKG_IO_ETH_DRIVERS
+    active_if	  CYGPKG_HAL_POWERPC 
+    active_if	  CYGPKG_HAL_POWERPC_MPC8xx
+    active_if	  CYGPKG_HAL_POWERPC_MBX
+
+    requires      CYGPKG_DEVS_ETH_POWERPC_QUICC
+
+    include_dir   cyg/io
+    define_proc {
+        puts $::cdl_system_header "#define CYGDAT_DEVS_QUICC_ETH_INL <cyg/io/mbx_eth.inl>"
+    }
+}
new file mode 100644
--- /dev/null
+++ b/packages/devs/eth/powerpc/mbx/current/include/mbx_eth.inl
@@ -0,0 +1,99 @@
+#ifndef CYGONCE_DEVS_MBX_ETH_INL
+#define CYGONCE_DEVS_MBX_ETH_INL
+//==========================================================================
+//
+//      mbx_eth.inl
+//
+//      Hardware specifics for Motorola MBX ethernet support
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2002 Gary Thomas
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    gthomas
+// Contributors: gthomas
+// Date:         2002-11-19
+// Purpose:      
+// Description:  
+//              
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#define _get_led()  
+#define _set_led(v) 
+
+#define LED_TxACTIVE  7
+#define LED_RxACTIVE  6
+#define LED_IntACTIVE 5
+
+#if 0
+// Fetch ESA from on-board EEPROM
+extern int _mbx_fetch_VPD(int, void *, int);
+#define QUICC_ETH_FETCH_ESA(_ok_)                              \
+     _ok_ = _mbx_fetch_VPD(VPD_ETHERNET_ADDRESS, enaddr, sizeof(enaddr));
+#endif
+
+// Reset/enable any external hardware
+#define QUICC_ETH_ENABLE()                                     \
+    *MBX_CTL1 = MBX_CTL1_ETEN | MBX_CTL1_TPEN;  /* Enable ethernet, TP mode */
+
+
+// Port layout - uses SCC1
+#define QUICC_ETH_PA_RXD            0x0001  // Rx Data on Port A
+#define QUICC_ETH_PA_TXD            0x0002  // Tx Data on Port A
+#define QUICC_ETH_PA_Tx_CLOCK       0x0200  // Tx Clock = CLK2
+#define QUICC_ETH_PA_Rx_CLOCK       0x0800  // Rx Clock = CLK4
+#define QUICC_ETH_PC_Tx_ENABLE      0x0001  // Tx Enable (TENA)
+#define QUICC_ETH_PC_COLLISION      0x0010  // Collision detect
+#define QUICC_ETH_PC_Rx_ENABLE      0x0020  // Rx Enable (RENA)
+#define QUICC_ETH_SICR_MASK         0x00FF  // SI Clock Route - important bits
+#define QUICC_ETH_SICR_ENET  (7<<3)|(5<<0)  //   Rx=CLK4, Tx=CLK2
+#define QUICC_ETH_SICR_ENABLE       0x0040  // Enable SCC1 to use NMSI
+#define QUICC_ETH_INT               CYGNUM_HAL_INTERRUPT_CPM_SCC1
+#define QUICC_ETH_SCC               0       // SCC1
+#define QUICC_CPM_SCCx              QUICC_CPM_SCC1
+
+#define MBX_CTL1   (cyg_uint8 *)0xFA100000  // System control register
+#define MBX_CTL1_ETEN                 0x80  // 1 = Enable ethernet tranceiver
+#define MBX_CTL1_ELEN                 0x40  // 1 = Enable ethernet loopback
+#define MBX_CTL1_EAEN                 0x20  // 1 = Auto select ethernet interface
+#define MBX_CTL1_TPEN                 0x10  // 0 = AUI, 1 = TPI
+#define MBX_CTL1_FDDIS                0x08  // 1 = Disable full duplex (if TP mode)
+
+
+#endif  // CYGONCE_DEVS_MBX_ETH_INL
+// ------------------------------------------------------------------------
--- a/packages/devs/eth/powerpc/quicc/current/ChangeLog
+++ b/packages/devs/eth/powerpc/quicc/current/ChangeLog
@@ -1,3 +1,8 @@
+2002-11-25  Gary Thomas  <gthomas@ecoscentric.com>
+
+	* src/quicc_eth.h: 
+	* src/if_quicc.c: Split platform specifics into separate packages.
+
 2002-08-08  Gary Thomas  <gthomas@ecoscentric.com>
 2002-08-08  Luoqi Chen <lchen@onetta.com>
 
--- a/packages/devs/eth/powerpc/quicc/current/src/if_quicc.c
+++ b/packages/devs/eth/powerpc/quicc/current/src/if_quicc.c
@@ -130,7 +130,28 @@ NETDEVTAB_ENTRY(quicc_netdev,
                 quicc_eth_init, 
                 &quicc_eth0_sc);
 
-extern int _mbx_fetch_VPD(int, void *, int);
+// LED activity [exclusive of hardware bits]
+#ifndef _get_led
+#define _get_led()  
+#define _set_led(v) 
+#endif
+#ifndef LED_TxACTIVE
+#define LED_TxACTIVE  7
+#define LED_RxACTIVE  6
+#define LED_IntACTIVE 5
+#endif
+
+static void
+set_led(int bit)
+{
+  _set_led(_get_led() | (1<<bit));
+}
+
+static void
+clear_led(int bit)
+{
+  _set_led(_get_led() & ~(1<<bit));
+}
 
 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
 static cyg_interrupt quicc_eth_interrupt;
@@ -143,8 +164,8 @@ static void          quicc_eth_int(struc
 static int
 quicc_eth_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs)
 {
-    cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_CPM_SCC1);
-    cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_CPM_SCC1);
+    cyg_drv_interrupt_mask(QUICC_ETH_INT);
+    cyg_drv_interrupt_acknowledge(QUICC_ETH_INT);
     return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR);  // Run the DSR
 }
 #endif
@@ -156,7 +177,7 @@ quicc_eth_deliver(struct eth_drv_sc * sc
     quicc_eth_int(sc);
 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
     // Allow interrupts to happen again
-    cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_CPM_SCC1);
+    cyg_drv_interrupt_unmask(QUICC_ETH_INT);
 #endif
 }
 
@@ -178,11 +199,13 @@ quicc_eth_init(struct cyg_netdevtab_entr
     int TxBD, RxBD;
     int cache_state;
     int i;
-    bool esa_ok;
+    bool esa_ok = false;
 
-    // Fetch the board address from the VPD
-#define VPD_ETHERNET_ADDRESS 0x08
-    if (_mbx_fetch_VPD(VPD_ETHERNET_ADDRESS, enaddr, sizeof(enaddr)) == 0) {
+#ifdef QUICC_ETH_FETCH_ESA
+    QUICC_ETH_FETCH_ESA(esa_ok);
+#endif
+
+    if (!esa_ok) {
 #if defined(CYGPKG_REDBOOT) && \
     defined(CYGSEM_REDBOOT_FLASH_CONFIG)
         esa_ok = flash_get_config("quicc_esa", enaddr, CONFIG_ESA);
@@ -204,7 +227,7 @@ quicc_eth_init(struct cyg_netdevtab_entr
 
 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
     // Set up to handle interrupts
-    cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_CPM_SCC1,
+    cyg_drv_interrupt_create(QUICC_ETH_INT,
                              CYGARC_SIU_PRIORITY_HIGH,
                              (cyg_addrword_t)sc, //  Data item passed to interrupt handler
                              (cyg_ISR_t *)quicc_eth_isr,
@@ -212,20 +235,20 @@ quicc_eth_init(struct cyg_netdevtab_entr
                              &quicc_eth_interrupt_handle,
                              &quicc_eth_interrupt);
     cyg_drv_interrupt_attach(quicc_eth_interrupt_handle);
-    cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_CPM_SCC1);
-    cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_CPM_SCC1);
+    cyg_drv_interrupt_acknowledge(QUICC_ETH_INT);
+    cyg_drv_interrupt_unmask(QUICC_ETH_INT);
 #endif
 
-    qi->pram = enet_pram = &eppc->pram[0].enet_scc;
-    qi->ctl = scc = &eppc->scc_regs[0];  // Use SCC1
+    qi->pram = enet_pram = &eppc->pram[QUICC_ETH_SCC].enet_scc;
+    qi->ctl = scc = &eppc->scc_regs[QUICC_ETH_SCC];  // Use SCCx
 
     // Shut down ethernet, in case it is already running
     scc->scc_gsmr_l &= ~(QUICC_SCC_GSML_ENR | QUICC_SCC_GSML_ENT);
 
     memset((void *)enet_pram, 0, sizeof(*enet_pram));
 
-    TxBD = 0x2C00;  // FIXME
-    RxBD = TxBD + CYGNUM_DEVS_ETH_POWERPC_QUICC_TxNUM * sizeof(struct cp_bufdesc);
+    TxBD = cyg_hal_allocBd(CYGNUM_DEVS_ETH_POWERPC_QUICC_TxNUM * sizeof(struct cp_bufdesc));
+    RxBD = cyg_hal_allocBd(CYGNUM_DEVS_ETH_POWERPC_QUICC_RxNUM * sizeof(struct cp_bufdesc));
 
     txbd = (struct cp_bufdesc *)((char *)eppc + TxBD);
     rxbd = (struct cp_bufdesc *)((char *)eppc + RxBD);
@@ -235,6 +258,7 @@ quicc_eth_init(struct cyg_netdevtab_entr
     qi->rbase = rxbd;
     qi->rxbd = rxbd;
     qi->rnext = rxbd;
+    qi->txactive = 0;
 
     RxBUF = &quicc_eth_rxbufs[0][0];
     TxBUF = &quicc_eth_txbufs[0][0];
@@ -259,22 +283,22 @@ quicc_eth_init(struct cyg_netdevtab_entr
     txbd--;
     txbd->ctrl |= QUICC_BD_CTL_Wrap;  // Last buffer
 
-    // Set up parallel ports for connection to MC68160 ethernet tranceiver
-    eppc->pio_papar |= (QUICC_MBX_PA_RXD | QUICC_MBX_PA_TXD);
-    eppc->pio_padir &= ~(QUICC_MBX_PA_RXD | QUICC_MBX_PA_TXD);
-    eppc->pio_paodr &= ~QUICC_MBX_PA_TXD;
+    // Set up parallel ports for connection to ethernet tranceiver
+    eppc->pio_papar |= (QUICC_ETH_PA_RXD | QUICC_ETH_PA_TXD);
+    eppc->pio_padir &= ~(QUICC_ETH_PA_RXD | QUICC_ETH_PA_TXD);
+    eppc->pio_paodr &= ~QUICC_ETH_PA_TXD;
 
-    eppc->pio_pcpar &= ~(QUICC_MBX_PC_COLLISION | QUICC_MBX_PC_Rx_ENABLE);
-    eppc->pio_pcdir &= ~(QUICC_MBX_PC_COLLISION | QUICC_MBX_PC_Rx_ENABLE);
-    eppc->pio_pcso  |= (QUICC_MBX_PC_COLLISION | QUICC_MBX_PC_Rx_ENABLE);
+    eppc->pio_pcpar &= ~(QUICC_ETH_PC_COLLISION | QUICC_ETH_PC_Rx_ENABLE);
+    eppc->pio_pcdir &= ~(QUICC_ETH_PC_COLLISION | QUICC_ETH_PC_Rx_ENABLE);
+    eppc->pio_pcso  |= (QUICC_ETH_PC_COLLISION | QUICC_ETH_PC_Rx_ENABLE);
 
-    eppc->pio_papar |= (QUICC_MBX_PA_Tx_CLOCK | QUICC_MBX_PA_Rx_CLOCK);
-    eppc->pio_padir &= ~(QUICC_MBX_PA_Tx_CLOCK | QUICC_MBX_PA_Rx_CLOCK);
+    eppc->pio_papar |= (QUICC_ETH_PA_Tx_CLOCK | QUICC_ETH_PA_Rx_CLOCK);
+    eppc->pio_padir &= ~(QUICC_ETH_PA_Tx_CLOCK | QUICC_ETH_PA_Rx_CLOCK);
 
     // Set up clock routing
-    eppc->si_sicr &= ~QUICC_MBX_SICR_MASK;
-    eppc->si_sicr |= QUICC_MBX_SICR_ENET;
-    eppc->si_sicr &= ~QUICC_MBX_SICR_SCC1_ENABLE;
+    eppc->si_sicr &= ~QUICC_ETH_SICR_MASK;
+    eppc->si_sicr |= QUICC_ETH_SICR_ENET;
+    eppc->si_sicr &= ~QUICC_ETH_SICR_ENABLE;
 
     // Set up DMA mode
     eppc->dma_sdcr = 0x0001;
@@ -339,7 +363,7 @@ quicc_eth_init(struct cyg_netdevtab_entr
     enet_pram->taddr_l = 0;
 
     // Initialize the CPM (set up buffer pointers, etc).
-    eppc->cp_cr = QUICC_CPM_SCC1 | QUICC_CPM_CR_INIT_TXRX | QUICC_CPM_CR_BUSY;
+    eppc->cp_cr = QUICC_CPM_SCCx | QUICC_CPM_CR_INIT_TXRX | QUICC_CPM_CR_BUSY;
     while (eppc->cp_cr & QUICC_CPM_CR_BUSY) ;
 
     // Clear any pending interrupt/exceptions
@@ -348,7 +372,7 @@ quicc_eth_init(struct cyg_netdevtab_entr
     // Enable interrupts
     scc->scc_sccm = QUICC_SCCE_INTS;
 
-    // Set up SCC1 to run in ethernet mode
+    // Set up SCCx to run in ethernet mode
     scc->scc_gsmr_h = 0;
     scc->scc_gsmr_l = QUICC_SCC_GSML_TCI | QUICC_SCC_GSML_TPL_48 |
         QUICC_SCC_GSML_TPP_01 | QUICC_SCC_GSML_MODE_ENET;
@@ -360,12 +384,22 @@ quicc_eth_init(struct cyg_netdevtab_entr
     scc->scc_psmr = QUICC_PMSR_ENET_CRC | QUICC_PMSR_SEARCH_AFTER_22 |
         QUICC_PMSR_RCV_SHORT_FRAMES;
 
-    // Configure board interface
-    *MBX_CTL1 = MBX_CTL1_ETEN | MBX_CTL1_TPEN;  // Enable ethernet, TP mode
+#ifdef QUICC_ETH_ENABLE
+    QUICC_ETH_ENABLE();
+#endif
+
+#ifdef QUICC_ETH_RESET_PHY
+    QUICC_ETH_RESET_PHY();
+#endif
 
     // Enable ethernet interface
-    eppc->pio_pcpar |= QUICC_MBX_PC_Tx_ENABLE;
-    eppc->pio_pcdir &= ~QUICC_MBX_PC_Tx_ENABLE;
+#ifdef QUICC_ETH_PC_Tx_ENABLE
+    eppc->pio_pcpar |= QUICC_ETH_PC_Tx_ENABLE;
+    eppc->pio_pcdir &= ~QUICC_ETH_PC_Tx_ENABLE;
+#else
+    eppc->pip_pbpar |= QUICC_ETH_PB_Tx_ENABLE;
+    eppc->pip_pbdir |= QUICC_ETH_PB_Tx_ENABLE;
+#endif
 
     if (cache_state)
         HAL_DCACHE_ENABLE();
@@ -373,6 +407,10 @@ quicc_eth_init(struct cyg_netdevtab_entr
     // Initialize upper level driver
     (sc->funs->eth_drv->init)(sc, (unsigned char *)&enaddr);
 
+    // Set LED state
+    clear_led(LED_TxACTIVE);
+    clear_led(LED_RxACTIVE);
+
     return true;
 }
 
@@ -431,9 +469,8 @@ static int
 quicc_eth_can_send(struct eth_drv_sc *sc)
 {
     struct quicc_eth_info *qi = (struct quicc_eth_info *)sc->driver_private;
-    volatile struct cp_bufdesc *txbd = qi->txbd;
 
-    return ((txbd->ctrl & QUICC_BD_CTL_Ready) == 0);
+    return (qi->txactive < CYGNUM_DEVS_ETH_POWERPC_QUICC_TxNUM);
 }
 
 //
@@ -480,7 +517,7 @@ quicc_eth_send(struct eth_drv_sc *sc, st
         memcpy((void *)bp, (void *)sg_list[i].buf, sg_list[i].len);
         bp += sg_list[i].len;
     }
-    // Note: the MBX860 does not seem to snoop/invalidate the data cache properly!
+    // Note: the MPC8xx does not seem to snoop/invalidate the data cache properly!
     HAL_DCACHE_IS_ENABLED(cache_state);
     if (cache_state) {
         HAL_DCACHE_FLUSH(txbd->buffer, txbd->length);  // Make sure no stale data
@@ -492,6 +529,8 @@ quicc_eth_send(struct eth_drv_sc *sc, st
     }
     txbd->ctrl = ctrl | QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int | 
         QUICC_BD_TX_LAST | QUICC_BD_TX_TC;
+    qi->txactive++;
+    set_led(LED_TxACTIVE);
 }
 
 //
@@ -510,7 +549,9 @@ quicc_eth_RxEvent(struct eth_drv_sc *sc)
     rxbd = qi->rnext;
     while ((rxbd->ctrl & (QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int)) == QUICC_BD_CTL_Int) {
         qi->rxbd = rxbd;  // Save for callback
+        set_led(LED_RxACTIVE);
         (sc->funs->eth_drv->recv)(sc, rxbd->length);
+        clear_led(LED_RxACTIVE);
         rxbd->ctrl |= QUICC_BD_CTL_Ready;
         if (rxbd->ctrl & QUICC_BD_CTL_Wrap) {
             rxbd = qi->rbase;
@@ -537,7 +578,7 @@ quicc_eth_recv(struct eth_drv_sc *sc, st
     int i, cache_state;
 
     bp = (unsigned char *)qi->rxbd->buffer;
-    // Note: the MBX860 does not seem to snoop/invalidate the data cache properly!
+    // Note: the MPC8xx does not seem to snoop/invalidate the data cache properly!
     HAL_DCACHE_IS_ENABLED(cache_state);
     if (cache_state) {
         HAL_DCACHE_INVALIDATE(qi->rxbd->buffer, qi->rxbd->length);  // Make sure no stale data
@@ -567,6 +608,9 @@ quicc_eth_TxEvent(struct eth_drv_sc *sc,
         } else {
             txbd++;
         }
+	if (--qi->txactive == 0) {
+	  clear_led(LED_TxACTIVE);
+	}
     }
     // Remember where we left off
     qi->tnext = (struct cp_bufdesc *)txbd;
@@ -599,5 +643,5 @@ quicc_eth_int(struct eth_drv_sc *sc)
 static int          
 quicc_eth_int_vector(struct eth_drv_sc *sc)
 {
-    return (CYGNUM_HAL_INTERRUPT_CPM_SCC1);
+    return (QUICC_ETH_INT);
 }
--- a/packages/devs/eth/powerpc/quicc/current/src/quicc_eth.h
+++ b/packages/devs/eth/powerpc/quicc/current/src/quicc_eth.h
@@ -9,6 +9,7 @@
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2002 Gary Thomas
 //
 // eCos is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free
@@ -72,6 +73,7 @@ struct quicc_eth_info {
     struct cp_bufdesc              *tbase, *rbase;   // First Tx,Rx descriptor
     struct cp_bufdesc              *tnext, *rnext;   // Next descriptor to check for interrupt
     int                             txsize, rxsize;  // Length of individual buffers
+    int                             txactive;        // Count of active Tx buffers
     unsigned long                   txkey[CYGNUM_DEVS_ETH_POWERPC_QUICC_TxNUM];
 };
 
@@ -155,24 +157,7 @@ struct quicc_eth_info {
 #define QUICC_BD_TX_UN              0x0002  // Tx underrun
 #define QUICC_BD_TX_CSL             0x0001  // Carrier lost
 
-// MBX specific "wiring" - aux connections to MX68160 Ethernet support chip
-#define QUICC_MBX_PA_RXD            0x0001  // Rx Data on Port A
-#define QUICC_MBX_PA_TXD            0x0002  // Tx Data on Port A
-#define QUICC_MBX_PA_Tx_CLOCK       0x0200  // Tx Clock = CLK2
-#define QUICC_MBX_PA_Rx_CLOCK       0x0800  // Rx Clock = CLK4
-#define QUICC_MBX_PC_Tx_ENABLE      0x0001  // Tx Enable (TENA)
-#define QUICC_MBX_PC_COLLISION      0x0010  // Collision detect
-#define QUICC_MBX_PC_Rx_ENABLE      0x0020  // Rx Enable (RENA)
-#define QUICC_MBX_SICR_MASK         0x00FF  // SI Clock Route - important bits
-#define QUICC_MBX_SICR_ENET  (7<<3)|(5<<0)  //   Rx=CLK4, Tx=CLK2
-#define QUICC_MBX_SICR_SCC1_ENABLE  0x0040  // Enable SCC1 to use NMSI
-
-#define MBX_CTL1   (cyg_uint8 *)0xFA100000  // System control register
-#define MBX_CTL1_ETEN                 0x80  // 1 = Enable ethernet tranceiver
-#define MBX_CTL1_ELEN                 0x40  // 1 = Enable ethernet loopback
-#define MBX_CTL1_EAEN                 0x20  // 1 = Auto select ethernet interface
-#define MBX_CTL1_TPEN                 0x10  // 0 = AUI, 1 = TPI
-#define MBX_CTL1_FDDIS                0x08  // 1 = Disable full duplex (if TP mode)
+#include CYGDAT_DEVS_QUICC_ETH_INL  // Platform specifics
 
 #define IEEE_8023_MAX_FRAME         1518    // Largest possible ethernet frame
 #define IEEE_8023_MIN_FRAME           64    // Smallest possible ethernet frame
--- a/packages/hal/powerpc/mbx/current/ChangeLog
+++ b/packages/hal/powerpc/mbx/current/ChangeLog
@@ -1,3 +1,7 @@
+2002-11-25  Gary Thomas  <gthomas@ecoscentric.com>
+
+	* cdl/hal_powerpc_mbx.cdl: Add new CDL which describes port layout.
+
 2002-08-02  Andrew Lunn <Andrew.Lunn@ascom.ch>
 
 	* cdl/hal_powerpc_mbx.cdl: Redboot exec command can now be disabled 
--- a/packages/hal/powerpc/mbx/current/cdl/hal_powerpc_mbx.cdl
+++ b/packages/hal/powerpc/mbx/current/cdl/hal_powerpc_mbx.cdl
@@ -9,6 +9,7 @@
 ## -------------------------------------------
 ## This file is part of eCos, the Embedded Configurable Operating System.
 ## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+## Copyright (C) 2002 Gary Thomas
 ##
 ## eCos is free software; you can redistribute it and/or modify it under
 ## the terms of the GNU General Public License as published by the Free
@@ -64,9 +65,11 @@ cdl_package CYGPKG_HAL_POWERPC_MBX {
     implements    CYGINT_HAL_DEBUG_GDB_STUBS
     implements    CYGINT_HAL_DEBUG_GDB_STUBS_BREAK
     implements    CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT
+    implements    CYGNUM_HAL_QUICC_SMC1
 
     define_proc {
         puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H   <pkgconf/hal_powerpc_mpc8xx.h>"
+        puts $::cdl_system_header "#define CYGBLD_HAL_VARIANT_H  <pkgconf/hal_powerpc_quicc.h>"
         puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_H <pkgconf/hal_powerpc_mbx.h>"
 
 	puts $::cdl_header "#define HAL_PLATFORM_CPU    \"PowerPC 860\""
@@ -114,51 +117,6 @@ cdl_package CYGPKG_HAL_POWERPC_MBX {
            or stub ROMs."
    }
 
-   cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS {
-       display      "Number of communication channels on the board"
-       flavor       data
-       calculated   1
-   }
-
-   cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL {
-       display          "Debug serial port"
-       active_if        CYGPRI_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_CONFIGURABLE
-       flavor data
-       legal_values     0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1
-       default_value    0
-       description      "
-           The MBX board has only one serial port. This option
-           chooses which port will be used to connect to a host
-           running GDB."
-    }
-
-    cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL {
-        display          "Diagnostic serial port"
-        active_if        CYGPRI_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_CONFIGURABLE
-        flavor data
-        legal_values     0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1
-        default_value    0
-        description      "
-           The MBX board has only one serial port.  This option
-           chooses which port will be used for diagnostic output."
-    }
-
-    # This option is only used when USE_ROM_MONITOR is enabled - but
-    # it cannot be a sub-option to that option, since the code uses the
-    # definition in a preprocessor comparison.
-    cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_ROM_DEBUG_CHANNEL {
-        display          "Debug serial port used by ROM monitor"
-        flavor data
-        legal_values     0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1
-        default_value    0
-        description      "
-            The MBX board has only one serial port.  This
-            option tells the code which port is in use by the ROM
-            monitor. It should only be necessary to change this
-            option if a non-standard configurated eCos GDB stub is
-            used."
-    }
-
     # Real-time clock/counter specifics
     cdl_component CYGNUM_HAL_RTC_CONSTANTS {
         display       "Real-time clock constants."
--- a/packages/hal/powerpc/mpc8xx/current/ChangeLog
+++ b/packages/hal/powerpc/mpc8xx/current/ChangeLog
@@ -1,3 +1,7 @@
+2002-11-25  Gary Thomas  <gthomas@ecoscentric.com>
+
+	* include/var_regs.h: Add CICR definitions.
+
 2002-11-15  Gary Thomas  <gthomas@ecoscentric.com>
 
 	* src/var_misc.c: Change in API for profile callback.
--- a/packages/hal/powerpc/mpc8xx/current/include/var_regs.h
+++ b/packages/hal/powerpc/mpc8xx/current/include/var_regs.h
@@ -12,6 +12,7 @@
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2002 Gary Thomas
 //
 // eCos is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free
@@ -331,6 +332,8 @@
 #define CYGARC_REG_IMM_CICR_IRQMASK 0x0000e000     // irq priority mask
 #define CYGARC_REG_IMM_CICR_IRQ_SHIFT 13
 
+// CPM interrupt in-pending register
+#define CYGARC_REG_IMM_CIPR        (CYGARC_REG_IMM_BASE + 0x944)
 // CPM interrupt mask register
 #define CYGARC_REG_IMM_CIMR        (CYGARC_REG_IMM_BASE + 0x948)
 // CPM interrupt in-service register
--- a/packages/hal/powerpc/quicc/current/ChangeLog
+++ b/packages/hal/powerpc/quicc/current/ChangeLog
@@ -1,3 +1,10 @@
+2002-11-25  Gary Thomas  <gthomas@ecoscentric.com>
+
+	* src/quicc_smc1.c: Support any combination of SMC1/SMC2 and
+	SCC1/SCC2/SCC3 [or at least lay foundation for it]
+
+	* cdl/hal_powerpc_quicc.cdl: Add more controls over port layout.
+
 2002-07-18  Gary Thomas  <gary@chez-thomas.org>
 
 	* src/quicc_smc1.c (cyg_hal_scc1_init_channel): Fix init which
--- a/packages/hal/powerpc/quicc/current/cdl/hal_powerpc_quicc.cdl
+++ b/packages/hal/powerpc/quicc/current/cdl/hal_powerpc_quicc.cdl
@@ -59,9 +59,23 @@ cdl_package CYGPKG_HAL_QUICC {
            The QUICC package provides some of the support needed
            to run eCos on a Motorola MPC8xx (MBX) board, using the QUICC
            feature of the MPC860 and MPC821 CPUs.
-           Currently only serial IO via SMC1 and SCC1 is provided by
+           Currently only serial IO via SMC1/2 and SCC1 is provided by
            this package."
 
+    cdl_interface CYGNUM_HAL_QUICC_SMC1 {
+        display    "SMC1 is available for serial I/O"
+        description "
+          This interface indicates that SMC1 can be outfitted as
+          a serial device."
+    }
+
+    cdl_interface CYGNUM_HAL_QUICC_SMC2 {
+        display    "SMC2 is available for serial I/O"
+        description "
+          This interface indicates that SMC2 can be outfitted as
+          a serial device."
+    }
+
     cdl_interface CYGNUM_HAL_QUICC_SCC1 {
         display    "SCC1 is available for serial I/O"
         description "
@@ -70,8 +84,63 @@ cdl_package CYGPKG_HAL_QUICC {
         serial since there is a separate ethernet machine."
     }
 
+    cdl_interface CYGNUM_HAL_QUICC_SCC2 {
+        display    "SCC2 is available for serial I/O"
+        description "
+          Port SCC2 is available for serial I/O"
+    }
+
+    cdl_interface CYGNUM_HAL_QUICC_SCC3 {
+        display    "SCC3 is available for serial I/O"
+        description "
+          Port SCC3 is available for serial I/O"
+    }
+
     compile       quicc_smc1.c
 
+   cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS {
+       display      "Number of communication channels on the board"
+       flavor       data
+       calculated   CYGNUM_HAL_QUICC_SMC1+CYGNUM_HAL_QUICC_SMC2+CYGNUM_HAL_QUICC_SCC1+CYGNUM_HAL_QUICC_SCC2+CYGNUM_HAL_QUICC_SCC3
+   }
+
+   cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL {
+       display          "Debug serial port"
+       active_if        CYGPRI_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_CONFIGURABLE
+       flavor data
+       legal_values     0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1
+       default_value    0
+       description      "
+           This option chooses which port will be used to connect to a host
+           via the GDB remote protocol."
+    }
+
+    cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL {
+        display          "Diagnostic serial port"
+        active_if        CYGPRI_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_CONFIGURABLE
+        flavor data
+        legal_values     0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1
+        default_value    0
+        description      "
+           This option chooses which port will be used for diagnostic output."
+    }
+
+    # This option is only used when USE_ROM_MONITOR is enabled - but
+    # it cannot be a sub-option to that option, since the code uses the
+    # definition in a preprocessor comparison.
+    cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_ROM_DEBUG_CHANNEL {
+        display          "Debug serial port used by ROM monitor"
+        flavor data
+        legal_values     0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1
+        default_value    0
+        description      "
+            If a platform has multiple serial ports, then this
+            option tells the code which port is in use by the ROM
+            monitor. It should only be necessary to change this
+            option if a non-standard configurated eCos GDB stub is
+            used."
+    }
+
     cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD {
         display       "Baud rate for the HAL diagnostic port"
         flavor        data
--- a/packages/hal/powerpc/quicc/current/include/ppc8xx.h
+++ b/packages/hal/powerpc/quicc/current/include/ppc8xx.h
@@ -107,6 +107,8 @@
 
 #else
 
+#include <cyg/infra/cyg_type.h>
+
 /*****************************************************************
 	Communications Processor Buffer Descriptor
 *****************************************************************/
@@ -935,6 +937,12 @@ static inline EPPC *eppc_base(void)
 }
 
 
+// Function used to allocate space in shared memory area
+// typically used for buffer descriptors, etc.
+__externC unsigned short cyg_hal_allocBd(int len);
+
+#define QUICC_BD_BASE               0x2000  // Start of shared memory
+
 
 #endif /* __ASSEMBLER__ */
 
--- a/packages/hal/powerpc/quicc/current/src/quicc_smc1.c
+++ b/packages/hal/powerpc/quicc/current/src/quicc_smc1.c
@@ -2,7 +2,7 @@
 //
 //      quicc_smc1.c
 //
-//      PowerPC QUICC basic Serial IO using port SMC1/SCC1
+//      PowerPC QUICC basic Serial IO using port(s) SMC1/SMC2/SCC1/SCC2/SCC3
 //
 //==========================================================================
 //####ECOSGPLCOPYRIGHTBEGIN####
@@ -46,11 +46,9 @@
 // Date:         1999-06-08
 // Purpose:      Provide basic Serial IO for MPC8xx boards (like Motorola MBX)
 // Description:  Serial IO for MPC8xx boards which connect their debug channel
-//               to SMC1 or SCC1; or any QUICC user who wants to use SMC1/SCC1
+//               to SMCx or SCCx; or any QUICC user who wants to use SMCx/SCCx
 // Usage:
-// Notes:        The driver hooks itself up on procs channel 0. This should
-//               probably be made configurable, allowing the platform
-//               to specify location.
+// Notes:        
 //
 //####DESCRIPTIONEND####
 //
@@ -82,10 +80,9 @@
 // Note: buffers will be placed just after descriptors
 // Sufficient space should be provided between descrptors
 // for the buffers (single characters)
+
 struct port_info {
-    int                         Txbd;    // Offset to Tx descriptors
     int                         Txnum;   // Number of Tx buffers
-    int                         Rxbd;    // Offset to Rx descriptors
     int                         Rxnum;   // Number of Rx buffers
     int                         intnum;  // Interrupt bit
     int                         timeout; // Timeout in msec
@@ -93,19 +90,40 @@ struct port_info {
     int                         regs;    // [Pointer] to control registers
     volatile struct cp_bufdesc *next_rxbd;
     int                         irq;     // Interrupt state
+    int                         init;    // Has port been initialized?
 };
 
 static struct port_info ports[] = {
-    { 0x2800, 1, 0x2810, 4, CYGNUM_HAL_INTERRUPT_CPM_SMC1, 1000,
+#if CYGNUM_HAL_QUICC_SMC1 > 0
+    { 1, 4, CYGNUM_HAL_INTERRUPT_CPM_SMC1, 1000,
       (int)&((EPPC *)0)->pram[2].scc.pothers.smc_modem.psmc.u, 
       (int)&((EPPC *)0)->smc_regs[0]
     }, 
+#endif
+#if CYGNUM_HAL_QUICC_SMC2 > 0
+    { 1, 4, CYGNUM_HAL_INTERRUPT_CPM_SMC2_PIP, 1000,
+      (int)&((EPPC *)0)->pram[3].scc.pothers.smc_modem.psmc.u, 
+      (int)&((EPPC *)0)->smc_regs[1]
+    }, 
+#endif
 #if CYGNUM_HAL_QUICC_SCC1 > 0
-    { 0x2700, 1, 0x2710, 4, CYGNUM_HAL_INTERRUPT_CPM_SCC1, 1000,
+    { 1, 4, CYGNUM_HAL_INTERRUPT_CPM_SCC1, 1000,
       (int)&((EPPC *)0)->pram[0].scc.pscc.u, 
       (int)&((EPPC *)0)->scc_regs[0]
     },
 #endif
+#if CYGNUM_HAL_QUICC_SCC2 > 0
+    { 1, 4, CYGNUM_HAL_INTERRUPT_CPM_SCC2, 1000,
+      (int)&((EPPC *)0)->pram[1].scc.pscc.u, 
+      (int)&((EPPC *)0)->scc_regs[1]
+    },
+#endif
+#if CYGNUM_HAL_QUICC_SCC3 > 0
+    { 1, 4, CYGNUM_HAL_INTERRUPT_CPM_SCC3, 1000,
+      (int)&((EPPC *)0)->pram[2].scc.pscc.u, 
+      (int)&((EPPC *)0)->scc_regs[2]
+    },
+#endif
 };
 
 // SMC Events (interrupts)
@@ -117,6 +135,9 @@ static struct port_info ports[] = {
 /*
  * Reset the communications processor
  */
+
+static short nextBd;
+
 static void
 reset_cpm(void)
 {
@@ -128,19 +149,37 @@ reset_cpm(void)
     init_done++;
 
     eppc->cp_cr = QUICC_CPM_CR_RESET | QUICC_CPM_CR_BUSY;
+    memset(eppc->pram, 0, 0x400);
     for (i = 0; i < 100000; i++);
 
+    nextBd = QUICC_BD_BASE;
+
 }
 
+//
+// Allocate a chunk of memory in the shared CPM memory, typically
+// used for buffer descriptors, etc.  The length will be aligned
+// to a multiple of 8 bytes.
+//
+unsigned short
+cyg_hal_allocBd(int len)
+{
+    unsigned short bd = nextBd;
+
+    len = (len + 7) & ~7;  // Multiple of 8 bytes
+    nextBd += len;
+    return bd;
+}
+
 /*
- *  Initialize SMC1 as a uart.
+ *  Initialize SMCX as a uart.
  *
  *  Comments below reference Motorola's "MPC860 User Manual".
  *  The basic initialization steps are from Section 16.15.8
  *  of that manual.
  */	
 static void
-cyg_hal_smc1_init_channel(struct port_info *info)
+cyg_hal_smcx_init_channel(struct port_info *info, int port)
 {
     EPPC *eppc = eppc_base();
     int i;
@@ -148,35 +187,61 @@ cyg_hal_smc1_init_channel(struct port_in
     volatile struct smc_regs *regs = (volatile struct smc_regs *)((char *)eppc + info->regs);
     struct cp_bufdesc *txbd, *rxbd;
 
-    static int init_done = 0;
-    if (init_done) return;
-    init_done++;
+    if (info->init) return;
+    info->init = 1;
 
     reset_cpm();
 
-    /*
-     *  Set up the PortB pins for UART operation.
-     *  Set PAR and DIR to allow SMCTXD1 and SMRXD1
-     *  (Table 16-39)
-     */
-    eppc->pip_pbpar |= 0xc0;
-    eppc->pip_pbdir &= ~0xc0;
+    switch (port) {
+#if CYGNUM_HAL_QUICC_SMC1 > 0
+    case QUICC_CPM_SMC1:
+        /*
+         *  Set up the PortB pins for UART operation.
+         *  Set PAR and DIR to allow SMCTXD1 and SMRXD1
+         *  (Table 16-39)
+         */
+        eppc->pip_pbpar |= 0xc0;
+        eppc->pip_pbdir &= ~0xc0;
+
+        /* Configure baud rate generator (Section 16.13.2) */
+        eppc->brgc1 = 0x10000 | (UART_BIT_RATE(UART_BAUD_RATE)<<1);
 
-    /* Configure baud rate generator (Section 16.13.2) */
-    eppc->brgc1 = 0x10000 | (UART_BIT_RATE(UART_BAUD_RATE)<<1);
+        /*
+         *  NMSI mode, BRG1 to SMC1
+         *  (Section 16.12.5.2)
+         */
+        eppc->si_simode = 0;
+        break;
+#endif
+#if CYGNUM_HAL_QUICC_SMC2 > 0
+    case QUICC_CPM_SMC2:
+        /*
+         *  Set up the PortA pins for UART operation.
+         *  Set PAR and DIR to allow SMCTXD2 and SMRXD2
+         *  (Table 16-39)
+         */
+        eppc->pio_papar |= 0xc0;
+        eppc->pio_padir &= ~0xc0;
+        eppc->pio_paodr &= ~0xc0;
 
-    /*
-     *  NMSI mode, BRG1 to SMC1
-     *  (Section 16.12.5.2)
-     */
-    eppc->si_simode = 0;
+        /* Configure baud rate generator (Section 16.13.2) */
+        eppc->brgc1 = 0x10000 | (UART_BIT_RATE(UART_BAUD_RATE)<<1);
+
+        /*
+         *  NMSI mode, BRG1 to SMC2
+         *  (Section 16.12.5.2)
+         */
+        eppc->si_simode = 0x00000000;
+        break;
+#endif
+    }
 
     /*
      *  Set pointers to buffer descriptors.
      *  (Sections 16.15.4.1, 16.15.7.12, and 16.15.7.13)
      */
-    uart_pram->rbase = info->Rxbd;
-    uart_pram->tbase = info->Txbd;
+    uart_pram->rbase = cyg_hal_allocBd(sizeof(struct cp_bufdesc)*info->Rxnum + info->Rxnum);
+    uart_pram->tbase = cyg_hal_allocBd(sizeof(struct cp_bufdesc)*info->Txnum + info->Txnum);
 
     /*
      *  SDMA & LCD bus request level 5
@@ -207,25 +272,21 @@ cyg_hal_smc1_init_channel(struct port_in
     uart_pram->brkcr = 1;
 
     /* setup RX buffer descriptors */
-    rxbd = (struct cp_bufdesc *)((char *)eppc + info->Rxbd);
+    rxbd = (struct cp_bufdesc *)((char *)eppc + uart_pram->rbase);
     info->next_rxbd = rxbd;
     for (i = 0;  i < info->Rxnum;  i++) {
         rxbd->length = 0;
-        rxbd->buffer = ((char *)eppc + (info->Rxbd+(info->Rxnum*sizeof(struct cp_bufdesc))))+i;
+        rxbd->buffer = ((char *)eppc + (uart_pram->rbase+(info->Rxnum*sizeof(struct cp_bufdesc))))+i;
         rxbd->ctrl   = QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int;
-        if (i == ((info->Rxnum)-1)) {
-            rxbd->ctrl   |= QUICC_BD_CTL_Wrap;
-        }
         rxbd++;
     }
-    // Compiler bug: for whatever reason, the Wrap code above fails!
-    rxbd = (struct cp_bufdesc *)((char *)eppc + info->Rxbd);
-    rxbd[(info->Rxnum)-1].ctrl   |= QUICC_BD_CTL_Wrap;
+    rxbd--;
+    rxbd->ctrl   |= QUICC_BD_CTL_Wrap;
 
     /* setup TX buffer descriptor */
-    txbd = (struct cp_bufdesc *)((char *)eppc + info->Txbd);
+    txbd = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbase);
     txbd->length = 1;
-    txbd->buffer = ((char *)eppc + (info->Txbd+(info->Txnum*sizeof(struct cp_bufdesc))));
+    txbd->buffer = ((char *)eppc + (uart_pram->tbase+(info->Txnum*sizeof(struct cp_bufdesc))));
     txbd->ctrl   = 0x2000;
 
     /*
@@ -243,16 +304,11 @@ cyg_hal_smc1_init_channel(struct port_in
     regs->smc_smcmr = 0x4823;
 
     /*
-     *  Init Rx & Tx params for SMC1
+     *  Init Rx & Tx params for SMCx
      */
-    eppc->cp_cr = QUICC_CPM_CR_INIT_TXRX | QUICC_CPM_SMC1 | QUICC_CPM_CR_BUSY;
+    eppc->cp_cr = QUICC_CPM_CR_INIT_TXRX | port | QUICC_CPM_CR_BUSY;
 
     info->irq = 0;  // Interrupts not enabled
-#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // remove below
-#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
-    HAL_INTERRUPT_UNMASK( CYGNUM_HAL_INTERRUPT_CPM_SMC1 );
-#endif
-#endif
 }
 
 
@@ -271,7 +327,7 @@ extern int enable_diag_uart;
 #endif // CYGDBG_DIAG_BUF
 
 static void 
-cyg_hal_smc1_putc(void* __ch_data, cyg_uint8 ch)
+cyg_hal_smcx_putc(void* __ch_data, cyg_uint8 ch)
 {
     volatile struct cp_bufdesc *bd, *first;
     EPPC *eppc = eppc_base();
@@ -367,7 +423,7 @@ cyg_hal_sxx_getc_nonblock(void* __ch_dat
     bd->buffer[0] = '\0';
     bd->ctrl |= QUICC_BD_CTL_Ready;
     if (bd->ctrl & QUICC_BD_CTL_Wrap) {
-        bd = (struct cp_bufdesc *)((char *)eppc + info->Rxbd);
+        bd = (struct cp_bufdesc *)((char *)eppc + uart_pram->rbase);
     } else {
         bd++;
     }
@@ -400,13 +456,13 @@ cyg_hal_sxx_getc(void* __ch_data)
 
 
 static void
-cyg_hal_smc1_write(void* __ch_data, const cyg_uint8* __buf, 
+cyg_hal_smcx_write(void* __ch_data, const cyg_uint8* __buf, 
                          cyg_uint32 __len)
 {
     CYGARC_HAL_SAVE_GP();
 
     while(__len-- > 0)
-        cyg_hal_smc1_putc(__ch_data, *__buf++);
+        cyg_hal_smcx_putc(__ch_data, *__buf++);
 
     CYGARC_HAL_RESTORE_GP();
 }
@@ -497,13 +553,14 @@ cyg_hal_sxx_control(void *__ch_data, __c
  * This function can be called on only an SMC port
  */
 static int
-cyg_hal_smc1_isr(void *__ch_data, int* __ctrlc, 
+cyg_hal_smcx_isr(void *__ch_data, int* __ctrlc, 
                  CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
 {
     EPPC *eppc = eppc_base();
     volatile struct cp_bufdesc *bd;
     struct port_info *info = (struct port_info *)__ch_data;
     volatile struct smc_regs *regs = (volatile struct smc_regs *)((char *)eppc + info->regs);
+    volatile struct smc_uart_pram *uart_pram = (volatile struct smc_uart_pram *)((char *)eppc + info->pram);
     char ch;
     int res = 0;
     CYGARC_HAL_SAVE_GP();
@@ -523,7 +580,7 @@ cyg_hal_smc1_isr(void *__ch_data, int* _
             bd->length = 1;
             bd->ctrl   |= QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int;
             if (bd->ctrl & QUICC_BD_CTL_Wrap) {
-                bd = (struct cp_bufdesc *)((char *)eppc + info->Rxbd);
+                bd = (struct cp_bufdesc *)((char *)eppc + uart_pram->rbase);
             } else {
                 bd++;
             }
@@ -542,16 +599,16 @@ cyg_hal_smc1_isr(void *__ch_data, int* _
     return res;
 }
 
-#if CYGNUM_HAL_QUICC_SCC1 > 0
+#if (CYGNUM_HAL_QUICC_SCC1+CYGNUM_HAL_QUICC_SCC2+CYGNUM_HAL_QUICC_SCC3) > 0
 /*
- *  Initialize SCC1 as a uart.
+ *  Initialize an SCC as a uart.
  *
  *  Comments below reference Motorola's "MPC860 User Manual".
  *  The basic initialization steps are from Section 16.15.8
  *  of that manual.
  */	
 static void
-cyg_hal_scc1_init_channel(struct port_info *info)
+cyg_hal_sccx_init_channel(struct port_info *info, int port)
 {
     EPPC *eppc = eppc_base();
     int i;
@@ -559,42 +616,98 @@ cyg_hal_scc1_init_channel(struct port_in
     volatile struct scc_regs *regs = (volatile struct scc_regs *)((char *)eppc + info->regs);
     struct cp_bufdesc *txbd, *rxbd;
 
-    static int init_done = 0;
-    if (init_done) return;
-    init_done++;
+    if (info->init) return;
+    info->init = 1;
 
     reset_cpm();
 
     /*
-     *  Set up the PortA pins for UART operation.
+     *  Set up the Port pins for UART operation.
      */
-    eppc->pio_papar |= 0x03;
-    eppc->pio_padir &= ~0x03;
-    eppc->pio_paodr &= ~0x03;
+    switch (port) {
+#if CYGNUM_HAL_QUICC_SCC1 > 0
+    case QUICC_CPM_SCC1:
+        eppc->pio_papar |= 0x03;
+        eppc->pio_padir &= ~0x03;
+        eppc->pio_paodr &= ~0x03;
+
+        /* CTS on PortC.11 */
+        eppc->pio_pcdir &= 0x800;
+        eppc->pio_pcpar &= 0x800;
+        eppc->pio_pcso  |= 0x800;
+
+        /* RTS on PortB.19 */
+        eppc->pip_pbpar |= 0x1000;
+        eppc->pip_pbdir |= 0x1000;
 
-    /* CTS on PortC.11 */
-    eppc->pio_pcdir &= 0x800;
-    eppc->pio_pcpar &= 0x800;
-    eppc->pio_pcso  |= 0x800;
+        /* Configure baud rate generator (Section 16.13.2) */
+        eppc->brgc2 = 0x10000 | (UART_BIT_RATE(UART_BAUD_RATE)<<1);
+
+        /*
+         *  NMSI mode, BRG2 to SCC1
+         */
+        eppc->si_sicr |= (1<<3)|(1<<0);
+        break;
+#endif
+#if CYGNUM_HAL_QUICC_SCC2 > 0
+    case QUICC_CPM_SCC2:
+#error FIXME
+        eppc->pio_papar |= 0x03;
+        eppc->pio_padir &= ~0x03;
+        eppc->pio_paodr &= ~0x03;
+
+        /* CTS on PortC.11 */
+        eppc->pio_pcdir &= 0x800;
+        eppc->pio_pcpar &= 0x800;
+        eppc->pio_pcso  |= 0x800;
 
-    /* RTS on PortB.19 */
-    eppc->pip_pbpar |= 0x1000;
-    eppc->pip_pbdir |= 0x1000;
+        /* RTS on PortB.19 */
+        eppc->pip_pbpar |= 0x1000;
+        eppc->pip_pbdir |= 0x1000;
+
+        /* Configure baud rate generator (Section 16.13.2) */
+        eppc->brgc2 = 0x10000 | (UART_BIT_RATE(UART_BAUD_RATE)<<1);
 
-    /* Configure baud rate generator (Section 16.13.2) */
-    eppc->brgc2 = 0x10000 | (UART_BIT_RATE(UART_BAUD_RATE)<<1);
+        /*
+         *  NMSI mode, BRG2 to SCC1
+         */
+        eppc->si_sicr |= (1<<3)|(1<<0);
+        break;
+#endif
+#if CYGNUM_HAL_QUICC_SCC3 > 0
+    case QUICC_CPM_SCC3:
+#if 0
+// CAUTION!  Enabling these bits made the port get stuck :-(
+        /* CTS/RTS/CD on PortC.4/5/13 */
+        eppc->pio_pcdir &= 0x0C04;
+        eppc->pio_pcpar &= 0x0C00;
+//        eppc->pio_pcpar |= 0x0004;
+        eppc->pio_pcso  |= 0x0C00;
+#endif
 
-    /*
-     *  NMSI mode, BRG2 to SCC1
-     */
-    eppc->si_simode = 0;
-    eppc->si_sicr = (1<<3)|(1<<0);
+        /* RxD/TxD on PortB.24/25 */
+        eppc->pip_pbpar |= 0x00C0;
+        eppc->pip_pbdir |= 0x00C0;
+        eppc->pip_pbodr &= ~0x00C0;
+
+        /* Configure baud rate generator (Section 16.13.2) */
+        eppc->brgc4 = 0x10000 | (UART_BIT_RATE(UART_BAUD_RATE)<<1);
+
+        /*
+         *  NMSI mode, BRG4 to SCC3
+         */
+        eppc->si_sicr &= ~(0xFF << 16);
+        eppc->si_sicr |= (3<<19)|(3<<16);
+        break;
+#endif
+    }
 
     /*
      *  Set pointers to buffer descriptors.
      */
-    uart_pram->rbase = info->Rxbd;
-    uart_pram->tbase = info->Txbd;
+    memset((void *)uart_pram, 0xFF, 0x100);
+    uart_pram->rbase = cyg_hal_allocBd(sizeof(struct cp_bufdesc)*info->Rxnum + info->Rxnum);
+    uart_pram->tbase = cyg_hal_allocBd(sizeof(struct cp_bufdesc)*info->Txnum + info->Txnum);
 
     /*
      *  SDMA & LCD bus request level 5
@@ -625,39 +738,36 @@ cyg_hal_scc1_init_channel(struct port_in
     /* character mask */
     uart_pram->rccm  = 0xC0FF;
 
+    /* control characters */
+    for (i = 0;  i < 8;  i++) {
+        uart_pram->cc[i] = 0x8000;  // Mark unused
+    }
+
     /* setup RX buffer descriptors */
-    rxbd = (struct cp_bufdesc *)((char *)eppc + info->Rxbd);
+    rxbd = (struct cp_bufdesc *)((char *)eppc + uart_pram->rbase);
     info->next_rxbd = rxbd;
     for (i = 0;  i < info->Rxnum;  i++) {
         rxbd->length = 0;
-        rxbd->buffer = ((char *)eppc + (info->Rxbd+(info->Rxnum*sizeof(struct cp_bufdesc))))+i;
+        rxbd->buffer = ((char *)eppc + (uart_pram->rbase+(info->Rxnum*sizeof(struct cp_bufdesc))))+i;
         rxbd->ctrl   = QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int;
-        if (i == ((info->Rxnum)-1)) {
-            rxbd->ctrl   |= QUICC_BD_CTL_Wrap;
-        }
         rxbd++;
     }
-    // Compiler bug: for whatever reason, the Wrap code above fails!
-    rxbd = (struct cp_bufdesc *)((char *)eppc + info->Rxbd);
-    rxbd[(info->Rxnum)-1].ctrl   |= QUICC_BD_CTL_Wrap;
+    rxbd--;
+    rxbd->ctrl   |= QUICC_BD_CTL_Wrap;
 
     /* setup TX buffer descriptor */
-    txbd = (struct cp_bufdesc *)((char *)eppc + info->Txbd);
-    txbd->length = 1;
-    txbd->buffer = ((char *)eppc + (info->Txbd+(info->Txnum*sizeof(struct cp_bufdesc))));
+    txbd = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbase);
+    txbd->length = 0;
+    txbd->buffer = ((char *)eppc + (uart_pram->tbase+(info->Txnum*sizeof(struct cp_bufdesc))));
     txbd->ctrl   = 0x2000;
 
     /*
-     *  Init Rx & Tx params for SCC1
-     */
-    eppc->cp_cr = QUICC_CPM_CR_INIT_TXRX | QUICC_CPM_SCC1 | QUICC_CPM_CR_BUSY;
-
-    /*
      *  Clear any previous events. Mask interrupts.
      *  (Section 16.15.7.14 and 16.15.7.15)
      */
-    regs->scc_scce = 0xff;
+    regs->scc_scce = 0xffff;
     regs->scc_sccm = 5;
+    regs->scc_sccm = 3;
 
     /*
      *  Set 8,n,1 characters
@@ -665,18 +775,19 @@ cyg_hal_scc1_init_channel(struct port_in
     regs->scc_psmr = (3<<12);
     regs->scc_gsmr_h = 0x20;          // 8bit FIFO
     regs->scc_gsmr_l = 0x00028004;    // 16x TxCLK, 16x RxCLK, UART
+
+    /*
+     *  Init Rx & Tx params for SCCX
+     */
+    eppc->cp_cr = QUICC_CPM_CR_INIT_TXRX | port | QUICC_CPM_CR_BUSY;
+
     regs->scc_gsmr_l |= 0x30;         // Enable Rx, Tx
 
     info->irq = 0;
-#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // remove below
-#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
-    HAL_INTERRUPT_UNMASK( CYGNUM_HAL_INTERRUPT_CPM_SCC1 );
-#endif
-#endif
 }
 
 static void 
-cyg_hal_scc1_putc(void* __ch_data, cyg_uint8 ch)
+cyg_hal_sccx_putc(void* __ch_data, cyg_uint8 ch)
 {
     volatile struct cp_bufdesc *bd, *first;
     EPPC *eppc = eppc_base();
@@ -705,35 +816,36 @@ cyg_hal_scc1_putc(void* __ch_data, cyg_u
         bd->length = 0;
     }
 
+    bd->length = 0;
     bd->buffer[bd->length++] = ch;
     bd->ctrl      |= QUICC_BD_CTL_Ready;
 
     while (bd->ctrl & QUICC_BD_CTL_Ready) ;  // Wait until buffer free
-    bd->length = 0;
 
     CYGARC_HAL_RESTORE_GP();
 }
 
 static void
-cyg_hal_scc1_write(void* __ch_data, const cyg_uint8* __buf, 
+cyg_hal_sccx_write(void* __ch_data, const cyg_uint8* __buf, 
                          cyg_uint32 __len)
 {
     CYGARC_HAL_SAVE_GP();
 
     while(__len-- > 0)
-        cyg_hal_scc1_putc(__ch_data, *__buf++);
+        cyg_hal_sccx_putc(__ch_data, *__buf++);
 
     CYGARC_HAL_RESTORE_GP();
 }
 
 static int
-cyg_hal_scc1_isr(void *__ch_data, int* __ctrlc, 
+cyg_hal_sccx_isr(void *__ch_data, int* __ctrlc, 
                  CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
 {
     EPPC *eppc = eppc_base();
     volatile struct cp_bufdesc *bd;
     struct port_info *info = (struct port_info *)__ch_data;
     volatile struct scc_regs *regs = (volatile struct scc_regs *)((char *)eppc + info->regs);
+    volatile struct uart_pram *uart_pram = (volatile struct uart_pram *)((char *)eppc + info->pram);
     char ch;
     int res = 0;
     CYGARC_HAL_SAVE_GP();
@@ -753,7 +865,7 @@ cyg_hal_scc1_isr(void *__ch_data, int* _
             bd->length = 1;
             bd->ctrl   |= QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int;
             if (bd->ctrl & QUICC_BD_CTL_Wrap) {
-                bd = (struct cp_bufdesc *)((char *)eppc + info->Rxbd);
+                bd = (struct cp_bufdesc *)((char *)eppc + uart_pram->rbase);
             } else {
                 bd++;
             }
@@ -771,7 +883,7 @@ cyg_hal_scc1_isr(void *__ch_data, int* _
     CYGARC_HAL_RESTORE_GP();
     return res;
 }
-#endif // CYGNUM_HAL_QUICC_SCC1
+#endif // CYGNUM_HAL_QUICC_SCCX
 
 /*
  * Early initialization of comm channels. Must not rely
@@ -785,38 +897,90 @@ cyg_hal_plf_serial_init(void)
     int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
 
     static int init = 0;  // It's wrong to do this more than once
+    int chan = 0;
     if (init) return;
     init++;
 
     // Setup procs in the vector table
 
-    // Set channel 0 - SMC1
-    cyg_hal_smc1_init_channel(&ports[0]);
-    CYGACC_CALL_IF_SET_CONSOLE_COMM(0);// Should be configurable!
+#if CYGNUM_HAL_QUICC_SMC1 > 0
+    // Set up SMC1
+    cyg_hal_smcx_init_channel(&ports[chan], QUICC_CPM_SMC1);
+    CYGACC_CALL_IF_SET_CONSOLE_COMM(chan);// Should be configurable!
     comm = CYGACC_CALL_IF_CONSOLE_PROCS();
-    CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[0]);
-    CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_smc1_write);
+    CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[chan]);
+    CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_smcx_write);
     CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_sxx_read);
-    CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_smc1_putc);
+    CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_smcx_putc);
     CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_sxx_getc);
     CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_sxx_control);
-    CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_smc1_isr);
+    CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_smcx_isr);
     CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_sxx_getc_timeout);
+    chan++;
+#endif
+
+#if CYGNUM_HAL_QUICC_SMC2 > 0
+    // Set up SMC2
+    cyg_hal_smcx_init_channel(&ports[chan], QUICC_CPM_SMC2);
+    CYGACC_CALL_IF_SET_CONSOLE_COMM(chan);// Should be configurable!
+    comm = CYGACC_CALL_IF_CONSOLE_PROCS();
+    CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[chan]);
+    CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_smcx_write);
+    CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_sxx_read);
+    CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_smcx_putc);
+    CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_sxx_getc);
+    CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_sxx_control);
+    CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_smcx_isr);
+    CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_sxx_getc_timeout);
+    chan++;
+#endif
 
 #if CYGNUM_HAL_QUICC_SCC1 > 0
-
-    // Set channel 1 - SCC1
-    cyg_hal_scc1_init_channel(&ports[1]);
-    CYGACC_CALL_IF_SET_CONSOLE_COMM(1);// Should be configurable!
+    // Set  up SCC1
+    cyg_hal_sccx_init_channel(&ports[chan], QUICC_CPM_SCC1);
+    CYGACC_CALL_IF_SET_CONSOLE_COMM(chan);// Should be configurable!
     comm = CYGACC_CALL_IF_CONSOLE_PROCS();
-    CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[1]);
-    CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_scc1_write);
+    CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[chan]);
+    CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_sccx_write);
     CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_sxx_read);
-    CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_scc1_putc);
+    CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_sccx_putc);
     CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_sxx_getc);
     CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_sxx_control);
-    CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_scc1_isr);
+    CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_sccx_isr);
+    CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_sxx_getc_timeout);
+    chan++;
+#endif
+
+#if CYGNUM_HAL_QUICC_SCC2 > 0
+    // Set  up SCC2
+    cyg_hal_sccx_init_channel(&ports[chan], QUICC_CPM_SCC2);
+    CYGACC_CALL_IF_SET_CONSOLE_COMM(chan);// Should be configurable!
+    comm = CYGACC_CALL_IF_CONSOLE_PROCS();
+    CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[chan]);
+    CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_sccx_write);
+    CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_sxx_read);
+    CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_sccx_putc);
+    CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_sxx_getc);
+    CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_sxx_control);
+    CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_sccx_isr);
     CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_sxx_getc_timeout);
+    chan++;
+#endif
+
+#if CYGNUM_HAL_QUICC_SCC3 > 0
+    // Set  up SCC3
+    cyg_hal_sccx_init_channel(&ports[chan], QUICC_CPM_SCC3);
+    CYGACC_CALL_IF_SET_CONSOLE_COMM(chan);// Should be configurable!
+    comm = CYGACC_CALL_IF_CONSOLE_PROCS();
+    CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[chan]);
+    CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_sccx_write);
+    CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_sxx_read);
+    CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_sccx_putc);
+    CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_sxx_getc);
+    CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_sxx_control);
+    CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_sccx_isr);
+    CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_sxx_getc_timeout);
+    chan++;
 #endif
 
     // Restore original console
--- a/packages/hal/powerpc/ts1000/current/ChangeLog
+++ b/packages/hal/powerpc/ts1000/current/ChangeLog
@@ -1,3 +1,9 @@
+2002-11-25  Gary Thomas  <gthomas@ecoscentric.com>
+
+	* src/ts1000.S: Minor include file cleanup.
+
+	* cdl/hal_powerpc_ts1000.cdl: Update port layout CDL.
+
 2002-10-18  Gary Thomas  <gthomas@ecoscentric.com>
 
 	* cdl/hal_powerpc_ts1000.cdl: Fix clock rate calculation.
--- a/packages/hal/powerpc/ts1000/current/cdl/hal_powerpc_ts1000.cdl
+++ b/packages/hal/powerpc/ts1000/current/cdl/hal_powerpc_ts1000.cdl
@@ -65,9 +65,11 @@ cdl_package CYGPKG_HAL_POWERPC_TS1000 {
     implements    CYGINT_HAL_DEBUG_GDB_STUBS
     implements    CYGINT_HAL_DEBUG_GDB_STUBS_BREAK
     implements    CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT
+    implements    CYGNUM_HAL_QUICC_SMC1
 
     define_proc {
         puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H   <pkgconf/hal_powerpc_mpc8xx.h>"
+        puts $::cdl_system_header "#define CYGBLD_HAL_VARIANT_H  <pkgconf/hal_powerpc_quicc.h>"
         puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_H <pkgconf/hal_powerpc_ts1000.h>"
 
     puts $::cdl_header "#define HAL_PLATFORM_CPU    \"PowerPC 855\""
@@ -101,51 +103,6 @@ cdl_package CYGPKG_HAL_POWERPC_TS1000 {
            baud rate correctly, amongst other things."
    }
 
-   cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS {
-       display      "Number of communication channels on the board"
-       flavor       data
-       calculated   1
-   }
-
-   cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL {
-       display          "Debug serial port"
-       active_if        CYGPRI_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_CONFIGURABLE
-       flavor data
-       legal_values     0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1
-       default_value    0
-       description      "
-           The TS1000 board has only one serial port. This option
-           chooses which port will be used to connect to a host
-           running GDB."
-    }
-
-    cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL {
-        display          "Diagnostic serial port"
-        active_if        CYGPRI_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_CONFIGURABLE
-        flavor data
-        legal_values     0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1
-        default_value    0
-        description      "
-           The TS1000 board has only one serial port.  This option
-           chooses which port will be used for diagnostic output."
-    }
-
-    # This option is only used when USE_ROM_MONITOR is enabled - but
-    # it cannot be a sub-option to that option, since the code uses the
-    # definition in a preprocessor comparison.
-    cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_ROM_DEBUG_CHANNEL {
-        display          "Debug serial port used by ROM monitor"
-        flavor data
-        legal_values     0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1
-        default_value    0
-        description      "
-            The TS1000 board has only one serial port.  This
-            option tells the code which port is in use by the ROM
-            monitor. It should only be necessary to change this
-            option if a non-standard configurated eCos GDB stub is
-            used."
-    }
-
     # Real-time clock/counter specifics
     cdl_component CYGNUM_HAL_RTC_CONSTANTS {
         display       "Real-time clock constants."
--- a/packages/hal/powerpc/ts1000/current/src/ts1000.S
+++ b/packages/hal/powerpc/ts1000/current/src/ts1000.S
@@ -52,10 +52,7 @@
 ##
 ##=============================================================================
 
-#include <pkgconf/system.h>
 #include <pkgconf/hal.h>
-#include <pkgconf/hal_powerpc.h>
-#include <pkgconf/hal_powerpc_ts1000.h>
         
 #include <cyg/hal/arch.inc>		/* register symbols et al */
 #include <cyg/hal/ppc_regs.h>		/* on-chip resource layout, special */
--- a/packages/hal/powerpc/viper/current/ChangeLog
+++ b/packages/hal/powerpc/viper/current/ChangeLog
@@ -1,3 +1,8 @@
+2002-11-25  Gary Thomas  <gthomas@ecoscentric.com>
+
+	* src/viper.S: Minor include file cleanups.
+	* cdl/hal_powerpc_viper.cdl: Update port layout CDL.
+
 2002-10-18  Gary Thomas  <gthomas@ecoscentric.com>
 
 	* include/plf_cache.h: No need for old FLASH cache support.
--- a/packages/hal/powerpc/viper/current/cdl/hal_powerpc_viper.cdl
+++ b/packages/hal/powerpc/viper/current/cdl/hal_powerpc_viper.cdl
@@ -65,10 +65,12 @@ cdl_package CYGPKG_HAL_POWERPC_VIPER {
     implements    CYGINT_HAL_DEBUG_GDB_STUBS
     implements    CYGINT_HAL_DEBUG_GDB_STUBS_BREAK
     implements    CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT
+    implements    CYGNUM_HAL_QUICC_SMC1
     implements    CYGNUM_HAL_QUICC_SCC1
 
     define_proc {
         puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H   <pkgconf/hal_powerpc_mpc8xx.h>"
+        puts $::cdl_system_header "#define CYGBLD_HAL_VARIANT_H  <pkgconf/hal_powerpc_quicc.h>"
         puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_H <pkgconf/hal_powerpc_viper.h>"
 
 	puts $::cdl_header "#define HAL_PLATFORM_CPU    \"PowerPC 860\""
@@ -102,51 +104,6 @@ cdl_package CYGPKG_HAL_POWERPC_VIPER {
            baud rate correctly, amongst other things."
    }
 
-   cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS {
-       display      "Number of communication channels on the board"
-       flavor       data
-       calculated   1+CYGNUM_HAL_QUICC_SCC1
-   }
-
-   cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL {
-       display          "Debug serial port"
-       active_if        CYGPRI_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_CONFIGURABLE
-       flavor data
-       legal_values     0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1
-       default_value    0
-       description      "
-           The VIPER board has two serial ports (SMC1 & SCC1). This option
-           chooses which port will be used to connect to a host
-           running GDB."
-    }
-
-    cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL {
-        display          "Diagnostic serial port"
-        active_if        CYGPRI_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_CONFIGURABLE
-        flavor data
-        legal_values     0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1
-        default_value    0
-        description      "
-           The VIPER board has two serial ports (SMC1 & SCC1).  This option
-           chooses which port will be used for diagnostic output."
-    }
-
-    # This option is only used when USE_ROM_MONITOR is enabled - but
-    # it cannot be a sub-option to that option, since the code uses the
-    # definition in a preprocessor comparison.
-    cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_ROM_DEBUG_CHANNEL {
-        display          "Debug serial port used by ROM monitor"
-        flavor data
-        legal_values     0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1
-        default_value    0
-        description      "
-            The VIPER board has two serial ports (SMC1 & SCC1).  This
-            option tells the code which port is in use by the ROM
-            monitor. It should only be necessary to change this
-            option if a non-standard configurated eCos GDB stub is
-            used."
-    }
-
     # Real-time clock/counter specifics
     cdl_component CYGNUM_HAL_RTC_CONSTANTS {
         display       "Real-time clock constants."
--- a/packages/hal/powerpc/viper/current/src/viper.S
+++ b/packages/hal/powerpc/viper/current/src/viper.S
@@ -52,11 +52,8 @@
 ##
 ##=============================================================================
 
-#include <pkgconf/system.h>
 #include <pkgconf/hal.h>
-#include <pkgconf/hal_powerpc.h>
-#include <pkgconf/hal_powerpc_viper.h>
-        
+
 #include <cyg/hal/arch.inc>		/* register symbols et al */
 #include <cyg/hal/ppc_regs.h>		/* on-chip resource layout, special */
 					/* registers, IMM layout...         */