summaryrefslogtreecommitdiffstats
path: root/arch/ppc
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-05-12 21:05:59 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-05-12 21:05:59 +0000
commitba2dacab305c598cd4c34a604f8e276bf5bab5ff (patch)
tree78670a0139bf4d5ace617b29b7eba82bbc74d602 /arch/ppc
parentb77bf69998121e689c5e86cc5630d39a0a9ee6ca (diff)
Merge with Linux 2.3.99-pre7 and various other bits.
Diffstat (limited to 'arch/ppc')
-rw-r--r--arch/ppc/8260_io/Config.in22
-rw-r--r--arch/ppc/8260_io/Makefile20
-rw-r--r--arch/ppc/8260_io/commproc.c162
-rw-r--r--arch/ppc/8260_io/enet.c856
-rw-r--r--arch/ppc/8260_io/uart.c2772
-rw-r--r--arch/ppc/8xx_io/enet.c187
-rw-r--r--arch/ppc/8xx_io/uart.c213
-rw-r--r--arch/ppc/Makefile14
-rw-r--r--arch/ppc/config.in21
-rw-r--r--arch/ppc/configs/chrp_defconfig319
-rw-r--r--arch/ppc/configs/common_defconfig182
-rw-r--r--arch/ppc/configs/pmac_defconfig550
-rw-r--r--arch/ppc/configs/prep_defconfig361
-rw-r--r--arch/ppc/defconfig149
-rw-r--r--arch/ppc/kernel/Makefile9
-rw-r--r--arch/ppc/kernel/align.c25
-rw-r--r--arch/ppc/kernel/feature.c69
-rw-r--r--arch/ppc/kernel/gemini_pci.c175
-rw-r--r--arch/ppc/kernel/gemini_setup.c223
-rw-r--r--arch/ppc/kernel/head.S25
-rw-r--r--arch/ppc/kernel/head_8xx.S176
-rw-r--r--arch/ppc/kernel/irq.c10
-rw-r--r--arch/ppc/kernel/m8260_setup.c303
-rw-r--r--arch/ppc/kernel/m8xx_setup.c1
-rw-r--r--arch/ppc/kernel/misc.S18
-rw-r--r--arch/ppc/kernel/pmac_nvram.c274
-rw-r--r--arch/ppc/kernel/pmac_pci.c23
-rw-r--r--arch/ppc/kernel/pmac_pic.c16
-rw-r--r--arch/ppc/kernel/pmac_setup.c11
-rw-r--r--arch/ppc/kernel/ppc-stub.c60
-rw-r--r--arch/ppc/kernel/ppc8260_pic.c111
-rw-r--r--arch/ppc/kernel/ppc8260_pic.h15
-rw-r--r--arch/ppc/kernel/ppc8xx_pic.c22
-rw-r--r--arch/ppc/kernel/ppc_htab.c2
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c35
-rw-r--r--arch/ppc/kernel/process.c4
-rw-r--r--arch/ppc/kernel/prom.c27
-rw-r--r--arch/ppc/kernel/qspan_pci.c2
-rw-r--r--arch/ppc/kernel/setup.c46
-rw-r--r--arch/ppc/kernel/totalmp.c109
-rw-r--r--arch/ppc/kernel/traps.c2
-rw-r--r--arch/ppc/mbxboot/Makefile13
-rw-r--r--arch/ppc/mbxboot/embed_config.c49
-rw-r--r--arch/ppc/mbxboot/head_8260.S246
-rw-r--r--arch/ppc/mbxboot/iic.c9
-rw-r--r--arch/ppc/mbxboot/m8260_tty.c201
-rw-r--r--arch/ppc/mbxboot/misc.c10
-rw-r--r--arch/ppc/mbxboot/pci.c3
-rw-r--r--arch/ppc/mbxboot/qspan_pci.c3
-rw-r--r--arch/ppc/mm/fault.c4
-rw-r--r--arch/ppc/mm/init.c57
-rw-r--r--arch/ppc/xmon/Makefile4
-rw-r--r--arch/ppc/xmon/privinst.h9
-rw-r--r--arch/ppc/xmon/start.c57
-rw-r--r--arch/ppc/xmon/start_8xx.c288
-rw-r--r--arch/ppc/xmon/xmon.c36
56 files changed, 6419 insertions, 2191 deletions
diff --git a/arch/ppc/8260_io/Config.in b/arch/ppc/8260_io/Config.in
new file mode 100644
index 000000000..8cdd8c615
--- /dev/null
+++ b/arch/ppc/8260_io/Config.in
@@ -0,0 +1,22 @@
+#
+# MPC8260 Communication options
+#
+if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
+ mainmenu_option next_comment
+ comment 'MPC8260 Communication Options'
+ bool 'CPM SCC Ethernet' CONFIG_SCC_ENET
+ if [ "$CONFIG_SCC_ENET" = "y" ]; then
+ bool 'Ethernet on SCC1' CONFIG_SCC1_ENET
+ if [ "$CONFIG_SCC1_ENET" != "y" ]; then
+ bool 'Ethernet on SCC2' CONFIG_SCC2_ENET
+ fi
+ fi
+ bool 'FCC Ethernet' CONFIG_FCC_ENET
+ if [ "$CONFIG_FCC_ENET" = "y" ]; then
+ bool 'Ethernet on FCC1' CONFIG_FCC1_ENET
+ if [ "$CONFIG_FCC1_ENET" != "y" ]; then
+ bool 'Ethernet on FCC2' CONFIG_FCC2_ENET
+ fi
+ fi
+ endmenu
+fi
diff --git a/arch/ppc/8260_io/Makefile b/arch/ppc/8260_io/Makefile
new file mode 100644
index 000000000..240a85628
--- /dev/null
+++ b/arch/ppc/8260_io/Makefile
@@ -0,0 +1,20 @@
+#
+# Makefile for the linux MPC8xx ppc-specific parts of comm processor
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+O_TARGET := 8260_io.a
+O_OBJS = commproc.o uart.o
+
+ifdef CONFIG_FCC_ENET
+O_OBJS += fcc.o
+endif
+ifdef CONFIG_SCC_ENET
+O_OBJS += enet.o
+endif
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/ppc/8260_io/commproc.c b/arch/ppc/8260_io/commproc.c
new file mode 100644
index 000000000..8642fa420
--- /dev/null
+++ b/arch/ppc/8260_io/commproc.c
@@ -0,0 +1,162 @@
+
+/*
+ * General Purpose functions for the global management of the
+ * 8260 Communication Processor Module.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
+ * 2.3.99 Updates
+ *
+ * In addition to the individual control of the communication
+ * channels, there are a few functions that globally affect the
+ * communication processor.
+ *
+ * Buffer descriptors must be allocated from the dual ported memory
+ * space. The allocator for that is here. When the communication
+ * process is reset, we reclaim the memory available. There is
+ * currently no deallocator for this memory.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/bootmem.h>
+#include <asm/irq.h>
+#include <asm/mpc8260.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/immap_8260.h>
+#include <asm/cpm_8260.h>
+
+static uint dp_alloc_base; /* Starting offset in DP ram */
+static uint dp_alloc_top; /* Max offset + 1 */
+static uint host_buffer; /* One page of host buffer */
+static uint host_end; /* end + 1 */
+cpm8260_t *cpmp; /* Pointer to comm processor space */
+
+/* We allocate this here because it is used almost exclusively for
+ * the communication processor devices.
+ */
+immap_t *immr;
+
+void
+m8260_cpm_reset(void)
+{
+ volatile immap_t *imp;
+ volatile cpm8260_t *commproc;
+ uint vpgaddr;
+
+ immr = imp = (volatile immap_t *)IMAP_ADDR;
+ commproc = &imp->im_cpm;
+
+ /* Reclaim the DP memory for our use.
+ */
+ dp_alloc_base = CPM_DATAONLY_BASE;
+ dp_alloc_top = dp_alloc_base + CPM_DATAONLY_SIZE;
+
+ /* Set the host page for allocation.
+ */
+ host_buffer =
+ (uint) alloc_bootmem_pages(PAGE_SIZE * NUM_CPM_HOST_PAGES);
+ host_end = host_buffer + (PAGE_SIZE * NUM_CPM_HOST_PAGES);
+
+ vpgaddr = host_buffer;
+
+ /* Tell everyone where the comm processor resides.
+ */
+ cpmp = (cpm8260_t *)commproc;
+}
+
+/* Allocate some memory from the dual ported ram. We may want to
+ * enforce alignment restrictions, but right now everyone is a good
+ * citizen.
+ */
+uint
+m8260_cpm_dpalloc(uint size)
+{
+ uint retloc;
+
+ if ((dp_alloc_base + size) >= dp_alloc_top)
+ return(CPM_DP_NOSPACE);
+
+ retloc = dp_alloc_base;
+ dp_alloc_base += size;
+
+ return(retloc);
+}
+
+/* We also own one page of host buffer space for the allocation of
+ * UART "fifos" and the like.
+ */
+uint
+m8260_cpm_hostalloc(uint size)
+{
+ uint retloc;
+
+ if ((host_buffer + size) >= host_end)
+ return(0);
+
+ retloc = host_buffer;
+ host_buffer += size;
+
+ return(retloc);
+}
+
+/* Set a baud rate generator. This needs lots of work. There are
+ * eight BRGs, which can be connected to the CPM channels or output
+ * as clocks. The BRGs are in two different block of internal
+ * memory mapped space.
+ * The baud rate clock is the system clock divided by something.
+ * It was set up long ago during the initial boot phase and is
+ * is given to us.
+ * Baud rate clocks are zero-based in the driver code (as that maps
+ * to port numbers). Documentation uses 1-based numbering.
+ */
+#define BRG_INT_CLK (((bd_t *)__res)->bi_brgfreq * 1000000)
+#define BRG_UART_CLK (BRG_INT_CLK/16)
+
+/* This function is used by UARTS, or anything else that uses a 16x
+ * oversampled clock.
+ */
+void
+m8260_cpm_setbrg(uint brg, uint rate)
+{
+ volatile uint *bp;
+
+ /* This is good enough to get SMCs running.....
+ */
+ if (brg < 4) {
+ bp = (uint *)&immr->im_brgc1;
+ }
+ else {
+ bp = (uint *)&immr->im_brgc5;
+ brg -= 4;
+ }
+ bp += brg;
+ *bp = ((BRG_UART_CLK / rate) << 1) | CPM_BRG_EN;
+}
+
+/* This function is used to set high speed synchronous baud rate
+ * clocks.
+ */
+void
+m8260_cpm_fastbrg(uint brg, uint rate, int div16)
+{
+ volatile uint *bp;
+
+ /* This is good enough to get SMCs running.....
+ */
+ if (brg < 4) {
+ bp = (uint *)&immr->im_brgc1;
+ }
+ else {
+ bp = (uint *)&immr->im_brgc5;
+ brg -= 4;
+ }
+ bp += brg;
+ *bp = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN;
+ if (div16)
+ *bp |= CPM_BRG_DIV16;
+}
diff --git a/arch/ppc/8260_io/enet.c b/arch/ppc/8260_io/enet.c
new file mode 100644
index 000000000..82ed8f9ec
--- /dev/null
+++ b/arch/ppc/8260_io/enet.c
@@ -0,0 +1,856 @@
+/*
+ * Ethernet driver for Motorola MPC8260.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ * Copyright (c) 2000 MontaVista Software Inc. (source@mvista.com)
+ * 2.3.99 Updates
+ *
+ * I copied this from the 8xx CPM Ethernet driver, so follow the
+ * credits back through that.
+ *
+ * This version of the driver is somewhat selectable for the different
+ * processor/board combinations. It works for the boards I know about
+ * now, and should be easily modified to include others. Some of the
+ * configuration information is contained in "commproc.h" and the
+ * remainder is here.
+ *
+ * Buffer descriptors are kept in the CPM dual port RAM, and the frame
+ * buffers are in the host memory.
+ *
+ * Right now, I am very watseful with the buffers. I allocate memory
+ * pages and then divide them into 2K frame buffers. This way I know I
+ * have buffers large enough to hold one frame within one buffer descriptor.
+ * Once I get this working, I will use 64 or 128 byte CPM buffers, which
+ * will be much more memory efficient and will easily handle lots of
+ * small packets.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+
+#include <asm/immap_8260.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8260.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/cpm_8260.h>
+#include <asm/irq.h>
+
+/*
+ * Theory of Operation
+ *
+ * The MPC8260 CPM performs the Ethernet processing on an SCC. It can use
+ * an aribtrary number of buffers on byte boundaries, but must have at
+ * least two receive buffers to prevent constant overrun conditions.
+ *
+ * The buffer descriptors are allocated from the CPM dual port memory
+ * with the data buffers allocated from host memory, just like all other
+ * serial communication protocols. The host memory buffers are allocated
+ * from the free page pool, and then divided into smaller receive and
+ * transmit buffers. The size of the buffers should be a power of two,
+ * since that nicely divides the page. This creates a ring buffer
+ * structure similar to the LANCE and other controllers.
+ *
+ * Like the LANCE driver:
+ * The driver runs as two independent, single-threaded flows of control. One
+ * is the send-packet routine, which enforces single-threaded use by the
+ * cep->tx_busy flag. The other thread is the interrupt handler, which is
+ * single threaded by the hardware and other software.
+ */
+
+/* The transmitter timeout
+ */
+#define TX_TIMEOUT (2*HZ)
+
+/* The number of Tx and Rx buffers. These are allocated from the page
+ * pool. The code may assume these are power of two, so it is best
+ * to keep them that size.
+ * We don't need to allocate pages for the transmitter. We just use
+ * the skbuffer directly.
+ */
+#define CPM_ENET_RX_PAGES 4
+#define CPM_ENET_RX_FRSIZE 2048
+#define CPM_ENET_RX_FRPPG (PAGE_SIZE / CPM_ENET_RX_FRSIZE)
+#define RX_RING_SIZE (CPM_ENET_RX_FRPPG * CPM_ENET_RX_PAGES)
+#define TX_RING_SIZE 8 /* Must be power of two */
+#define TX_RING_MOD_MASK 7 /* for this to work */
+
+/* The CPM stores dest/src/type, data, and checksum for receive packets.
+ */
+#define PKT_MAXBUF_SIZE 1518
+#define PKT_MINBUF_SIZE 64
+#define PKT_MAXBLR_SIZE 1520
+
+/* The CPM buffer descriptors track the ring buffers. The rx_bd_base and
+ * tx_bd_base always point to the base of the buffer descriptors. The
+ * cur_rx and cur_tx point to the currently available buffer.
+ * The dirty_tx tracks the current buffer that is being sent by the
+ * controller. The cur_tx and dirty_tx are equal under both completely
+ * empty and completely full conditions. The empty/ready indicator in
+ * the buffer descriptor determines the actual condition.
+ */
+struct scc_enet_private {
+ /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+ struct sk_buff* tx_skbuff[TX_RING_SIZE];
+ ushort skb_cur;
+ ushort skb_dirty;
+
+ /* CPM dual port RAM relative addresses.
+ */
+ cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */
+ cbd_t *tx_bd_base;
+ cbd_t *cur_rx, *cur_tx; /* The next free ring entry */
+ cbd_t *dirty_tx; /* The ring entries to be free()ed. */
+ scc_t *sccp;
+ struct net_device_stats stats;
+ uint tx_full;
+ spinlock_t lock;
+};
+
+static int scc_enet_open(struct net_device *dev);
+static int scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int scc_enet_rx(struct net_device *dev);
+static void scc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
+static int scc_enet_close(struct net_device *dev);
+static struct net_device_stats *scc_enet_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+
+/* These will be configurable for the SCC choice.
+*/
+#define CPM_ENET_BLOCK CPM_CR_SCC1_SBLOCK
+#define CPM_ENET_PAGE CPM_CR_SCC1_PAGE
+#define PROFF_ENET PROFF_SCC1
+#define SCC_ENET 0
+#define SIU_INT_ENET SIU_INT_SCC1
+
+/* These are both board and SCC dependent....
+*/
+#define PD_ENET_RXD ((uint)0x00000001)
+#define PD_ENET_TXD ((uint)0x00000002)
+#define PD_ENET_TENA ((uint)0x00000004)
+#define PC_ENET_RENA ((uint)0x00020000)
+#define PC_ENET_CLSN ((uint)0x00000004)
+#define PC_ENET_TXCLK ((uint)0x00000800)
+#define PC_ENET_RXCLK ((uint)0x00000400)
+#define CMX_CLK_ROUTE ((uint)0x25000000)
+#define CMX_CLK_MASK ((uint)0xff000000)
+
+/* Specific to a board.
+*/
+#define PC_EST8260_ENET_LOOPBACK ((uint)0x80000000)
+#define PC_EST8260_ENET_SQE ((uint)0x40000000)
+#define PC_EST8260_ENET_NOTFD ((uint)0x20000000)
+
+static int
+scc_enet_open(struct net_device *dev)
+{
+
+ /* I should reset the ring buffers here, but I don't yet know
+ * a simple way to do that.
+ */
+ netif_start_queue(dev);
+ return 0; /* Always succeed */
+}
+
+static int
+scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+ volatile cbd_t *bdp;
+
+
+ /* Fill in a Tx ring entry */
+ bdp = cep->cur_tx;
+
+#ifndef final_version
+ if (bdp->cbd_sc & BD_ENET_TX_READY) {
+ /* Ooops. All transmit buffers are full. Bail out.
+ * This should not happen, since cep->tx_busy should be set.
+ */
+ printk("%s: tx queue full!.\n", dev->name);
+ return 1;
+ }
+#endif
+
+ /* Clear all of the status flags.
+ */
+ bdp->cbd_sc &= ~BD_ENET_TX_STATS;
+
+ /* If the frame is short, tell CPM to pad it.
+ */
+ if (skb->len <= ETH_ZLEN)
+ bdp->cbd_sc |= BD_ENET_TX_PAD;
+ else
+ bdp->cbd_sc &= ~BD_ENET_TX_PAD;
+
+ /* Set buffer length and buffer pointer.
+ */
+ bdp->cbd_datlen = skb->len;
+ bdp->cbd_bufaddr = __pa(skb->data);
+
+ /* Save skb pointer.
+ */
+ cep->tx_skbuff[cep->skb_cur] = skb;
+
+ cep->stats.tx_bytes += skb->len;
+ cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK;
+
+ /* Push the data cache so the CPM does not get stale memory
+ * data.
+ */
+ flush_dcache_range((unsigned long)(skb->data),
+ (unsigned long)(skb->data + skb->len));
+
+ spin_lock_irq(&cep->lock);
+
+ /* Send it on its way. Tell CPM its ready, interrupt when done,
+ * its the last BD of the frame, and to put the CRC on the end.
+ */
+ bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+
+ dev->trans_start = jiffies;
+
+ /* If this was the last BD in the ring, start at the beginning again.
+ */
+ if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+ bdp = cep->tx_bd_base;
+ else
+ bdp++;
+
+ if (bdp->cbd_sc & BD_ENET_TX_READY)
+ netif_stop_queue(dev);
+
+ cep->cur_tx = (cbd_t *)bdp;
+
+ spin_unlock_irq(&cep->lock);
+
+ return 0;
+}
+
+static void
+scc_enet_timeout(struct net_device *dev)
+{
+ struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+
+ printk("%s: transmit timed out.\n", dev->name);
+ cep->stats.tx_errors++;
+#ifndef final_version
+ {
+ int i;
+ cbd_t *bdp;
+ printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n",
+ cep->cur_tx, cep->tx_full ? " (full)" : "",
+ cep->cur_rx);
+ bdp = cep->tx_bd_base;
+ for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
+ printk("%04x %04x %08x\n",
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ bdp = cep->rx_bd_base;
+ for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
+ printk("%04x %04x %08x\n",
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ }
+#endif
+ if (!cep->tx_full)
+ netif_wake_queue(dev);
+}
+
+/* The interrupt handler.
+ * This is called from the CPM handler, not the MPC core interrupt.
+ */
+static void
+scc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+ struct net_device *dev = dev_id;
+ volatile struct scc_enet_private *cep;
+ volatile cbd_t *bdp;
+ ushort int_events;
+ int must_restart;
+
+ cep = (struct scc_enet_private *)dev->priv;
+
+ /* Get the interrupt events that caused us to be here.
+ */
+ int_events = cep->sccp->scc_scce;
+ cep->sccp->scc_scce = int_events;
+ must_restart = 0;
+
+ /* Handle receive event in its own function.
+ */
+ if (int_events & SCCE_ENET_RXF)
+ scc_enet_rx(dev_id);
+
+ /* Check for a transmit error. The manual is a little unclear
+ * about this, so the debug code until I get it figured out. It
+ * appears that if TXE is set, then TXB is not set. However,
+ * if carrier sense is lost during frame transmission, the TXE
+ * bit is set, "and continues the buffer transmission normally."
+ * I don't know if "normally" implies TXB is set when the buffer
+ * descriptor is closed.....trial and error :-).
+ */
+
+ /* Transmit OK, or non-fatal error. Update the buffer descriptors.
+ */
+ if (int_events & (SCCE_ENET_TXE | SCCE_ENET_TXB)) {
+ spin_lock(&cep->lock);
+ bdp = cep->dirty_tx;
+ while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
+ if ((bdp==cep->cur_tx) && (cep->tx_full == 0))
+ break;
+
+ if (bdp->cbd_sc & BD_ENET_TX_HB) /* No heartbeat */
+ cep->stats.tx_heartbeat_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_LC) /* Late collision */
+ cep->stats.tx_window_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_RL) /* Retrans limit */
+ cep->stats.tx_aborted_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_UN) /* Underrun */
+ cep->stats.tx_fifo_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */
+ cep->stats.tx_carrier_errors++;
+
+
+ /* No heartbeat or Lost carrier are not really bad errors.
+ * The others require a restart transmit command.
+ */
+ if (bdp->cbd_sc &
+ (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
+ must_restart = 1;
+ cep->stats.tx_errors++;
+ }
+
+ cep->stats.tx_packets++;
+
+ /* Deferred means some collisions occurred during transmit,
+ * but we eventually sent the packet OK.
+ */
+ if (bdp->cbd_sc & BD_ENET_TX_DEF)
+ cep->stats.collisions++;
+
+ /* Free the sk buffer associated with this last transmit.
+ */
+ dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]);
+ cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
+
+ /* Update pointer to next buffer descriptor to be transmitted.
+ */
+ if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+ bdp = cep->tx_bd_base;
+ else
+ bdp++;
+
+ /* I don't know if we can be held off from processing these
+ * interrupts for more than one frame time. I really hope
+ * not. In such a case, we would now want to check the
+ * currently available BD (cur_tx) and determine if any
+ * buffers between the dirty_tx and cur_tx have also been
+ * sent. We would want to process anything in between that
+ * does not have BD_ENET_TX_READY set.
+ */
+
+ /* Since we have freed up a buffer, the ring is no longer
+ * full.
+ */
+ if (cep->tx_full) {
+ if (netif_queue_stopped(dev)) {
+ netif_wake_queue(dev);
+ }
+ }
+
+ cep->dirty_tx = (cbd_t *)bdp;
+ }
+
+ if (must_restart) {
+ volatile cpm8260_t *cp;
+
+ /* Some transmit errors cause the transmitter to shut
+ * down. We now issue a restart transmit. Since the
+ * errors close the BD and update the pointers, the restart
+ * _should_ pick up without having to reset any of our
+ * pointers either.
+ */
+ cp = cpmp;
+ cp->cp_cpcr =
+ mk_cr_cmd(CPM_ENET_PAGE, CPM_ENET_BLOCK, 0,
+ CPM_CR_RESTART_TX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+ }
+ spin_unlock(&cep->lock);
+ }
+
+ /* Check for receive busy, i.e. packets coming but no place to
+ * put them. This "can't happen" because the receive interrupt
+ * is tossing previous frames.
+ */
+ if (int_events & SCCE_ENET_BSY) {
+ cep->stats.rx_dropped++;
+ printk("SCC ENET: BSY can't happen.\n");
+ }
+
+ return;
+}
+
+/* During a receive, the cur_rx points to the current incoming buffer.
+ * When we update through the ring, if the next incoming buffer has
+ * not been given to the system, we just set the empty indicator,
+ * effectively tossing the packet.
+ */
+static int
+scc_enet_rx(struct net_device *dev)
+{
+ struct scc_enet_private *cep;
+ volatile cbd_t *bdp;
+ struct sk_buff *skb;
+ ushort pkt_len;
+
+ cep = (struct scc_enet_private *)dev->priv;
+
+ /* First, grab all of the stats for the incoming packet.
+ * These get messed up if we get called due to a busy condition.
+ */
+ bdp = cep->cur_rx;
+
+for (;;) {
+ if (bdp->cbd_sc & BD_ENET_RX_EMPTY)
+ break;
+
+#ifndef final_version
+ /* Since we have allocated space to hold a complete frame, both
+ * the first and last indicators should be set.
+ */
+ if ((bdp->cbd_sc & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) !=
+ (BD_ENET_RX_FIRST | BD_ENET_RX_LAST))
+ printk("CPM ENET: rcv is not first+last\n");
+#endif
+
+ /* Frame too long or too short.
+ */
+ if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
+ cep->stats.rx_length_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_NO) /* Frame alignment */
+ cep->stats.rx_frame_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_CR) /* CRC Error */
+ cep->stats.rx_crc_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_OV) /* FIFO overrun */
+ cep->stats.rx_crc_errors++;
+
+ /* Report late collisions as a frame error.
+ * On this error, the BD is closed, but we don't know what we
+ * have in the buffer. So, just drop this frame on the floor.
+ */
+ if (bdp->cbd_sc & BD_ENET_RX_CL) {
+ cep->stats.rx_frame_errors++;
+ }
+ else {
+
+ /* Process the incoming frame.
+ */
+ cep->stats.rx_packets++;
+ pkt_len = bdp->cbd_datlen;
+ cep->stats.rx_bytes += pkt_len;
+
+ /* This does 16 byte alignment, much more than we need.
+ */
+ skb = dev_alloc_skb(pkt_len);
+
+ if (skb == NULL) {
+ printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+ cep->stats.rx_dropped++;
+ }
+ else {
+ skb->dev = dev;
+ skb_put(skb,pkt_len); /* Make room */
+ eth_copy_and_sum(skb,
+ (unsigned char *)__va(bdp->cbd_bufaddr),
+ pkt_len, 0);
+ skb->protocol=eth_type_trans(skb,dev);
+ netif_rx(skb);
+ }
+ }
+
+ /* Clear the status flags for this buffer.
+ */
+ bdp->cbd_sc &= ~BD_ENET_RX_STATS;
+
+ /* Mark the buffer empty.
+ */
+ bdp->cbd_sc |= BD_ENET_RX_EMPTY;
+
+ /* Update BD pointer to next entry.
+ */
+ if (bdp->cbd_sc & BD_ENET_RX_WRAP)
+ bdp = cep->rx_bd_base;
+ else
+ bdp++;
+
+ }
+ cep->cur_rx = (cbd_t *)bdp;
+
+ return 0;
+}
+
+static int
+scc_enet_close(struct net_device *dev)
+{
+ /* Don't know what to do yet.
+ */
+ netif_stop_queue(dev);
+
+ return 0;
+}
+
+static struct net_device_stats *scc_enet_get_stats(struct net_device *dev)
+{
+ struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+
+ return &cep->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+ * Skeleton taken from sunlance driver.
+ * The CPM Ethernet implementation allows Multicast as well as individual
+ * MAC address filtering. Some of the drivers check to make sure it is
+ * a group multicast address, and discard those that are not. I guess I
+ * will do the same for now, but just remove the test if you want
+ * individual filtering as well (do the upper net layers want or support
+ * this kind of feature?).
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{
+ struct scc_enet_private *cep;
+ struct dev_mc_list *dmi;
+ u_char *mcptr, *tdptr;
+ volatile scc_enet_t *ep;
+ int i, j;
+ cep = (struct scc_enet_private *)dev->priv;
+
+ /* Get pointer to SCC area in parameter RAM.
+ */
+ ep = (scc_enet_t *)dev->base_addr;
+
+ if (dev->flags&IFF_PROMISC) {
+
+ /* Log any net taps. */
+ printk("%s: Promiscuous mode enabled.\n", dev->name);
+ cep->sccp->scc_pmsr |= SCC_PMSR_PRO;
+ } else {
+
+ cep->sccp->scc_pmsr &= ~SCC_PMSR_PRO;
+
+ if (dev->flags & IFF_ALLMULTI) {
+ /* Catch all multicast addresses, so set the
+ * filter to all 1's.
+ */
+ ep->sen_gaddr1 = 0xffff;
+ ep->sen_gaddr2 = 0xffff;
+ ep->sen_gaddr3 = 0xffff;
+ ep->sen_gaddr4 = 0xffff;
+ }
+ else {
+ /* Clear filter and add the addresses in the list.
+ */
+ ep->sen_gaddr1 = 0;
+ ep->sen_gaddr2 = 0;
+ ep->sen_gaddr3 = 0;
+ ep->sen_gaddr4 = 0;
+
+ dmi = dev->mc_list;
+
+ for (i=0; i<dev->mc_count; i++) {
+
+ /* Only support group multicast for now.
+ */
+ if (!(dmi->dmi_addr[0] & 1))
+ continue;
+
+ /* The address in dmi_addr is LSB first,
+ * and taddr is MSB first. We have to
+ * copy bytes MSB first from dmi_addr.
+ */
+ mcptr = (u_char *)dmi->dmi_addr + 5;
+ tdptr = (u_char *)&ep->sen_taddrh;
+ for (j=0; j<6; j++)
+ *tdptr++ = *mcptr--;
+
+ /* Ask CPM to run CRC and set bit in
+ * filter mask.
+ */
+ cpmp->cp_cpcr = mk_cr_cmd(CPM_ENET_PAGE,
+ CPM_ENET_BLOCK, 0,
+ CPM_CR_SET_GADDR) | CPM_CR_FLG;
+ /* this delay is necessary here -- Cort */
+ udelay(10);
+ while (cpmp->cp_cpcr & CPM_CR_FLG);
+ }
+ }
+ }
+}
+
+/* Initialize the CPM Ethernet on SCC.
+ */
+int __init scc_enet_init(void)
+{
+ struct net_device *dev;
+ struct scc_enet_private *cep;
+ int i, j;
+ unsigned char *eap;
+ unsigned long mem_addr;
+ bd_t *bd;
+ volatile cbd_t *bdp;
+ volatile cpm8260_t *cp;
+ volatile scc_t *sccp;
+ volatile scc_enet_t *ep;
+ volatile immap_t *immap;
+ volatile iop8260_t *io;
+
+ cp = cpmp; /* Get pointer to Communication Processor */
+
+ immap = (immap_t *)IMAP_ADDR; /* and to internal registers */
+ io = &immap->im_ioport;
+
+ bd = (bd_t *)__res;
+
+ /* Allocate some private information.
+ */
+ cep = (struct scc_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
+ __clear_user(cep,sizeof(*cep));
+ spin_lock_init(&cep->lock);
+
+ /* Create an Ethernet device instance.
+ */
+ dev = init_etherdev(0, 0);
+
+ /* Get pointer to SCC area in parameter RAM.
+ */
+ ep = (scc_enet_t *)(&immap->im_dprambase[PROFF_ENET]);
+
+ /* And another to the SCC register area.
+ */
+ sccp = (volatile scc_t *)(&immap->im_scc[SCC_ENET]);
+ cep->sccp = (scc_t *)sccp; /* Keep the pointer handy */
+
+ /* Disable receive and transmit in case someone left it running.
+ */
+ sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ /* Configure port C and D pins for SCC Ethernet. This
+ * won't work for all SCC possibilities....it will be
+ * board/port specific.
+ */
+ io->iop_pparc |=
+ (PC_ENET_RENA | PC_ENET_CLSN | PC_ENET_TXCLK | PC_ENET_RXCLK);
+ io->iop_pdirc &=
+ ~(PC_ENET_RENA | PC_ENET_CLSN | PC_ENET_TXCLK | PC_ENET_RXCLK);
+ io->iop_psorc &=
+ ~(PC_ENET_RENA | PC_ENET_TXCLK | PC_ENET_RXCLK);
+ io->iop_psorc |= PC_ENET_CLSN;
+
+ io->iop_ppard |= (PD_ENET_RXD | PD_ENET_TXD | PD_ENET_TENA);
+ io->iop_pdird |= (PD_ENET_TXD | PD_ENET_TENA);
+ io->iop_pdird &= ~PD_ENET_RXD;
+ io->iop_psord |= PD_ENET_TXD;
+ io->iop_psord &= ~(PD_ENET_RXD | PD_ENET_TENA);
+
+ /* Configure Serial Interface clock routing.
+ * First, clear all SCC bits to zero, then set the ones we want.
+ */
+ immap->im_cpmux.cmx_scr &= ~CMX_CLK_MASK;
+ immap->im_cpmux.cmx_scr |= CMX_CLK_ROUTE;
+
+ /* Allocate space for the buffer descriptors in the DP ram.
+ * These are relative offsets in the DP ram address space.
+ * Initialize base addresses for the buffer descriptors.
+ */
+ i = m8260_cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE);
+ ep->sen_genscc.scc_rbase = i;
+ cep->rx_bd_base = (cbd_t *)&immap->im_dprambase[i];
+
+ i = m8260_cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE);
+ ep->sen_genscc.scc_tbase = i;
+ cep->tx_bd_base = (cbd_t *)&immap->im_dprambase[i];
+
+ cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
+ cep->cur_rx = cep->rx_bd_base;
+
+ ep->sen_genscc.scc_rfcr = SCC_EB;
+ ep->sen_genscc.scc_tfcr = SCC_EB;
+
+ /* Set maximum bytes per receive buffer.
+ * This appears to be an Ethernet frame size, not the buffer
+ * fragment size. It must be a multiple of four.
+ */
+ ep->sen_genscc.scc_mrblr = PKT_MAXBLR_SIZE;
+
+ /* Set CRC preset and mask.
+ */
+ ep->sen_cpres = 0xffffffff;
+ ep->sen_cmask = 0xdebb20e3;
+
+ ep->sen_crcec = 0; /* CRC Error counter */
+ ep->sen_alec = 0; /* alignment error counter */
+ ep->sen_disfc = 0; /* discard frame counter */
+
+ ep->sen_pads = 0x8888; /* Tx short frame pad character */
+ ep->sen_retlim = 15; /* Retry limit threshold */
+
+ ep->sen_maxflr = PKT_MAXBUF_SIZE; /* maximum frame length register */
+ ep->sen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register */
+
+ ep->sen_maxd1 = PKT_MAXBLR_SIZE; /* maximum DMA1 length */
+ ep->sen_maxd2 = PKT_MAXBLR_SIZE; /* maximum DMA2 length */
+
+ /* Clear hash tables.
+ */
+ ep->sen_gaddr1 = 0;
+ ep->sen_gaddr2 = 0;
+ ep->sen_gaddr3 = 0;
+ ep->sen_gaddr4 = 0;
+ ep->sen_iaddr1 = 0;
+ ep->sen_iaddr2 = 0;
+ ep->sen_iaddr3 = 0;
+ ep->sen_iaddr4 = 0;
+
+ /* Set Ethernet station address.
+ *
+ * This is supplied in the board information structure, so we
+ * copy that into the controller.
+ */
+ eap = (unsigned char *)&(ep->sen_paddrh);
+ for (i=5; i>=0; i--)
+ *eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
+
+ ep->sen_pper = 0; /* 'cause the book says so */
+ ep->sen_taddrl = 0; /* temp address (LSB) */
+ ep->sen_taddrm = 0;
+ ep->sen_taddrh = 0; /* temp address (MSB) */
+
+ /* Now allocate the host memory pages and initialize the
+ * buffer descriptors.
+ */
+ bdp = cep->tx_bd_base;
+ for (i=0; i<TX_RING_SIZE; i++) {
+
+ /* Initialize the BD for every fragment in the page.
+ */
+ bdp->cbd_sc = 0;
+ bdp->cbd_bufaddr = 0;
+ bdp++;
+ }
+
+ /* Set the last buffer to wrap.
+ */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+
+ bdp = cep->rx_bd_base;
+ for (i=0; i<CPM_ENET_RX_PAGES; i++) {
+
+ /* Allocate a page.
+ */
+ mem_addr = __get_free_page(GFP_KERNEL);
+
+ /* Initialize the BD for every fragment in the page.
+ */
+ for (j=0; j<CPM_ENET_RX_FRPPG; j++) {
+ bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
+ bdp->cbd_bufaddr = __pa(mem_addr);
+ mem_addr += CPM_ENET_RX_FRSIZE;
+ bdp++;
+ }
+ }
+
+ /* Set the last buffer to wrap.
+ */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+
+ /* Let's re-initialize the channel now. We have to do it later
+ * than the manual describes because we have just now finished
+ * the BD initialization.
+ */
+ cpmp->cp_cpcr = mk_cr_cmd(CPM_ENET_PAGE, CPM_ENET_BLOCK, 0,
+ CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ cep->skb_cur = cep->skb_dirty = 0;
+
+ sccp->scc_scce = 0xffff; /* Clear any pending events */
+
+ /* Enable interrupts for transmit error, complete frame
+ * received, and any transmit buffer we have also set the
+ * interrupt flag.
+ */
+ sccp->scc_sccm = (SCCE_ENET_TXE | SCCE_ENET_RXF | SCCE_ENET_TXB);
+
+ /* Install our interrupt handler.
+ */
+ request_8xxirq(SIU_INT_ENET, scc_enet_interrupt, 0, "enet", dev);
+
+ /* Set GSMR_H to enable all normal operating modes.
+ * Set GSMR_L to enable Ethernet to MC68160.
+ */
+ sccp->scc_gsmrh = 0;
+ sccp->scc_gsmrl = (SCC_GSMRL_TCI | SCC_GSMRL_TPL_48 | SCC_GSMRL_TPP_10 | SCC_GSMRL_MODE_ENET);
+
+ /* Set sync/delimiters.
+ */
+ sccp->scc_dsr = 0xd555;
+
+ /* Set processing mode. Use Ethernet CRC, catch broadcast, and
+ * start frame search 22 bit times after RENA.
+ */
+ sccp->scc_pmsr = (SCC_PMSR_ENCRC | SCC_PMSR_NIB22);
+
+ /* It is now OK to enable the Ethernet transmitter.
+ * Unfortunately, there are board implementation differences here.
+ */
+ io->iop_pparc &= ~(PC_EST8260_ENET_LOOPBACK |
+ PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
+ io->iop_psorc &= ~(PC_EST8260_ENET_LOOPBACK |
+ PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
+ io->iop_pdirc |= (PC_EST8260_ENET_LOOPBACK |
+ PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
+ io->iop_pdatc &= ~(PC_EST8260_ENET_LOOPBACK | PC_EST8260_ENET_SQE);
+ io->iop_pdatc |= PC_EST8260_ENET_NOTFD;
+
+ dev->base_addr = (unsigned long)ep;
+ dev->priv = cep;
+
+ /* The CPM Ethernet specific entries in the device structure. */
+ dev->open = scc_enet_open;
+ dev->hard_start_xmit = scc_enet_start_xmit;
+ dev->tx_timeout = scc_enet_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+ dev->stop = scc_enet_close;
+ dev->get_stats = scc_enet_get_stats;
+ dev->set_multicast_list = set_multicast_list;
+
+ /* And last, enable the transmit and receive processing.
+ */
+ sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ printk("%s: SCC ENET Version 0.1, ", dev->name);
+ for (i=0; i<5; i++)
+ printk("%02x:", dev->dev_addr[i]);
+ printk("%02x\n", dev->dev_addr[5]);
+
+ return 0;
+}
+
diff --git a/arch/ppc/8260_io/uart.c b/arch/ppc/8260_io/uart.c
new file mode 100644
index 000000000..9e93bcdd5
--- /dev/null
+++ b/arch/ppc/8260_io/uart.c
@@ -0,0 +1,2772 @@
+/*
+ * UART driver for MPC8260 CPM SCC or SMC
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ * Copyright (c) 2000 MontaVista Software, Inc. (source@mvista.com)
+ * 2.3.99 updates
+ *
+ * I used the 8xx uart.c driver as the framework for this driver.
+ * The original code was written for the EST8260 board. I tried to make
+ * it generic, but there may be some assumptions in the structures that
+ * have to be fixed later.
+ *
+ * The 8xx and 8260 are similar, but not identical. Over time we
+ * could probably merge these two drivers.
+ * To save porting time, I did not bother to change any object names
+ * that are not accessed outside of this file.
+ * It still needs lots of work........When it was easy, I included code
+ * to support the SCCs.
+ * Only the SCCs support modem control, so that is not complete either.
+ *
+ * This module exports the following rs232 io functions:
+ *
+ * int rs_8xx_init(void);
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+#include <asm/immap_8260.h>
+#include <asm/mpc8260.h>
+#include <asm/cpm_8260.h>
+#include <asm/irq.h>
+
+#ifdef CONFIG_SERIAL_CONSOLE
+#include <linux/console.h>
+
+/* this defines the index into rs_table for the port to use
+*/
+#ifndef CONFIG_SERIAL_CONSOLE_PORT
+#define CONFIG_SERIAL_CONSOLE_PORT 0
+#endif
+#endif
+
+#define TX_WAKEUP ASYNC_SHARE_IRQ
+
+static char *serial_name = "CPM UART driver";
+static char *serial_version = "0.01";
+
+static DECLARE_TASK_QUEUE(tq_serial);
+
+static struct tty_driver serial_driver, callout_driver;
+static int serial_refcount;
+static int serial_console_setup(struct console *co, char *options);
+
+/*
+ * Serial driver configuration section. Here are the various options:
+ */
+#define SERIAL_PARANOIA_CHECK
+#define CONFIG_SERIAL_NOPAUSE_IO
+#define SERIAL_DO_RESTART
+
+/* Set of debugging defines */
+
+#undef SERIAL_DEBUG_INTR
+#undef SERIAL_DEBUG_OPEN
+#undef SERIAL_DEBUG_FLOW
+#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+
+#define _INLINE_ inline
+
+#define DBG_CNT(s)
+
+/* We overload some of the items in the data structure to meet our
+ * needs. For example, the port address is the CPM parameter ram
+ * offset for the SCC or SMC. The maximum number of ports is 4 SCCs and
+ * 2 SMCs. The "hub6" field is used to indicate the channel number, with
+ * 0 and 1 indicating the SMCs and 2, 3, 4, and 5 are the SCCs.
+ * Since these ports are so versatile, I don't yet have a strategy for
+ * their management. For example, SCC1 is used for Ethernet. Right
+ * now, just don't put them in the table. Of course, right now I just
+ * want the SMC to work as a uart :-)..
+ * The "type" field is currently set to 0, for PORT_UNKNOWN. It is
+ * not currently used. I should probably use it to indicate the port
+ * type of CMS or SCC.
+ * The SMCs do not support any modem control signals.
+ */
+#define smc_scc_num hub6
+
+/* SMC2 is sometimes used for low performance TDM interfaces. Define
+ * this as 1 if you want SMC2 as a serial port UART managed by this driver.
+ * Define this as 0 if you wish to use SMC2 for something else.
+ */
+#define USE_SMC2 1
+
+/* Define SCC to ttySx mapping.
+*/
+#define SCC_NUM_BASE (USE_SMC2 + 1) /* SCC base tty "number" */
+
+/* Define which SCC is the first one to use for a serial port. These
+ * are 0-based numbers, i.e. this assumes the first SCC (SCC1) is used
+ * for Ethernet, and the first available SCC for serial UART is SCC2.
+ * NOTE: IF YOU CHANGE THIS, you have to change the PROFF_xxx and
+ * interrupt vectors in the table below to match.
+ */
+#define SCC_IDX_BASE 1 /* table index */
+
+static struct serial_state rs_table[] = {
+ /* UART CLK PORT IRQ FLAGS NUM */
+ { 0, 0, PROFF_SMC1, SIU_INT_SMC1, 0, 0 }, /* SMC1 ttyS0 */
+#if USE_SMC2
+ { 0, 0, PROFF_SMC2, SIU_INT_SMC2, 0, 1 }, /* SMC2 ttyS1 */
+#endif
+ { 0, 0, PROFF_SCC2, SIU_INT_SCC2, 0, SCC_NUM_BASE}, /* SCC2 ttyS2 */
+ { 0, 0, PROFF_SCC3, SIU_INT_SCC3, 0, SCC_NUM_BASE + 1}, /* SCC3 ttyS3 */
+};
+
+#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state))
+
+static struct tty_struct *serial_table[NR_PORTS];
+static struct termios *serial_termios[NR_PORTS];
+static struct termios *serial_termios_locked[NR_PORTS];
+
+/* The number of buffer descriptors and their sizes.
+*/
+#define RX_NUM_FIFO 4
+#define RX_BUF_SIZE 32
+#define TX_NUM_FIFO 4
+#define TX_BUF_SIZE 32
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+/* The async_struct in serial.h does not really give us what we
+ * need, so define our own here.
+ */
+typedef struct serial_info {
+ int magic;
+ int flags;
+ struct serial_state *state;
+ struct tty_struct *tty;
+ int read_status_mask;
+ int ignore_status_mask;
+ int timeout;
+ int line;
+ int x_char; /* xon/xoff character */
+ int close_delay;
+ unsigned short closing_wait;
+ unsigned short closing_wait2;
+ unsigned long event;
+ unsigned long last_active;
+ int blocked_open; /* # of blocked opens */
+ long session; /* Session of opening process */
+ long pgrp; /* pgrp of opening process */
+ struct tq_struct tqueue;
+ struct tq_struct tqueue_hangup;
+ wait_queue_head_t open_wait;
+ wait_queue_head_t close_wait;
+
+ /* CPM Buffer Descriptor pointers.
+ */
+ cbd_t *rx_bd_base;
+ cbd_t *rx_cur;
+ cbd_t *tx_bd_base;
+ cbd_t *tx_cur;
+} ser_info_t;
+
+static void change_speed(ser_info_t *info);
+static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout);
+
+static inline int serial_paranoia_check(ser_info_t *info,
+ kdev_t device, const char *routine)
+{
+#ifdef SERIAL_PARANOIA_CHECK
+ static const char *badmagic =
+ "Warning: bad magic number for serial struct (%s) in %s\n";
+ static const char *badinfo =
+ "Warning: null async_struct for (%s) in %s\n";
+
+ if (!info) {
+ printk(badinfo, kdevname(device), routine);
+ return 1;
+ }
+ if (info->magic != SERIAL_MAGIC) {
+ printk(badmagic, kdevname(device), routine);
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+/*
+ * This is used to figure out the divisor speeds and the timeouts,
+ * indexed by the termio value. The generic CPM functions are responsible
+ * for setting and assigning baud rate generators for us.
+ */
+static int baud_table[] = {
+ 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+ 9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 };
+
+
+/*
+ * ------------------------------------------------------------
+ * rs_stop() and rs_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * They enable or disable transmitter interrupts, as necessary.
+ * ------------------------------------------------------------
+ */
+static void rs_8xx_stop(struct tty_struct *tty)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ int idx;
+ unsigned long flags;
+ volatile scc_t *sccp;
+ volatile smc_t *smcp;
+
+ if (serial_paranoia_check(info, tty->device, "rs_stop"))
+ return;
+
+ save_flags(flags); cli();
+ if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+ smcp = &immr->im_smc[idx];
+ smcp->smc_smcm &= ~SMCM_TX;
+ }
+ else {
+ sccp = &immr->im_scc[idx - SCC_IDX_BASE];
+ sccp->scc_sccm &= ~UART_SCCM_TX;
+ }
+ restore_flags(flags);
+}
+
+static void rs_8xx_start(struct tty_struct *tty)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ int idx;
+ unsigned long flags;
+ volatile scc_t *sccp;
+ volatile smc_t *smcp;
+
+ if (serial_paranoia_check(info, tty->device, "rs_stop"))
+ return;
+
+ save_flags(flags); cli();
+ if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+ smcp = &immr->im_smc[idx];
+ smcp->smc_smcm |= SMCM_TX;
+ }
+ else {
+ sccp = &immr->im_scc[idx - SCC_IDX_BASE];
+ sccp->scc_sccm |= UART_SCCM_TX;
+ }
+ restore_flags(flags);
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * Here starts the interrupt handling routines. All of the following
+ * subroutines are declared as inline and are folded into
+ * rs_interrupt(). They were separated out for readability's sake.
+ *
+ * Note: rs_interrupt() is a "fast" interrupt, which means that it
+ * runs with interrupts turned off. People who may want to modify
+ * rs_interrupt() should try to keep the interrupt handler as fast as
+ * possible. After you are done making modifications, it is not a bad
+ * idea to do:
+ *
+ * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
+ *
+ * and look at the resulting assemble code in serial.s.
+ *
+ * - Ted Ts'o (tytso@mit.edu), 7-Mar-93
+ * -----------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used by the interrupt handler to schedule
+ * processing in the software interrupt portion of the driver.
+ */
+static _INLINE_ void rs_sched_event(ser_info_t *info,
+ int event)
+{
+ info->event |= 1 << event;
+ queue_task(&info->tqueue, &tq_serial);
+ mark_bh(SERIAL_BH);
+}
+
+static _INLINE_ void receive_chars(ser_info_t *info)
+{
+ struct tty_struct *tty = info->tty;
+ unsigned char ch, *cp;
+ /*int ignored = 0;*/
+ int i;
+ ushort status;
+ struct async_icount *icount;
+ volatile cbd_t *bdp;
+
+ icount = &info->state->icount;
+
+ /* Just loop through the closed BDs and copy the characters into
+ * the buffer.
+ */
+ bdp = info->rx_cur;
+ for (;;) {
+ if (bdp->cbd_sc & BD_SC_EMPTY) /* If this one is empty */
+ break; /* we are all done */
+
+ /* The read status mask tell us what we should do with
+ * incoming characters, especially if errors occur.
+ * One special case is the use of BD_SC_EMPTY. If
+ * this is not set, we are supposed to be ignoring
+ * inputs. In this case, just mark the buffer empty and
+ * continue.
+ if (!(info->read_status_mask & BD_SC_EMPTY)) {
+ bdp->cbd_sc |= BD_SC_EMPTY;
+ bdp->cbd_sc &=
+ ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
+
+ if (bdp->cbd_sc & BD_SC_WRAP)
+ bdp = info->rx_bd_base;
+ else
+ bdp++;
+ continue;
+ }
+ */
+
+ /* Get the number of characters and the buffer pointer.
+ */
+ i = bdp->cbd_datlen;
+ cp = (unsigned char *)__va(bdp->cbd_bufaddr);
+ status = bdp->cbd_sc;
+
+ /* Check to see if there is room in the tty buffer for
+ * the characters in our BD buffer. If not, we exit
+ * now, leaving the BD with the characters. We'll pick
+ * them up again on the next receive interrupt (which could
+ * be a timeout).
+ */
+ if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE)
+ break;
+
+ while (i-- > 0) {
+ ch = *cp++;
+ *tty->flip.char_buf_ptr = ch;
+ icount->rx++;
+
+#ifdef SERIAL_DEBUG_INTR
+ printk("DR%02x:%02x...", ch, *status);
+#endif
+ *tty->flip.flag_buf_ptr = 0;
+ if (status & (BD_SC_BR | BD_SC_FR |
+ BD_SC_PR | BD_SC_OV)) {
+ /*
+ * For statistics only
+ */
+ if (status & BD_SC_BR)
+ icount->brk++;
+ else if (status & BD_SC_PR)
+ icount->parity++;
+ else if (status & BD_SC_FR)
+ icount->frame++;
+ if (status & BD_SC_OV)
+ icount->overrun++;
+
+ /*
+ * Now check to see if character should be
+ * ignored, and mask off conditions which
+ * should be ignored.
+ if (status & info->ignore_status_mask) {
+ if (++ignored > 100)
+ break;
+ continue;
+ }
+ */
+ status &= info->read_status_mask;
+
+ if (status & (BD_SC_BR)) {
+#ifdef SERIAL_DEBUG_INTR
+ printk("handling break....");
+#endif
+ *tty->flip.flag_buf_ptr = TTY_BREAK;
+ if (info->flags & ASYNC_SAK)
+ do_SAK(tty);
+ } else if (status & BD_SC_PR)
+ *tty->flip.flag_buf_ptr = TTY_PARITY;
+ else if (status & BD_SC_FR)
+ *tty->flip.flag_buf_ptr = TTY_FRAME;
+ if (status & BD_SC_OV) {
+ /*
+ * Overrun is special, since it's
+ * reported immediately, and doesn't
+ * affect the current character
+ */
+ if (tty->flip.count < TTY_FLIPBUF_SIZE) {
+ tty->flip.count++;
+ tty->flip.flag_buf_ptr++;
+ tty->flip.char_buf_ptr++;
+ *tty->flip.flag_buf_ptr =
+ TTY_OVERRUN;
+ }
+ }
+ }
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+ break;
+
+ tty->flip.flag_buf_ptr++;
+ tty->flip.char_buf_ptr++;
+ tty->flip.count++;
+ }
+
+ /* This BD is ready to be used again. Clear status.
+ * Get next BD.
+ */
+ bdp->cbd_sc |= BD_SC_EMPTY;
+ bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
+
+ if (bdp->cbd_sc & BD_SC_WRAP)
+ bdp = info->rx_bd_base;
+ else
+ bdp++;
+ }
+
+ info->rx_cur = (cbd_t *)bdp;
+
+ queue_task(&tty->flip.tqueue, &tq_timer);
+}
+
+static _INLINE_ void transmit_chars(ser_info_t *info)
+{
+
+ if (info->flags & TX_WAKEUP) {
+ rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+ }
+
+#ifdef SERIAL_DEBUG_INTR
+ printk("THRE...");
+#endif
+}
+
+#ifdef notdef
+ /* I need to do this for the SCCs, so it is left as a reminder.
+ */
+static _INLINE_ void check_modem_status(struct async_struct *info)
+{
+ int status;
+ struct async_icount *icount;
+
+ status = serial_in(info, UART_MSR);
+
+ if (status & UART_MSR_ANY_DELTA) {
+ icount = &info->state->icount;
+ /* update input line counters */
+ if (status & UART_MSR_TERI)
+ icount->rng++;
+ if (status & UART_MSR_DDSR)
+ icount->dsr++;
+ if (status & UART_MSR_DDCD) {
+ icount->dcd++;
+#ifdef CONFIG_HARD_PPS
+ if ((info->flags & ASYNC_HARDPPS_CD) &&
+ (status & UART_MSR_DCD))
+ hardpps();
+#endif
+ }
+ if (status & UART_MSR_DCTS)
+ icount->cts++;
+ wake_up_interruptible(&info->delta_msr_wait);
+ }
+
+ if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
+#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
+ printk("ttys%d CD now %s...", info->line,
+ (status & UART_MSR_DCD) ? "on" : "off");
+#endif
+ if (status & UART_MSR_DCD)
+ wake_up_interruptible(&info->open_wait);
+ else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+ (info->flags & ASYNC_CALLOUT_NOHUP))) {
+#ifdef SERIAL_DEBUG_OPEN
+ printk("scheduling hangup...");
+#endif
+ queue_task(&info->tqueue_hangup,
+ &tq_scheduler);
+ }
+ }
+ if (info->flags & ASYNC_CTS_FLOW) {
+ if (info->tty->hw_stopped) {
+ if (status & UART_MSR_CTS) {
+#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
+ printk("CTS tx start...");
+#endif
+ info->tty->hw_stopped = 0;
+ info->IER |= UART_IER_THRI;
+ serial_out(info, UART_IER, info->IER);
+ rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+ return;
+ }
+ } else {
+ if (!(status & UART_MSR_CTS)) {
+#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
+ printk("CTS tx stop...");
+#endif
+ info->tty->hw_stopped = 1;
+ info->IER &= ~UART_IER_THRI;
+ serial_out(info, UART_IER, info->IER);
+ }
+ }
+ }
+}
+#endif
+
+/*
+ * This is the serial driver's interrupt routine for a single port
+ */
+static void rs_8xx_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+ u_char events;
+ int idx;
+ ser_info_t *info;
+ volatile smc_t *smcp;
+ volatile scc_t *sccp;
+
+ info = (ser_info_t *)dev_id;
+
+ if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+ smcp = &immr->im_smc[idx];
+ events = smcp->smc_smce;
+ if (events & SMCM_RX)
+ receive_chars(info);
+ if (events & SMCM_TX)
+ transmit_chars(info);
+ smcp->smc_smce = events;
+ }
+ else {
+ sccp = &immr->im_scc[idx - SCC_IDX_BASE];
+ events = sccp->scc_scce;
+ if (events & SCCM_RX)
+ receive_chars(info);
+ if (events & SCCM_TX)
+ transmit_chars(info);
+ sccp->scc_scce = events;
+ }
+
+#ifdef SERIAL_DEBUG_INTR
+ printk("rs_interrupt_single(%d, %x)...",
+ info->state->smc_scc_num, events);
+#endif
+#ifdef modem_control
+ check_modem_status(info);
+#endif
+ info->last_active = jiffies;
+#ifdef SERIAL_DEBUG_INTR
+ printk("end.\n");
+#endif
+}
+
+
+/*
+ * -------------------------------------------------------------------
+ * Here ends the serial interrupt routines.
+ * -------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used to handle the "bottom half" processing for the
+ * serial driver, known also the "software interrupt" processing.
+ * This processing is done at the kernel interrupt level, after the
+ * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This
+ * is where time-consuming activities which can not be done in the
+ * interrupt driver proper are done; the interrupt driver schedules
+ * them using rs_sched_event(), and they get done here.
+ */
+static void do_serial_bh(void)
+{
+ run_task_queue(&tq_serial);
+}
+
+static void do_softint(void *private_)
+{
+ ser_info_t *info = (ser_info_t *) private_;
+ struct tty_struct *tty;
+
+ tty = info->tty;
+ if (!tty)
+ return;
+
+ if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup)(tty);
+ wake_up_interruptible(&tty->write_wait);
+ }
+}
+
+/*
+ * This routine is called from the scheduler tqueue when the interrupt
+ * routine has signalled that a hangup has occurred. The path of
+ * hangup processing is:
+ *
+ * serial interrupt routine -> (scheduler tqueue) ->
+ * do_serial_hangup() -> tty->hangup() -> rs_hangup()
+ *
+ */
+static void do_serial_hangup(void *private_)
+{
+ struct async_struct *info = (struct async_struct *) private_;
+ struct tty_struct *tty;
+
+ tty = info->tty;
+ if (!tty)
+ return;
+
+ tty_hangup(tty);
+}
+
+/*static void rs_8xx_timer(void)
+{
+ printk("rs_8xx_timer\n");
+}*/
+
+
+static int startup(ser_info_t *info)
+{
+ unsigned long flags;
+ int retval=0;
+ int idx;
+ struct serial_state *state= info->state;
+ volatile smc_t *smcp;
+ volatile scc_t *sccp;
+ volatile smc_uart_t *up;
+ volatile scc_uart_t *scup;
+
+
+ save_flags(flags); cli();
+
+ if (info->flags & ASYNC_INITIALIZED) {
+ goto errout;
+ }
+
+#ifdef maybe
+ if (!state->port || !state->type) {
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+ goto errout;
+ }
+#endif
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("starting up ttys%d (irq %d)...", info->line, state->irq);
+#endif
+
+
+#ifdef modem_control
+ info->MCR = 0;
+ if (info->tty->termios->c_cflag & CBAUD)
+ info->MCR = UART_MCR_DTR | UART_MCR_RTS;
+#endif
+
+ if (info->tty)
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+
+ /*
+ * and set the speed of the serial port
+ */
+ change_speed(info);
+
+ if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+ smcp = &immr->im_smc[idx];
+
+ /* Enable interrupts and I/O.
+ */
+ smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
+ smcp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN);
+
+ /* We can tune the buffer length and idle characters
+ * to take advantage of the entire incoming buffer size.
+ * If mrblr is something other than 1, maxidl has to be
+ * non-zero or we never get an interrupt. The maxidl
+ * is the number of character times we wait after reception
+ * of the last character before we decide no more characters
+ * are coming.
+ */
+ up = (smc_uart_t *)&immr->im_dprambase[state->port];
+#if 0
+ up->smc_mrblr = 1; /* receive buffer length */
+ up->smc_maxidl = 0; /* wait forever for next char */
+#else
+ up->smc_mrblr = RX_BUF_SIZE;
+ up->smc_maxidl = RX_BUF_SIZE;
+#endif
+ up->smc_brkcr = 1; /* number of break chars */
+ }
+ else {
+ sccp = &immr->im_scc[idx - SCC_IDX_BASE];
+ scup = (scc_uart_t *)&immr->im_dprambase[state->port];
+#if 0
+ scup->scc_genscc.scc_mrblr = 1; /* receive buffer length */
+ scup->scc_maxidl = 0; /* wait forever for next char */
+#else
+ scup->scc_genscc.scc_mrblr = RX_BUF_SIZE;
+ scup->scc_maxidl = RX_BUF_SIZE;
+#endif
+
+ sccp->scc_sccm |= (UART_SCCM_TX | UART_SCCM_RX);
+ sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+ }
+
+ info->flags |= ASYNC_INITIALIZED;
+ restore_flags(flags);
+ return 0;
+
+errout:
+ restore_flags(flags);
+ return retval;
+}
+
+/*
+ * This routine will shutdown a serial port; interrupts are disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+static void shutdown(ser_info_t * info)
+{
+ unsigned long flags;
+ struct serial_state *state;
+ int idx;
+ volatile smc_t *smcp;
+ volatile scc_t *sccp;
+
+ if (!(info->flags & ASYNC_INITIALIZED))
+ return;
+
+ state = info->state;
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("Shutting down serial port %d (irq %d)....", info->line,
+ state->irq);
+#endif
+
+ save_flags(flags); cli(); /* Disable interrupts */
+
+ if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+ smcp = &immr->im_smc[idx];
+
+ /* Disable interrupts and I/O.
+ */
+ smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
+#ifdef CONFIG_SERIAL_CONSOLE
+ /* We can't disable the transmitter if this is the
+ * system console.
+ */
+ if (idx != CONFIG_SERIAL_CONSOLE_PORT)
+#endif
+ smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+ }
+ else {
+ sccp = &immr->im_scc[idx - SCC_IDX_BASE];
+ sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
+ sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+ }
+
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+ info->flags &= ~ASYNC_INITIALIZED;
+ restore_flags(flags);
+}
+
+/*
+ * This routine is called to set the UART divisor registers to match
+ * the specified baud rate for a serial port.
+ */
+static void change_speed(ser_info_t *info)
+{
+ int baud_rate;
+ unsigned cflag, cval, scval, prev_mode;
+ int i, bits, sbits, idx;
+ unsigned long flags;
+ volatile smc_t *smcp;
+ volatile scc_t *sccp;
+
+ if (!info->tty || !info->tty->termios)
+ return;
+ cflag = info->tty->termios->c_cflag;
+
+ /* Character length programmed into the mode register is the
+ * sum of: 1 start bit, number of data bits, 0 or 1 parity bit,
+ * 1 or 2 stop bits, minus 1.
+ * The value 'bits' counts this for us.
+ */
+ cval = 0;
+ scval = 0;
+
+ /* byte size and parity */
+ switch (cflag & CSIZE) {
+ case CS5: bits = 5; break;
+ case CS6: bits = 6; break;
+ case CS7: bits = 7; break;
+ case CS8: bits = 8; break;
+ /* Never happens, but GCC is too dumb to figure it out */
+ default: bits = 8; break;
+ }
+ sbits = bits - 5;
+
+ if (cflag & CSTOPB) {
+ cval |= SMCMR_SL; /* Two stops */
+ scval |= SCU_PMSR_SL;
+ bits++;
+ }
+ if (cflag & PARENB) {
+ cval |= SMCMR_PEN;
+ scval |= SCU_PMSR_PEN;
+ bits++;
+ }
+ if (!(cflag & PARODD)) {
+ cval |= SMCMR_PM_EVEN;
+ scval |= (SCU_PMSR_REVP | SCU_PMSR_TEVP);
+ }
+
+ /* Determine divisor based on baud rate */
+ i = cflag & CBAUD;
+ if (i >= (sizeof(baud_table)/sizeof(int)))
+ baud_rate = 9600;
+ else
+ baud_rate = baud_table[i];
+
+ info->timeout = (TX_BUF_SIZE*HZ*bits);
+ info->timeout += HZ/50; /* Add .02 seconds of slop */
+
+#ifdef modem_control
+ /* CTS flow control flag and modem status interrupts */
+ info->IER &= ~UART_IER_MSI;
+ if (info->flags & ASYNC_HARDPPS_CD)
+ info->IER |= UART_IER_MSI;
+ if (cflag & CRTSCTS) {
+ info->flags |= ASYNC_CTS_FLOW;
+ info->IER |= UART_IER_MSI;
+ } else
+ info->flags &= ~ASYNC_CTS_FLOW;
+ if (cflag & CLOCAL)
+ info->flags &= ~ASYNC_CHECK_CD;
+ else {
+ info->flags |= ASYNC_CHECK_CD;
+ info->IER |= UART_IER_MSI;
+ }
+ serial_out(info, UART_IER, info->IER);
+#endif
+
+ /*
+ * Set up parity check flag
+ */
+#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+ info->read_status_mask = (BD_SC_EMPTY | BD_SC_OV);
+ if (I_INPCK(info->tty))
+ info->read_status_mask |= BD_SC_FR | BD_SC_PR;
+ if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
+ info->read_status_mask |= BD_SC_BR;
+
+ /*
+ * Characters to ignore
+ */
+ info->ignore_status_mask = 0;
+ if (I_IGNPAR(info->tty))
+ info->ignore_status_mask |= BD_SC_PR | BD_SC_FR;
+ if (I_IGNBRK(info->tty)) {
+ info->ignore_status_mask |= BD_SC_BR;
+ /*
+ * If we're ignore parity and break indicators, ignore
+ * overruns too. (For real raw support).
+ */
+ if (I_IGNPAR(info->tty))
+ info->ignore_status_mask |= BD_SC_OV;
+ }
+ /*
+ * !!! ignore all characters if CREAD is not set
+ */
+ if ((cflag & CREAD) == 0)
+ info->read_status_mask &= ~BD_SC_EMPTY;
+ save_flags(flags); cli();
+
+ /* Start bit has not been added (so don't, because we would just
+ * subtract it later), and we need to add one for the number of
+ * stops bits (there is always at least one).
+ */
+ bits++;
+ if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+ smcp = &immr->im_smc[idx];
+
+ /* Set the mode register. We want to keep a copy of the
+ * enables, because we want to put them back if they were
+ * present.
+ */
+ prev_mode = smcp->smc_smcmr;
+ smcp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART;
+ smcp->smc_smcmr |= (prev_mode & (SMCMR_REN | SMCMR_TEN));
+ }
+ else {
+ sccp = &immr->im_scc[idx - SCC_IDX_BASE];
+ sccp->scc_pmsr = (sbits << 12) | scval;
+ }
+
+ m8260_cpm_setbrg(info->state->smc_scc_num, baud_rate);
+
+ restore_flags(flags);
+}
+
+static void rs_8xx_put_char(struct tty_struct *tty, unsigned char ch)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ volatile cbd_t *bdp;
+
+ if (serial_paranoia_check(info, tty->device, "rs_put_char"))
+ return;
+
+ if (!tty)
+ return;
+
+ bdp = info->tx_cur;
+ while (bdp->cbd_sc & BD_SC_READY);
+
+ *((char *)__va(bdp->cbd_bufaddr)) = ch;
+ bdp->cbd_datlen = 1;
+ bdp->cbd_sc |= BD_SC_READY;
+
+ /* Get next BD.
+ */
+ if (bdp->cbd_sc & BD_SC_WRAP)
+ bdp = info->tx_bd_base;
+ else
+ bdp++;
+
+ info->tx_cur = (cbd_t *)bdp;
+
+}
+
+static int rs_8xx_write(struct tty_struct * tty, int from_user,
+ const unsigned char *buf, int count)
+{
+ int c, ret = 0;
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ volatile cbd_t *bdp;
+
+ if (serial_paranoia_check(info, tty->device, "rs_write"))
+ return 0;
+
+ if (!tty)
+ return 0;
+
+ bdp = info->tx_cur;
+
+ while (1) {
+ c = MIN(count, TX_BUF_SIZE);
+
+ if (c <= 0)
+ break;
+
+ if (bdp->cbd_sc & BD_SC_READY) {
+ info->flags |= TX_WAKEUP;
+ break;
+ }
+
+ if (from_user) {
+ if (c !=
+ copy_from_user(__va(bdp->cbd_bufaddr), buf, c)) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
+ } else {
+ memcpy(__va(bdp->cbd_bufaddr), buf, c);
+ }
+
+ bdp->cbd_datlen = c;
+ bdp->cbd_sc |= BD_SC_READY;
+
+ buf += c;
+ count -= c;
+ ret += c;
+
+ /* Get next BD.
+ */
+ if (bdp->cbd_sc & BD_SC_WRAP)
+ bdp = info->tx_bd_base;
+ else
+ bdp++;
+ info->tx_cur = (cbd_t *)bdp;
+ }
+ return ret;
+}
+
+static int rs_8xx_write_room(struct tty_struct *tty)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ int ret;
+
+ if (serial_paranoia_check(info, tty->device, "rs_write_room"))
+ return 0;
+
+ if ((info->tx_cur->cbd_sc & BD_SC_READY) == 0) {
+ info->flags &= ~TX_WAKEUP;
+ ret = TX_BUF_SIZE;
+ }
+ else {
+ info->flags |= TX_WAKEUP;
+ ret = 0;
+ }
+ return ret;
+}
+
+/* I could track this with transmit counters....maybe later.
+*/
+static int rs_8xx_chars_in_buffer(struct tty_struct *tty)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+
+ if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))
+ return 0;
+ return 0;
+}
+
+static void rs_8xx_flush_buffer(struct tty_struct *tty)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+
+ if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))
+ return;
+
+ /* There is nothing to "flush", whatever we gave the CPM
+ * is on its way out.
+ */
+ wake_up_interruptible(&tty->write_wait);
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup)(tty);
+ info->flags &= ~TX_WAKEUP;
+}
+
+/*
+ * This function is used to send a high-priority XON/XOFF character to
+ * the device
+ */
+static void rs_8xx_send_xchar(struct tty_struct *tty, char ch)
+{
+ volatile cbd_t *bdp;
+
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+
+ if (serial_paranoia_check(info, tty->device, "rs_send_char"))
+ return;
+
+ bdp = info->tx_cur;
+ while (bdp->cbd_sc & BD_SC_READY);
+
+ *((char *)__va(bdp->cbd_bufaddr)) = ch;
+ bdp->cbd_datlen = 1;
+ bdp->cbd_sc |= BD_SC_READY;
+
+ /* Get next BD.
+ */
+ if (bdp->cbd_sc & BD_SC_WRAP)
+ bdp = info->tx_bd_base;
+ else
+ bdp++;
+
+ info->tx_cur = (cbd_t *)bdp;
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_throttle()
+ *
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ * ------------------------------------------------------------
+ */
+static void rs_8xx_throttle(struct tty_struct * tty)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+#ifdef SERIAL_DEBUG_THROTTLE
+ char buf[64];
+
+ printk("throttle %s: %d....\n", _tty_name(tty, buf),
+ tty->ldisc.chars_in_buffer(tty));
+#endif
+
+ if (serial_paranoia_check(info, tty->device, "rs_throttle"))
+ return;
+
+ if (I_IXOFF(tty))
+ rs_8xx_send_xchar(tty, STOP_CHAR(tty));
+
+#ifdef modem_control
+ if (tty->termios->c_cflag & CRTSCTS)
+ info->MCR &= ~UART_MCR_RTS;
+
+ cli();
+ serial_out(info, UART_MCR, info->MCR);
+ sti();
+#endif
+}
+
+static void rs_8xx_unthrottle(struct tty_struct * tty)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+#ifdef SERIAL_DEBUG_THROTTLE
+ char buf[64];
+
+ printk("unthrottle %s: %d....\n", _tty_name(tty, buf),
+ tty->ldisc.chars_in_buffer(tty));
+#endif
+
+ if (serial_paranoia_check(info, tty->device, "rs_unthrottle"))
+ return;
+
+ if (I_IXOFF(tty)) {
+ if (info->x_char)
+ info->x_char = 0;
+ else
+ rs_8xx_send_xchar(tty, START_CHAR(tty));
+ }
+#ifdef modem_control
+ if (tty->termios->c_cflag & CRTSCTS)
+ info->MCR |= UART_MCR_RTS;
+ cli();
+ serial_out(info, UART_MCR, info->MCR);
+ sti();
+#endif
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_ioctl() and friends
+ * ------------------------------------------------------------
+ */
+
+#ifdef maybe
+/*
+ * get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ * is emptied. On bus types like RS485, the transmitter must
+ * release the bus after transmitting. This must be done when
+ * the transmit shift register is empty, not be done when the
+ * transmit holding register is empty. This functionality
+ * allows an RS485 driver to be written in user space.
+ */
+static int get_lsr_info(struct async_struct * info, unsigned int *value)
+{
+ unsigned char status;
+ unsigned int result;
+
+ cli();
+ status = serial_in(info, UART_LSR);
+ sti();
+ result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
+ return put_user(result,value);
+}
+#endif
+
+static int get_modem_info(ser_info_t *info, unsigned int *value)
+{
+ unsigned int result = 0;
+#ifdef modem_control
+ unsigned char control, status;
+
+ control = info->MCR;
+ cli();
+ status = serial_in(info, UART_MSR);
+ sti();
+ result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
+ | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
+#ifdef TIOCM_OUT1
+ | ((control & UART_MCR_OUT1) ? TIOCM_OUT1 : 0)
+ | ((control & UART_MCR_OUT2) ? TIOCM_OUT2 : 0)
+#endif
+ | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
+ | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
+ | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
+ | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
+#endif
+ return put_user(result,value);
+}
+
+static int set_modem_info(ser_info_t *info, unsigned int cmd,
+ unsigned int *value)
+{
+ int error;
+ unsigned int arg;
+
+ error = get_user(arg, value);
+ if (error)
+ return error;
+#ifdef modem_control
+ switch (cmd) {
+ case TIOCMBIS:
+ if (arg & TIOCM_RTS)
+ info->MCR |= UART_MCR_RTS;
+ if (arg & TIOCM_DTR)
+ info->MCR |= UART_MCR_DTR;
+#ifdef TIOCM_OUT1
+ if (arg & TIOCM_OUT1)
+ info->MCR |= UART_MCR_OUT1;
+ if (arg & TIOCM_OUT2)
+ info->MCR |= UART_MCR_OUT2;
+#endif
+ break;
+ case TIOCMBIC:
+ if (arg & TIOCM_RTS)
+ info->MCR &= ~UART_MCR_RTS;
+ if (arg & TIOCM_DTR)
+ info->MCR &= ~UART_MCR_DTR;
+#ifdef TIOCM_OUT1
+ if (arg & TIOCM_OUT1)
+ info->MCR &= ~UART_MCR_OUT1;
+ if (arg & TIOCM_OUT2)
+ info->MCR &= ~UART_MCR_OUT2;
+#endif
+ break;
+ case TIOCMSET:
+ info->MCR = ((info->MCR & ~(UART_MCR_RTS |
+#ifdef TIOCM_OUT1
+ UART_MCR_OUT1 |
+ UART_MCR_OUT2 |
+#endif
+ UART_MCR_DTR))
+ | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
+#ifdef TIOCM_OUT1
+ | ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0)
+ | ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0)
+#endif
+ | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
+ break;
+ default:
+ return -EINVAL;
+ }
+ cli();
+ serial_out(info, UART_MCR, info->MCR);
+ sti();
+#endif
+ return 0;
+}
+
+/* Sending a break is a two step process on the SMC/SCC. It is accomplished
+ * by sending a STOP TRANSMIT command followed by a RESTART TRANSMIT
+ * command. We take advantage of the begin/end functions to make this
+ * happen.
+ */
+static void begin_break(ser_info_t *info)
+{
+ volatile cpm8260_t *cp;
+ uint page, sblock;
+ ushort num;
+
+ cp = cpmp;
+
+ if ((num = info->state->smc_scc_num) < SCC_NUM_BASE) {
+ if (num == 0) {
+ page = CPM_CR_SMC1_PAGE;
+ sblock = CPM_CR_SMC1_SBLOCK;
+ }
+ else {
+ page = CPM_CR_SMC2_PAGE;
+ sblock = CPM_CR_SMC2_SBLOCK;
+ }
+ }
+ else {
+ num -= SCC_NUM_BASE;
+ switch (num) {
+ case 0:
+ page = CPM_CR_SCC1_PAGE;
+ sblock = CPM_CR_SCC1_SBLOCK;
+ break;
+ case 1:
+ page = CPM_CR_SCC2_PAGE;
+ sblock = CPM_CR_SCC2_SBLOCK;
+ break;
+ case 2:
+ page = CPM_CR_SCC3_PAGE;
+ sblock = CPM_CR_SCC3_SBLOCK;
+ break;
+ case 3:
+ page = CPM_CR_SCC4_PAGE;
+ sblock = CPM_CR_SCC4_SBLOCK;
+ break;
+ default: return;
+ }
+ }
+ cp->cp_cpcr = mk_cr_cmd(page, sblock, 0, CPM_CR_STOP_TX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+}
+
+static void end_break(ser_info_t *info)
+{
+ volatile cpm8260_t *cp;
+ uint page, sblock;
+ ushort num;
+
+ cp = cpmp;
+
+ if ((num = info->state->smc_scc_num) < SCC_NUM_BASE) {
+ if (num == 0) {
+ page = CPM_CR_SMC1_PAGE;
+ sblock = CPM_CR_SMC1_SBLOCK;
+ }
+ else {
+ page = CPM_CR_SMC2_PAGE;
+ sblock = CPM_CR_SMC2_SBLOCK;
+ }
+ }
+ else {
+ num -= SCC_NUM_BASE;
+ switch (num) {
+ case 0:
+ page = CPM_CR_SCC1_PAGE;
+ sblock = CPM_CR_SCC1_SBLOCK;
+ break;
+ case 1:
+ page = CPM_CR_SCC2_PAGE;
+ sblock = CPM_CR_SCC2_SBLOCK;
+ break;
+ case 2:
+ page = CPM_CR_SCC3_PAGE;
+ sblock = CPM_CR_SCC3_SBLOCK;
+ break;
+ case 3:
+ page = CPM_CR_SCC4_PAGE;
+ sblock = CPM_CR_SCC4_SBLOCK;
+ break;
+ default: return;
+ }
+ }
+ cp->cp_cpcr = mk_cr_cmd(page, sblock, 0, CPM_CR_RESTART_TX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+}
+
+/*
+ * This routine sends a break character out the serial port.
+ */
+static void send_break(ser_info_t *info, int duration)
+{
+ current->state = TASK_INTERRUPTIBLE;
+#ifdef SERIAL_DEBUG_SEND_BREAK
+ printk("rs_send_break(%d) jiff=%lu...", duration, jiffies);
+#endif
+ begin_break(info);
+ schedule_timeout(duration);
+ end_break(info);
+#ifdef SERIAL_DEBUG_SEND_BREAK
+ printk("done jiffies=%lu\n", jiffies);
+#endif
+}
+
+
+static int rs_8xx_ioctl(struct tty_struct *tty, struct file * file,
+ unsigned int cmd, unsigned long arg)
+{
+ int error;
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ int retval;
+ struct async_icount cnow; /* kernel counter temps */
+ struct serial_icounter_struct *p_cuser; /* user space */
+
+ if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
+ return -ENODEV;
+
+ if ((cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+ }
+
+ switch (cmd) {
+ case TCSBRK: /* SVID version: non-zero arg --> no break */
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ if (signal_pending(current))
+ return -EINTR;
+ if (!arg) {
+ send_break(info, HZ/4); /* 1/4 second */
+ if (signal_pending(current))
+ return -EINTR;
+ }
+ return 0;
+ case TCSBRKP: /* support for POSIX tcsendbreak() */
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ if (signal_pending(current))
+ return -EINTR;
+ send_break(info, arg ? arg*(HZ/10) : HZ/4);
+ if (signal_pending(current))
+ return -EINTR;
+ return 0;
+ case TIOCSBRK:
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ begin_break(info);
+ return 0;
+ case TIOCCBRK:
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ end_break(info);
+ return 0;
+ case TIOCGSOFTCAR:
+ return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg);
+ case TIOCSSOFTCAR:
+ error = get_user(arg, (unsigned int *) arg);
+ if (error)
+ return error;
+ tty->termios->c_cflag =
+ ((tty->termios->c_cflag & ~CLOCAL) |
+ (arg ? CLOCAL : 0));
+ return 0;
+ case TIOCMGET:
+ return get_modem_info(info, (unsigned int *) arg);
+ case TIOCMBIS:
+ case TIOCMBIC:
+ case TIOCMSET:
+ return set_modem_info(info, cmd, (unsigned int *) arg);
+#ifdef maybe
+ case TIOCSERGETLSR: /* Get line status register */
+ return get_lsr_info(info, (unsigned int *) arg);
+#endif
+ /*
+ * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+ * - mask passed in arg for lines of interest
+ * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+ * Caller should use TIOCGICOUNT to see which one it was
+ */
+ case TIOCMIWAIT:
+#ifdef modem_control
+ cli();
+ /* note the counters on entry */
+ cprev = info->state->icount;
+ sti();
+ while (1) {
+ interruptible_sleep_on(&info->delta_msr_wait);
+ /* see if a signal did it */
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ cli();
+ cnow = info->state->icount; /* atomic copy */
+ sti();
+ if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+ cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+ return -EIO; /* no change => error */
+ if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+ ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+ ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
+ ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
+ return 0;
+ }
+ cprev = cnow;
+ }
+ /* NOTREACHED */
+#else
+ return 0;
+#endif
+
+ /*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ * RI where only 0->1 is counted.
+ */
+ case TIOCGICOUNT:
+ cli();
+ cnow = info->state->icount;
+ sti();
+ p_cuser = (struct serial_icounter_struct *) arg;
+ error = put_user(cnow.cts, &p_cuser->cts);
+ if (error) return error;
+ error = put_user(cnow.dsr, &p_cuser->dsr);
+ if (error) return error;
+ error = put_user(cnow.rng, &p_cuser->rng);
+ if (error) return error;
+ error = put_user(cnow.dcd, &p_cuser->dcd);
+ if (error) return error;
+ return 0;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+}
+
+/* FIX UP modem control here someday......
+*/
+static void rs_8xx_set_termios(struct tty_struct *tty, struct termios *old_termios)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+
+ if ( (tty->termios->c_cflag == old_termios->c_cflag)
+ && ( RELEVANT_IFLAG(tty->termios->c_iflag)
+ == RELEVANT_IFLAG(old_termios->c_iflag)))
+ return;
+
+ change_speed(info);
+
+#ifdef modem_control
+ /* Handle transition to B0 status */
+ if ((old_termios->c_cflag & CBAUD) &&
+ !(tty->termios->c_cflag & CBAUD)) {
+ info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
+ cli();
+ serial_out(info, UART_MCR, info->MCR);
+ sti();
+ }
+
+ /* Handle transition away from B0 status */
+ if (!(old_termios->c_cflag & CBAUD) &&
+ (tty->termios->c_cflag & CBAUD)) {
+ info->MCR |= UART_MCR_DTR;
+ if (!tty->hw_stopped ||
+ !(tty->termios->c_cflag & CRTSCTS)) {
+ info->MCR |= UART_MCR_RTS;
+ }
+ cli();
+ serial_out(info, UART_MCR, info->MCR);
+ sti();
+ }
+
+ /* Handle turning off CRTSCTS */
+ if ((old_termios->c_cflag & CRTSCTS) &&
+ !(tty->termios->c_cflag & CRTSCTS)) {
+ tty->hw_stopped = 0;
+ rs_8xx_start(tty);
+ }
+#endif
+
+#if 0
+ /*
+ * No need to wake up processes in open wait, since they
+ * sample the CLOCAL flag once, and don't recheck it.
+ * XXX It's not clear whether the current behavior is correct
+ * or not. Hence, this may change.....
+ */
+ if (!(old_termios->c_cflag & CLOCAL) &&
+ (tty->termios->c_cflag & CLOCAL))
+ wake_up_interruptible(&info->open_wait);
+#endif
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_close()
+ *
+ * This routine is called when the serial port gets closed. First, we
+ * wait for the last remaining data to be sent. Then, we unlink its
+ * async structure from the interrupt chain if necessary, and we free
+ * that IRQ if nothing is left in the chain.
+ * ------------------------------------------------------------
+ */
+static void rs_8xx_close(struct tty_struct *tty, struct file * filp)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ struct serial_state *state;
+ unsigned long flags;
+ int idx;
+ volatile smc_t *smcp;
+ volatile scc_t *sccp;
+
+ if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
+ return;
+
+ state = info->state;
+
+ save_flags(flags); cli();
+
+ if (tty_hung_up_p(filp)) {
+ DBG_CNT("before DEC-hung");
+ MOD_DEC_USE_COUNT;
+ restore_flags(flags);
+ return;
+ }
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_close ttys%d, count = %d\n", info->line, state->count);
+#endif
+ if ((tty->count == 1) && (state->count != 1)) {
+ /*
+ * Uh, oh. tty->count is 1, which means that the tty
+ * structure will be freed. state->count should always
+ * be one in these conditions. If it's greater than
+ * one, we've got real problems, since it means the
+ * serial port won't be shutdown.
+ */
+ printk("rs_close: bad serial port count; tty->count is 1, "
+ "state->count is %d\n", state->count);
+ state->count = 1;
+ }
+ if (--state->count < 0) {
+ printk("rs_close: bad serial port count for ttys%d: %d\n",
+ info->line, state->count);
+ state->count = 0;
+ }
+ if (state->count) {
+ DBG_CNT("before DEC-2");
+ MOD_DEC_USE_COUNT;
+ restore_flags(flags);
+ return;
+ }
+ info->flags |= ASYNC_CLOSING;
+ /*
+ * Save the termios structure, since this port may have
+ * separate termios for callout and dialin.
+ */
+ if (info->flags & ASYNC_NORMAL_ACTIVE)
+ info->state->normal_termios = *tty->termios;
+ if (info->flags & ASYNC_CALLOUT_ACTIVE)
+ info->state->callout_termios = *tty->termios;
+ /*
+ * Now we wait for the transmit buffer to clear; and we notify
+ * the line discipline to only process XON/XOFF characters.
+ */
+ tty->closing = 1;
+ if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+ tty_wait_until_sent(tty, info->closing_wait);
+ /*
+ * At this point we stop accepting input. To do this, we
+ * disable the receive line status interrupts, and tell the
+ * interrupt driver to stop checking the data ready bit in the
+ * line status register.
+ */
+ info->read_status_mask &= ~BD_SC_EMPTY;
+ if (info->flags & ASYNC_INITIALIZED) {
+ if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+ smcp = &immr->im_smc[idx];
+ smcp->smc_smcm &= ~SMCM_RX;
+ smcp->smc_smcmr &= ~SMCMR_REN;
+ }
+ else {
+ sccp = &immr->im_scc[idx - SCC_IDX_BASE];
+ sccp->scc_sccm &= ~UART_SCCM_RX;
+ sccp->scc_gsmrl &= ~SCC_GSMRL_ENR;
+ }
+ /*
+ * Before we drop DTR, make sure the UART transmitter
+ * has completely drained; this is especially
+ * important if there is a transmit FIFO!
+ */
+ rs_8xx_wait_until_sent(tty, info->timeout);
+ }
+ shutdown(info);
+ if (tty->driver.flush_buffer)
+ tty->driver.flush_buffer(tty);
+ if (tty->ldisc.flush_buffer)
+ tty->ldisc.flush_buffer(tty);
+ tty->closing = 0;
+ info->event = 0;
+ info->tty = 0;
+ if (info->blocked_open) {
+ if (info->close_delay) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(info->close_delay);
+ }
+ wake_up_interruptible(&info->open_wait);
+ }
+ info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
+ ASYNC_CLOSING);
+ wake_up_interruptible(&info->close_wait);
+ MOD_DEC_USE_COUNT;
+ restore_flags(flags);
+}
+
+/*
+ * rs_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ unsigned long orig_jiffies, char_time;
+ /*int lsr;*/
+ volatile cbd_t *bdp;
+
+ if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent"))
+ return;
+
+#ifdef maybe
+ if (info->state->type == PORT_UNKNOWN)
+ return;
+#endif
+
+ orig_jiffies = jiffies;
+ /*
+ * Set the check interval to be 1/5 of the estimated time to
+ * send a single character, and make it at least 1. The check
+ * interval should also be less than the timeout.
+ *
+ * Note: we have to use pretty tight timings here to satisfy
+ * the NIST-PCTS.
+ */
+ char_time = 1;
+ if (timeout)
+ char_time = MIN(char_time, timeout);
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+ printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
+ printk("jiff=%lu...", jiffies);
+#endif
+
+ /* We go through the loop at least once because we can't tell
+ * exactly when the last character exits the shifter. There can
+ * be at least two characters waiting to be sent after the buffers
+ * are empty.
+ */
+ do {
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+ printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
+#endif
+ current->state = TASK_INTERRUPTIBLE;
+/* current->counter = 0; make us low-priority */
+ schedule_timeout(char_time);
+ if (signal_pending(current))
+ break;
+ if (timeout && ((orig_jiffies + timeout) < jiffies))
+ break;
+ bdp = info->tx_cur;
+ } while (bdp->cbd_sc & BD_SC_READY);
+ current->state = TASK_RUNNING;
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+ printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
+#endif
+}
+
+/*
+ * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
+ */
+static void rs_8xx_hangup(struct tty_struct *tty)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ struct serial_state *state = info->state;
+
+ if (serial_paranoia_check(info, tty->device, "rs_hangup"))
+ return;
+
+ state = info->state;
+
+ rs_8xx_flush_buffer(tty);
+ shutdown(info);
+ info->event = 0;
+ state->count = 0;
+ info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
+ info->tty = 0;
+ wake_up_interruptible(&info->open_wait);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_open() and friends
+ * ------------------------------------------------------------
+ */
+static int block_til_ready(struct tty_struct *tty, struct file * filp,
+ ser_info_t *info)
+{
+#ifdef DO_THIS_LATER
+ DECLARE_WAITQUEUE(wait, current);
+#endif
+ struct serial_state *state = info->state;
+ int retval;
+ int do_clocal = 0;
+
+ /*
+ * If the device is in the middle of being closed, then block
+ * until it's done, and then try again.
+ */
+ if (tty_hung_up_p(filp) ||
+ (info->flags & ASYNC_CLOSING)) {
+ if (info->flags & ASYNC_CLOSING)
+ interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+ if (info->flags & ASYNC_HUP_NOTIFY)
+ return -EAGAIN;
+ else
+ return -ERESTARTSYS;
+#else
+ return -EAGAIN;
+#endif
+ }
+
+ /*
+ * If this is a callout device, then just make sure the normal
+ * device isn't being used.
+ */
+ if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+ if (info->flags & ASYNC_NORMAL_ACTIVE)
+ return -EBUSY;
+ if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+ (info->flags & ASYNC_SESSION_LOCKOUT) &&
+ (info->session != current->session))
+ return -EBUSY;
+ if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+ (info->flags & ASYNC_PGRP_LOCKOUT) &&
+ (info->pgrp != current->pgrp))
+ return -EBUSY;
+ info->flags |= ASYNC_CALLOUT_ACTIVE;
+ return 0;
+ }
+
+ /*
+ * If non-blocking mode is set, or the port is not enabled,
+ * then make the check up front and then exit.
+ * If this is an SMC port, we don't have modem control to wait
+ * for, so just get out here.
+ */
+ if ((filp->f_flags & O_NONBLOCK) ||
+ (tty->flags & (1 << TTY_IO_ERROR)) ||
+ (info->state->smc_scc_num < SCC_NUM_BASE)) {
+ if (info->flags & ASYNC_CALLOUT_ACTIVE)
+ return -EBUSY;
+ info->flags |= ASYNC_NORMAL_ACTIVE;
+ return 0;
+ }
+
+ if (info->flags & ASYNC_CALLOUT_ACTIVE) {
+ if (state->normal_termios.c_cflag & CLOCAL)
+ do_clocal = 1;
+ } else {
+ if (tty->termios->c_cflag & CLOCAL)
+ do_clocal = 1;
+ }
+
+ /*
+ * Block waiting for the carrier detect and the line to become
+ * free (i.e., not in use by the callout). While we are in
+ * this loop, state->count is dropped by one, so that
+ * rs_close() knows when to free things. We restore it upon
+ * exit, either normal or abnormal.
+ */
+ retval = 0;
+#ifdef DO_THIS_LATER
+ add_wait_queue(&info->open_wait, &wait);
+#ifdef SERIAL_DEBUG_OPEN
+ printk("block_til_ready before block: ttys%d, count = %d\n",
+ state->line, state->count);
+#endif
+ cli();
+ if (!tty_hung_up_p(filp))
+ state->count--;
+ sti();
+ info->blocked_open++;
+ while (1) {
+ cli();
+ if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+ (tty->termios->c_cflag & CBAUD))
+ serial_out(info, UART_MCR,
+ serial_inp(info, UART_MCR) |
+ (UART_MCR_DTR | UART_MCR_RTS));
+ sti();
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (tty_hung_up_p(filp) ||
+ !(info->flags & ASYNC_INITIALIZED)) {
+#ifdef SERIAL_DO_RESTART
+ if (info->flags & ASYNC_HUP_NOTIFY)
+ retval = -EAGAIN;
+ else
+ retval = -ERESTARTSYS;
+#else
+ retval = -EAGAIN;
+#endif
+ break;
+ }
+ if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+ !(info->flags & ASYNC_CLOSING) &&
+ (do_clocal || (serial_in(info, UART_MSR) &
+ UART_MSR_DCD)))
+ break;
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+#ifdef SERIAL_DEBUG_OPEN
+ printk("block_til_ready blocking: ttys%d, count = %d\n",
+ info->line, state->count);
+#endif
+ schedule();
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&info->open_wait, &wait);
+ if (!tty_hung_up_p(filp))
+ state->count++;
+ info->blocked_open--;
+#ifdef SERIAL_DEBUG_OPEN
+ printk("block_til_ready after blocking: ttys%d, count = %d\n",
+ info->line, state->count);
+#endif
+#endif /* DO_THIS_LATER */
+ if (retval)
+ return retval;
+ info->flags |= ASYNC_NORMAL_ACTIVE;
+ return 0;
+}
+
+static int get_async_struct(int line, ser_info_t **ret_info)
+{
+ struct serial_state *sstate;
+
+ sstate = rs_table + line;
+ if (sstate->info) {
+ sstate->count++;
+ *ret_info = (ser_info_t *)sstate->info;
+ return 0;
+ }
+ else {
+ return -ENOMEM;
+ }
+}
+
+/*
+ * This routine is called whenever a serial port is opened. It
+ * enables interrupts for a serial port, linking in its async structure into
+ * the IRQ chain. It also performs the serial-specific
+ * initialization for the tty structure.
+ */
+static int rs_8xx_open(struct tty_struct *tty, struct file * filp)
+{
+ ser_info_t *info;
+ int retval, line;
+
+ line = MINOR(tty->device) - tty->driver.minor_start;
+ if ((line < 0) || (line >= NR_PORTS))
+ return -ENODEV;
+ retval = get_async_struct(line, &info);
+ if (retval)
+ return retval;
+ if (serial_paranoia_check(info, tty->device, "rs_open"))
+ return -ENODEV;
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
+ info->state->count);
+#endif
+ tty->driver_data = info;
+ info->tty = tty;
+
+ /*
+ * Start up serial port
+ */
+ retval = startup(info);
+ if (retval)
+ return retval;
+
+ MOD_INC_USE_COUNT;
+ retval = block_til_ready(tty, filp, info);
+ if (retval) {
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_open returning after block_til_ready with %d\n",
+ retval);
+#endif
+ return retval;
+ }
+
+ if ((info->state->count == 1) &&
+ (info->flags & ASYNC_SPLIT_TERMIOS)) {
+ if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+ *tty->termios = info->state->normal_termios;
+ else
+ *tty->termios = info->state->callout_termios;
+ change_speed(info);
+ }
+
+ info->session = current->session;
+ info->pgrp = current->pgrp;
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_open ttys%d successful...", info->line);
+#endif
+ return 0;
+}
+
+/*
+ * /proc fs routines....
+ */
+
+static int inline line_info(char *buf, struct serial_state *state)
+{
+#ifdef notdef
+ struct async_struct *info = state->info, scr_info;
+ char stat_buf[30], control, status;
+#endif
+ int ret;
+
+ ret = sprintf(buf, "%d: uart:%s port:%X irq:%d",
+ state->line,
+ (state->smc_scc_num < SCC_NUM_BASE) ? "SMC" : "SCC",
+ state->port, state->irq);
+
+ if (!state->port || (state->type == PORT_UNKNOWN)) {
+ ret += sprintf(buf+ret, "\n");
+ return ret;
+ }
+
+#ifdef notdef
+ /*
+ * Figure out the current RS-232 lines
+ */
+ if (!info) {
+ info = &scr_info; /* This is just for serial_{in,out} */
+
+ info->magic = SERIAL_MAGIC;
+ info->port = state->port;
+ info->flags = state->flags;
+ info->quot = 0;
+ info->tty = 0;
+ }
+ cli();
+ status = serial_in(info, UART_MSR);
+ control = info ? info->MCR : serial_in(info, UART_MCR);
+ sti();
+
+ stat_buf[0] = 0;
+ stat_buf[1] = 0;
+ if (control & UART_MCR_RTS)
+ strcat(stat_buf, "|RTS");
+ if (status & UART_MSR_CTS)
+ strcat(stat_buf, "|CTS");
+ if (control & UART_MCR_DTR)
+ strcat(stat_buf, "|DTR");
+ if (status & UART_MSR_DSR)
+ strcat(stat_buf, "|DSR");
+ if (status & UART_MSR_DCD)
+ strcat(stat_buf, "|CD");
+ if (status & UART_MSR_RI)
+ strcat(stat_buf, "|RI");
+
+ if (info->quot) {
+ ret += sprintf(buf+ret, " baud:%d",
+ state->baud_base / info->quot);
+ }
+
+ ret += sprintf(buf+ret, " tx:%d rx:%d",
+ state->icount.tx, state->icount.rx);
+
+ if (state->icount.frame)
+ ret += sprintf(buf+ret, " fe:%d", state->icount.frame);
+
+ if (state->icount.parity)
+ ret += sprintf(buf+ret, " pe:%d", state->icount.parity);
+
+ if (state->icount.brk)
+ ret += sprintf(buf+ret, " brk:%d", state->icount.brk);
+
+ if (state->icount.overrun)
+ ret += sprintf(buf+ret, " oe:%d", state->icount.overrun);
+
+ /*
+ * Last thing is the RS-232 status lines
+ */
+ ret += sprintf(buf+ret, " %s\n", stat_buf+1);
+#endif
+ return ret;
+}
+
+int rs_8xx_read_proc(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+{
+ int i, len = 0;
+ off_t begin = 0;
+
+ len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
+ for (i = 0; i < NR_PORTS && len < 4000; i++) {
+ len += line_info(page + len, &rs_table[i]);
+ if (len+begin > off+count)
+ goto done;
+ if (len+begin < off) {
+ begin += len;
+ len = 0;
+ }
+ }
+ *eof = 1;
+done:
+ if (off >= len+begin)
+ return 0;
+ *start = page + (begin-off);
+ return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * ---------------------------------------------------------------------
+ * rs_init() and friends
+ *
+ * rs_init() is called at boot-time to initialize the serial driver.
+ * ---------------------------------------------------------------------
+ */
+
+/*
+ * This routine prints out the appropriate serial driver version
+ * number, and identifies which options were configured into this
+ * driver.
+ */
+static _INLINE_ void show_serial_version(void)
+{
+ printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
+}
+
+
+/*
+ * The serial console driver used during boot. Note that these names
+ * clash with those found in "serial.c", so we currently can't support
+ * the 16xxx uarts and these at the same time. I will fix this to become
+ * an indirect function call from tty_io.c (or something).
+ */
+
+#ifdef CONFIG_SERIAL_CONSOLE
+
+/*
+ * Print a string to the serial port trying not to disturb any possible
+ * real use of the port...
+ */
+static void serial_console_write(struct console *c, const char *s,
+ unsigned count)
+{
+ struct serial_state *ser;
+ ser_info_t *info;
+ unsigned i;
+ volatile cbd_t *bdp, *bdbase;
+ volatile smc_uart_t *up;
+ volatile u_char *cp;
+
+ ser = rs_table + c->index;
+
+ /* If the port has been initialized for general use, we have
+ * to use the buffer descriptors allocated there. Otherwise,
+ * we simply use the single buffer allocated.
+ */
+ if ((info = (ser_info_t *)ser->info) != NULL) {
+ bdp = info->tx_cur;
+ bdbase = info->tx_bd_base;
+ }
+ else {
+ /* Pointer to UART in parameter ram.
+ */
+ up = (smc_uart_t *)&immr->im_dprambase[ser->port];
+
+ /* Get the address of the host memory buffer.
+ */
+ bdp = bdbase = (cbd_t *)&immr->im_dprambase[up->smc_tbase];
+ }
+
+ /*
+ * We need to gracefully shut down the transmitter, disable
+ * interrupts, then send our bytes out.
+ */
+
+ /*
+ * Now, do each character. This is not as bad as it looks
+ * since this is a holding FIFO and not a transmitting FIFO.
+ * We could add the complexity of filling the entire transmit
+ * buffer, but we would just wait longer between accesses......
+ */
+ for (i = 0; i < count; i++, s++) {
+ /* Wait for transmitter fifo to empty.
+ * Ready indicates output is ready, and xmt is doing
+ * that, not that it is ready for us to send.
+ */
+ while (bdp->cbd_sc & BD_SC_READY);
+ /* Send the character out. */
+ cp = __va(bdp->cbd_bufaddr);
+ *cp = *s;
+
+ bdp->cbd_datlen = 1;
+ bdp->cbd_sc |= BD_SC_READY;
+
+ if (bdp->cbd_sc & BD_SC_WRAP)
+ bdp = bdbase;
+ else
+ bdp++;
+
+ /* if a LF, also do CR... */
+ if (*s == 10) {
+ while (bdp->cbd_sc & BD_SC_READY);
+ cp = __va(bdp->cbd_bufaddr);
+ *cp = 13;
+ bdp->cbd_datlen = 1;
+ bdp->cbd_sc |= BD_SC_READY;
+
+ if (bdp->cbd_sc & BD_SC_WRAP) {
+ bdp = bdbase;
+ }
+ else {
+ bdp++;
+ }
+ }
+ }
+
+ /*
+ * Finally, Wait for transmitter & holding register to empty
+ * and restore the IER
+ */
+ while (bdp->cbd_sc & BD_SC_READY);
+
+ if (info)
+ info->tx_cur = (cbd_t *)bdp;
+}
+
+/*
+ * Receive character from the serial port. This only works well
+ * before the port is initialize for real use.
+ */
+static int serial_console_wait_key(struct console *co)
+{
+ struct serial_state *ser;
+ u_char c, *cp;
+ ser_info_t *info;
+ volatile cbd_t *bdp;
+ volatile smc_uart_t *up;
+
+ ser = rs_table + co->index;
+
+ /* Pointer to UART in parameter ram.
+ */
+ up = (smc_uart_t *)&immr->im_dprambase[ser->port];
+
+ /* Get the address of the host memory buffer.
+ * If the port has been initialized for general use, we must
+ * use information from the port structure.
+ */
+ if ((info = (ser_info_t *)ser->info))
+ bdp = info->rx_cur;
+ else
+ bdp = (cbd_t *)&immr->im_dprambase[up->smc_rbase];
+
+ /*
+ * We need to gracefully shut down the receiver, disable
+ * interrupts, then read the input.
+ */
+ while (bdp->cbd_sc & BD_SC_EMPTY); /* Wait for a character */
+ cp = __va(bdp->cbd_bufaddr);
+
+ if (info) {
+ if (bdp->cbd_sc & BD_SC_WRAP) {
+ bdp = info->rx_bd_base;
+ }
+ else {
+ bdp++;
+ }
+ info->rx_cur = (cbd_t *)bdp;
+ }
+
+ c = *cp;
+ return((int)c);
+}
+
+static kdev_t serial_console_device(struct console *c)
+{
+ return MKDEV(TTYAUX_MAJOR, 64 + c->index);
+}
+
+
+static struct console sercons = {
+ "ttyS",
+ serial_console_write,
+ NULL,
+ serial_console_device,
+ serial_console_wait_key,
+ NULL,
+ serial_console_setup,
+ CON_PRINTBUFFER,
+ CONFIG_SERIAL_CONSOLE_PORT,
+ 0,
+ NULL
+};
+
+/*
+ * Register console.
+ */
+long __init console_8xx_init(long kmem_start, long kmem_end)
+{
+ register_console(&sercons);
+ return kmem_start;
+}
+
+#endif
+
+/* Default console baud rate as determined by the board information
+ * structure.
+ */
+static int baud_idx;
+
+/*
+ * The serial driver boot-time initialization code!
+ */
+int __init rs_8xx_init(void)
+{
+ struct serial_state * state;
+ ser_info_t *info;
+ uint mem_addr, dp_addr;
+ int i, j, idx;
+ uint page, sblock;
+ volatile cbd_t *bdp;
+ volatile cpm8260_t *cp;
+ volatile smc_t *sp;
+ volatile smc_uart_t *up;
+ volatile scc_t *scp;
+ volatile scc_uart_t *sup;
+ volatile immap_t *immap;
+ volatile iop8260_t *io;
+
+ init_bh(SERIAL_BH, do_serial_bh);
+#if 0
+ timer_table[RS_TIMER].fn = rs_8xx_timer;
+ timer_table[RS_TIMER].expires = 0;
+#endif
+
+ show_serial_version();
+
+ /* Initialize the tty_driver structure */
+
+ /*memset(&serial_driver, 0, sizeof(struct tty_driver));*/
+ __clear_user(&serial_driver,sizeof(struct tty_driver));
+ serial_driver.magic = TTY_DRIVER_MAGIC;
+ serial_driver.driver_name = "serial";
+ serial_driver.name = "ttyS";
+ serial_driver.major = TTY_MAJOR;
+ serial_driver.minor_start = 64;
+ serial_driver.num = NR_PORTS;
+ serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
+ serial_driver.subtype = SERIAL_TYPE_NORMAL;
+ serial_driver.init_termios = tty_std_termios;
+ serial_driver.init_termios.c_cflag =
+ baud_idx | CS8 | CREAD | HUPCL | CLOCAL;
+ serial_driver.flags = TTY_DRIVER_REAL_RAW;
+ serial_driver.refcount = &serial_refcount;
+ serial_driver.table = serial_table;
+ serial_driver.termios = serial_termios;
+ serial_driver.termios_locked = serial_termios_locked;
+
+ serial_driver.open = rs_8xx_open;
+ serial_driver.close = rs_8xx_close;
+ serial_driver.write = rs_8xx_write;
+ serial_driver.put_char = rs_8xx_put_char;
+ serial_driver.write_room = rs_8xx_write_room;
+ serial_driver.chars_in_buffer = rs_8xx_chars_in_buffer;
+ serial_driver.flush_buffer = rs_8xx_flush_buffer;
+ serial_driver.ioctl = rs_8xx_ioctl;
+ serial_driver.throttle = rs_8xx_throttle;
+ serial_driver.unthrottle = rs_8xx_unthrottle;
+ serial_driver.send_xchar = rs_8xx_send_xchar;
+ serial_driver.set_termios = rs_8xx_set_termios;
+ serial_driver.stop = rs_8xx_stop;
+ serial_driver.start = rs_8xx_start;
+ serial_driver.hangup = rs_8xx_hangup;
+ serial_driver.wait_until_sent = rs_8xx_wait_until_sent;
+ serial_driver.read_proc = rs_8xx_read_proc;
+
+ /*
+ * The callout device is just like normal device except for
+ * major number and the subtype code.
+ */
+ callout_driver = serial_driver;
+ callout_driver.name = "cua";
+ callout_driver.major = TTYAUX_MAJOR;
+ callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+ callout_driver.read_proc = 0;
+ callout_driver.proc_entry = 0;
+
+ if (tty_register_driver(&serial_driver))
+ panic("Couldn't register serial driver\n");
+ if (tty_register_driver(&callout_driver))
+ panic("Couldn't register callout driver\n");
+
+ immap = immr;
+ cp = &immap->im_cpm;
+ io = &immap->im_ioport;
+
+ /* This should have been done long ago by the early boot code,
+ * but do it again to make sure.
+ */
+ *(ushort *)(&immap->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
+ *(ushort *)(&immap->im_dprambase[PROFF_SMC2_BASE]) = PROFF_SMC2;
+
+ /* Geeze, here we go....Picking I/O port bits....Lots of
+ * choices. If you don't like mine, pick your own.
+ * Configure SMCs Tx/Rx. SMC1 is only on Port D, SMC2 is
+ * only on Port A. You either pick 'em, or not.
+ */
+ io->iop_ppard |= 0x00c00000;
+ io->iop_pdird |= 0x00400000;
+ io->iop_pdird &= ~0x00800000;
+ io->iop_psord &= ~0x00c00000;
+#if USE_SMC2
+ io->iop_ppara |= 0x01800000;
+ io->iop_pdira |= 0x00800000;
+ io->iop_pdira &= ~0x01000000;
+ io->iop_psora &= ~0x01800000;
+#endif
+
+ /* Configure SCC2 and SCC3. Be careful about the fine print.
+ * Secondary options are only available when you take away
+ * the primary option. Unless the pins are used for something
+ * else, SCC2 and SCC3 are on Port B.
+ * Port B, 8 - SCC3 TxD
+ * Port B, 12 - SCC2 TxD
+ * Port B, 14 - SCC3 RxD
+ * Port B, 15 - SCC2 RxD
+ */
+ io->iop_pparb |= 0x008b0000;
+ io->iop_pdirb |= 0x00880000;
+ io->iop_psorb |= 0x00880000;
+ io->iop_pdirb &= ~0x00030000;
+ io->iop_psorb &= ~0x00030000;
+
+ /* Wire BRG1 to SMC1 and BRG2 to SMC2.
+ */
+ immap->im_cpmux.cmx_smr = 0;
+
+ /* Connect SCC2 and SCC3 to NMSI. Connect BRG3 to SCC2 and
+ * BRG4 to SCC3.
+ */
+ immap->im_cpmux.cmx_scr &= ~0x00ffff00;
+ immap->im_cpmux.cmx_scr |= 0x00121b00;
+
+ for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
+ state->magic = SSTATE_MAGIC;
+ state->line = i;
+ state->type = PORT_UNKNOWN;
+ state->custom_divisor = 0;
+ state->close_delay = 5*HZ/10;
+ state->closing_wait = 30*HZ;
+ state->callout_termios = callout_driver.init_termios;
+ state->normal_termios = serial_driver.init_termios;
+ state->icount.cts = state->icount.dsr =
+ state->icount.rng = state->icount.dcd = 0;
+ state->icount.rx = state->icount.tx = 0;
+ state->icount.frame = state->icount.parity = 0;
+ state->icount.overrun = state->icount.brk = 0;
+ printk(KERN_INFO "ttyS%02d at 0x%04x is a %s\n",
+ i, state->port,
+ (state->smc_scc_num < SCC_NUM_BASE) ? "SMC" : "SCC");
+#ifdef CONFIG_SERIAL_CONSOLE
+ /* If we just printed the message on the console port, and
+ * we are about to initialize it for general use, we have
+ * to wait a couple of character times for the CR/NL to
+ * make it out of the transmit buffer.
+ */
+ if (i == CONFIG_SERIAL_CONSOLE_PORT)
+ mdelay(2);
+#endif
+ info = kmalloc(sizeof(ser_info_t), GFP_KERNEL);
+ if (info) {
+ /*memset(info, 0, sizeof(ser_info_t));*/
+ __clear_user(info,sizeof(ser_info_t));
+ info->magic = SERIAL_MAGIC;
+ info->flags = state->flags;
+ info->tqueue.routine = do_softint;
+ info->tqueue.data = info;
+ info->tqueue_hangup.routine = do_serial_hangup;
+ info->tqueue_hangup.data = info;
+ info->line = i;
+ info->state = state;
+ state->info = (struct async_struct *)info;
+
+ /* We need to allocate a transmit and receive buffer
+ * descriptors from dual port ram, and a character
+ * buffer area from host mem.
+ */
+ dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * RX_NUM_FIFO);
+
+ /* Allocate space for FIFOs in the host memory.
+ */
+ mem_addr = m8260_cpm_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE);
+
+ /* Set the physical address of the host memory
+ * buffers in the buffer descriptors, and the
+ * virtual address for us to work with.
+ */
+ bdp = (cbd_t *)&immap->im_dprambase[dp_addr];
+ info->rx_cur = info->rx_bd_base = (cbd_t *)bdp;
+
+ for (j=0; j<(RX_NUM_FIFO-1); j++) {
+ bdp->cbd_bufaddr = __pa(mem_addr);
+ bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
+ mem_addr += RX_BUF_SIZE;
+ bdp++;
+ }
+ bdp->cbd_bufaddr = __pa(mem_addr);
+ bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
+
+ if ((idx = state->smc_scc_num) < SCC_NUM_BASE) {
+ sp = &immap->im_smc[idx];
+ up = (smc_uart_t *)&immap->im_dprambase[state->port];
+ up->smc_rbase = dp_addr;
+ }
+ else {
+ scp = &immap->im_scc[idx - SCC_IDX_BASE];
+ sup = (scc_uart_t *)&immap->im_dprambase[state->port];
+ sup->scc_genscc.scc_rbase = dp_addr;
+ }
+
+ dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * TX_NUM_FIFO);
+
+ /* Allocate space for FIFOs in the host memory.
+ */
+ mem_addr = m8260_cpm_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE);
+
+ /* Set the physical address of the host memory
+ * buffers in the buffer descriptors, and the
+ * virtual address for us to work with.
+ */
+ bdp = (cbd_t *)&immap->im_dprambase[dp_addr];
+ info->tx_cur = info->tx_bd_base = (cbd_t *)bdp;
+
+ for (j=0; j<(TX_NUM_FIFO-1); j++) {
+ bdp->cbd_bufaddr = __pa(mem_addr);
+ bdp->cbd_sc = BD_SC_INTRPT;
+ mem_addr += TX_BUF_SIZE;
+ bdp++;
+ }
+ bdp->cbd_bufaddr = __pa(mem_addr);
+ bdp->cbd_sc = (BD_SC_WRAP | BD_SC_INTRPT);
+
+ if (idx < SCC_NUM_BASE) {
+ up->smc_tbase = dp_addr;
+
+ /* Set up the uart parameters in the
+ * parameter ram.
+ */
+ up->smc_rfcr = SMC_EB;
+ up->smc_tfcr = SMC_EB;
+
+ /* Set this to 1 for now, so we get single
+ * character interrupts. Using idle charater
+ * time requires some additional tuning.
+ */
+ up->smc_mrblr = 1;
+ up->smc_maxidl = 0;
+ up->smc_brkcr = 1;
+
+ /* Send the CPM an initialize command.
+ */
+ if (state->smc_scc_num == 0) {
+ page = CPM_CR_SMC1_PAGE;
+ sblock = CPM_CR_SMC1_SBLOCK;
+ }
+ else {
+ page = CPM_CR_SMC2_PAGE;
+ sblock = CPM_CR_SMC2_SBLOCK;
+ }
+
+ cp->cp_cpcr = mk_cr_cmd(page, sblock, 0,
+ CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+ /* Disable all interrupts and clear all pending
+ * events.
+ */
+ sp->smc_smcm = 0;
+ sp->smc_smce = 0xff;
+ }
+ else {
+ sup->scc_genscc.scc_tbase = dp_addr;
+
+ /* Set up the uart parameters in the
+ * parameter ram.
+ */
+ sup->scc_genscc.scc_rfcr = SMC_EB;
+ sup->scc_genscc.scc_tfcr = SMC_EB;
+
+ /* Set this to 1 for now, so we get single
+ * character interrupts. Using idle charater
+ * time requires some additional tuning.
+ */
+ sup->scc_genscc.scc_mrblr = 1;
+ sup->scc_maxidl = 0;
+ sup->scc_brkcr = 1;
+ sup->scc_parec = 0;
+ sup->scc_frmec = 0;
+ sup->scc_nosec = 0;
+ sup->scc_brkec = 0;
+ sup->scc_uaddr1 = 0;
+ sup->scc_uaddr2 = 0;
+ sup->scc_toseq = 0;
+ sup->scc_char1 = 0x8000;
+ sup->scc_char2 = 0x8000;
+ sup->scc_char3 = 0x8000;
+ sup->scc_char4 = 0x8000;
+ sup->scc_char5 = 0x8000;
+ sup->scc_char6 = 0x8000;
+ sup->scc_char7 = 0x8000;
+ sup->scc_char8 = 0x8000;
+ sup->scc_rccm = 0xc0ff;
+
+ /* Send the CPM an initialize command.
+ */
+ if (state->smc_scc_num == 2) {
+ page = CPM_CR_SCC2_PAGE;
+ sblock = CPM_CR_SCC2_SBLOCK;
+ }
+ else {
+ page = CPM_CR_SCC3_PAGE;
+ sblock = CPM_CR_SCC3_SBLOCK;
+ }
+
+ cp->cp_cpcr = mk_cr_cmd(page, sblock, 0,
+ CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ scp->scc_gsmrh = 0;
+ scp->scc_gsmrl =
+ (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
+
+ /* Disable all interrupts and clear all pending
+ * events.
+ */
+ scp->scc_sccm = 0;
+ scp->scc_scce = 0xffff;
+ scp->scc_dsr = 0x7e7e;
+ scp->scc_pmsr = 0x3000;
+ }
+
+ /* Install interrupt handler.
+ */
+ request_8xxirq(state->irq, rs_8xx_interrupt, 0, "uart", info);
+
+ /* Set up the baud rate generator.
+ */
+ m8260_cpm_setbrg(state->smc_scc_num,
+ baud_table[baud_idx]);
+
+ /* If the port is the console, enable Rx and Tx.
+ */
+#ifdef CONFIG_SERIAL_CONSOLE
+ if (i == CONFIG_SERIAL_CONSOLE_PORT)
+ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+#endif
+ }
+ }
+ return 0;
+}
+
+/* This must always be called before the rs_8xx_init() function, otherwise
+ * it blows away the port control information.
+*/
+static int __init serial_console_setup(struct console *co, char *options)
+{
+ struct serial_state *ser;
+ uint mem_addr, dp_addr, bidx;
+ volatile cbd_t *bdp;
+ volatile cpm8260_t *cp;
+ volatile immap_t *immap;
+ volatile smc_t *sp;
+ volatile smc_uart_t *up;
+ volatile iop8260_t *io;
+ bd_t *bd;
+
+ bd = (bd_t *)__res;
+
+ for (bidx = 0; bidx < (sizeof(baud_table) / sizeof(int)); bidx++)
+ if (bd->bi_baudrate == baud_table[bidx])
+ break;
+
+ co->cflag = CREAD|CLOCAL|bidx|CS8;
+ baud_idx = bidx;
+
+ ser = rs_table + co->index;
+
+
+ immap = immr;
+ cp = &immap->im_cpm;
+ io = &immap->im_ioport;
+
+ /* This should have been done long ago by the early boot code,
+ * but do it again to make sure.
+ */
+ *(ushort *)(&immap->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
+ *(ushort *)(&immap->im_dprambase[PROFF_SMC2_BASE]) = PROFF_SMC2;
+
+ /* Right now, assume we are using SMCs.
+ */
+ sp = &immap->im_smc[ser->smc_scc_num];
+
+ /* When we get here, the CPM has been reset, so we need
+ * to configure the port.
+ * We need to allocate a transmit and receive buffer descriptor
+ * from dual port ram, and a character buffer area from host mem.
+ */
+ up = (smc_uart_t *)&immap->im_dprambase[ser->port];
+
+ /* Disable transmitter/receiver.
+ */
+ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+ /* Use Port D for SMC1 instead of other functions.
+ */
+ io->iop_ppard |= 0x00c00000;
+ io->iop_pdird |= 0x00400000;
+ io->iop_pdird &= ~0x00800000;
+ io->iop_psord &= ~0x00c00000;
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ */
+ dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * 2);
+
+ /* Allocate space for two 2 byte FIFOs in the host memory.
+ */
+ mem_addr = m8260_cpm_hostalloc(4);
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ bdp = (cbd_t *)&immap->im_dprambase[dp_addr];
+ bdp->cbd_bufaddr = __pa(mem_addr);
+ (bdp+1)->cbd_bufaddr = __pa(mem_addr+2);
+
+ /* For the receive, set empty and wrap.
+ * For transmit, set wrap.
+ */
+ bdp->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+ (bdp+1)->cbd_sc = BD_SC_WRAP;
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+ up->smc_rbase = dp_addr; /* Base of receive buffer desc. */
+ up->smc_tbase = dp_addr+sizeof(cbd_t); /* Base of xmt buffer desc. */
+ up->smc_rfcr = SMC_EB;
+ up->smc_tfcr = SMC_EB;
+
+ /* Set this to 1 for now, so we get single character interrupts.
+ */
+ up->smc_mrblr = 1; /* receive buffer length */
+ up->smc_maxidl = 0; /* wait forever for next char */
+
+ /* Send the CPM an initialize command.
+ */
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0,
+ CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+ /* Set up the baud rate generator.
+ */
+ m8260_cpm_setbrg(ser->smc_scc_num, bd->bi_baudrate);
+
+ /* And finally, enable Rx and Tx.
+ */
+ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+
+ return 0;
+}
diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c
index f6b37dcb4..00a0d776f 100644
--- a/arch/ppc/8xx_io/enet.c
+++ b/arch/ppc/8xx_io/enet.c
@@ -37,6 +37,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
+#include <linux/spinlock.h>
#include <asm/8xx_immap.h>
#include <asm/pgtable.h>
@@ -108,6 +109,10 @@
* Port C, 9 (CTS2) - SCC Ethernet Collision
*/
+/* The transmitter timeout
+ */
+#define TX_TIMEOUT (2*HZ)
+
/* The number of Tx and Rx buffers. These are allocated from the page
* pool. The code may assume these are power of two, so it is best
* to keep them that size.
@@ -135,7 +140,7 @@
* empty and completely full conditions. The empty/ready indicator in
* the buffer descriptor determines the actual condition.
*/
-struct cpm_enet_private {
+struct scc_enet_private {
/* The saved address of a sent-in-place packet/buffer, for skfree(). */
struct sk_buff* tx_skbuff[TX_RING_SIZE];
ushort skb_cur;
@@ -150,17 +155,15 @@ struct cpm_enet_private {
scc_t *sccp;
struct net_device_stats stats;
uint tx_full;
- uint tx_busy;
- unsigned long lock;
- int interrupt;
+ spinlock_t lock;
};
-static int cpm_enet_open(struct net_device *dev);
-static int cpm_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static int cpm_enet_rx(struct net_device *dev);
-static void cpm_enet_interrupt(void *dev_id);
-static int cpm_enet_close(struct net_device *dev);
-static struct net_device_stats *cpm_enet_get_stats(struct net_device *dev);
+static int scc_enet_open(struct net_device *dev);
+static int scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int scc_enet_rx(struct net_device *dev);
+static void scc_enet_interrupt(void *dev_id);
+static int scc_enet_close(struct net_device *dev);
+static struct net_device_stats *scc_enet_get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
/* Get this from various configuration locations (depends on board).
@@ -185,7 +188,7 @@ static void set_multicast_list(struct net_device *dev);
#endif
static int
-cpm_enet_open(struct net_device *dev)
+scc_enet_open(struct net_device *dev)
{
/* I should reset the ring buffers here, but I don't yet know
@@ -197,60 +200,10 @@ cpm_enet_open(struct net_device *dev)
}
static int
-cpm_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct cpm_enet_private *cep = (struct cpm_enet_private *)dev->priv;
+ struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
volatile cbd_t *bdp;
- unsigned long flags;
-
- /* Transmitter timeout, serious problems. */
- if (cep->tx_busy) {
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 200)
- return 1;
- printk("%s: transmit timed out.\n", dev->name);
- cep->stats.tx_errors++;
-#ifndef final_version
- {
- int i;
- cbd_t *bdp;
- printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n",
- cep->cur_tx, cep->tx_full ? " (full)" : "",
- cep->cur_rx);
- bdp = cep->tx_bd_base;
- for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
- printk("%04x %04x %08x\n",
- bdp->cbd_sc,
- bdp->cbd_datlen,
- bdp->cbd_bufaddr);
- bdp = cep->rx_bd_base;
- for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
- printk("%04x %04x %08x\n",
- bdp->cbd_sc,
- bdp->cbd_datlen,
- bdp->cbd_bufaddr);
- }
-#endif
-
- cep->tx_busy=0;
- dev->trans_start = jiffies;
-
- return 0;
- }
-
- /* Block a timer-based transmit from overlapping. This could better be
- * done with atomic_swap(1, cep->tx_busy), but set_bit() works as well.
- */
- if (test_and_set_bit(0, (void*)&cep->tx_busy) != 0) {
- printk("%s: Transmitter access conflict.\n", dev->name);
- return 1;
- }
-
- if (test_and_set_bit(0, (void*)&cep->lock) != 0) {
- printk("%s: tx queue lock!.\n", dev->name);
- /* don't clear cep->tx_busy flag. */
- return 1;
- }
/* Fill in a Tx ring entry */
bdp = cep->cur_tx;
@@ -261,7 +214,6 @@ cpm_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
* This should not happen, since cep->tx_busy should be set.
*/
printk("%s: tx queue full!.\n", dev->name);
- cep->lock = 0;
return 1;
}
#endif
@@ -292,7 +244,10 @@ cpm_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Push the data cache so the CPM does not get stale memory
* data.
*/
- flush_dcache_range(skb->data, skb->data + skb->len);
+ flush_dcache_range((unsigned long)(skb->data),
+ (unsigned long)(skb->data + skb->len));
+
+ spin_lock_irq(&cep->lock);
/* Send it on its way. Tell CPM its ready, interrupt when done,
* its the last BD of the frame, and to put the CRC on the end.
@@ -308,37 +263,61 @@ cpm_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
else
bdp++;
- save_flags(flags);
- cli();
- cep->lock = 0;
if (bdp->cbd_sc & BD_ENET_TX_READY)
- cep->tx_full = 1;
- else
- cep->tx_busy=0;
- restore_flags(flags);
+ netif_stop_queue(dev);
cep->cur_tx = (cbd_t *)bdp;
+ spin_unlock_irq(&cep->lock);
+
return 0;
}
+static void
+scc_enet_timeout(struct net_device *dev)
+{
+ struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+
+ printk("%s: transmit timed out.\n", dev->name);
+ cep->stats.tx_errors++;
+#ifndef final_version
+ {
+ int i;
+ cbd_t *bdp;
+ printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n",
+ cep->cur_tx, cep->tx_full ? " (full)" : "",
+ cep->cur_rx);
+ bdp = cep->tx_bd_base;
+ for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
+ printk("%04x %04x %08x\n",
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ bdp = cep->rx_bd_base;
+ for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
+ printk("%04x %04x %08x\n",
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ }
+#endif
+ if (!cep->tx_full)
+ netif_wake_queue(dev);
+}
+
/* The interrupt handler.
* This is called from the CPM handler, not the MPC core interrupt.
*/
static void
-cpm_enet_interrupt(void *dev_id)
+scc_enet_interrupt(void *dev_id)
{
struct net_device *dev = dev_id;
- volatile struct cpm_enet_private *cep;
+ volatile struct scc_enet_private *cep;
volatile cbd_t *bdp;
ushort int_events;
int must_restart;
- cep = (struct cpm_enet_private *)dev->priv;
- if (cep->interrupt)
- printk("%s: Re-entering the interrupt handler.\n", dev->name);
-
- cep->interrupt = 1;
+ cep = (struct scc_enet_private *)dev->priv;
/* Get the interrupt events that caused us to be here.
*/
@@ -349,7 +328,7 @@ cpm_enet_interrupt(void *dev_id)
/* Handle receive event in its own function.
*/
if (int_events & SCCE_ENET_RXF)
- cpm_enet_rx(dev_id);
+ scc_enet_rx(dev_id);
/* Check for a transmit error. The manual is a little unclear
* about this, so the debug code until I get it figured out. It
@@ -363,6 +342,7 @@ cpm_enet_interrupt(void *dev_id)
/* Transmit OK, or non-fatal error. Update the buffer descriptors.
*/
if (int_events & (SCCE_ENET_TXE | SCCE_ENET_TXB)) {
+ spin_lock(&cep->lock);
bdp = cep->dirty_tx;
while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
if ((bdp==cep->cur_tx) && (cep->tx_full == 0))
@@ -421,10 +401,9 @@ cpm_enet_interrupt(void *dev_id)
/* Since we have freed up a buffer, the ring is no longer
* full.
*/
- if (cep->tx_full && cep->tx_busy) {
- cep->tx_full = 0;
- cep->tx_busy = 0;
- netif_wake_queue(dev);
+ if (cep->tx_full) {
+ if (netif_queue_stopped(dev))
+ netif_wake_queue(dev);
}
cep->dirty_tx = (cbd_t *)bdp;
@@ -444,6 +423,7 @@ cpm_enet_interrupt(void *dev_id)
mk_cr_cmd(CPM_CR_ENET, CPM_CR_RESTART_TX) | CPM_CR_FLG;
while (cp->cp_cpcr & CPM_CR_FLG);
}
+ spin_unlock(&cep->lock);
}
/* Check for receive busy, i.e. packets coming but no place to
@@ -455,8 +435,6 @@ cpm_enet_interrupt(void *dev_id)
printk("CPM ENET: BSY can't happen.\n");
}
- cep->interrupt = 0;
-
return;
}
@@ -466,14 +444,14 @@ cpm_enet_interrupt(void *dev_id)
* effectively tossing the packet.
*/
static int
-cpm_enet_rx(struct net_device *dev)
+scc_enet_rx(struct net_device *dev)
{
- struct cpm_enet_private *cep;
+ struct scc_enet_private *cep;
volatile cbd_t *bdp;
struct sk_buff *skb;
ushort pkt_len;
- cep = (struct cpm_enet_private *)dev->priv;
+ cep = (struct scc_enet_private *)dev->priv;
/* First, grab all of the stats for the incoming packet.
* These get messed up if we get called due to a busy condition.
@@ -560,7 +538,7 @@ for (;;) {
}
static int
-cpm_enet_close(struct net_device *dev)
+scc_enet_close(struct net_device *dev)
{
/* Don't know what to do yet.
*/
@@ -569,9 +547,9 @@ cpm_enet_close(struct net_device *dev)
return 0;
}
-static struct net_device_stats *cpm_enet_get_stats(struct net_device *dev)
+static struct net_device_stats *scc_enet_get_stats(struct net_device *dev)
{
- struct cpm_enet_private *cep = (struct cpm_enet_private *)dev->priv;
+ struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
return &cep->stats;
}
@@ -588,12 +566,12 @@ static struct net_device_stats *cpm_enet_get_stats(struct net_device *dev)
static void set_multicast_list(struct net_device *dev)
{
- struct cpm_enet_private *cep;
+ struct scc_enet_private *cep;
struct dev_mc_list *dmi;
u_char *mcptr, *tdptr;
volatile scc_enet_t *ep;
int i, j;
- cep = (struct cpm_enet_private *)dev->priv;
+ cep = (struct scc_enet_private *)dev->priv;
/* Get pointer to SCC area in parameter RAM.
*/
@@ -661,10 +639,10 @@ static void set_multicast_list(struct net_device *dev)
* transmit and receive to make sure we don't catch the CPM with some
* inconsistent control information.
*/
-int __init cpm_enet_init(void)
+int __init scc_enet_init(void)
{
struct net_device *dev;
- struct cpm_enet_private *cep;
+ struct scc_enet_private *cep;
int i, j;
unsigned char *eap;
unsigned long mem_addr;
@@ -684,9 +662,10 @@ int __init cpm_enet_init(void)
/* Allocate some private information.
*/
- cep = (struct cpm_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
+ cep = (struct scc_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
/*memset(cep, 0, sizeof(*cep));*/
__clear_user(cep,sizeof(*cep));
+ spin_lock_init(&cep->lock);
/* Create an Ethernet device instance.
*/
@@ -858,7 +837,7 @@ int __init cpm_enet_init(void)
*/
pte = find_pte(&init_mm, mem_addr);
pte_val(*pte) |= _PAGE_NO_CACHE;
- flush_tlb_page(current->mm->mmap, mem_addr);
+ flush_tlb_page(init_mm.mmap, mem_addr);
/* Initialize the BD for every fragment in the page.
*/
@@ -894,7 +873,7 @@ int __init cpm_enet_init(void)
/* Install our interrupt handler.
*/
- cpm_install_handler(CPMVEC_ENET, cpm_enet_interrupt, dev);
+ cpm_install_handler(CPMVEC_ENET, scc_enet_interrupt, dev);
/* Set GSMR_H to enable all normal operating modes.
* Set GSMR_L to enable Ethernet to MC68160.
@@ -953,10 +932,12 @@ int __init cpm_enet_init(void)
#endif
/* The CPM Ethernet specific entries in the device structure. */
- dev->open = cpm_enet_open;
- dev->hard_start_xmit = cpm_enet_start_xmit;
- dev->stop = cpm_enet_close;
- dev->get_stats = cpm_enet_get_stats;
+ dev->open = scc_enet_open;
+ dev->hard_start_xmit = scc_enet_start_xmit;
+ dev->tx_timeout = scc_enet_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+ dev->stop = scc_enet_close;
+ dev->get_stats = scc_enet_get_stats;
dev->set_multicast_list = set_multicast_list;
/* And last, enable the transmit and receive processing.
diff --git a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c
index f5088b9e4..2ae320e7a 100644
--- a/arch/ppc/8xx_io/uart.c
+++ b/arch/ppc/8xx_io/uart.c
@@ -41,6 +41,10 @@
#include <asm/8xx_immap.h>
#include <asm/mpc8xx.h>
#include "commproc.h"
+
+#ifdef CONFIG_KGDB
+extern int kgdb_output_string (const char* s, unsigned int count);
+#endif
#ifdef CONFIG_SERIAL_CONSOLE
#include <linux/console.h>
@@ -700,25 +704,18 @@ static int startup(ser_info_t *info)
* are coming.
*/
up = (smc_uart_t *)&cpmp->cp_dparam[state->port];
-#if 0
- up->smc_mrblr = 1; /* receive buffer length */
- up->smc_maxidl = 0; /* wait forever for next char */
-#else
+
up->smc_mrblr = RX_BUF_SIZE;
up->smc_maxidl = RX_BUF_SIZE;
-#endif
+
up->smc_brkcr = 1; /* number of break chars */
}
else {
sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE];
scup = (scc_uart_t *)&cpmp->cp_dparam[state->port];
-#if 0
- scup->scc_genscc.scc_mrblr = 1; /* receive buffer length */
- scup->scc_maxidl = 0; /* wait forever for next char */
-#else
+
scup->scc_genscc.scc_mrblr = RX_BUF_SIZE;
scup->scc_maxidl = RX_BUF_SIZE;
-#endif
sccp->scc_sccm |= (UART_SCCM_TX | UART_SCCM_RX);
sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
@@ -959,6 +956,12 @@ static int rs_8xx_write(struct tty_struct * tty, int from_user,
ser_info_t *info = (ser_info_t *)tty->driver_data;
volatile cbd_t *bdp;
+#ifdef CONFIG_KGDB
+ /* Try to let stub handle output. Returns true if it did. */
+ if (kgdb_output_string(buf, count))
+ return ret;
+#endif
+
if (serial_paranoia_check(info, tty->device, "rs_write"))
return 0;
@@ -979,8 +982,8 @@ static int rs_8xx_write(struct tty_struct * tty, int from_user,
}
if (from_user) {
- if (c !=
- copy_from_user(__va(bdp->cbd_bufaddr), buf, c)) {
+ c -= copy_from_user(__va(bdp->cbd_bufaddr), buf, c);
+ if (!c) {
if (!ret)
ret = -EFAULT;
break;
@@ -2099,7 +2102,7 @@ static _INLINE_ void show_serial_version(void)
* Print a string to the serial port trying not to disturb any possible
* real use of the port...
*/
-static void serial_console_write(struct console *c, const char *s,
+static void my_console_write(int idx, const char *s,
unsigned count)
{
struct serial_state *ser;
@@ -2109,7 +2112,7 @@ static void serial_console_write(struct console *c, const char *s,
volatile smc_uart_t *up;
volatile u_char *cp;
- ser = rs_table + c->index;
+ ser = rs_table + idx;
/* If the port has been initialized for general use, we have
* to use the buffer descriptors allocated there. Otherwise,
@@ -2146,8 +2149,15 @@ static void serial_console_write(struct console *c, const char *s,
* that, not that it is ready for us to send.
*/
while (bdp->cbd_sc & BD_SC_READY);
- /* Send the character out. */
- cp = __va(bdp->cbd_bufaddr);
+
+ /* Send the character out.
+ * If the buffer address is in the CPM DPRAM, don't
+ * convert it.
+ */
+ if ((uint)(bdp->cbd_bufaddr) > (uint)IMAP_ADDR)
+ cp = (u_char *)(bdp->cbd_bufaddr);
+ else
+ cp = __va(bdp->cbd_bufaddr);
*cp = *s;
bdp->cbd_datlen = 1;
@@ -2185,19 +2195,48 @@ static void serial_console_write(struct console *c, const char *s,
info->tx_cur = (cbd_t *)bdp;
}
+static void serial_console_write(struct console *c, const char *s,
+ unsigned count)
+{
+#ifdef CONFIG_KGDB
+ /* Try to let stub handle output. Returns true if it did. */
+ if (kgdb_output_string(s, count))
+ return;
+#endif
+ my_console_write(c->index, s, count);
+}
+
+#ifdef CONFIG_XMON
+int
+xmon_8xx_write(const char *s, unsigned count)
+{
+ my_console_write(0, s, count);
+ return(count);
+}
+#endif
+
+#ifdef CONFIG_KGDB
+void
+putDebugChar(char ch)
+{
+ my_console_write(0, &ch, 1);
+}
+#endif
+
/*
* Receive character from the serial port. This only works well
* before the port is initialize for real use.
*/
-static int serial_console_wait_key(struct console *co)
+static int my_console_wait_key(int idx, int xmon, char *obuf)
{
struct serial_state *ser;
u_char c, *cp;
ser_info_t *info;
volatile cbd_t *bdp;
volatile smc_uart_t *up;
+ int i;
- ser = rs_table + co->index;
+ ser = rs_table + idx;
/* Pointer to UART in parameter ram.
*/
@@ -2215,9 +2254,34 @@ static int serial_console_wait_key(struct console *co)
/*
* We need to gracefully shut down the receiver, disable
* interrupts, then read the input.
+ * XMON just wants a poll. If no character, return -1, else
+ * return the character.
+ */
+ if (!xmon) {
+ while (bdp->cbd_sc & BD_SC_EMPTY);
+ }
+ else {
+ if (bdp->cbd_sc & BD_SC_EMPTY)
+ return -1;
+ }
+
+ /* If the buffer address is in the CPM DPRAM, don't
+ * convert it.
*/
- while (bdp->cbd_sc & BD_SC_EMPTY); /* Wait for a character */
- cp = __va(bdp->cbd_bufaddr);
+ if ((uint)(bdp->cbd_bufaddr) > (uint)IMAP_ADDR)
+ cp = (u_char *)(bdp->cbd_bufaddr);
+ else
+ cp = __va(bdp->cbd_bufaddr);
+
+ if (obuf) {
+ i = c = bdp->cbd_datlen;
+ while (i-- > 0)
+ *obuf++ = *cp++;
+ }
+ else {
+ c = *cp;
+ }
+ bdp->cbd_sc |= BD_SC_EMPTY;
if (info) {
if (bdp->cbd_sc & BD_SC_WRAP) {
@@ -2229,10 +2293,89 @@ static int serial_console_wait_key(struct console *co)
info->rx_cur = (cbd_t *)bdp;
}
- c = *cp;
return((int)c);
}
+static int serial_console_wait_key(struct console *co)
+{
+ return(my_console_wait_key(co->index, 0, NULL));
+}
+
+#ifdef CONFIG_XMON
+int
+xmon_8xx_read_poll(void)
+{
+ return(my_console_wait_key(0, 1, NULL));
+}
+
+int
+xmon_8xx_read_char(void)
+{
+ return(my_console_wait_key(0, 0, NULL));
+}
+#endif
+
+#ifdef CONFIG_KGDB
+static char kgdb_buf[RX_BUF_SIZE], *kgdp;
+static int kgdb_chars;
+
+unsigned char
+getDebugChar(void)
+{
+ if (kgdb_chars <= 0) {
+ kgdb_chars = my_console_wait_key(0, 0, kgdb_buf);
+ kgdp = kgdb_buf;
+ }
+ kgdb_chars--;
+
+ return(*kgdp++);
+}
+
+void kgdb_interruptible(int state)
+{
+}
+void kgdb_map_scc(void)
+{
+ struct serial_state *ser;
+ uint mem_addr;
+ volatile cbd_t *bdp;
+ volatile smc_uart_t *up;
+
+ cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
+
+ /* To avoid data cache CPM DMA coherency problems, allocate a
+ * buffer in the CPM DPRAM. This will work until the CPM and
+ * serial ports are initialized. At that time a memory buffer
+ * will be allcoated.
+ * The port is already initialized from the boot procedure, all
+ * we do here is give it a different buffer and make it a FIFO.
+ */
+
+ ser = rs_table;
+
+ /* Right now, assume we are using SMCs.
+ */
+ up = (smc_uart_t *)&cpmp->cp_dparam[ser->port];
+
+ /* Allocate space for an input FIFO, plus a few bytes for output.
+ * Allocate bytes to maintain word alignment.
+ */
+ mem_addr = (uint)(&cpmp->cp_dpmem[0x1000]);
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ bdp = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
+ bdp->cbd_bufaddr = mem_addr;
+
+ bdp = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase];
+ bdp->cbd_bufaddr = mem_addr+RX_BUF_SIZE;
+
+ up->smc_mrblr = RX_BUF_SIZE; /* receive buffer length */
+ up->smc_maxidl = RX_BUF_SIZE;
+}
+#endif
+
static kdev_t serial_console_device(struct console *c)
{
return MKDEV(TTYAUX_MAJOR, 64 + c->index);
@@ -2522,8 +2665,8 @@ int __init rs_8xx_init(void)
* character interrupts. Using idle charater
* time requires some additional tuning.
*/
- up->smc_mrblr = 1;
- up->smc_maxidl = 0;
+ up->smc_mrblr = RX_BUF_SIZE;
+ up->smc_maxidl = RX_BUF_SIZE;
up->smc_brkcr = 1;
/* Send the CPM an initialize command.
@@ -2557,12 +2700,8 @@ int __init rs_8xx_init(void)
sup->scc_genscc.scc_rfcr = SMC_EB;
sup->scc_genscc.scc_tfcr = SMC_EB;
- /* Set this to 1 for now, so we get single
- * character interrupts. Using idle charater
- * time requires some additional tuning.
- */
- sup->scc_genscc.scc_mrblr = 1;
- sup->scc_maxidl = 0;
+ sup->scc_genscc.scc_mrblr = RX_BUF_SIZE;
+ sup->scc_maxidl = RX_BUF_SIZE;
sup->scc_brkcr = 1;
sup->scc_parec = 0;
sup->scc_frmec = 0;
@@ -2629,6 +2768,7 @@ int __init rs_8xx_init(void)
#endif
}
}
+
return 0;
}
@@ -2678,16 +2818,17 @@ static int __init serial_console_setup(struct console *co, char *options)
*/
dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * 2);
- /* Allocate space for two 2 byte FIFOs in the host memory.
- */
- mem_addr = m8xx_cpm_hostalloc(4);
+ /* Allocate space for an input FIFO, plus a few bytes for output.
+ * Allocate bytes to maintain word alignment.
+ */
+ mem_addr = m8xx_cpm_hostalloc(RX_BUF_SIZE + 4);
/* Set the physical address of the host memory buffers in
* the buffer descriptors.
*/
bdp = (cbd_t *)&cp->cp_dpmem[dp_addr];
bdp->cbd_bufaddr = __pa(mem_addr);
- (bdp+1)->cbd_bufaddr = __pa(mem_addr+2);
+ (bdp+1)->cbd_bufaddr = __pa(mem_addr+RX_BUF_SIZE);
/* For the receive, set empty and wrap.
* For transmit, set wrap.
@@ -2702,10 +2843,8 @@ static int __init serial_console_setup(struct console *co, char *options)
up->smc_rfcr = SMC_EB;
up->smc_tfcr = SMC_EB;
- /* Set this to 1 for now, so we get single character interrupts.
- */
- up->smc_mrblr = 1; /* receive buffer length */
- up->smc_maxidl = 0; /* wait forever for next char */
+ up->smc_mrblr = RX_BUF_SIZE; /* receive buffer length */
+ up->smc_maxidl = RX_BUF_SIZE;
/* Send the CPM an initialize command.
*/
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index 4b578da45..6acdc9a65 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -22,7 +22,7 @@ ASFLAGS =
LINKFLAGS = -T arch/ppc/vmlinux.lds -Ttext $(KERNELLOAD) -Bstatic
CPPFLAGS := $(CPPFLAGS) -D__powerpc__
CFLAGS := $(CFLAGS) -D__powerpc__ -fsigned-char \
- -msoft-float -pipe -fno-builtin -ffixed-r2 -Wno-uninitialized \
+ -msoft-float -pipe -ffixed-r2 -Wno-uninitialized \
-mmultiple -mstring
CPP = $(CC) -E $(CFLAGS)
@@ -75,6 +75,11 @@ SUBDIRS += arch/ppc/8xx_io
DRIVERS += arch/ppc/8xx_io/8xx_io.a
endif
+ifdef CONFIG_8260
+SUBDIRS += arch/ppc/8260_io
+DRIVERS += arch/ppc/8260_io/8260_io.a
+endif
+
ifdef CONFIG_APUS
SUBDIRS += arch/ppc/amiga
ARCHIVES += arch/ppc/amiga/amiga.o
@@ -98,6 +103,7 @@ $(BOOT_TARGETS): $(CHECKS) vmlinux
endif
ifdef CONFIG_6xx
+ifndef CONFIG_8260
$(BOOT_TARGETS): $(CHECKS) vmlinux
@$(MAKECOFFBOOT) $@
@$(MAKEBOOT) $@
@@ -114,6 +120,12 @@ endif
@$(MAKECOFFBOOT) $@
@$(MAKEBOOT) $@
@$(MAKECHRPBOOT) $@
+else
+# 8260 is custom 6xx
+$(BOOT_TARGETS): $(CHECKS) vmlinux
+ @$(MAKECOFFBOOT) $@
+ @$(MAKEMBXBOOT) $@
+endif
endif
ifdef CONFIG_PPC64
diff --git a/arch/ppc/config.in b/arch/ppc/config.in
index e9499fbc9..7e2c47c0b 100644
--- a/arch/ppc/config.in
+++ b/arch/ppc/config.in
@@ -18,9 +18,14 @@ choice 'Processor Type' \
"6xx/7xx/7400 CONFIG_6xx \
4xx CONFIG_4xx \
630/Power3(64-Bit) CONFIG_PPC64 \
- 82xx CONFIG_82xx \
+ 8260 CONFIG_8260 \
8xx CONFIG_8xx" 6xx
+if [ "$CONFIG_8260" = "y" ]; then
+ define_bool CONFIG_6xx y
+ define_bool CONFIG_SERIAL_CONSOLE y
+fi
+
if [ "$CONFIG_4xx" = "y" ]; then
choice 'Machine Type' \
"Oak CONFIG_OAK \
@@ -49,6 +54,7 @@ if [ "$CONFIG_6xx" = "y" ]; then
choice 'Machine Type' \
"PowerMac/PReP/MTX/CHRP CONFIG_ALL_PPC \
Gemini CONFIG_GEMINI \
+ EST8260 CONFIG_EST8260 \
APUS CONFIG_APUS" PowerMac/PReP/MTX/CHRP
fi
@@ -56,6 +62,10 @@ if [ "$CONFIG_PPC64" = "y" ]; then
define_bool CONFIG_ALL_PPC y
fi
+if [ "$CONFIG_8xx" = "y" -o "$CONFIG_8260" = "y" ]; then
+ define_bool CONFIG_ALL_PPC n
+fi
+
bool 'Symmetric multi-processing support' CONFIG_SMP
if [ "$CONFIG_6xx" = "y" ];then
bool 'AltiVec Support' CONFIG_ALTIVEC
@@ -86,7 +96,7 @@ define_bool CONFIG_ISA n
define_bool CONFIG_SBUS n
if [ "$CONFIG_APUS" = "y" -o "$CONFIG_4xx" = "y" -o \
- "$CONFIG_82xx" = "y" ]; then
+ "$CONFIG_8260" = "y" ]; then
define_bool CONFIG_PCI n
else
if [ "$CONFIG_6xx" = "y" -o "$CONFIG_PPC64" = "y" ]; then
@@ -144,7 +154,6 @@ if [ "$CONFIG_4xx" != "y" -a "$CONFIG_8xx" != "y" ]; then
bool 'Support for ADB mouse' CONFIG_ADBMOUSE
fi
bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE
- bool 'Support for TotalImpact TotalMP' CONFIG_TOTALMP
bool 'Support for early boot text console (BootX only)' CONFIG_BOOTX_TEXT
bool 'Support for Motorola Hot Swap' CONFIG_MOTOROLA_HOTSWAP
fi
@@ -226,6 +235,8 @@ fi
source net/ax25/Config.in
+source net/irda/Config.in
+
mainmenu_option next_comment
comment 'ISDN subsystem'
@@ -266,6 +277,10 @@ if [ "$CONFIG_8xx" = "y" ]; then
source arch/ppc/8xx_io/Config.in
fi
+if [ "$CONFIG_8260" = "y" ]; then
+source arch/ppc/8260_io/Config.in
+fi
+
source drivers/usb/Config.in
mainmenu_option next_comment
diff --git a/arch/ppc/configs/chrp_defconfig b/arch/ppc/configs/chrp_defconfig
deleted file mode 100644
index 48e305f44..000000000
--- a/arch/ppc/configs/chrp_defconfig
+++ /dev/null
@@ -1,319 +0,0 @@
-#
-# Automatically generated by make menuconfig: don't edit
-#
-
-#
-# Platform support
-#
-CONFIG_PPC=y
-CONFIG_6xx=y
-# CONFIG_8xx is not set
-# CONFIG_PMAC is not set
-# CONFIG_PREP is not set
-CONFIG_CHRP=y
-# CONFIG_ALL_PPC is not set
-# CONFIG_APUS is not set
-# CONFIG_MBX is not set
-# CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
-
-#
-# General setup
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
-CONFIG_PCI=y
-# CONFIG_PCI_QUIRKS is not set
-CONFIG_PCI_OLD_PROC=y
-CONFIG_NET=y
-CONFIG_SYSCTL=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_BINFMT_JAVA is not set
-# CONFIG_PARPORT is not set
-CONFIG_FB=y
-CONFIG_FB_COMPAT_XPMAC=y
-# CONFIG_PMAC_PBOOK is not set
-CONFIG_MAC_KEYBOARD=y
-# CONFIG_MAC_FLOPPY is not set
-# CONFIG_MAC_SERIAL is not set
-# CONFIG_ADBMOUSE is not set
-CONFIG_PROC_DEVICETREE=y
-# CONFIG_KGDB is not set
-# CONFIG_XMON is not set
-# CONFIG_TOTALMP is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-CONFIG_BLK_DEV_IDE=y
-# CONFIG_BLK_DEV_HD_IDE is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_RZ1000 is not set
-# CONFIG_BLK_DEV_IDEPCI is not set
-CONFIG_BLK_DEV_SL82C105=y
-# CONFIG_IDE_CHIPSETS is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_MD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_BLK_DEV_XD is not set
-CONFIG_PARIDE_PARPORT=y
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-# CONFIG_NETLINK is not set
-# CONFIG_FIREWALL is not set
-# CONFIG_FILTER is not set
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_IP_ROUTER is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-CONFIG_IP_ALIAS=y
-# CONFIG_SYN_COOKIES is not set
-CONFIG_INET_RARP=y
-CONFIG_IP_NOSR=y
-CONFIG_SKB_LARGE=y
-# CONFIG_IPV6 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_LLC is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-# CONFIG_CPU_IS_SLOW is not set
-# CONFIG_NET_SCHED is not set
-
-#
-# SCSI support
-#
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=y
-# CONFIG_SCSI_MULTI_LUN is not set
-CONFIG_SCSI_CONSTANTS=y
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AHA1740 is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA_DMA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-CONFIG_SCSI_NCR53C8XX=y
-CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
-CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4
-CONFIG_SCSI_NCR53C8XX_SYNC=5
-# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_SEAGATE is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
-# CONFIG_SCSI_DEBUG is not set
-CONFIG_SCSI_MESH=y
-CONFIG_SCSI_MESH_SYNC_RATE=10
-CONFIG_SCSI_MAC53C94=y
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_NET_ETHERNET=y
-# CONFIG_MACE is not set
-# CONFIG_BMAC is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_RTL8139 is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_EISA=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-# CONFIG_CS89x0 is not set
-# CONFIG_DE4X5 is not set
-CONFIG_DEC_ELCP=y
-# CONFIG_DGRS is not set
-# CONFIG_EEXPRESS_PRO100 is not set
-# CONFIG_LNE390 is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_TLAN is not set
-# CONFIG_ES3210 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_ZNET is not set
-# CONFIG_NET_POCKET is not set
-# CONFIG_FDDI is not set
-# CONFIG_DLCI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_NET_RADIO is not set
-# CONFIG_TR is not set
-# CONFIG_SHAPER is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Console drivers
-#
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FB_OF=y
-# CONFIG_FB_CONTROL is not set
-# CONFIG_FB_PLATINUM is not set
-# CONFIG_FB_VALKYRIE is not set
-CONFIG_FB_ATY=y
-CONFIG_FB_IMSTT=y
-# CONFIG_FB_CT65550 is not set
-# CONFIG_FB_S3TRIO is not set
-CONFIG_FB_VGA=y
-# CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_CFB24=y
-CONFIG_FBCON_CFB32=y
-CONFIG_FBCON_VGA=y
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-# CONFIG_FBCON_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_MOUSE is not set
-# CONFIG_UMISC is not set
-# CONFIG_QIC02_TAPE is not set
-# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-# CONFIG_VIDEO_DEV is not set
-CONFIG_NVRAM=y
-# CONFIG_JOYSTICK is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-
-#
-# Filesystems
-#
-# CONFIG_QUOTA is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_EXT2_FS=y
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_NFS_FS=y
-# CONFIG_NFSD is not set
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-# CONFIG_CODA_FS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_AFFS_FS is not set
-CONFIG_HFS_FS=y
-# CONFIG_ROMFS_FS is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_ADFS_FS is not set
-CONFIG_MAC_PARTITION=y
-# CONFIG_NLS is not set
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_OSS is not set
diff --git a/arch/ppc/configs/common_defconfig b/arch/ppc/configs/common_defconfig
index 72d8f66ee..caf15d27d 100644
--- a/arch/ppc/configs/common_defconfig
+++ b/arch/ppc/configs/common_defconfig
@@ -1,5 +1,5 @@
#
-# Automatically generated make config: don't edit
+# Automatically generated by make menuconfig: don't edit
#
# CONFIG_UID16 is not set
@@ -33,8 +33,8 @@ CONFIG_KMOD=y
#
# General setup
#
-# CONFIG_PCI is not set
-CONFIG_PCI=y
+# CONFIG_ISA is not set
+# CONFIG_SBUS is not set
CONFIG_PCI=y
CONFIG_NET=y
CONFIG_SYSCTL=y
@@ -46,6 +46,7 @@ CONFIG_KERNEL_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_PCI_NAMES is not set
# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
#
# Parallel port support
@@ -57,6 +58,7 @@ CONFIG_FB_COMPAT_XPMAC=y
CONFIG_PMAC_PBOOK=y
CONFIG_MAC_FLOPPY=y
CONFIG_MAC_SERIAL=y
+# CONFIG_SERIAL_CONSOLE is not set
CONFIG_ADB=y
CONFIG_ADB_CUDA=y
CONFIG_ADB_MACIO=y
@@ -64,7 +66,6 @@ CONFIG_ADB_PMU=y
CONFIG_ADB_KEYBOARD=y
CONFIG_ADBMOUSE=y
CONFIG_PROC_DEVICETREE=y
-# CONFIG_TOTALMP is not set
CONFIG_BOOTX_TEXT=y
# CONFIG_MOTOROLA_HOTSWAP is not set
# CONFIG_CMDLINE_BOOL is not set
@@ -73,21 +74,22 @@ CONFIG_BOOTX_TEXT=y
# Plug and Play configuration
#
# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
-
-#
-# Additional Block Devices
-#
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_LVM is not set
# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_STRIPED is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_INITRD=y
@@ -112,18 +114,10 @@ CONFIG_IP_MULTICAST=y
# CONFIG_IP_MROUTE is not set
CONFIG_IP_ALIAS=y
CONFIG_SYN_COOKIES=y
-
-#
-# (it is safe to leave these untouched)
-#
CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
# CONFIG_KHTTPD is not set
# CONFIG_ATM is not set
-
-#
-#
-#
# CONFIG_IPX is not set
CONFIG_ATALK=m
# CONFIG_DECNET is not set
@@ -150,35 +144,52 @@ CONFIG_IDE=y
# IDE, ATA and ATAPI Block devices
#
CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
# CONFIG_BLK_DEV_HD_IDE is not set
# CONFIG_BLK_DEV_HD is not set
CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECS is not set
CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
CONFIG_BLK_DEV_IDESCSI=y
-
-#
-# IDE chipset support/bugfixes
-#
# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
# CONFIG_BLK_DEV_RZ1000 is not set
CONFIG_BLK_DEV_IDEPCI=y
# CONFIG_IDEPCI_SHARE_IRQ is not set
# CONFIG_BLK_DEV_IDEDMA_PCI is not set
# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
# CONFIG_BLK_DEV_IDEDMA is not set
CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
+# CONFIG_IDEDMA_PCI_WIP is not set
+# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_WDC_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD7409 is not set
+# CONFIG_AMD7409_OVERRIDE is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_CMD64X_RAID is not set
# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_HPT34X_AUTODMA is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_HPT366_FIP is not set
+# CONFIG_HPT366_MODE3 is not set
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_PDC202XX is not set
+# CONFIG_PDC202XX_BURST is not set
+# CONFIG_PDC202XX_MASTER is not set
+# CONFIG_BLK_DEV_SIS5513 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_VIA82CXXX_TUNING is not set
# CONFIG_BLK_DEV_SL82C105 is not set
CONFIG_BLK_DEV_IDE_PMAC=y
CONFIG_BLK_DEV_IDEDMA_PMAC=y
@@ -192,10 +203,6 @@ CONFIG_BLK_DEV_IDE_MODES=y
# SCSI support
#
CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
CONFIG_BLK_DEV_SD=y
CONFIG_SD_EXTRA_DEVS=40
CONFIG_CHR_DEV_ST=y
@@ -203,10 +210,6 @@ CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_SR_EXTRA_DEVS=2
CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
# CONFIG_SCSI_DEBUG_QUEUES is not set
# CONFIG_SCSI_MULTI_LUN is not set
CONFIG_SCSI_CONSTANTS=y
@@ -226,12 +229,12 @@ CONFIG_SCSI_AIC7XXX=y
CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
CONFIG_AIC7XXX_PROC_STATS=y
CONFIG_AIC7XXX_RESET_DELAY=15
-# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
# CONFIG_SCSI_AM53C974 is not set
# CONFIG_SCSI_MEGARAID is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_DTC3280 is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_EATA_DMA is not set
@@ -262,11 +265,9 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_SEAGATE is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_T128 is not set
# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
# CONFIG_SCSI_DEBUG is not set
CONFIG_SCSI_MESH=y
CONFIG_SCSI_MESH_SYNC_RATE=5
@@ -345,6 +346,7 @@ CONFIG_DE4X5=y
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
# CONFIG_PPP_ASYNC is not set
# CONFIG_PPP_SYNC_TTY is not set
# CONFIG_PPP_DEFLATE is not set
@@ -483,66 +485,17 @@ CONFIG_NVRAM=y
#
# CONFIG_FTAPE is not set
# CONFIG_DRM is not set
+# CONFIG_DRM_TDFX is not set
# CONFIG_AGP is not set
#
-# USB support
-#
-CONFIG_USB=y
-
-#
-# USB Controllers
-#
-# CONFIG_USB_UHCI is not set
-# CONFIG_USB_UHCI_ALT is not set
-CONFIG_USB_OHCI=y
-
-#
-# Miscellaneous USB options
-#
-# CONFIG_USB_DEVICEFS is not set
-
-#
-# USB Devices
-#
-# CONFIG_USB_PRINTER is not set
-# CONFIG_USB_SCANNER is not set
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_SERIAL is not set
-# CONFIG_USB_CPIA is not set
-# CONFIG_USB_IBMCAM is not set
-# CONFIG_USB_OV511 is not set
-# CONFIG_USB_DC2XX is not set
-# CONFIG_USB_STORAGE is not set
-# CONFIG_USB_DABUSB is not set
-# CONFIG_USB_PLUSB is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_DSBR is not set
-
-#
-# USB HID
-#
-# CONFIG_USB_HID is not set
-CONFIG_USB_KBD=y
-CONFIG_USB_MOUSE=y
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_WMFORCE is not set
-CONFIG_INPUT_KEYBDEV=y
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_MIX is not set
-# CONFIG_INPUT_MOUSEDEV_DIGITIZER is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-
-#
# File systems
#
# CONFIG_QUOTA is not set
CONFIG_AUTOFS_FS=y
# CONFIG_AUTOFS4_FS is not set
# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
# CONFIG_AFFS_FS is not set
CONFIG_HFS_FS=y
# CONFIG_BFS_FS is not set
@@ -552,32 +505,51 @@ CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
# CONFIG_ROMFS_FS is not set
CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
#
# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_ROOT_NFS is not set
CONFIG_NFSD=y
# CONFIG_NFSD_V3 is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
# CONFIG_SMB_FS is not set
# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
#
# Partition Types
@@ -632,6 +604,7 @@ CONFIG_NLS=y
# Sound
#
CONFIG_SOUND=y
+CONFIG_DMASOUND_AWACS=y
CONFIG_DMASOUND=y
# CONFIG_SOUND_CMPCI is not set
# CONFIG_SOUND_ES1370 is not set
@@ -652,6 +625,7 @@ CONFIG_SOUND_OSS=y
CONFIG_SOUND_CS4232=m
# CONFIG_SOUND_SSCAPE is not set
# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_ICH is not set
# CONFIG_SOUND_VMIDI is not set
# CONFIG_SOUND_TRIX is not set
# CONFIG_SOUND_MSS is not set
@@ -659,6 +633,7 @@ CONFIG_SOUND_CS4232=m
# CONFIG_SOUND_NM256 is not set
# CONFIG_SOUND_MAD16 is not set
# CONFIG_SOUND_PAS is not set
+# CONFIG_PAS_JOYSTICK is not set
# CONFIG_SOUND_PSS is not set
# CONFIG_SOUND_SOFTOSS is not set
# CONFIG_SOUND_SB is not set
@@ -673,6 +648,41 @@ CONFIG_SOUND_CS4232=m
# CONFIG_SOUND_AEDSP16 is not set
#
+# USB support
+#
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_UHCI is not set
+# CONFIG_USB_UHCI_ALT is not set
+CONFIG_USB_OHCI=y
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_SERIAL is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_USS720 is not set
+# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_PLUSB is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_DSBR is not set
+CONFIG_USB_HID=y
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_WMFORCE is not set
+CONFIG_INPUT_KEYBDEV=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+
+#
# Kernel hacking
#
CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/ppc/configs/pmac_defconfig b/arch/ppc/configs/pmac_defconfig
deleted file mode 100644
index e2b7c31bd..000000000
--- a/arch/ppc/configs/pmac_defconfig
+++ /dev/null
@@ -1,550 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-
-#
-# Platform support
-#
-CONFIG_PPC=y
-CONFIG_6xx=y
-# CONFIG_PPC64 is not set
-# CONFIG_82xx is not set
-# CONFIG_8xx is not set
-CONFIG_PMAC=y
-# CONFIG_PREP is not set
-# CONFIG_CHRP is not set
-# CONFIG_ALL_PPC is not set
-# CONFIG_GEMINI is not set
-# CONFIG_APUS is not set
-# CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
-CONFIG_6xx=y
-
-#
-# General setup
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-CONFIG_PCI=y
-CONFIG_NET=y
-CONFIG_SYSCTL=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_MISC=m
-CONFIG_HOTPLUG=y
-
-#
-# PCMCIA/Cardbus support
-#
-CONFIG_PCMCIA=m
-CONFIG_CARDBUS=y
-# CONFIG_PARPORT is not set
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FB=y
-CONFIG_FB_COMPAT_XPMAC=y
-CONFIG_PMAC_PBOOK=y
-CONFIG_MAC_FLOPPY=y
-CONFIG_MAC_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
-CONFIG_ADB=y
-CONFIG_ADB_CUDA=y
-CONFIG_ADB_MACIO=y
-CONFIG_ADB_PMU=y
-CONFIG_ADB_KEYBOARD=y
-CONFIG_PROC_DEVICETREE=y
-# CONFIG_TOTALMP is not set
-CONFIG_BOOTX_TEXT=y
-# CONFIG_MOTOROLA_HOTSWAP is not set
-
-#
-# Plug and Play configuration
-#
-# CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD_IDE is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=y
-# CONFIG_BLK_DEV_IDESCSI is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_RZ1000 is not set
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-CONFIG_IDEDMA_PCI_AUTO=y
-CONFIG_IDEDMA_NEW_DRIVE_LISTINGS=y
-CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_AEC6210 is not set
-CONFIG_BLK_DEV_CMD646=y
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_PDC202XX is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
-CONFIG_BLK_DEV_IDE_PMAC=y
-CONFIG_BLK_DEV_IDEDMA_PMAC=y
-CONFIG_IDEDMA_PMAC_AUTO=y
-CONFIG_BLK_DEV_IDEDMA=y
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_IDE_CHIPSETS is not set
-# CONFIG_BLK_CPQ_DA is not set
-
-#
-# Additional Block Devices
-#
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_MD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_BLK_DEV_XD is not set
-CONFIG_PARIDE_PARPORT=y
-# CONFIG_PARIDE is not set
-CONFIG_BLK_DEV_IDE_MODES=y
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK=y
-# CONFIG_RTNETLINK is not set
-# CONFIG_NETLINK_DEV is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-# CONFIG_FILTER is not set
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_IP_ROUTER is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-CONFIG_IP_ALIAS=y
-# CONFIG_SYN_COOKIES is not set
-
-#
-# (it is safe to leave these untouched)
-#
-CONFIG_SKB_LARGE=y
-# CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
-# CONFIG_ATM is not set
-
-#
-#
-#
-# CONFIG_IPX is not set
-CONFIG_ATALK=m
-# CONFIG_DECNET is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_LLC is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# SCSI support
-#
-CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-# CONFIG_CHR_DEV_SG is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-CONFIG_SCSI_CONSTANTS=y
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AHA1740 is not set
-CONFIG_SCSI_AIC7XXX=y
-# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
-CONFIG_AIC7XXX_PROC_STATS=y
-CONFIG_AIC7XXX_RESET_DELAY=15
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_DMA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-# CONFIG_SCSI_NCR53C8XX is not set
-# CONFIG_SCSI_SYM53C8XX is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_SEAGATE is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
-# CONFIG_SCSI_DEBUG is not set
-CONFIG_SCSI_MESH=y
-CONFIG_SCSI_MESH_SYNC_RATE=5
-CONFIG_SCSI_MAC53C94=y
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_ETHERTAP is not set
-# CONFIG_NET_SB1000 is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MACE=y
-CONFIG_BMAC=y
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_RTL8139 is not set
-# CONFIG_SIS900 is not set
-# CONFIG_DM9102 is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_EISA=y
-# CONFIG_PCNET32 is not set
-# CONFIG_ACENIC is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-# CONFIG_CS89x0 is not set
-CONFIG_DE4X5=y
-# CONFIG_DEC_ELCP is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEXPRESS_PRO100 is not set
-# CONFIG_LNE390 is not set
-# CONFIG_NE3210 is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_ES3210 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_ZNET is not set
-# CONFIG_NET_POCKET is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-
-#
-# Appletalk devices
-#
-# CONFIG_LTPC is not set
-# CONFIG_COPS is not set
-# CONFIG_IPDDP is not set
-CONFIG_PPP=y
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=m
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring driver support
-#
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# PCMCIA network devices
-#
-# CONFIG_PCMCIA_PCNET is not set
-# CONFIG_PCMCIA_3C589 is not set
-# CONFIG_PCMCIA_RAYCS is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Console drivers
-#
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FB_CLGEN is not set
-# CONFIG_FB_PM2 is not set
-CONFIG_FB_OF=y
-CONFIG_FB_CONTROL=y
-CONFIG_FB_PLATINUM=y
-CONFIG_FB_VALKYRIE=y
-CONFIG_FB_IMSTT=y
-CONFIG_FB_CT65550=y
-# CONFIG_FB_S3TRIO is not set
-# CONFIG_FB_VGA16 is not set
-# CONFIG_FB_MATROX is not set
-CONFIG_FB_ATY=y
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_CFB24=y
-CONFIG_FBCON_CFB32=y
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-CONFIG_FBCON_FONTS=y
-# CONFIG_FONT_8x8 is not set
-CONFIG_FONT_8x16=y
-CONFIG_FONT_SUN8x16=y
-CONFIG_FONT_SUN12x22=y
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=m
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# Mice
-#
-CONFIG_BUSMOUSE=y
-# CONFIG_ATIXL_BUSMOUSE is not set
-# CONFIG_LOGIBUSMOUSE is not set
-# CONFIG_MS_BUSMOUSE is not set
-CONFIG_ADBMOUSE=y
-# CONFIG_MOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-# CONFIG_WATCHDOG is not set
-CONFIG_NVRAM=y
-# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Joystick support
-#
-# CONFIG_JOYSTICK is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-
-#
-# USB drivers - not for the faint of heart
-#
-CONFIG_USB=y
-
-#
-# USB Controllers
-#
-# CONFIG_USB_UHCI is not set
-CONFIG_USB_OHCI=y
-CONFIG_USB_OHCI_DEBUG=y
-# CONFIG_USB_OHCI_HCD is not set
-
-#
-# Miscellaneous USB options
-#
-CONFIG_USB_DEBUG_ISOC=y
-CONFIG_USB_PROC=y
-# CONFIG_USB_EZUSB is not set
-
-#
-# USB Devices
-#
-CONFIG_USB_HUB=y
-CONFIG_USB_MOUSE=y
-CONFIG_USB_HP_SCANNER=m
-CONFIG_USB_KBD=y
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-# CONFIG_USB_SERIAL is not set
-# CONFIG_USB_CPIA is not set
-CONFIG_USB_SCSI=m
-CONFIG_USB_SCSI_DEBUG=y
-# CONFIG_USB_USS720 is not set
-
-#
-# Filesystems
-#
-# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_EFS_FS is not set
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_DEVPTS_FS=y
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-# CONFIG_CODA_FS is not set
-CONFIG_NFS_FS=y
-CONFIG_NFSD=y
-# CONFIG_NFSD_SUN is not set
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-# CONFIG_SMB_FS is not set
-# CONFIG_NCP_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_OSF_PARTITION is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_NLS is not set
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-CONFIG_DMASOUND=y
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_OSS is not set
-
-#
-# Kernel hacking
-#
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_KGDB is not set
-# CONFIG_XMON is not set
diff --git a/arch/ppc/configs/prep_defconfig b/arch/ppc/configs/prep_defconfig
deleted file mode 100644
index 01c314cb3..000000000
--- a/arch/ppc/configs/prep_defconfig
+++ /dev/null
@@ -1,361 +0,0 @@
-#
-# Automatically generated by make menuconfig: don't edit
-#
-
-#
-# Platform support
-#
-CONFIG_PPC=y
-CONFIG_6xx=y
-# CONFIG_8xx is not set
-# CONFIG_PMAC is not set
-CONFIG_PREP=y
-# CONFIG_CHRP is not set
-# CONFIG_ALL_PPC is not set
-# CONFIG_APUS is not set
-# CONFIG_MBX is not set
-# CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
-
-#
-# General setup
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-CONFIG_PCI=y
-# CONFIG_PCI_QUIRKS is not set
-CONFIG_PCI_OLD_PROC=y
-CONFIG_NET=y
-CONFIG_SYSCTL=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_BINFMT_JAVA is not set
-# CONFIG_PARPORT is not set
-# CONFIG_FB is not set
-CONFIG_VGA_CONSOLE=y
-# CONFIG_PMAC_PBOOK is not set
-# CONFIG_MAC_KEYBOARD is not set
-# CONFIG_MAC_FLOPPY is not set
-# CONFIG_MAC_SERIAL is not set
-# CONFIG_ADBMOUSE is not set
-# CONFIG_PROC_DEVICETREE is not set
-# CONFIG_KGDB is not set
-# CONFIG_XMON is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-CONFIG_BLK_DEV_IDE=y
-# CONFIG_BLK_DEV_HD_IDE is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_RZ1000 is not set
-# CONFIG_BLK_DEV_IDEPCI is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
-# CONFIG_IDE_CHIPSETS is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_MD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_BLK_DEV_XD is not set
-CONFIG_PARIDE_PARPORT=y
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-# CONFIG_NETLINK is not set
-# CONFIG_FIREWALL is not set
-# CONFIG_FILTER is not set
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_IP_ROUTER is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_RARP is not set
-# CONFIG_IP_NOSR is not set
-CONFIG_SKB_LARGE=y
-# CONFIG_IPV6 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_LLC is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-# CONFIG_CPU_IS_SLOW is not set
-# CONFIG_NET_SCHED is not set
-
-#
-# SCSI support
-#
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-# CONFIG_CHR_DEV_SG is not set
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AHA1740 is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA_DMA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-CONFIG_SCSI_NCR53C8XX=y
-CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
-CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4
-CONFIG_SCSI_NCR53C8XX_SYNC=5
-# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-CONFIG_SCSI_NCR53C8XX_IOMAPPED=y
-# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_SEAGATE is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_MESH is not set
-# CONFIG_SCSI_MAC53C94 is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_NET_ETHERNET=y
-# CONFIG_MACE is not set
-# CONFIG_BMAC is not set
-# CONFIG_NET_VENDOR_3COM is not set
-CONFIG_LANCE=y
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_RTL8139 is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_EISA=y
-CONFIG_PCNET32=y
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-# CONFIG_CS89x0 is not set
-CONFIG_DE4X5=y
-# CONFIG_DEC_ELCP is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEXPRESS_PRO100 is not set
-# CONFIG_LNE390 is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_TLAN is not set
-# CONFIG_ES3210 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_ZNET is not set
-# CONFIG_NET_POCKET is not set
-# CONFIG_FDDI is not set
-# CONFIG_DLCI is not set
-CONFIG_PPP=m
-# CONFIG_SLIP is not set
-# CONFIG_NET_RADIO is not set
-# CONFIG_TR is not set
-# CONFIG_SHAPER is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Console drivers
-#
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_MOUSE=y
-# CONFIG_ATIXL_BUSMOUSE is not set
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MS_BUSMOUSE is not set
-CONFIG_PSMOUSE=y
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
-# CONFIG_UMISC is not set
-# CONFIG_QIC02_TAPE is not set
-# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_NVRAM is not set
-# CONFIG_JOYSTICK is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-
-#
-# Filesystems
-#
-# CONFIG_QUOTA is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_EXT2_FS=y
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_NFS_FS=y
-# CONFIG_NFSD is not set
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-# CONFIG_CODA_FS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_ADFS_FS is not set
-# CONFIG_DEVPTS_FS is not set
-# CONFIG_MAC_PARTITION is not set
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_KOI8_R is not set
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-CONFIG_SOUND_OSS=y
-# CONFIG_SOUND_PAS is not set
-# CONFIG_SOUND_SB is not set
-# CONFIG_SOUND_ADLIB is not set
-# CONFIG_SOUND_GUS is not set
-# CONFIG_SOUND_MPU401 is not set
-# CONFIG_SOUND_PSS is not set
-# CONFIG_SOUND_MSS is not set
-# CONFIG_SOUND_SSCAPE is not set
-# CONFIG_SOUND_TRIX is not set
-# CONFIG_SOUND_MAD16 is not set
-# CONFIG_SOUND_WAVEFRONT is not set
-CONFIG_SOUND_CS4232=y
-CONFIG_CS4232_BASE=530
-CONFIG_CS4232_IRQ=11
-CONFIG_CS4232_DMA=0
-CONFIG_CS4232_DMA2=3
-CONFIG_CS4232_MPU_BASE=330
-CONFIG_CS4232_MPU_IRQ=9
-# CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_SGALAXY is not set
-# CONFIG_SOUND_OPL3SA1 is not set
-# CONFIG_SOUND_SOFTOSS is not set
-# CONFIG_SOUND_YM3812 is not set
-# CONFIG_SOUND_VMIDI is not set
-# CONFIG_SOUND_UART6850 is not set
-
-#
-# Additional low level sound drivers
-#
-# CONFIG_LOWLEVEL_SOUND is not set
diff --git a/arch/ppc/defconfig b/arch/ppc/defconfig
index 229768b9b..c93118bae 100644
--- a/arch/ppc/defconfig
+++ b/arch/ppc/defconfig
@@ -1,5 +1,5 @@
#
-# Automatically generated make config: don't edit
+# Automatically generated by make menuconfig: don't edit
#
# CONFIG_UID16 is not set
@@ -66,7 +66,6 @@ CONFIG_ADB_PMU=y
CONFIG_ADB_KEYBOARD=y
CONFIG_ADBMOUSE=y
CONFIG_PROC_DEVICETREE=y
-# CONFIG_TOTALMP is not set
CONFIG_BOOTX_TEXT=y
# CONFIG_MOTOROLA_HOTSWAP is not set
# CONFIG_CMDLINE_BOOL is not set
@@ -85,13 +84,12 @@ CONFIG_BOOTX_TEXT=y
# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
-
-#
-# Additional Block Devices
-#
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_LVM is not set
# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_STRIPED is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_INITRD=y
@@ -116,18 +114,10 @@ CONFIG_IP_MULTICAST=y
# CONFIG_IP_MROUTE is not set
CONFIG_IP_ALIAS=y
CONFIG_SYN_COOKIES=y
-
-#
-# (it is safe to leave these untouched)
-#
CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
# CONFIG_KHTTPD is not set
# CONFIG_ATM is not set
-
-#
-#
-#
# CONFIG_IPX is not set
CONFIG_ATALK=m
# CONFIG_DECNET is not set
@@ -154,10 +144,6 @@ CONFIG_IDE=y
# IDE, ATA and ATAPI Block devices
#
CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
# CONFIG_BLK_DEV_HD_IDE is not set
# CONFIG_BLK_DEV_HD is not set
CONFIG_BLK_DEV_IDEDISK=y
@@ -167,10 +153,6 @@ CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
CONFIG_BLK_DEV_IDESCSI=y
-
-#
-# IDE chipset support/bugfixes
-#
# CONFIG_BLK_DEV_CMD640 is not set
# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
# CONFIG_BLK_DEV_ISAPNP is not set
@@ -207,6 +189,7 @@ CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
# CONFIG_BLK_DEV_SIS5513 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_VIA82CXXX_TUNING is not set
# CONFIG_BLK_DEV_SL82C105 is not set
CONFIG_BLK_DEV_IDE_PMAC=y
CONFIG_BLK_DEV_IDEDMA_PMAC=y
@@ -220,10 +203,6 @@ CONFIG_BLK_DEV_IDE_MODES=y
# SCSI support
#
CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
CONFIG_BLK_DEV_SD=y
CONFIG_SD_EXTRA_DEVS=40
CONFIG_CHR_DEV_ST=y
@@ -231,10 +210,6 @@ CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_SR_EXTRA_DEVS=2
CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
# CONFIG_SCSI_DEBUG_QUEUES is not set
# CONFIG_SCSI_MULTI_LUN is not set
CONFIG_SCSI_CONSTANTS=y
@@ -254,12 +229,12 @@ CONFIG_SCSI_AIC7XXX=y
CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
CONFIG_AIC7XXX_PROC_STATS=y
CONFIG_AIC7XXX_RESET_DELAY=15
-# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
# CONFIG_SCSI_AM53C974 is not set
# CONFIG_SCSI_MEGARAID is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_DTC3280 is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_EATA_DMA is not set
@@ -290,11 +265,9 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_SEAGATE is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_T128 is not set
# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
# CONFIG_SCSI_DEBUG is not set
CONFIG_SCSI_MESH=y
CONFIG_SCSI_MESH_SYNC_RATE=5
@@ -373,6 +346,7 @@ CONFIG_DE4X5=y
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
# CONFIG_PPP_ASYNC is not set
# CONFIG_PPP_SYNC_TTY is not set
# CONFIG_PPP_DEFLATE is not set
@@ -515,65 +489,13 @@ CONFIG_NVRAM=y
# CONFIG_AGP is not set
#
-# USB support
-#
-CONFIG_USB=y
-
-#
-# USB Controllers
-#
-# CONFIG_USB_UHCI is not set
-# CONFIG_USB_UHCI_ALT is not set
-CONFIG_USB_OHCI=y
-
-#
-# Miscellaneous USB options
-#
-# CONFIG_USB_DEVICEFS is not set
-
-#
-# USB Devices
-#
-# CONFIG_USB_PRINTER is not set
-# CONFIG_USB_SCANNER is not set
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_SERIAL is not set
-# CONFIG_USB_CPIA is not set
-# CONFIG_USB_IBMCAM is not set
-# CONFIG_USB_OV511 is not set
-# CONFIG_USB_DC2XX is not set
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_STORAGE is not set
-# CONFIG_USB_USS720 is not set
-# CONFIG_USB_DABUSB is not set
-# CONFIG_USB_PLUSB is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_DSBR is not set
-
-#
-# USB HID
-#
-# CONFIG_USB_HID is not set
-CONFIG_USB_KBD=y
-CONFIG_USB_MOUSE=y
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_WMFORCE is not set
-CONFIG_INPUT_KEYBDEV=y
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_MIX is not set
-# CONFIG_INPUT_MOUSEDEV_DIGITIZER is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-
-#
# File systems
#
# CONFIG_QUOTA is not set
CONFIG_AUTOFS_FS=y
# CONFIG_AUTOFS4_FS is not set
# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
# CONFIG_AFFS_FS is not set
CONFIG_HFS_FS=y
# CONFIG_BFS_FS is not set
@@ -583,27 +505,35 @@ CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
# CONFIG_ROMFS_FS is not set
CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
#
# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
# CONFIG_ROOT_NFS is not set
CONFIG_NFSD=y
# CONFIG_NFSD_V3 is not set
@@ -611,6 +541,16 @@ CONFIG_SUNRPC=y
CONFIG_LOCKD=y
# CONFIG_SMB_FS is not set
# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
#
# Partition Types
@@ -665,6 +605,7 @@ CONFIG_NLS=y
# Sound
#
CONFIG_SOUND=y
+CONFIG_DMASOUND_AWACS=y
CONFIG_DMASOUND=y
# CONFIG_SOUND_CMPCI is not set
# CONFIG_SOUND_ES1370 is not set
@@ -685,6 +626,7 @@ CONFIG_SOUND_OSS=y
CONFIG_SOUND_CS4232=m
# CONFIG_SOUND_SSCAPE is not set
# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_ICH is not set
# CONFIG_SOUND_VMIDI is not set
# CONFIG_SOUND_TRIX is not set
# CONFIG_SOUND_MSS is not set
@@ -707,6 +649,41 @@ CONFIG_SOUND_CS4232=m
# CONFIG_SOUND_AEDSP16 is not set
#
+# USB support
+#
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_UHCI is not set
+# CONFIG_USB_UHCI_ALT is not set
+CONFIG_USB_OHCI=y
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_SERIAL is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_USS720 is not set
+# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_PLUSB is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_DSBR is not set
+CONFIG_USB_HID=y
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_WMFORCE is not set
+CONFIG_INPUT_KEYBDEV=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+
+#
# Kernel hacking
#
CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index 73db2269e..ed16da557 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -31,7 +31,7 @@ CONFIG_CHRP=y
endif
O_OBJS := entry.o traps.o irq.o idle.o time.o process.o signal.o syscalls.o \
- misc.o bitops.o ptrace.o align.o ppc_htab.o semaphore.o
+ misc.o ptrace.o align.o ppc_htab.o semaphore.o bitops.o
ifndef CONFIG_8xx
O_OBJS += hashtable.o
@@ -45,10 +45,6 @@ ifdef CONFIG_KGDB
O_OBJS += ppc-stub.o
endif
-ifdef CONFIG_TOTALMP
-O_OBJS += totalmp.o
-endif
-
ifdef CONFIG_PMAC_PBOOK
O_OBJS += sleep.o
endif
@@ -100,6 +96,9 @@ endif
ifeq ($(CONFIG_GEMINI),y)
O_OBJS += gemini_prom.o gemini_pci.o gemini_setup.o open_pic.o
endif
+ifeq ($(CONFIG_8260),y)
+ O_OBJS += m8260_setup.o ppc8260_pic.o
+endif
all: $(KHEAD) kernel.o
diff --git a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c
index 7f6340261..5b7366adc 100644
--- a/arch/ppc/kernel/align.c
+++ b/arch/ppc/kernel/align.c
@@ -14,6 +14,7 @@
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/system.h>
+#include <asm/cache.h>
struct aligninfo {
unsigned char len;
@@ -38,6 +39,8 @@ struct aligninfo {
#define S 0x40 /* single-precision fp, or byte-swap value */
#define HARD 0x80 /* string, stwcx. */
+#define DCBZ 0x5f /* 8xx/82xx dcbz faults when cache not enabled */
+
/*
* The PowerPC stores certain bits of the instruction that caused the
* alignment exception in the DSISR register. This array maps those
@@ -220,9 +223,27 @@ fix_alignment(struct pt_regs *regs)
areg = regs->dsisr & 0x1f; /* register to update */
instr = (regs->dsisr >> 10) & 0x7f;
#endif
+
nb = aligninfo[instr].len;
- if (nb == 0)
- return 0; /* too hard or invalid instruction bits */
+ if (nb == 0) {
+ long *p;
+ int i;
+
+ if (instr != DCBZ)
+ return 0; /* too hard or invalid instruction */
+ /*
+ * The dcbz (data cache block zero) instruction
+ * gives an alignment fault if used on non-cacheable
+ * memory. We handle the fault mainly for the
+ * case when we are running with the cache disabled
+ * for debugging.
+ */
+ p = (long *) (regs->dar & -L1_CACHE_BYTES);
+ for (i = 0; i < L1_CACHE_BYTES / sizeof(long); ++i)
+ p[i] = 0;
+ return 1;
+ }
+
flags = aligninfo[instr].flags;
/* For the 4xx-family processors, the 'dar' field of the
diff --git a/arch/ppc/kernel/feature.c b/arch/ppc/kernel/feature.c
index d5baa3747..e47befdd3 100644
--- a/arch/ppc/kernel/feature.c
+++ b/arch/ppc/kernel/feature.c
@@ -57,8 +57,8 @@ static fbit feature_bits_ohare_pbook[] = {
{0x38,1,OH_BAY_RESET_N}, /* FEATURE_Mediabay_reset */
{0x38,1,OH_BAY_POWER_N}, /* FEATURE_Mediabay_power */
{0x38,0,OH_BAY_PCI_ENABLE}, /* FEATURE_Mediabay_PCI_enable */
- {0x38,0,OH_BAY_IDE_ENABLE}, /* FEATURE_Mediabay_IDE_enable */
- {0x38,1,OH_IDE1_RESET_N}, /* FEATURE_Mediabay_IDE_reset */
+ {0x38,0,OH_BAY_IDE_ENABLE}, /* FEATURE_IDE1_enable */
+ {0x38,1,OH_IDE1_RESET_N}, /* FEATURE_IDE1_reset */
{0x38,0,OH_BAY_FLOPPY_ENABLE}, /* FEATURE_Mediabay_floppy_enable */
{0x38,0,0}, /* FEATURE_BMac_reset */
{0x38,0,0}, /* FEATURE_BMac_IO_enable */
@@ -68,6 +68,8 @@ static fbit feature_bits_ohare_pbook[] = {
{0x38,0,0}, /* FEATURE_Sound_CLK_Enable */
{0x38,0,0}, /* FEATURE_IDE2_enable */
{0x38,0,0}, /* FEATURE_IDE2_reset */
+ {0x38,0,0}, /* FEATURE_Mediabay_IDE_switch */
+ {0x38,0,0}, /* FEATURE_Mediabay_content */
};
/* Those bits are from a PowerBook. It's possible that desktop machines
@@ -87,8 +89,8 @@ static fbit feature_bits_heathrow[] = {
{0x38,1,HRW_BAY_RESET_N}, /* FEATURE_Mediabay_reset */
{0x38,1,HRW_BAY_POWER_N}, /* FEATURE_Mediabay_power */
{0x38,0,HRW_BAY_PCI_ENABLE}, /* FEATURE_Mediabay_PCI_enable */
- {0x38,0,HRW_BAY_IDE_ENABLE}, /* FEATURE_Mediabay_IDE_enable */
- {0x38,1,HRW_IDE1_RESET_N}, /* FEATURE_Mediabay_IDE_reset */
+ {0x38,0,HRW_BAY_IDE_ENABLE}, /* FEATURE_IDE1_enable */
+ {0x38,1,HRW_IDE1_RESET_N}, /* FEATURE_IDE1_reset */
{0x38,0,HRW_BAY_FLOPPY_ENABLE}, /* FEATURE_Mediabay_floppy_enable */
{0x38,0,HRW_BMAC_RESET}, /* FEATURE_BMac_reset */
{0x38,0,HRW_BMAC_IO_ENABLE}, /* FEATURE_BMac_IO_enable */
@@ -98,9 +100,44 @@ static fbit feature_bits_heathrow[] = {
{0x38,0,HRW_SOUND_CLK_ENABLE}, /* FEATURE_Sound_CLK_Enable */
{0x38,0,0}, /* FEATURE_IDE2_enable */
{0x38,0,0}, /* FEATURE_IDE2_reset */
+ {0x38,0,0}, /* FEATURE_Mediabay_IDE_switch */
+ {0x38,0,0}, /* FEATURE_Mediabay_content */
};
-/* Those bits are from an iBook.
+/*
+ * Those bits are from a 1999 G3 PowerBook, with a paddington chip.
+ * Mostly the same as the heathrow.
+ */
+static fbit feature_bits_paddington[] = {
+ {0x38,0,0}, /* FEATURE_null */
+ {0x38,0,0}, /* FEATURE_Serial_reset */
+ {0x38,0,HRW_SCC_ENABLE}, /* FEATURE_Serial_enable */
+ {0x38,0,HRW_SCCA_IO}, /* FEATURE_Serial_IO_A */
+ {0x38,0,HRW_SCCB_IO}, /* FEATURE_Serial_IO_B */
+ {0x38,0,HRW_SWIM_ENABLE}, /* FEATURE_SWIM3_enable */
+ {0x38,0,HRW_MESH_ENABLE}, /* FEATURE_MESH_enable */
+ {0x38,0,HRW_IDE0_ENABLE}, /* FEATURE_IDE0_enable */
+ {0x38,1,HRW_IDE0_RESET_N}, /* FEATURE_IDE0_reset */
+ {0x38,0,HRW_IOBUS_ENABLE}, /* FEATURE_IOBUS_enable */
+ {0x38,1,HRW_BAY_RESET_N}, /* FEATURE_Mediabay_reset */
+ {0x38,1,HRW_BAY_POWER_N}, /* FEATURE_Mediabay_power */
+ {0x38,0,HRW_BAY_PCI_ENABLE}, /* FEATURE_Mediabay_PCI_enable */
+ {0x38,0,HRW_BAY_IDE_ENABLE}, /* FEATURE_IDE1_enable */
+ {0x38,1,HRW_IDE1_RESET_N}, /* FEATURE_IDE1_reset */
+ {0x38,0,HRW_BAY_FLOPPY_ENABLE}, /* FEATURE_Mediabay_floppy_enable */
+ {0x38,0,HRW_BMAC_RESET}, /* FEATURE_BMac_reset */
+ {0x38,0,HRW_BMAC_IO_ENABLE}, /* FEATURE_BMac_IO_enable */
+ {0x38,1,PADD_MODEM_POWER_N}, /* FEATURE_Modem_power */
+ {0x38,0,HRW_SLOW_SCC_PCLK}, /* FEATURE_Slow_SCC_PCLK */
+ {0x38,1,HRW_SOUND_POWER_N}, /* FEATURE_Sound_Power */
+ {0x38,0,HRW_SOUND_CLK_ENABLE}, /* FEATURE_Sound_CLK_Enable */
+ {0x38,0,0}, /* FEATURE_IDE2_enable */
+ {0x38,0,0}, /* FEATURE_IDE2_reset */
+ {0x38,0,0}, /* FEATURE_Mediabay_IDE_switch */
+ {0x38,0,0}, /* FEATURE_Mediabay_content */
+};
+
+/* Those bits are for Core99 machines (iBook,G4,iMacSL/DV,Pismo,...).
*/
static fbit feature_bits_keylargo[] = {
{0x38,0,0}, /* FEATURE_null */
@@ -110,14 +147,14 @@ static fbit feature_bits_keylargo[] = {
{0x38,0,0}, /* FEATURE_Serial_IO_B */
{0x38,0,0}, /* FEATURE_SWIM3_enable */
{0x38,0,0}, /* FEATURE_MESH_enable */
- {0x38,0,0}, /* FEATURE_IDE0_enable */
- {0x3c,1,0x01000000}, /* FEATURE_IDE0_reset */
+ {0x3c,0,0}, /* FEATURE_IDE0_enable */
+ {0x3c,1,0x01000000}, /* FEATURE_IDE0_reset */
{0x38,0,0}, /* FEATURE_IOBUS_enable */
- {0x38,0,0}, /* FEATURE_Mediabay_reset */
- {0x38,0,0}, /* FEATURE_Mediabay_power */
+ {0x34,1,0x00000200}, /* FEATURE_Mediabay_reset */
+ {0x34,1,0x00000400}, /* FEATURE_Mediabay_power */
{0x38,0,0}, /* FEATURE_Mediabay_PCI_enable */
- {0x38,0,0}, /* FEATURE_Mediabay_IDE_enable */
- {0x3c,1,0x08000000}, /* FEATURE_Mediabay_IDE_reset */
+ {0x3c,0,0x0}, /* FEATURE_IDE1_enable */
+ {0x3c,1,0x08000000}, /* FEATURE_IDE1_reset */
{0x38,0,0}, /* FEATURE_Mediabay_floppy_enable */
{0x38,0,0}, /* FEATURE_BMac_reset */
{0x38,0,0}, /* FEATURE_BMac_IO_enable */
@@ -127,6 +164,8 @@ static fbit feature_bits_keylargo[] = {
{0x38,0,0}, /* FEATURE_Sound_CLK_Enable */
{0x38,0,0}, /* FEATURE_IDE2_enable */
{0x3c,1,0x40000000}, /* FEATURE_IDE2_reset */
+ {0x34,0,0x00001000}, /* FEATURE_Mediabay_IDE_switch */
+ {0x34,0,0x00000100}, /* FEATURE_Mediabay_content */
};
/* definition of a feature controller object */
@@ -164,6 +203,8 @@ feature_init(void)
*/
if (device_is_compatible(np, "Keylargo")) {
feature_add_controller(np, feature_bits_keylargo);
+ } else if (device_is_compatible(np, "paddington")) {
+ feature_add_controller(np, feature_bits_paddington);
} else {
feature_add_controller(np, feature_bits_heathrow);
}
@@ -268,6 +309,8 @@ feature_set(struct device_node* device, enum system_feature f)
if (!controller)
return -ENODEV;
bit = &controller->bits[f];
+ if (!bit->mask)
+ return -EINVAL;
#ifdef DEBUG_FEATURE
printk("feature: <%s> setting feature %d in controller @0x%x\n",
@@ -299,6 +342,8 @@ feature_clear(struct device_node* device, enum system_feature f)
if (!controller)
return -ENODEV;
bit = &controller->bits[f];
+ if (!bit->mask)
+ return -EINVAL;
#ifdef DEBUG_FEATURE
printk("feature: <%s> clearing feature %d in controller @0x%x\n",
@@ -329,6 +374,8 @@ feature_test(struct device_node* device, enum system_feature f)
if (!controller)
return -ENODEV;
bit = &controller->bits[f];
+ if (!bit->mask)
+ return -EINVAL;
#ifdef DEBUG_FEATURE
printk("feature: <%s> clearing feature %d in controller @0x%x\n",
diff --git a/arch/ppc/kernel/gemini_pci.c b/arch/ppc/kernel/gemini_pci.c
index fb80dc493..1ac83d1c8 100644
--- a/arch/ppc/kernel/gemini_pci.c
+++ b/arch/ppc/kernel/gemini_pci.c
@@ -77,178 +77,19 @@ gemini_pcibios_write_config_dword(unsigned char bus, unsigned char dev,
return PCIBIOS_SUCCESSFUL;
}
-struct gemini_device {
- unsigned short vendor, device;
- unsigned char irq;
- unsigned short cmd;
- unsigned char cache_line, latency;
- void (*init)(struct pci_dev *dev);
-};
-
-static struct gemini_device gemini_map[] = {
- { PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C885, 11, 0x15, 32, 248, NULL },
- { PCI_VENDOR_ID_NCR, 0x701, 10, 0, 0, 0, NULL },
- { PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C042, 3, 0, 0, 0, NULL },
- { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_MPIC, 0xff, 0, 0, 0, NULL },
- { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_670, 0xff, 0, 0, 0, NULL },
- { PCI_VENDOR_ID_MOTOROLA, PCI_DEVICE_ID_MOTOROLA_MPC106, 0xff, 0, 0, 0, NULL },
-};
-
-static int gemini_map_count = (sizeof( gemini_map ) /
- sizeof( gemini_map[0] ));
-
-
-
-/* This just sets up the known devices on the board. */
-static void __init mapin_device( struct pci_dev *dev )
-{
- struct gemini_device *p;
- unsigned short cmd;
- int i;
-
-
- for( i=0; i < gemini_map_count; i++ ) {
- p = &(gemini_map[i]);
-
- if ( p->vendor == dev->vendor &&
- p->device == dev->device ) {
-
- if (p->irq != 0xff) {
- pci_write_config_byte( dev, PCI_INTERRUPT_LINE, p->irq );
- dev->irq = p->irq;
- }
-
- if (p->cmd) {
- pci_read_config_word( dev, PCI_COMMAND, &cmd );
- pci_write_config_word( dev, PCI_COMMAND, (p->cmd|cmd));
- }
-
- if (p->cache_line)
- pci_write_config_byte( dev, PCI_CACHE_LINE_SIZE, p->cache_line );
-
- if (p->latency)
- pci_write_config_byte( dev, PCI_LATENCY_TIMER, p->latency );
- }
- }
-}
-
-#define KB 1024
-#define MB (KB*KB)
-
-#define ALIGN(val,align) (((val) + ((align) -1))&(~((align) -1)))
-#define MAX(a,b) (((a) > (b)) ? (a) : (b))
-
-#define FIRST_IO_ADDR 0x10000
-#define FIRST_MEM_ADDR 0x02000000
-
-#define GEMINI_PCI_MEM_BASE (0xf0000000)
-#define GEMINI_PCI_IO_BASE (0xfe800000)
-
-static unsigned long pci_mem_base = GEMINI_PCI_MEM_BASE;
-static unsigned long pci_io_base = GEMINI_PCI_IO_BASE;
-
-static unsigned int io_base = FIRST_IO_ADDR;
-static unsigned int mem_base = FIRST_MEM_ADDR;
-
-
-
-__init void layout_dev( struct pci_dev *dev )
+void __init gemini_pcibios_fixup(void)
{
int i;
- struct pci_bus *bus;
- unsigned short cmd;
- unsigned int reg, base, mask, size, alignto, type;
-
- bus = dev->bus;
-
- /* make any known settings happen */
- mapin_device( dev );
-
- gemini_pcibios_read_config_word( bus->number, dev->devfn, PCI_COMMAND, &cmd );
-
- for( reg = PCI_BASE_ADDRESS_0, i=0; reg <= PCI_BASE_ADDRESS_5; reg += 4, i++ ) {
-
- /* MPIC already done */
- if (dev->vendor == PCI_VENDOR_ID_IBM &&
- dev->device == PCI_DEVICE_ID_IBM_MPIC)
- return;
-
- gemini_pcibios_write_config_dword( bus->number, dev->devfn, reg, 0xffffffff );
- gemini_pcibios_read_config_dword( bus->number, dev->devfn, reg, &base );
- if (!base) {
- dev->resource[i].start = 0;
- continue;
- }
-
- if (base & PCI_BASE_ADDRESS_SPACE_IO) {
- cmd |= PCI_COMMAND_IO;
- base &= PCI_BASE_ADDRESS_IO_MASK;
- mask = (~base << 1) | 0x1;
- size = (mask & base) & 0xffffffff;
- alignto = MAX(0x400, size);
- base = ALIGN(io_base, alignto);
- io_base = base + size;
- gemini_pcibios_write_config_dword( bus->number, dev->devfn, reg,
- ((pci_io_base + base) & 0x00ffffff) | 0x1);
- dev->resource[i].start = (pci_io_base + base) | 0x1;
- }
-
- else {
- cmd |= PCI_COMMAND_MEMORY;
- type = base & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
- mask = (~base << 1) | 0x1;
- size = (mask & base) & 0xffffffff;
- switch( type ) {
-
- case PCI_BASE_ADDRESS_MEM_TYPE_32:
- break;
- case PCI_BASE_ADDRESS_MEM_TYPE_64:
- printk("Warning: Ignoring 64-bit device; slot %d, function %d.\n",
- PCI_SLOT( dev->devfn ), PCI_FUNC( dev->devfn ));
- reg += 4;
- continue;
+ struct pci_dev *dev;
+
+ pci_for_each_dev(dev) {
+ for(i = 0; i < 6; i++) {
+ if (dev->resource[i].flags & IORESOURCE_IO) {
+ dev->resource[i].start |= (0xfe << 24);
+ dev->resource[i].end |= (0xfe << 24);
}
-
- alignto = MAX(0x1000, size);
- base = ALIGN(mem_base, alignto);
- mem_base = base + size;
- gemini_pcibios_write_config_dword( bus->number, dev->devfn,
- reg, (pci_mem_base + base));
- dev->resource[i].start = pci_mem_base + base;
}
}
-
- if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
- cmd |= PCI_COMMAND_IO;
-
- gemini_pcibios_write_config_word( bus->number, dev->devfn, PCI_COMMAND,
- (cmd|PCI_COMMAND_MASTER));
-}
-
-__init void layout_bus( struct pci_bus *bus )
-{
- struct pci_dev *dev;
-
- io_base = ALIGN(io_base, 4*KB);
- mem_base = ALIGN(mem_base, 4*KB);
-
- pci_for_each_dev(dev)
- {
- if (((dev->class >> 16) != PCI_BASE_CLASS_BRIDGE) ||
- ((dev->class >> 8) == PCI_CLASS_BRIDGE_OTHER))
- layout_dev( dev );
- }
-}
-
-void __init gemini_pcibios_fixup(void)
-{
- unsigned long orig_mem_base, orig_io_base;
-
- orig_mem_base = pci_mem_base;
- orig_io_base = pci_io_base;
-
- pci_mem_base = orig_mem_base;
- pci_io_base = orig_io_base;
}
decl_config_access_method(gemini);
diff --git a/arch/ppc/kernel/gemini_setup.c b/arch/ppc/kernel/gemini_setup.c
index ae9a0bd5c..e069baf5b 100644
--- a/arch/ppc/kernel/gemini_setup.c
+++ b/arch/ppc/kernel/gemini_setup.c
@@ -35,15 +35,14 @@
#include "open_pic.h"
void gemini_setup_pci_ptrs(void);
+static int gemini_get_clock_speed(void);
+extern void gemini_pcibios_fixup(void);
-static unsigned char gemini_switch_map = 0;
static char *gemini_board_families[] = {
- "VGM", "VSS", "KGM", "VGR", "KSS"
-};
-
-static char *gemini_memtypes[] = {
- "EDO DRAM, 60nS", "SDRAM, 15nS, CL=2", "SDRAM, 15nS, CL=2 with ECC"
+ "VGM", "VSS", "KGM", "VGR", "VCM", "VCS", "KCM", "VCR"
};
+static int gemini_board_count = sizeof(gemini_board_families) /
+ sizeof(gemini_board_families[0]);
static unsigned int cpu_7xx[16] = {
0, 15, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
@@ -66,14 +65,14 @@ static inline unsigned long _get_HID1(void)
int
gemini_get_cpuinfo(char *buffer)
{
- int i, len;
+ int len;
unsigned char reg, rev;
char *family;
unsigned int type;
reg = readb(GEMINI_FEAT);
family = gemini_board_families[((reg>>4) & 0xf)];
- if (((reg>>4) & 0xf) > 2)
+ if (((reg>>4) & 0xf) > gemini_board_count)
printk(KERN_ERR "cpuinfo(): unable to determine board family\n");
reg = readb(GEMINI_BREV);
@@ -85,18 +84,17 @@ gemini_get_cpuinfo(char *buffer)
len = sprintf( buffer, "machine\t\t: Gemini %s%d, rev %c, eco %d\n",
family, type, (rev + 'A'), (reg & 0xf));
- len += sprintf( buffer+len, "vendor\t\t: %s\n",
- (_get_PVR() & (1<<15)) ? "IBM" : "Motorola");
+ len = sprintf(buffer, "board\t\t: Gemini %s", family);
+ if (type > 9)
+ len += sprintf(buffer+len, "%c", (type - 10) + 'A');
+ else
+ len += sprintf(buffer+len, "%d", type);
- reg = readb(GEMINI_MEMCFG);
- len += sprintf( buffer+len, "memory type\t: %s\n",
- gemini_memtypes[(reg & 0xc0)>>6]);
- len += sprintf( buffer+len, "switches on\t: ");
- for( i=0; i < 8; i++ ) {
- if ( gemini_switch_map & (1<<i))
- len += sprintf(buffer+len, "%d ", i);
- }
- len += sprintf(buffer+len, "\n");
+ len += sprintf(buffer+len, ", rev %c, eco %d\n",
+ (rev + 'A'), (reg & 0xf));
+
+ len += sprintf(buffer+len, "clock\t\t: %dMhz\n",
+ gemini_get_clock_speed());
return len;
}
@@ -116,11 +114,16 @@ static u_char gemini_openpic_initsenses[] = {
void __init gemini_openpic_init(void)
{
+
+ OpenPIC = (volatile struct OpenPIC *)
+ grackle_read(0x80005800 + 0x10);
+#if 0
grackle_write(GEMINI_MPIC_PCI_CFG + PCI_BASE_ADDRESS_0,
GEMINI_MPIC_ADDR);
grackle_write(GEMINI_MPIC_PCI_CFG + PCI_COMMAND, PCI_COMMAND_MEMORY);
OpenPIC = (volatile struct OpenPIC *) GEMINI_MPIC_ADDR;
+#endif
OpenPIC_InitSenses = gemini_openpic_initsenses;
OpenPIC_NumInitSenses = sizeof( gemini_openpic_initsenses );
@@ -148,7 +151,6 @@ gemini_heartbeat(void)
void __init gemini_setup_arch(void)
{
- unsigned int cpu;
extern char cmd_line[];
@@ -165,29 +167,8 @@ void __init gemini_setup_arch(void)
/* nothing but serial consoles... */
sprintf(cmd_line, "%s console=ttyS0", cmd_line);
-
- /* The user switches on the front panel can be used as follows:
-
- Switch 0 - adds "debug" to the command line for verbose boot info,
- Switch 7 - boots in single-user mode
-
- */
-
- gemini_switch_map = readb( GEMINI_USWITCH );
-
- if ( gemini_switch_map & (1<<GEMINI_SWITCH_VERBOSE))
- sprintf(cmd_line, "%s debug", cmd_line);
-
- if ( gemini_switch_map & (1<<GEMINI_SWITCH_SINGLE_USER))
- sprintf(cmd_line, "%s single", cmd_line);
-
printk("Boot arguments: %s\n", cmd_line);
- /* mutter some kind words about who made the CPU */
- cpu = _get_PVR();
- printk("CPU manufacturer: %s [rev=%04x]\n", (cpu & (1<<15)) ? "IBM" :
- "Motorola", (cpu & 0xffff));
-
ppc_md.heartbeat = gemini_heartbeat;
ppc_md.heartbeat_reset = HZ/8;
ppc_md.heartbeat_count = 1;
@@ -202,19 +183,17 @@ void __init gemini_setup_arch(void)
int
gemini_get_clock_speed(void)
{
- unsigned long hid1;
+ unsigned long hid1, pvr = _get_PVR();
int clock;
- unsigned char reg;
-
- hid1 = _get_HID1();
- if ((_get_PVR()>>16) == 8)
+
+ hid1 = (_get_HID1() >> 28) & 0xf;
+ if (PVR_VER(pvr) == 8 ||
+ PVR_VER(pvr) == 12)
hid1 = cpu_7xx[hid1];
else
hid1 = cpu_6xx[hid1];
- reg = readb(GEMINI_BSTAT) & 0xc0;
-
- switch( reg >> 2 ) {
+ switch((readb(GEMINI_BSTAT) & 0xc) >> 2) {
case 0:
default:
@@ -226,7 +205,7 @@ gemini_get_clock_speed(void)
break;
case 2:
- clock = (hid1*50)/3;
+ clock = (hid1*50);
break;
}
@@ -242,83 +221,72 @@ gemini_get_clock_speed(void)
void __init gemini_init_l2(void)
{
- unsigned char reg;
- unsigned long cache;
- int speed;
-
- reg = readb(GEMINI_L2CFG);
-
- /* 750's L2 initializes differently from a 604's. Also note that a Grackle
- bug will hang a dual-604 board, so make sure that doesn't happen by not
- turning on the L2 */
- if ( _get_PVR() >> 16 != 8 ) {
-
- /* check for dual cpus and cry sadly about the loss of an L2... */
- if ((( readb(GEMINI_CPUSTAT) & 0x0c ) >> 2) != 1)
- printk("Sorry. Your dual-604 does not allow the L2 to be enabled due "
- "to a Grackle bug.\n");
- else if ( reg & GEMINI_L2_SIZE_MASK ) {
- printk("Enabling 604 L2 cache: %dKb\n",
- (128<<((reg & GEMINI_L2_SIZE_MASK)>>6)));
- writeb( 1, GEMINI_L2CFG );
- }
- }
+ unsigned char reg, brev, fam, creg;
+ unsigned long cache;
+ unsigned long pvr = _get_PVR();
+
+ reg = readb(GEMINI_L2CFG);
+ brev = readb(GEMINI_BREV);
+ fam = readb(GEMINI_FEAT);
+
+ switch(PVR_VER(pvr)) {
+
+ case 8:
+ if (reg & 0xc0)
+ cache = (((reg >> 6) & 0x3) << 28);
+ else
+ cache = 0x3 << 28;
- /* do a 750 */
- else {
- /* Synergy's first round of 750 boards had the L2 size stuff into the
- board register above. If it's there, it's used; if not, the
- standard default is 1Mb. The L2 type, I'm told, is "most likely
- probably always going to be late-write". --Dan */
-
- if (reg & 0xc0) {
- printk("Enabling 750 L2 cache: %dKb\n",
- (128 << ((reg & 0xc0)>>6)));
- /* take the size given */
- cache = (((reg>>6) & 0x3)<<28);
- }
- else
- {
- printk("Enabling 750 L2 cache: 1M\n");
- /* default of 1Mb */
- cache = 0x3<<28;
- }
-
- reg &= 0x3;
-
- /* a cache ratio of 1:1 and CPU clock speeds in excess of 300Mhz are bad
- things. If found, tune it down to 1:1.5. -- Dan */
- if (!reg) {
-
-printk("3\n");
- speed = gemini_get_clock_speed();
-
- if (speed >= 300) {
- printk("Warning: L2 ratio is 1:1 on a %dMhz processor. Dropping to 1:1.5.\n",
- speed );
- printk("Contact Synergy Microsystems for an ECO to fix this problem\n");
- reg = 0x1;
- }
- }
-
- /* standard stuff */
- cache |= ((1<<reg)<<25);
#ifdef CONFIG_SMP
- /* A couple errata for the 750's (both IBM and Motorola silicon)
- note that you can get missed cache lines on MP implementations.
- The workaround - if you call it that - is to make the L2
- write-through. This is fixed in IBM's 3.1 rev (I'm told), but
- for now, always make 2.x versions use L2 write-through. --Dan */
- if (((_get_PVR()>>8) & 0xf) <= 2)
- {
- cache |= L2CR_L2WT;
- printk("L2 cache: Enabling Write-Through due to 750 Errata.\n");
- }
-#endif
- cache |= L2CR_PIPE_LATEWR|L2CR_L2CTL|L2CR_INST_DISABLE;
- _set_L2CR(0);
- _set_L2CR(cache|L2CR_L2I|L2CR_L2E);
+ /* Pre-3.0 processor revs had snooping errata. Leave
+ their L2's disabled with SMP. -- Dan */
+ if (PVR_CFG(pvr) < 3) {
+ printk("Pre-3.0 750; L2 left disabled!\n");
+ return;
+ }
+#endif /* CONFIG_SMP */
+
+ /* Special case: VGM5-B's came before L2 ratios were set on
+ the board. Processor speed shouldn't be too high, so
+ set L2 ratio to 1:1.5. */
+ if ((brev == 0x51) && ((fam & 0xa0) >> 4) == 0)
+ reg |= 1;
+
+ /* determine best cache ratio based upon what the board
+ tells us (which sometimes _may_ not be true) and
+ the processor speed. */
+ else {
+ if (gemini_get_clock_speed() > 250)
+ reg = 2;
+ }
+ break;
+ case 12:
+ {
+ static unsigned long l2_size_val = 0;
+
+ if (!l2_size_val)
+ l2_size_val = _get_L2CR();
+ cache = l2_size_val;
+ break;
}
+ case 4:
+ case 9:
+ creg = readb(GEMINI_CPUSTAT);
+ if (((creg & 0xc) >> 2) != 1)
+ printk("Dual-604 boards don't support the use of L2\n");
+ else
+ writeb(1, GEMINI_L2CFG);
+ return;
+ default:
+ printk("Unknown processor; L2 left disabled\n");
+ return;
+ }
+
+ cache |= ((1<<reg) << 25);
+ cache |= (L2CR_PIPE_LATEWR|L2CR_L2CTL|L2CR_INST_DISABLE);
+ _set_L2CR(0);
+ _set_L2CR(cache | L2CR_L2I | L2CR_L2E);
+
}
void
@@ -540,8 +508,11 @@ void gemini_post_irq(struct pt_regs* regs, int irq)
void __init gemini_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
+ int i;
int chrp_get_irq( struct pt_regs * );
- void layout_bus( struct pci_bus * );
+
+ for(i = 0; i < GEMINI_LEDS; i++)
+ gemini_led_off(i);
gemini_setup_pci_ptrs();
@@ -585,5 +556,5 @@ void __init gemini_init(unsigned long r3, unsigned long r4, unsigned long r5,
#ifdef CONFIG_MAGIC_SYSRQ
ppc_md.ppc_kbd_sysrq_xlate = NULL;
#endif
- ppc_md.pcibios_fixup_bus = layout_bus;
+ ppc_md.pcibios_fixup_bus = gemini_pcibios_fixup;
}
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index 218bb4ebb..6700806bd 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -1274,6 +1274,7 @@ __secondary_start:
ori r3,r3,start_secondary@l
mtspr SRR0,r3
mtspr SRR1,r4
+ SYNC
rfi
#endif /* CONFIG_SMP */
@@ -1436,7 +1437,7 @@ start_here:
tlbsync /* ... on all CPUs */
sync
#endif
-
+
bl load_up_mmu
/* Set up for using our exception vectors */
@@ -1544,6 +1545,28 @@ setup_screen_bat:
mtspr IBAT1U,r3
blr
#endif
+
+#ifdef CONFIG_8260
+/* Jump into the system reset for the rom.
+ * We first disable the MMU, and then jump to the ROM reset address.
+ *
+ * r3 is the board info structure, r4 is the location for starting.
+ * I use this for building a small kernel that can load other kernels,
+ * rather than trying to write or rely on a rom monitor that can tftp load.
+ */
+ .globl m8260_gorom
+m8260_gorom:
+ li r5,MSR_KERNEL & ~(MSR_IR|MSR_DR)
+ lis r6,2f@h
+ addis r6,r6,-KERNELBASE@h
+ ori r6,r6,2f@l
+ mtspr SRR0,r6
+ mtspr SRR1,r5
+ rfi
+2:
+ mtlr r4
+ blr
+#endif
/*
* We put a few things here that have to be page-aligned.
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index 83f276585..59b8a49c6 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -136,7 +136,7 @@ __start:
mtspr DC_CST, r8
lis r8, IDC_ENABLE@h
mtspr IC_CST, r8
-#if 0
+#ifdef CONFIG_8xx_COPYBACK
mtspr DC_CST, r8
#else
/* For a debug option, I left this here to easily enable
@@ -356,15 +356,26 @@ SystemCall:
* only perform the attribute functions.
*/
InstructionTLBMiss:
+#ifdef CONFIG_8xx_CPU6
+ stw r3, 8(r0)
+ li r3, 0x3f80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr M_TW, r20 /* Save a couple of working registers */
mfcr r20
stw r20, 0(r0)
stw r21, 4(r0)
mfspr r20, SRR0 /* Get effective address of fault */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3780
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_EPN, r20 /* Have to use MD_EPN for walk, MI_EPN can't */
mfspr r20, M_TWB /* Get level 1 table entry address */
lwz r21, 0(r20) /* Get the level 1 entry */
- rlwinm. r20, r21,0,0,20 /* Extract page descriptor page address */
+ rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */
beq 2f /* If zero, don't try to find a pte */
/* We have a pte table, so load the MI_TWC with the attributes
@@ -372,88 +383,131 @@ InstructionTLBMiss:
*/
tophys(r21,r21)
ori r21,r21,1 /* Set valid bit */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x2b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MI_TWC, r21 /* Set page attributes */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_TWC, r21 /* Load pte table base address */
mfspr r21, MD_TWC /* ....and get the pte address */
- lwz r21, 0(r21) /* Get the pte */
+ lwz r20, 0(r21) /* Get the pte */
+#if 0
+ ori r20, r20, _PAGE_ACCESSED
+ stw r20, 0(r21)
+#endif
/* Set four subpage valid bits (24, 25, 26, and 27).
- * Since we currently run MI_CTR.PPCS = 0, the manual says,
- * "If the page size is larger than 4k byte, then all the
- * 4 bits should have the same value."
- * I don't really know what to do if the page size is 4k Bytes,
- * but I know setting them all to 0 does not work, and setting them
- * all to 1 does, so that is the way it is right now.
- * BTW, these four bits map to the software only bits in the
- * linux page table. I used to turn them all of, but now just
- * set them all for the hardware.
- li r20, 0x00f0
- andc r20, r21, r20
- ori r20, r20, 0x0080
+ * Clear bit 28 (which should be in the PTE, but we do this anyway).
*/
- ori r20, r21, 0x00f0
-
+ li r21, 0x00f0
+ rlwimi r20, r21, 0, 24, 28
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x2d80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MI_RPN, r20 /* Update TLB entry */
mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
rfi
2: mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
b InstructionAccess
. = 0x1200
DataStoreTLBMiss:
+#ifdef CONFIG_8xx_CPU6
+ stw r3, 8(r0)
+ li r3, 0x3f80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr M_TW, r20 /* Save a couple of working registers */
mfcr r20
stw r20, 0(r0)
stw r21, 4(r0)
mfspr r20, M_TWB /* Get level 1 table entry address */
lwz r21, 0(r20) /* Get the level 1 entry */
- rlwinm. r20, r21,0,0,20 /* Extract page descriptor page address */
+ rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */
beq 2f /* If zero, don't try to find a pte */
/* We have a pte table, so load fetch the pte from the table.
*/
tophys(r21, r21)
ori r21, r21, 1 /* Set valid bit in physical L2 page */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_TWC, r21 /* Load pte table base address */
- mfspr r21, MD_TWC /* ....and get the pte address */
- lwz r21, 0(r21) /* Get the pte */
+ mfspr r20, MD_TWC /* ....and get the pte address */
+ lwz r20, 0(r20) /* Get the pte */
+
+ /* Insert the Guarded flag into the TWC from the Linux PTE.
+ * It is bit 27 of both the Linux PTE and the TWC (at least
+ * I got that right :-). It will be better when we can put
+ * this into the Linux pgd/pmd and load it in the operation
+ * above.
+ */
+ rlwimi r21, r20, 0, 27, 27
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
+ mtspr MD_TWC, r21
/* Set four subpage valid bits (24, 25, 26, and 27).
- * Since we currently run MD_CTR.PPCS = 0, the manual says,
- * "If the page size is larger than 4k byte, then all the
- * 4 bits should have the same value."
- * I don't really know what to do if the page size is 4k Bytes,
- * but I know setting them all to 0 does not work, and setting them
- * all to 1 does, so that is the way it is right now.
- * BTW, these four bits map to the software only bits in the
- * linux page table. I used to turn them all of, but now just
- * set them all for the hardware.
- li r20, 0x00f0
- andc r20, r21, r20
- ori r20, r20, 0x0080
+ * Clear bit 28 (which should be in the PTE, but we do this anyway).
*/
- ori r20, r21, 0x00f0
-
+#if 0
+ ori r20, r20, 0x00f0
+#else
+ li r21, 0x00f0
+ rlwimi r20, r21, 0, 24, 28
+#endif
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3d80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_RPN, r20 /* Update TLB entry */
mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
rfi
2: mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
b DataAccess
/* This is an instruction TLB error on the MPC8xx. This could be due
@@ -474,6 +528,12 @@ InstructionTLBError:
*/
. = 0x1400
DataTLBError:
+#ifdef CONFIG_8xx_CPU6
+ stw r3, 8(r0)
+ li r3, 0x3f80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr M_TW, r20 /* Save a couple of working registers */
mfcr r20
stw r20, 0(r0)
@@ -487,52 +547,59 @@ DataTLBError:
mfspr r20, M_TWB /* Get level 1 table entry address */
lwz r21, 0(r20) /* Get the level 1 entry */
- rlwinm. r20, r21,0,0,20 /* Extract page descriptor page address */
+ rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */
beq 2f /* If zero, bail */
/* We have a pte table, so fetch the pte from the table.
*/
tophys(r21, r21)
ori r21, r21, 1 /* Set valid bit in physical L2 page */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_TWC, r21 /* Load pte table base address */
mfspr r21, MD_TWC /* ....and get the pte address */
- lwz r21, 0(r21) /* Get the pte */
+ lwz r20, 0(r21) /* Get the pte */
- andi. r20, r21, _PAGE_RW /* Is it writeable? */
+ andi. r21, r20, _PAGE_RW /* Is it writeable? */
beq 2f /* Bail out if not */
- ori r21, r21, _PAGE_DIRTY /* Update changed bit */
- mfspr r20, MD_TWC /* Get pte address again */
- stw r21, 0(r20) /* and update pte in table */
+ /* Update 'changed', among others.
+ */
+ ori r20, r20, _PAGE_DIRTY|_PAGE_HWWRITE|_PAGE_ACCESSED
+ mfspr r21, MD_TWC /* Get pte address again */
+ stw r20, 0(r21) /* and update pte in table */
/* Set four subpage valid bits (24, 25, 26, and 27).
- * Since we currently run MD_CTR.PPCS = 0, the manual says,
- * "If the page size is larger than 4k byte, then all the
- * 4 bits should have the same value."
- * I don't really know what to do if the page size is 4k Bytes,
- * but I know setting them all to 0 does not work, and setting them
- * all to 1 does, so that is the way it is right now.
- * BTW, these four bits map to the software only bits in the
- * linux page table. I used to turn them all of, but now just
- * set them all for the hardware.
- li r20, 0x00f0
- andc r20, r21, r20
- ori r20, r20, 0x0080
+ * Clear bit 28 (which should be in the PTE, but we do this anyway).
*/
- ori r20, r21, 0x00f0
-
+ li r21, 0x00f0
+ rlwimi r20, r21, 0, 24, 28
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3d80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_RPN, r20 /* Update TLB entry */
mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
rfi
2:
mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
b DataAccess
STD_EXCEPTION(0x1500, Trap_15, UnknownException)
@@ -542,6 +609,7 @@ DataTLBError:
STD_EXCEPTION(0x1900, Trap_19, UnknownException)
STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
+
/* On the MPC8xx, these next four traps are used for development
* support of breakpoints and such. Someday I will get around to
* using them.
diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
index c0cc492ad..28be8bf46 100644
--- a/arch/ppc/kernel/irq.c
+++ b/arch/ppc/kernel/irq.c
@@ -117,9 +117,9 @@ void irq_kfree(void *ptr)
kfree(ptr);
}
-#ifdef CONFIG_8xx
+#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
/* Name change so we can catch standard drivers that potentially mess up
- * the internal interrupt controller on 8xx and 82xx. Just bear with me,
+ * the internal interrupt controller on 8xx and 8260. Just bear with me,
* I don't like this either and I am searching a better solution. For
* now, this is what I need. -- Dan
*/
@@ -194,10 +194,10 @@ void sys_free_irq(unsigned int irq, void *dev_id)
#else
void free_irq(unsigned int irq, void *dev_id)
{
-#ifndef CONFIG_8xx
- request_irq(irq, NULL, 0, NULL, dev_id);
-#else
+#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
request_8xxirq(irq, NULL, 0, NULL, dev_id);
+#else
+ request_irq(irq, NULL, 0, NULL, dev_id);
#endif
}
#endif
diff --git a/arch/ppc/kernel/m8260_setup.c b/arch/ppc/kernel/m8260_setup.c
new file mode 100644
index 000000000..65ea973d8
--- /dev/null
+++ b/arch/ppc/kernel/m8260_setup.c
@@ -0,0 +1,303 @@
+/*
+ * $Id: m8xx_setup.c,v 1.4 1999/09/18 18:40:36 dmalek Exp $
+ *
+ * linux/arch/ppc/kernel/setup.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Adapted from 'alpha' version by Gary Thomas
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * Modified for MBX using prep/chrp/pmac functions by Dan (dmalek@jlc.net)
+ * Further modified for generic 8xx and 8260 by Dan.
+ */
+
+/*
+ * bootup setup stuff..
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/major.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/blk.h>
+#include <linux/ioport.h>
+#include <linux/ide.h>
+
+#include <asm/mmu.h>
+#include <asm/processor.h>
+#include <asm/residual.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/ide.h>
+#include <asm/mpc8260.h>
+#include <asm/immap_8260.h>
+#include <asm/machdep.h>
+
+#include "time.h"
+#include "ppc8260_pic.h"
+
+static int m8260_set_rtc_time(unsigned long time);
+unsigned long m8260_get_rtc_time(void);
+void m8260_calibrate_decr(void);
+
+#if 0
+extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int mackbd_getkeycode(unsigned int scancode);
+extern int mackbd_pretranslate(unsigned char scancode, char raw_mode);
+extern int mackbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode);
+extern char mackbd_unexpected_up(unsigned char keycode);
+extern void mackbd_leds(unsigned char leds);
+extern void mackbd_init_hw(void);
+#endif
+
+extern unsigned long loops_per_sec;
+
+unsigned char __res[sizeof(bd_t)];
+unsigned long empty_zero_page[1024];
+
+#ifdef CONFIG_BLK_DEV_RAM
+extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start; /* starting block # of image */
+#endif
+
+extern char saved_command_line[256];
+
+extern unsigned long find_available_memory(void);
+extern void m8260_cpm_reset(void);
+
+void __init adbdev_init(void)
+{
+}
+
+void __init
+m8260_setup_arch(void)
+{
+ extern char cmd_line[];
+
+ printk("Boot arguments: %s\n", cmd_line);
+
+ /* Reset the Communication Processor Module.
+ */
+ m8260_cpm_reset();
+}
+
+void
+abort(void)
+{
+#ifdef CONFIG_XMON
+ extern void xmon(void *);
+ xmon(0);
+#endif
+ machine_restart(NULL);
+}
+
+/* The decrementer counts at the system (internal) clock frequency
+ * divided by four.
+ */
+void __init m8260_calibrate_decr(void)
+{
+ bd_t *binfo = (bd_t *)__res;
+ int freq, divisor;
+
+ freq = (binfo->bi_intfreq * 1000000);
+ divisor = 16;
+ decrementer_count = freq / HZ / divisor;
+ count_period_num = divisor;
+ count_period_den = freq / 1000000;
+}
+
+/* The 8260 has an internal 1-second timer update register that
+ * we should use for this purpose.
+ */
+static uint rtc_time;
+static int
+m8260_set_rtc_time(unsigned long time)
+{
+ rtc_time = time;
+ return(0);
+}
+
+unsigned long __init
+m8260_get_rtc_time(void)
+{
+
+ /* Get time from the RTC.
+ */
+ return((unsigned long)rtc_time);
+}
+
+void
+m8260_restart(char *cmd)
+{
+ extern void m8260_gorom(bd_t *bi, uint addr);
+
+ m8260_gorom(NULL, 0xff000100);
+}
+
+void
+m8260_power_off(void)
+{
+ m8260_restart(NULL);
+}
+
+void
+m8260_halt(void)
+{
+ m8260_restart(NULL);
+}
+
+
+int m8260_setup_residual(char *buffer)
+{
+ int len = 0;
+ bd_t *bp;
+
+ bp = (bd_t *)__res;
+
+ len += sprintf(len+buffer,"clock\t\t: %dMHz\n"
+ "bus clock\t: %dMHz\n",
+ bp->bi_intfreq /*/ 1000000*/,
+ bp->bi_busfreq /*/ 1000000*/);
+
+ return len;
+}
+
+/* Initialize the internal interrupt controller. The number of
+ * interrupts supported can vary with the processor type, and the
+ * 8260 family can have up to 64.
+ * External interrupts can be either edge or level triggered, and
+ * need to be initialized by the appropriate driver.
+ */
+void __init
+m8260_init_IRQ(void)
+{
+ int i;
+ void cpm_interrupt_init(void);
+
+#if 0
+ ppc8260_pic.irq_offset = 0;
+#endif
+ for ( i = 0 ; i < NR_SIU_INTS ; i++ )
+ irq_desc[i].handler = &ppc8260_pic;
+
+ /* Initialize the default interrupt mapping priorities,
+ * in case the boot rom changed something on us.
+ */
+ immr->im_intctl.ic_sicr = 0;
+ immr->im_intctl.ic_siprr = 0x05309770;
+ immr->im_intctl.ic_scprrh = 0x05309770;
+ immr->im_intctl.ic_scprrl = 0x05309770;
+
+}
+
+
+void __init
+m8260_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+
+ if ( r3 )
+ memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* take care of initrd if we have one */
+ if ( r4 )
+ {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+ /* take care of cmd line */
+ if ( r6 )
+ {
+
+ *(char *)(r7+KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6+KERNELBASE));
+ }
+
+ ppc_md.setup_arch = m8260_setup_arch;
+ ppc_md.setup_residual = m8260_setup_residual;
+ ppc_md.get_cpuinfo = NULL;
+ ppc_md.irq_cannonicalize = NULL;
+ ppc_md.init_IRQ = m8260_init_IRQ;
+ ppc_md.get_irq = m8260_get_irq;
+ ppc_md.init = NULL;
+
+ ppc_md.restart = m8260_restart;
+ ppc_md.power_off = m8260_power_off;
+ ppc_md.halt = m8260_halt;
+
+ ppc_md.time_init = NULL;
+ ppc_md.set_rtc_time = m8260_set_rtc_time;
+ ppc_md.get_rtc_time = m8260_get_rtc_time;
+ ppc_md.calibrate_decr = m8260_calibrate_decr;
+
+#if 0
+ ppc_md.kbd_setkeycode = pckbd_setkeycode;
+ ppc_md.kbd_getkeycode = pckbd_getkeycode;
+ ppc_md.kbd_pretranslate = pckbd_pretranslate;
+ ppc_md.kbd_translate = pckbd_translate;
+ ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
+ ppc_md.kbd_leds = pckbd_leds;
+ ppc_md.kbd_init_hw = pckbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.kbd_sysrq_xlate = pckbd_sysrq_xlate;
+#endif
+#else
+ ppc_md.kbd_setkeycode = NULL;
+ ppc_md.kbd_getkeycode = NULL;
+ ppc_md.kbd_translate = NULL;
+ ppc_md.kbd_unexpected_up = NULL;
+ ppc_md.kbd_leds = NULL;
+ ppc_md.kbd_init_hw = NULL;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.kbd_sysrq_xlate = NULL;
+#endif
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ ppc_ide_md.insw = m8xx_ide_insw;
+ ppc_ide_md.outsw = m8xx_ide_outsw;
+ ppc_ide_md.default_irq = m8xx_ide_default_irq;
+ ppc_ide_md.default_io_base = m8xx_ide_default_io_base;
+ ppc_ide_md.check_region = m8xx_ide_check_region;
+ ppc_ide_md.request_region = m8xx_ide_request_region;
+ ppc_ide_md.release_region = m8xx_ide_release_region;
+ ppc_ide_md.fix_driveid = m8xx_ide_fix_driveid;
+ ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports;
+ ppc_ide_md.ide_request_irq = m8xx_ide_request_irq;
+
+ ppc_ide_md.io_base = _IO_BASE;
+#endif
+}
+
+void
+prom_init(uint r3, uint r4, uint r5, uint r6)
+{
+ /* Nothing to do now, but we are called immediatedly upon
+ * kernel start up with MMU disabled, so if there is
+ * anything we need to do......
+ */
+}
+
+/* Mainly for ksyms.
+*/
+int
+request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flag, const char *naem, void *dev)
+{
+ panic("request IRQ\n");
+}
diff --git a/arch/ppc/kernel/m8xx_setup.c b/arch/ppc/kernel/m8xx_setup.c
index a417bed2e..9f0a517e3 100644
--- a/arch/ppc/kernel/m8xx_setup.c
+++ b/arch/ppc/kernel/m8xx_setup.c
@@ -130,7 +130,6 @@ void
abort(void)
{
#ifdef CONFIG_XMON
- extern void xmon(void *);
xmon(0);
#endif
machine_restart(NULL);
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index e4fbefbc3..96adb96cd 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -18,6 +18,7 @@
#include <asm/errno.h>
#include <asm/processor.h>
#include <asm/page.h>
+#include <asm/cache.h>
#include "ppc_asm.h"
#if defined(CONFIG_4xx) || defined(CONFIG_8xx)
@@ -165,6 +166,11 @@ _GLOBAL(_tlbie)
* This is a no-op on the 601.
*/
_GLOBAL(flush_instruction_cache)
+#ifdef CONFIG_8xx
+ isync
+ lis r5, IDC_INVALL@h
+ mtspr IC_CST, r5
+#else
mfspr r3,PVR
rlwinm r3,r3,16,16,31
cmpi 0,r3,1
@@ -173,6 +179,7 @@ _GLOBAL(flush_instruction_cache)
mfspr r3,HID0
ori r3,r3,HID0_ICFI
mtspr HID0,r3
+#endif /* CONFIG_8xx */
SYNC
blr
@@ -241,8 +248,7 @@ _GLOBAL(__flush_page_to_ram)
rlwinm r5,r5,16,16,31
cmpi 0,r5,1
beqlr /* for 601, do nothing */
- li r4,0x0FFF
- andc r3,r3,r4 /* Get page base address */
+ rlwinm r3,r3,0,0,19 /* Get page base address */
li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
mtctr r4
mr r6,r3
@@ -373,6 +379,7 @@ _GLOBAL(__spin_trylock)
* void atomic_clear_mask(atomic_t mask, atomic_t *addr)
* void atomic_set_mask(atomic_t mask, atomic_t *addr);
*/
+#if 0 /* now inline - paulus */
_GLOBAL(atomic_add)
10: lwarx r5,0,r4 /* Fetch old value & reserve */
add r5,r5,r3 /* Perform 'add' operation */
@@ -423,11 +430,10 @@ _GLOBAL(atomic_dec_and_test)
subi r5,r5,1 /* Perform 'add' operation */
stwcx. r5,0,r3 /* Update with new value */
bne- 10b /* Retry if "reservation" (i.e. lock) lost */
- cmpi 0,r5,0 /* Return 'true' IFF 0 */
- li r3,1
- beqlr
- li r3,0
+ cntlzw r3,r5
+ srwi r3,r3,5
blr
+#endif /* 0 */
_GLOBAL(atomic_clear_mask)
10: lwarx r5,0,r4
andc r5,r5,r3
diff --git a/arch/ppc/kernel/pmac_nvram.c b/arch/ppc/kernel/pmac_nvram.c
index a3a9bae70..db0632238 100644
--- a/arch/ppc/kernel/pmac_nvram.c
+++ b/arch/ppc/kernel/pmac_nvram.c
@@ -7,14 +7,18 @@
#include <linux/nvram.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/delay.h>
#include <asm/init.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/prom.h>
#include <asm/machdep.h>
+#include <asm/nvram.h>
#include <linux/adb.h>
#include <linux/pmu.h>
+#undef DEBUG
+
/*
* Read and write the non-volatile RAM on PowerMacs and CHRP machines.
*/
@@ -23,9 +27,191 @@ static volatile unsigned char *nvram_addr;
static volatile unsigned char *nvram_data;
static int nvram_mult, is_core_99;
static char* nvram_image;
+static int core99_bank = 0;
+
+extern int pmac_newworld;
#define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */
+#define CORE99_SIGNATURE 0x5a
+#define CORE99_ADLER_START 0x14
+
+/* Core99 nvram is a flash */
+#define CORE99_FLASH_STATUS_DONE 0x80
+#define CORE99_FLASH_STATUS_ERR 0x38
+#define CORE99_FLASH_CMD_ERASE_CONFIRM 0xd0
+#define CORE99_FLASH_CMD_ERASE_SETUP 0x20
+#define CORE99_FLASH_CMD_RESET 0xff
+#define CORE99_FLASH_CMD_WRITE_SETUP 0x40
+
+/* CHRP NVRAM header */
+struct chrp_header {
+ u8 signature;
+ u8 cksum;
+ u16 len;
+ char name[12];
+ u8 data[0];
+};
+
+struct core99_header {
+ struct chrp_header hdr;
+ u32 adler;
+ u32 generation;
+ u32 reserved[2];
+};
+
+static int nvram_partitions[3];
+
+static u8
+chrp_checksum(struct chrp_header* hdr)
+{
+ u8 *ptr;
+ u16 sum = hdr->signature;
+ for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++)
+ sum += *ptr;
+ while (sum > 0xFF)
+ sum = (sum & 0xFF) + (sum>>8);
+ return sum;
+}
+
+static u32
+core99_calc_adler(u8 *buffer)
+{
+ int cnt;
+ u32 low, high;
+
+ buffer += CORE99_ADLER_START;
+ low = 1;
+ high = 0;
+ for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) {
+ if ((cnt % 5000) == 0) {
+ high %= 65521UL;
+ high %= 65521UL;
+ }
+ low += buffer[cnt];
+ high += low;
+ }
+ low %= 65521UL;
+ high %= 65521UL;
+
+ return (high << 16) | low;
+}
+
+static u32
+core99_check(u8* datas)
+{
+ struct core99_header* hdr99 = (struct core99_header*)datas;
+
+ if (hdr99->hdr.signature != CORE99_SIGNATURE) {
+#ifdef DEBUG
+ printk("Invalid signature\n");
+#endif
+ return 0;
+ }
+ if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) {
+#ifdef DEBUG
+ printk("Invalid checksum\n");
+#endif
+ return 0;
+ }
+ if (hdr99->adler != core99_calc_adler(datas)) {
+#ifdef DEBUG
+ printk("Invalid adler\n");
+#endif
+ return 0;
+ }
+ return hdr99->generation;
+}
+
+static int
+core99_erase_bank(int bank)
+{
+ int stat, i;
+
+ u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+
+ out_8(base, CORE99_FLASH_CMD_ERASE_SETUP);
+ out_8(base, CORE99_FLASH_CMD_ERASE_CONFIRM);
+ do { stat = in_8(base); }
+ while(!(stat & CORE99_FLASH_STATUS_DONE));
+ out_8(base, CORE99_FLASH_CMD_RESET);
+ if (stat & CORE99_FLASH_STATUS_ERR) {
+ printk("nvram: flash error 0x%02x on erase !\n", stat);
+ return -ENXIO;
+ }
+ for (i=0; i<NVRAM_SIZE; i++)
+ if (base[i] != 0xff) {
+ printk("nvram: flash erase failed !\n");
+ return -ENXIO;
+ }
+ return 0;
+}
+
+static int
+core99_write_bank(int bank, u8* datas)
+{
+ int i, stat = 0;
+
+ u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+
+ for (i=0; i<NVRAM_SIZE; i++) {
+ out_8(base+i, CORE99_FLASH_CMD_WRITE_SETUP);
+ out_8(base+i, datas[i]);
+ do { stat = in_8(base); }
+ while(!(stat & CORE99_FLASH_STATUS_DONE));
+ if (stat & CORE99_FLASH_STATUS_ERR)
+ break;
+ }
+ out_8(base, CORE99_FLASH_CMD_RESET);
+ if (stat & CORE99_FLASH_STATUS_ERR) {
+ printk("nvram: flash error 0x%02x on write !\n", stat);
+ return -ENXIO;
+ }
+ for (i=0; i<NVRAM_SIZE; i++)
+ if (base[i] != datas[i]) {
+ printk("nvram: flash write failed !\n");
+ return -ENXIO;
+ }
+ return 0;
+}
+
+static void
+lookup_partitions(void)
+{
+ u8 buffer[17];
+ int i, offset;
+ struct chrp_header* hdr;
+
+ if (pmac_newworld) {
+ nvram_partitions[pmac_nvram_OF] = -1;
+ nvram_partitions[pmac_nvram_XPRAM] = -1;
+ nvram_partitions[pmac_nvram_NR] = -1;
+ hdr = (struct chrp_header *)buffer;
+
+ offset = 0;
+ do {
+ for (i=0;i<16;i++)
+ buffer[i] = nvram_read_byte(offset+i);
+ if (!strcmp(hdr->name, "common"))
+ nvram_partitions[pmac_nvram_OF] = offset + 0x10;
+ if (!strcmp(hdr->name, "APL,MacOS75")) {
+ nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10;
+ nvram_partitions[pmac_nvram_NR] = offset + 0x110;
+ }
+ offset += (hdr->len * 0x10);
+ } while(offset < NVRAM_SIZE);
+ } else {
+ nvram_partitions[pmac_nvram_OF] = 0x1800;
+ nvram_partitions[pmac_nvram_XPRAM] = 0x1300;
+ nvram_partitions[pmac_nvram_NR] = 0x1400;
+ }
+#ifdef DEBUG
+ printk("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]);
+ printk("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]);
+ printk("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]);
+#endif
+}
+
__init
void pmac_nvram_init(void)
{
@@ -40,17 +226,32 @@ void pmac_nvram_init(void)
}
nvram_naddrs = dp->n_addrs;
is_core_99 = device_is_compatible(dp, "nvram,flash");
- if (is_core_99)
- {
+ if (is_core_99) {
int i;
- if (nvram_naddrs < 1)
+ u32 gen_bank0, gen_bank1;
+
+ if (nvram_naddrs < 1) {
+ printk(KERN_ERR "nvram: no address\n");
return;
- nvram_image = kmalloc(dp->addrs[0].size, GFP_KERNEL);
- if (!nvram_image)
+ }
+ nvram_image = kmalloc(NVRAM_SIZE, GFP_KERNEL);
+ if (!nvram_image) {
+ printk(KERN_ERR "nvram: can't allocate image\n");
return;
- nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);
- for (i=0; i<dp->addrs[0].size; i++)
- nvram_image[i] = in_8(nvram_data + i);
+ }
+ nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2);
+#ifdef DEBUG
+ printk("nvram: Checking bank 0...\n");
+#endif
+ gen_bank0 = core99_check((u8 *)nvram_data);
+ gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE);
+ core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0;
+#ifdef DEBUG
+ printk("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1);
+ printk("nvram: Active bank is: %d\n", core99_bank);
+#endif
+ for (i=0; i<NVRAM_SIZE; i++)
+ nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE];
} else if (_machine == _MACH_chrp && nvram_naddrs == 1) {
nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);
nvram_mult = 1;
@@ -68,6 +269,33 @@ void pmac_nvram_init(void)
}
}
+void
+pmac_nvram_update(void)
+{
+ struct core99_header* hdr99;
+
+ if (!is_core_99 || !nvram_data || !nvram_image)
+ return;
+ if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE,
+ NVRAM_SIZE))
+ return;
+#ifdef DEBUG
+ printk("Updating nvram...\n");
+#endif
+ hdr99 = (struct core99_header*)nvram_image;
+ hdr99->generation++;
+ hdr99->hdr.signature = CORE99_SIGNATURE;
+ hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr);
+ hdr99->adler = core99_calc_adler(nvram_image);
+ core99_bank = core99_bank ? 0 : 1;
+ if (core99_erase_bank(core99_bank)) {
+ printk("nvram: Error erasing bank %d\n", core99_bank);
+ return;
+ }
+ if (core99_write_bank(core99_bank, nvram_image))
+ printk("nvram: Error writing bank %d\n", core99_bank);
+}
+
__openfirmware
unsigned char nvram_read_byte(int addr)
{
@@ -125,3 +353,33 @@ void nvram_write_byte(unsigned char val, int addr)
}
eieio();
}
+
+int
+pmac_get_partition(int partition)
+{
+ return nvram_partitions[partition];
+}
+
+u8
+pmac_xpram_read(int xpaddr)
+{
+ int offset = nvram_partitions[pmac_nvram_XPRAM];
+
+ if (offset < 0)
+ return 0;
+
+ return nvram_read_byte(xpaddr + offset);
+}
+
+void
+pmac_xpram_write(int xpaddr, u8 data)
+{
+ int offset = nvram_partitions[pmac_nvram_XPRAM];
+
+ if (offset < 0)
+ return;
+
+ nvram_write_byte(xpaddr + offset, data);
+}
+
+
diff --git a/arch/ppc/kernel/pmac_pci.c b/arch/ppc/kernel/pmac_pci.c
index b57d5aa28..ee54ba37d 100644
--- a/arch/ppc/kernel/pmac_pci.c
+++ b/arch/ppc/kernel/pmac_pci.c
@@ -525,7 +525,8 @@ static void __init init_bandit(struct bridge_data *bp)
bp->io_base);
}
-#define GRACKLE_STG_ENABLE 0x00000040
+#define GRACKLE_PICR1_STG 0x00000040
+#define GRACKLE_PICR1_LOOPSNOOP 0x00000010
/* N.B. this is called before bridges is initialized, so we can't
use grackle_pcibios_{read,write}_config_dword. */
@@ -535,11 +536,25 @@ static inline void grackle_set_stg(struct bridge_data *bp, int enable)
out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
val = in_le32((volatile unsigned int *)bp->cfg_data);
- val = enable? (val | GRACKLE_STG_ENABLE): (val & ~GRACKLE_STG_ENABLE);
+ val = enable? (val | GRACKLE_PICR1_STG) :
+ (val & ~GRACKLE_PICR1_STG);
out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
out_le32((volatile unsigned int *)bp->cfg_data, val);
}
+static inline void grackle_set_loop_snoop(struct bridge_data *bp, int enable)
+{
+ unsigned int val;
+
+ out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
+ val = in_le32((volatile unsigned int *)bp->cfg_data);
+ val = enable? (val | GRACKLE_PICR1_LOOPSNOOP) :
+ (val & ~GRACKLE_PICR1_LOOPSNOOP);
+ out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
+ out_le32((volatile unsigned int *)bp->cfg_data, val);
+}
+
+
void __init pmac_find_bridges(void)
{
int bus;
@@ -620,7 +635,9 @@ static void __init add_bridges(struct device_node *dev)
bp->cfg_data = (volatile unsigned char *)
ioremap(0xfee00000, 0x1000);
bp->io_base = (void *) ioremap(0xfe000000, 0x20000);
-#if 0 /* Disabled for now, HW problems */
+ if (machine_is_compatible("AAPL,PowerBook1998"))
+ grackle_set_loop_snoop(bp, 1);
+#if 0 /* Disabled for now, HW problems ??? */
grackle_set_stg(bp, 1);
#endif
} else {
diff --git a/arch/ppc/kernel/pmac_pic.c b/arch/ppc/kernel/pmac_pic.c
index b58d69fc9..ab2fdbc15 100644
--- a/arch/ppc/kernel/pmac_pic.c
+++ b/arch/ppc/kernel/pmac_pic.c
@@ -158,13 +158,13 @@ static void gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
{
int irq, bits;
- for (irq = max_irqs - 1; irq > max_real_irqs; irq -= 32) {
+ for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) {
int i = irq >> 5;
bits = ld_le32(&pmac_irq_hw[i]->flag)
| ppc_lost_interrupts[i];
if (bits == 0)
continue;
- irq -= cntlzw(bits);
+ irq += __ilog2(bits);
break;
}
/* The previous version of this code allowed for this case, we
@@ -213,13 +213,13 @@ pmac_get_irq(struct pt_regs *regs)
}
else
{
- for (irq = max_real_irqs - 1; irq > 0; irq -= 32) {
+ for (irq = max_real_irqs; (irq -= 32) >= 0; ) {
int i = irq >> 5;
bits = ld_le32(&pmac_irq_hw[i]->flag)
| ppc_lost_interrupts[i];
if (bits == 0)
continue;
- irq -= cntlzw(bits);
+ irq += __ilog2(bits);
break;
}
}
@@ -489,11 +489,9 @@ sleep_save_intrs(int viaint)
if (max_real_irqs > 32)
out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]);
(void)in_le32(&pmac_irq_hw[0]->flag);
- do {
- /* make sure mask gets to controller before we
- return to user */
- mb();
- } while(in_le32(&pmac_irq_hw[0]->enable) != ppc_cached_irq_mask[0]);
+ /* make sure mask gets to controller before we return to caller */
+ mb();
+ (void)in_le32(&pmac_irq_hw[0]->enable);
}
void
diff --git a/arch/ppc/kernel/pmac_setup.c b/arch/ppc/kernel/pmac_setup.c
index c2c4cbbf4..35aa7a76d 100644
--- a/arch/ppc/kernel/pmac_setup.c
+++ b/arch/ppc/kernel/pmac_setup.c
@@ -100,6 +100,8 @@ int has_l2cache = 0;
extern char saved_command_line[];
+extern int pmac_newworld;
+
#define DEFAULT_ROOT_DEVICE 0x0801 /* sda1 - slightly silly choice */
extern void zs_kgdb_hook(int tty_num);
@@ -198,6 +200,11 @@ pmac_get_cpuinfo(char *buffer)
}
}
+ /* Indicate newworld/oldworld */
+ len += sprintf(buffer+len, "pmac-generation\t: %s\n",
+ pmac_newworld ? "NewWorld" : "OldWorld");
+
+
return len;
}
@@ -499,6 +506,8 @@ pmac_restart(char *cmd)
struct adb_request req;
#endif /* CONFIG_ADB_CUDA */
+ pmac_nvram_update();
+
switch (sys_ctrler) {
#ifdef CONFIG_ADB_CUDA
case SYS_CTRLER_CUDA:
@@ -524,6 +533,8 @@ pmac_power_off(void)
struct adb_request req;
#endif /* CONFIG_ADB_CUDA */
+ pmac_nvram_update();
+
switch (sys_ctrler) {
#ifdef CONFIG_ADB_CUDA
case SYS_CTRLER_CUDA:
diff --git a/arch/ppc/kernel/ppc-stub.c b/arch/ppc/kernel/ppc-stub.c
index 42ca7eadc..7a673fb70 100644
--- a/arch/ppc/kernel/ppc-stub.c
+++ b/arch/ppc/kernel/ppc-stub.c
@@ -99,6 +99,7 @@
*
****************************************************************************/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/mm.h>
@@ -123,6 +124,7 @@ static char remcomOutBuffer[BUFMAX];
static int initialized = 0;
static int kgdb_active = 0;
+static int kgdb_started = 0;
static u_int fault_jmp_buf[100];
static int kdebug;
@@ -342,7 +344,7 @@ static void kgdb_flush_cache_all(void)
flush_instruction_cache();
}
-static inline int get_msr()
+static inline int get_msr(void)
{
int msr;
asm volatile("mfmsr %0" : "=r" (msr):);
@@ -460,6 +462,9 @@ static int computeSignal(unsigned int tt)
return SIGHUP; /* default for things we don't know about */
}
+#define PC_REGNUM 64
+#define SP_REGNUM 1
+
/*
* This function does all command processing for interfacing to gdb.
*/
@@ -481,6 +486,7 @@ handle_exception (struct pt_regs *regs)
return;
}
kgdb_active = 1;
+ kgdb_started = 1;
#ifdef KGDB_DEBUG
printk("kgdb: entering handle_exception; trap [0x%x]\n",
@@ -501,9 +507,25 @@ handle_exception (struct pt_regs *regs)
sigval = computeSignal(regs->trap);
ptr = remcomOutBuffer;
+#if 0
*ptr++ = 'S';
*ptr++ = hexchars[sigval >> 4];
*ptr++ = hexchars[sigval & 0xf];
+#else
+ *ptr++ = 'T';
+ *ptr++ = hexchars[sigval >> 4];
+ *ptr++ = hexchars[sigval & 0xf];
+ *ptr++ = hexchars[PC_REGNUM >> 4];
+ *ptr++ = hexchars[PC_REGNUM & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)&regs->nip, ptr, 4);
+ *ptr++ = ';';
+ *ptr++ = hexchars[SP_REGNUM >> 4];
+ *ptr++ = hexchars[SP_REGNUM & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex(((char *)&regs) + SP_REGNUM*4, ptr, 4);
+ *ptr++ = ';';
+#endif
*ptr++ = 0;
@@ -639,6 +661,7 @@ handle_exception (struct pt_regs *regs)
} else {
strcpy(remcomOutBuffer, "E03");
}
+ flush_icache_range(addr, addr+length);
} else {
strcpy(remcomOutBuffer, "E02");
}
@@ -668,7 +691,9 @@ handle_exception (struct pt_regs *regs)
case 's':
kgdb_flush_cache_all();
regs->msr |= MSR_SE;
+#if 0
set_msr(msr | MSR_SE);
+#endif
unlock_kernel();
kgdb_active = 0;
return;
@@ -700,6 +725,37 @@ breakpoint(void)
}
asm(" .globl breakinst
- breakinst: trap
+ breakinst: .long 0x7d821008
");
}
+
+/* Output string in GDB O-packet format if GDB has connected. If nothing
+ output, returns 0 (caller must then handle output). */
+int
+kgdb_output_string (const char* s, unsigned int count)
+{
+ char buffer[512];
+
+ if (!kgdb_started)
+ return 0;
+
+ count = (count <= (sizeof(buffer) / 2 - 2))
+ ? count : (sizeof(buffer) / 2 - 2);
+
+ buffer[0] = 'O';
+ mem2hex (s, &buffer[1], count);
+ putpacket(buffer);
+
+ return 1;
+ }
+
+#ifndef CONFIG_8xx
+
+/* I don't know why other platforms don't need this. The function for
+ * the 8xx is found in arch/ppc/8xx_io/uart.c. -- Dan
+ */
+void
+kgdb_map_scc(void)
+{
+}
+#endif
diff --git a/arch/ppc/kernel/ppc8260_pic.c b/arch/ppc/kernel/ppc8260_pic.c
new file mode 100644
index 000000000..21cfde0f7
--- /dev/null
+++ b/arch/ppc/kernel/ppc8260_pic.c
@@ -0,0 +1,111 @@
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <asm/irq.h>
+#include <asm/immap_8260.h>
+#include <asm/mpc8260.h>
+#include "ppc8260_pic.h"
+
+/* The 8260 internal interrupt controller. It is usually
+ * the only interrupt controller.
+ * There are two 32-bit registers (high/low) for up to 64
+ * possible interrupts.
+ *
+ * Now, the fun starts.....Interrupt Numbers DO NOT MAP
+ * in a simple arithmetic fashion to mask or pending registers.
+ * That is, interrupt 4 does not map to bit position 4.
+ * We create two tables, indexed by vector number, to indicate
+ * which register to use and which bit in the register to use.
+ */
+static u_char irq_to_siureg[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static u_char irq_to_siubit[] = {
+ 31, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30,
+ 29, 30, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 31,
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0
+};
+
+static void m8260_mask_irq(unsigned int irq_nr)
+{
+ int bit, word;
+ volatile uint *simr;
+
+ bit = irq_to_siubit[irq_nr];
+ word = irq_to_siureg[irq_nr];
+
+ simr = &(immr->im_intctl.ic_simrh);
+ ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+ simr[word] = ppc_cached_irq_mask[word];
+}
+
+static void m8260_unmask_irq(unsigned int irq_nr)
+{
+ int bit, word;
+ volatile uint *simr;
+
+ bit = irq_to_siubit[irq_nr];
+ word = irq_to_siureg[irq_nr];
+
+ simr = &(immr->im_intctl.ic_simrh);
+ ppc_cached_irq_mask[word] |= (1 << (31 - bit));
+ simr[word] = ppc_cached_irq_mask[word];
+}
+
+static void m8260_mask_and_ack(unsigned int irq_nr)
+{
+ int bit, word;
+ volatile uint *simr, *sipnr;
+
+ bit = irq_to_siubit[irq_nr];
+ word = irq_to_siureg[irq_nr];
+
+ simr = &(immr->im_intctl.ic_simrh);
+ sipnr = &(immr->im_intctl.ic_sipnrh);
+ ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+ simr[word] = ppc_cached_irq_mask[word];
+ sipnr[word] = 1 << bit;
+}
+
+struct hw_interrupt_type ppc8260_pic = {
+ " 8260 SIU ",
+ NULL,
+ NULL,
+ m8260_unmask_irq,
+ m8260_mask_irq,
+ m8260_mask_and_ack,
+ 0
+};
+
+
+int
+m8260_get_irq(struct pt_regs *regs)
+{
+ int irq;
+ unsigned long bits;
+
+ /* For MPC8260, read the SIVEC register and shift the bits down
+ * to get the irq number. */
+ bits = immr->im_intctl.ic_sivec;
+ irq = bits >> 26;
+#if 0
+ irq += ppc8260_pic.irq_offset;
+#endif
+ return irq;
+}
+
diff --git a/arch/ppc/kernel/ppc8260_pic.h b/arch/ppc/kernel/ppc8260_pic.h
new file mode 100644
index 000000000..b073dbe6b
--- /dev/null
+++ b/arch/ppc/kernel/ppc8260_pic.h
@@ -0,0 +1,15 @@
+
+#ifndef _PPC_KERNEL_PPC8260_H
+#define _PPC_KERNEL_PPC8260_H
+
+#include "local_irq.h"
+
+extern struct hw_interrupt_type ppc8260_pic;
+
+void m8260_pic_init(void);
+void m8260_do_IRQ(struct pt_regs *regs,
+ int cpu,
+ int isfake);
+int m8260_get_irq(struct pt_regs *regs);
+
+#endif /* _PPC_KERNEL_PPC8260_H */
diff --git a/arch/ppc/kernel/ppc8xx_pic.c b/arch/ppc/kernel/ppc8xx_pic.c
index afcda088b..e2db1e34d 100644
--- a/arch/ppc/kernel/ppc8xx_pic.c
+++ b/arch/ppc/kernel/ppc8xx_pic.c
@@ -8,7 +8,7 @@
#include <asm/mpc8xx.h>
#include "ppc8xx_pic.h"
-/* The 8xx or 82xx internal interrupt controller. It is usually
+/* The 8xx internal interrupt controller. It is usually
* the only interrupt controller. Some boards, like the MBX and
* Sandpoint have the 8259 as a secondary controller. Depending
* upon the processor type, the internal controller can have as
@@ -25,13 +25,8 @@ static void m8xx_mask_irq(unsigned int irq_nr)
word = irq_nr >> 5;
ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
-#ifdef CONFIG_82xx
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask[word] =
- ppc_cached_irq_mask[word];
-#else
((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
ppc_cached_irq_mask[word];
-#endif
}
static void m8xx_unmask_irq(unsigned int irq_nr)
@@ -42,13 +37,8 @@ static void m8xx_unmask_irq(unsigned int irq_nr)
word = irq_nr >> 5;
ppc_cached_irq_mask[word] |= (1 << (31-bit));
-#ifdef CONFIG_82xx
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask[word] =
- ppc_cached_irq_mask[word];
-#else
((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
ppc_cached_irq_mask[word];
-#endif
}
static void m8xx_mask_and_ack(unsigned int irq_nr)
@@ -59,15 +49,9 @@ static void m8xx_mask_and_ack(unsigned int irq_nr)
word = irq_nr >> 5;
ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
-#ifdef CONFIG_82xx
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask[word] =
- ppc_cached_irq_mask[word];
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend[word] = 1 << (31-bit);
-#else
((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
ppc_cached_irq_mask[word];
((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = 1 << (31-bit);
-#endif
}
struct hw_interrupt_type ppc8xx_pic = {
@@ -129,7 +113,7 @@ m8xx_get_irq(struct pt_regs *regs)
/* The MBX is the only 8xx board that uses the 8259.
*/
-#ifdef CONFIG_MBX
+#if defined(CONFIG_MBX) && defined(CONFIG_PCI)
void mbx_i8259_action(int cpl, void *dev_id, struct pt_regs *regs)
{
int bits, irq;
@@ -165,7 +149,7 @@ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *)
unsigned long irqflags, const char * devname, void *dev_id)
{
-#ifdef CONFIG_MBX
+#if defined(CONFIG_MBX) && defined(CONFIG_PCI)
irq += i8259_pic.irq_offset;
return (request_8xxirq(irq, handler, irqflags, devname, dev_id));
#else
diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
index 441310e68..655eb4390 100644
--- a/arch/ppc/kernel/ppc_htab.c
+++ b/arch/ppc/kernel/ppc_htab.c
@@ -502,7 +502,7 @@ int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
#define TMPBUFLEN 256
char buf[TMPBUFLEN], *p;
static const char *sizestrings[4] = {
- "unknown size", "256KB", "512KB", "1MB"
+ "2MB", "256KB", "512KB", "1MB"
};
static const char *clockstrings[8] = {
"clock disabled", "+1 clock", "+1.5 clock", "reserved(3)",
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 7d4c038ec..9b7d2be31 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -54,9 +54,10 @@ extern int sys_sigreturn(struct pt_regs *regs);
extern void do_lost_interrupts(unsigned long);
extern int do_signal(sigset_t *, struct pt_regs *);
-asmlinkage long long __ashrdi3(long long, int);
-asmlinkage long long __lshrdi3(long long, int);
-asmlinkage int abs(int);
+long long __ashrdi3(long long, int);
+long long __ashldi3(long long, int);
+long long __lshrdi3(long long, int);
+int abs(int);
EXPORT_SYMBOL(clear_page);
EXPORT_SYMBOL(do_signal);
@@ -95,25 +96,12 @@ EXPORT_SYMBOL(ucSystemType);
#endif
#endif
-EXPORT_SYMBOL(atomic_add);
-EXPORT_SYMBOL(atomic_sub);
-EXPORT_SYMBOL(atomic_inc);
-EXPORT_SYMBOL(atomic_inc_return);
-EXPORT_SYMBOL(atomic_dec);
-EXPORT_SYMBOL(atomic_dec_return);
-EXPORT_SYMBOL(atomic_dec_and_test);
-
EXPORT_SYMBOL(set_bit);
EXPORT_SYMBOL(clear_bit);
EXPORT_SYMBOL(change_bit);
EXPORT_SYMBOL(test_and_set_bit);
EXPORT_SYMBOL(test_and_clear_bit);
EXPORT_SYMBOL(test_and_change_bit);
-#if 0
-EXPORT_SYMBOL(ffz);
-EXPORT_SYMBOL(find_first_zero_bit);
-EXPORT_SYMBOL(find_next_zero_bit);
-#endif
EXPORT_SYMBOL(strcpy);
EXPORT_SYMBOL(strncpy);
@@ -254,6 +242,7 @@ EXPORT_SYMBOL(nvram_write_byte);
#endif /* CONFIG_NVRAM */
EXPORT_SYMBOL_NOVERS(__ashrdi3);
+EXPORT_SYMBOL_NOVERS(__ashldi3);
EXPORT_SYMBOL_NOVERS(__lshrdi3);
EXPORT_SYMBOL_NOVERS(memcpy);
EXPORT_SYMBOL_NOVERS(memset);
@@ -281,3 +270,17 @@ EXPORT_SYMBOL(console_drivers);
EXPORT_SYMBOL(xmon);
#endif
EXPORT_SYMBOL(down_read_failed);
+
+extern void (*debugger)(struct pt_regs *regs);
+extern int (*debugger_bpt)(struct pt_regs *regs);
+extern int (*debugger_sstep)(struct pt_regs *regs);
+extern int (*debugger_iabr_match)(struct pt_regs *regs);
+extern int (*debugger_dabr_match)(struct pt_regs *regs);
+extern void (*debugger_fault_handler)(struct pt_regs *regs);
+
+EXPORT_SYMBOL(debugger);
+EXPORT_SYMBOL(debugger_bpt);
+EXPORT_SYMBOL(debugger_sstep);
+EXPORT_SYMBOL(debugger_iabr_match);
+EXPORT_SYMBOL(debugger_dabr_match);
+EXPORT_SYMBOL(debugger_fault_handler);
diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
index ce8e039c0..e1f1b4983 100644
--- a/arch/ppc/kernel/process.c
+++ b/arch/ppc/kernel/process.c
@@ -489,7 +489,7 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
{
int error;
char * filename;
- lock_kernel();
+
filename = getname((char *) a0);
error = PTR_ERR(filename);
if (IS_ERR(filename))
@@ -503,8 +503,6 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
error = do_execve(filename, (char **) a1, (char **) a2, regs);
putname(filename);
out:
- unlock_kernel();
-
return error;
}
diff --git a/arch/ppc/kernel/prom.c b/arch/ppc/kernel/prom.c
index a987b8fd6..31fc85068 100644
--- a/arch/ppc/kernel/prom.c
+++ b/arch/ppc/kernel/prom.c
@@ -106,7 +106,10 @@ unsigned int rtas_entry = 0; /* physical pointer */
unsigned int rtas_size = 0;
unsigned int old_rtas = 0;
+/* Set for a newworld machine */
int use_of_interrupt_tree = 0;
+int pmac_newworld = 0;
+
static struct device_node *allnodes = 0;
#ifdef CONFIG_BOOTX_TEXT
@@ -802,7 +805,6 @@ __init
static void
setup_disp_fake_bi(ihandle dp)
{
- unsigned int len;
int width = 640, height = 480, depth = 8, pitch;
unsigned address;
boot_infos_t* bi;
@@ -982,15 +984,17 @@ void
finish_device_tree(void)
{
unsigned long mem = (unsigned long) klimit;
- char* model;
-
- /* Here, we decide if we'll use the interrupt-tree (new Core99 code) or not.
- * This code was only tested with Core99 machines so far, but should be easily
- * adapted to older newworld machines (iMac, B&W G3, Lombard).
- */
- model = get_property(allnodes, "model", 0);
- if ((boot_infos == 0) && model && (strcmp(model, "PowerBook2,1") == 0
- || strcmp(model, "PowerMac2,1") == 0 || strcmp(model, "PowerMac3,1") == 0))
+
+ /* All newworld machines now use the interrupt tree */
+ struct device_node *np = allnodes;
+ while(np) {
+ if (get_property(np, "interrupt-parent", 0)) {
+ pmac_newworld = 1;
+ break;
+ }
+ np = np->allnext;
+ }
+ if (boot_infos == 0 && pmac_newworld)
use_of_interrupt_tree = 1;
mem = finish_node(allnodes, mem, NULL);
@@ -1827,7 +1831,8 @@ abort()
#ifdef CONFIG_XMON
xmon(NULL);
#endif
- prom_exit();
+ for (;;)
+ prom_exit();
}
#ifdef CONFIG_BOOTX_TEXT
diff --git a/arch/ppc/kernel/qspan_pci.c b/arch/ppc/kernel/qspan_pci.c
index 860f4f0cc..c31dd9399 100644
--- a/arch/ppc/kernel/qspan_pci.c
+++ b/arch/ppc/kernel/qspan_pci.c
@@ -84,7 +84,7 @@
" .align 2\n" \
" .long 1b,3b\n" \
".text" \
- : "=r"(x) : "r"(addr))
+ : "=r"(x) : "r"(addr) : " %0")
#define QS_CONFIG_ADDR ((volatile uint *)(PCI_CSR_ADDR + 0x500))
#define QS_CONFIG_DATA ((volatile uint *)(PCI_CSR_ADDR + 0x504))
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 2b771ef14..49a8da139 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -27,6 +27,10 @@
#include <asm/mpc8xx.h>
#include <asm/8xx_immap.h>
#endif
+#ifdef CONFIG_8260
+#include <asm/mpc8260.h>
+#include <asm/immap_8260.h>
+#endif
#include <asm/bootx.h>
#include <asm/machdep.h>
#include <asm/feature.h>
@@ -109,8 +113,10 @@ struct machdep_calls ppc_md;
* on pmac as well so we don't need the ifdef's.
* Until we get multiple-console support in here
* that is. -- Cort
+ * Maybe tie it to serial consoles, since this is really what
+ * these processors use on existing boards. -- Dan
*/
-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260)
struct screen_info screen_info = {
0, 25, /* orig-x, orig-y */
0, /* unused */
@@ -283,10 +289,10 @@ int get_cpuinfo(char *buffer)
}
break;
case 0x0050:
- len += sprintf(len+buffer, "821\n");
+ len += sprintf(len+buffer, "8xx\n");
break;
case 0x0081:
- len += sprintf(len+buffer, "8240\n");
+ len += sprintf(len+buffer, "82xx\n");
break;
case 0x4011:
len += sprintf(len+buffer, "405GP\n");
@@ -300,7 +306,7 @@ int get_cpuinfo(char *buffer)
* Assume here that all clock rates are the same in a
* smp system. -- Cort
*/
-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260)
if ( have_of )
{
struct device_node *cpu_node;
@@ -418,10 +424,10 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
parse_bootinfo();
-
+
if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100);
-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260)
#ifndef CONFIG_MACH_SPECIFIC
/* if we didn't get any bootinfo telling us what we are... */
if ( _machine == 0 )
@@ -540,6 +546,8 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
oak_init(r3, r4, r5, r6, r7);
#elif defined(CONFIG_8xx)
m8xx_init(r3, r4, r5, r6, r7);
+#elif defined(CONFIG_8260)
+ m8260_init(r3, r4, r5, r6, r7);
#else
#error "No board type has been defined for identify_machine()!"
#endif /* CONFIG_4xx */
@@ -659,13 +667,19 @@ void __init setup_arch(char **cmdline_p)
map_bootx_text();
#endif
+#ifdef CONFIG_ALL_PPC
+ feature_init();
+#endif
+
#ifdef CONFIG_XMON
xmon_map_scc();
if (strstr(cmd_line, "xmon"))
xmon(0);
#endif /* CONFIG_XMON */
if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);
+
#if defined(CONFIG_KGDB)
+ kgdb_map_scc();
set_debug_traps();
breakpoint();
#endif
@@ -688,6 +702,7 @@ void __init setup_arch(char **cmdline_p)
ppc_md.setup_arch();
if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
+
paging_init();
}
@@ -696,7 +711,6 @@ void ppc_generic_ide_fix_driveid(struct hd_driveid *id)
int i;
unsigned short *stringcast;
-
id->config = __le16_to_cpu(id->config);
id->cyls = __le16_to_cpu(id->cyls);
id->reserved2 = __le16_to_cpu(id->reserved2);
@@ -708,16 +722,16 @@ void ppc_generic_ide_fix_driveid(struct hd_driveid *id)
id->vendor1 = __le16_to_cpu(id->vendor1);
id->vendor2 = __le16_to_cpu(id->vendor2);
stringcast = (unsigned short *)&id->serial_no[0];
- for (i=0; i<(20/2); i++)
+ for (i = 0; i < (20/2); i++)
stringcast[i] = __le16_to_cpu(stringcast[i]);
id->buf_type = __le16_to_cpu(id->buf_type);
id->buf_size = __le16_to_cpu(id->buf_size);
id->ecc_bytes = __le16_to_cpu(id->ecc_bytes);
stringcast = (unsigned short *)&id->fw_rev[0];
- for (i=0; i<(8/2); i++)
+ for (i = 0; i < (8/2); i++)
stringcast[i] = __le16_to_cpu(stringcast[i]);
stringcast = (unsigned short *)&id->model[0];
- for (i=0; i<(40/2); i++)
+ for (i = 0; i < (40/2); i++)
stringcast[i] = __le16_to_cpu(stringcast[i]);
id->dword_io = __le16_to_cpu(id->dword_io);
id->reserved50 = __le16_to_cpu(id->reserved50);
@@ -735,12 +749,12 @@ void ppc_generic_ide_fix_driveid(struct hd_driveid *id)
id->eide_dma_time = __le16_to_cpu(id->eide_dma_time);
id->eide_pio = __le16_to_cpu(id->eide_pio);
id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy);
- for (i=0; i<2; i++)
+ for (i = 0; i < 2; i++)
id->words69_70[i] = __le16_to_cpu(id->words69_70[i]);
- for (i=0; i<4; i++)
+ for (i = 0; i < 4; i++)
id->words71_74[i] = __le16_to_cpu(id->words71_74[i]);
id->queue_depth = __le16_to_cpu(id->queue_depth);
- for (i=0; i<4; i++)
+ for (i = 0; i < 4; i++)
id->words76_79[i] = __le16_to_cpu(id->words76_79[i]);
id->major_rev_num = __le16_to_cpu(id->major_rev_num);
id->minor_rev_num = __le16_to_cpu(id->minor_rev_num);
@@ -756,14 +770,14 @@ void ppc_generic_ide_fix_driveid(struct hd_driveid *id)
id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues);
id->word92 = __le16_to_cpu(id->word92);
id->hw_config = __le16_to_cpu(id->hw_config);
- for (i=0; i<32; i++)
+ for (i = 0; i < 32; i++)
id->words94_125[i] = __le16_to_cpu(id->words94_125[i]);
id->last_lun = __le16_to_cpu(id->last_lun);
id->word127 = __le16_to_cpu(id->word127);
id->dlf = __le16_to_cpu(id->dlf);
id->csfo = __le16_to_cpu(id->csfo);
- for (i=0; i<31; i++)
+ for (i = 0; i < 30; i++)
id->words130_159[i] = __le16_to_cpu(id->words130_159[i]);
- for (i=0; i<97; i++)
+ for (i = 0; i < 96; i++)
id->words160_255[i] = __le16_to_cpu(id->words160_255[i]);
}
diff --git a/arch/ppc/kernel/totalmp.c b/arch/ppc/kernel/totalmp.c
deleted file mode 100644
index ecbc04b57..000000000
--- a/arch/ppc/kernel/totalmp.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * $Id: totalmp.c,v 1.6 1999/08/31 06:54:10 davem Exp $
- *
- * Support for Total Impact's TotalMP PowerPC accelerator board.
- *
- * Written by Cort Dougan (cort@cs.nmt.edu)
- *
- * This program 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 of the License, or (at your option) any later version.
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/openpic.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-
-#include <asm/io.h>
-
-extern void totalmp_init(void);
-
-extern inline void openpic_writefield(volatile u_int *addr, u_int mask,
- u_int field);
-void __init totalmp_init(void)
-{
- struct pci_dev *dev;
- u32 val;
- unsigned long ctl_area, ctl_area_phys;
-
- /* it's a pci card */
- if ( !pci_present() ) return;
-
- /* search for a MPIC. For now, we assume
- * only one TotalMP card installed. -- Cort
- */
- for(dev=pci_devices; dev; dev=dev->next)
- {
- if ( (dev->vendor == PCI_VENDOR_ID_IBM)
- && ((dev->device == PCI_DEVICE_ID_IBM_MPIC)
- || (dev->device==PCI_DEVICE_ID_IBM_MPIC_2)) )
- {
- break;
- }
- }
-
- if ( !dev ) return;
-
- OpenPIC = (struct OpenPIC *)bus_to_virt(dev->base_address[0]);
-#if 0
- if ( (ulong)OpenPIC > 0x10000000 )
- {
- printk("TotalMP: relocating base %lx -> %lx\n",
- (ulong)OpenPIC, ((ulong)OpenPIC & 0x00FFFFFF) | 0x01000000);
- OpenPIC = (struct OpenPIC *)(((ulong)OpenPIC & 0x00FFFFFF) | 0x01000000);
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, (ulong)OpenPIC);
- }*/
-#endif
- OpenPIC = (struct OpenPIC *)((ulong)OpenPIC + _IO_BASE);
-
- openpic_init(0);
-
- /* put openpic in 8259-cascade mode */
- openpic_writefield(&OpenPIC->Global.Global_Configuration0, 0, 0x20000000);
- /* set ipi to highest priority */
- openpic_writefield(&OpenPIC->Global._IPI_Vector_Priority[0].Reg, 0, 0x000f0000);
-
- /* allocate and remap the control area to be no-cache */
- ctl_area = __get_free_pages(GFP_ATOMIC, 3);
- ctl_area_phys = (unsigned long) virt_to_phys((void *)ctl_area);
- ctl_area = (unsigned long)ioremap(ctl_area, 0x8000);
-
- /* soft reset cpu 0 */
- pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &val);
- openpic_writefield(&OpenPIC->Global._Processor_Initialization.Reg, 0, 0x1);
-
- /* wait for base address reg to change, signaling that cpu 0 is done */
-#define wait_for(where) { \
- udelay(100); \
- pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &val); \
- if ( val != 0x77700000 ) \
- { \
- printk("TotalMP: CPU0 did not respond: val %x %d\n", val, where); \
- /*free_pages((ulong)phys_to_virt(ctl_area_phys),1);*/ \
- return; \
- } }
-
- /* tell cpu0 where the control area is */
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,(~val) >> 16);
- wait_for(0);
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
- ((ulong)ctl_area & 0xff000000)>>20);
- wait_for(1);
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
- ((ulong)ctl_area & 0x00ff0000)>>12);
- wait_for(2);
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
- ((ulong)ctl_area & 0x0000ff00)>>4);
- wait_for(3);
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
- ((ulong)ctl_area & 0x000000ff)<<4);
- wait_for(4);
-#undef wait_for
- /* wait for cpu0 to "sign-on" */
-}
-
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index ac7f47602..28a5a5035 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -119,10 +119,10 @@ MachineCheckException(struct pt_regs *regs)
printk("Unknown values in msr\n");
}
show_regs(regs);
- print_backtrace((unsigned long *)regs->gpr[1]);
#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
debugger(regs);
#endif
+ print_backtrace((unsigned long *)regs->gpr[1]);
panic("machine check");
}
_exception(SIGSEGV, regs);
diff --git a/arch/ppc/mbxboot/Makefile b/arch/ppc/mbxboot/Makefile
index 6f9fd0135..9dd5d64f3 100644
--- a/arch/ppc/mbxboot/Makefile
+++ b/arch/ppc/mbxboot/Makefile
@@ -25,11 +25,20 @@ ZSZ = 0
IOFF = 0
ISZ = 0
-TFTPIMAGE=/tftpboot/zImage.mbx
-ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00180000
+TFTPIMAGE=/tftpboot/zImage.embedded
+ifdef CONFIG_8xx
+ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00180000
OBJECTS := head.o misc.o ../coffboot/zlib.o m8xx_tty.o
CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -DCONFIG_8xx
+endif
+
+ifdef CONFIG_8260
+ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00400000
+OBJECTS := head_8260.o misc.o ../coffboot/zlib.o m8260_tty.o embed_config.o
+CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -DCONFIG_8260
+endif
+
OBJCOPY_ARGS = -O elf32-powerpc
ifeq ($(CONFIG_MBX),y)
diff --git a/arch/ppc/mbxboot/embed_config.c b/arch/ppc/mbxboot/embed_config.c
index 009d0b4bc..1d76be70c 100644
--- a/arch/ppc/mbxboot/embed_config.c
+++ b/arch/ppc/mbxboot/embed_config.c
@@ -3,7 +3,13 @@
* not have boot monitor support for board information.
*/
#include <sys/types.h>
-#include "asm/mpc8xx.h"
+#include <linux/config.h>
+#ifdef CONFIG_8xx
+#include <asm/mpc8xx.h>
+#endif
+#ifdef CONFIG_8260
+#include <asm/mpc8260.h>
+#endif
/* IIC functions.
@@ -13,6 +19,14 @@
extern void iic_read(uint devaddr, u_char *buf, uint offset, uint count);
extern u_char aschex_to_byte(u_char *cp);
+/* Supply a default Ethernet address for those eval boards that don't
+ * ship with one. This is an address from the MBX board I have, so
+ * it is unlikely you will find it on your network.
+ */
+static ushort def_enet_addr[] = { 0x0800, 0x3e26, 0x1559 };
+
+#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
+
static void rpx_eth(bd_t *bd, u_char *cp);
static void rpx_brate(bd_t *bd, u_char *cp);
static void rpx_memsize(bd_t *bd, u_char *cp);
@@ -89,8 +103,10 @@ rpx_cfg(bd_t *bd)
bd->bi_memstart = 0;
#else
+ /* For boards without initialized EEPROM.
+ */
bd->bi_memstart = 0;
- bd->bi_memsize = (4 * 1024 * 1024);
+ bd->bi_memsize = (8 * 1024 * 1024);
bd->bi_intfreq = 48;
bd->bi_busfreq = 48;
bd->bi_baudrate = 9600;
@@ -174,7 +190,9 @@ rpx_cpuspeed(bd_t *bd, u_char *cp)
if (num > 50)
bd->bi_busfreq /= 2;
}
+#endif /* RPXLITE || RPXCLASSIC */
+#ifdef CONFIG_BSEIP
/* Build a board information structure for the BSE ip-Engine.
* There is more to come since we will add some environment
* variables and a function to read them.
@@ -204,4 +222,31 @@ bseip_cfg(bd_t *bd)
bd->bi_intfreq = 48;
bd->bi_busfreq = 48;
}
+#endif /* BSEIP */
+#ifdef CONFIG_EST8260
+void
+embed_config(bd_t *bd)
+{
+ u_char *cp;
+ int i;
+
+#if 1
+ /* This is actually provided by my boot rom. I have it
+ * here for those people that may load the kernel with
+ * a JTAG/COP tool and not the rom monitor.
+ */
+ bd->bi_baudrate = 115200;
+ bd->bi_intfreq = 200;
+ bd->bi_busfreq = 66;
+ bd->bi_cpmfreq = 66;
+ bd->bi_brgfreq = 33;
+ bd->bi_memsize = 16 * 1024 * 1024;
+#endif
+
+ cp = (u_char *)def_enet_addr;
+ for (i=0; i<6; i++) {
+ bd->bi_enetaddr[i] = *cp++;
+ }
+}
+#endif /* EST8260 */
diff --git a/arch/ppc/mbxboot/head_8260.S b/arch/ppc/mbxboot/head_8260.S
new file mode 100644
index 000000000..79377a2ac
--- /dev/null
+++ b/arch/ppc/mbxboot/head_8260.S
@@ -0,0 +1,246 @@
+#include "../kernel/ppc_defs.h"
+#include "../kernel/ppc_asm.tmpl"
+#include <asm/processor.h>
+#include <asm/cache.h>
+
+ .text
+
+/*
+ * $Id: head.S,v 1.33 1999/09/08 01:06:58 cort Exp $
+ *
+ * Boot loader philosophy:
+ * ROM loads us to some arbitrary location
+ * Move the boot code to the link address (8M)
+ * Call decompress_kernel()
+ * Relocate the initrd, zimage and residual data to 8M
+ * Decompress the kernel to 0
+ * Jump to the kernel entry
+ * -- Cort
+ */
+ .globl start
+start:
+ bl start_
+start_:
+ mr r11,r3 /* Save pointer to residual/board data */
+ mr r25,r5 /* Save OFW pointer */
+ li r3,MSR_IP /* Establish default MSR value */
+ mtmsr r3
+
+/* check if we need to relocate ourselves to the link addr or were we
+ loaded there to begin with -- Cort */
+ lis r4,start@h
+ ori r4,r4,start@l
+ mflr r3
+ subi r3,r3,4 /* we get the nip, not the ip of the branch */
+ mr r8,r3
+ cmp 0,r3,r4
+ bne 1010f
+/* compute size of whole image in words. this should be moved to
+ * start_ldr() -- Cort
+ */
+ lis r4,start@h
+ ori r4,r4,start@l
+ lis r5,end@h
+ ori r5,r5,end@l
+ addi r5,r5,3 /* round up */
+ sub r5,r5,r4
+ srwi r5,r5,2
+ mr r7,r5
+ b start_ldr
+1010:
+/*
+ * no matter where we're loaded, move ourselves to -Ttext address
+ */
+relocate:
+ mflr r3 /* Compute code bias */
+ subi r3,r3,4
+ mr r8,r3
+ lis r4,start@h
+ ori r4,r4,start@l
+ lis r5,end@h
+ ori r5,r5,end@l
+ addi r5,r5,3 /* Round up - just in case */
+ sub r5,r5,r4 /* Compute # longwords to move */
+ srwi r5,r5,2
+ mtctr r5
+ mr r7,r5
+ li r6,0
+ subi r3,r3,4 /* Set up for loop */
+ subi r4,r4,4
+00: lwzu r5,4(r3)
+ stwu r5,4(r4)
+ xor r6,r6,r5
+ bdnz 00b
+ lis r3,start_ldr@h
+ ori r3,r3,start_ldr@l
+ mtlr r3 /* Easiest way to do an absolute jump */
+ blr
+start_ldr:
+/* Clear all of BSS */
+ lis r3,edata@h
+ ori r3,r3,edata@l
+ lis r4,end@h
+ ori r4,r4,end@l
+ subi r3,r3,4
+ subi r4,r4,4
+ li r0,0
+50: stwu r0,4(r3)
+ cmp 0,r3,r4
+ bne 50b
+90: mr r9,r1 /* Save old stack pointer (in case it matters) */
+ lis r1,.stack@h
+ ori r1,r1,.stack@l
+ addi r1,r1,4096*2
+ subi r1,r1,256
+ li r2,0x000F /* Mask pointer to 16-byte boundary */
+ andc r1,r1,r2
+/* Run loader */
+ mr r3,r8 /* Load point */
+ mr r4,r7 /* Program length */
+ mr r5,r6 /* Checksum */
+ mr r6,r11 /* Residual data */
+ mr r7,r25 /* OFW interfaces */
+ bl decompress_kernel
+
+ /* changed to use r3 (as firmware does) for kernel
+ as ptr to residual -- Cort*/
+ lis r6,cmd_line@h
+ ori r6,r6,cmd_line@l
+ lwz r6, 0(r6)
+ subi r7,r6,1
+00: lbzu r2,1(r7)
+ cmpi 0,r2,0
+ bne 00b
+
+ /* r4,r5 have initrd_start, size */
+ lis r2,initrd_start@h
+ ori r2,r2,initrd_start@l
+ lwz r4,0(r2)
+ lis r2,initrd_end@h
+ ori r2,r2,initrd_end@l
+ lwz r5,0(r2)
+
+ /* tell kernel we're prep */
+ /*
+ * get start address of kernel code which is stored as a coff
+ * entry. see boot/head.S -- Cort
+ */
+ li r9,0x4
+ mtlr r9
+ lis r10,0xdeadc0de@h
+ ori r10,r10,0xdeadc0de@l
+ li r9,0
+ stw r10,0(r9)
+/*
+ * The Radstone firmware maps PCI memory at 0xc0000000 using BAT2
+ * so disable BATs before setting this to avoid a clash
+ */
+ li r8,0
+ mtspr DBAT0U,r8
+ mtspr DBAT1U,r8
+ mtspr DBAT2U,r8
+ mtspr DBAT3U,r8
+ mtspr IBAT0U,r8
+ mtspr IBAT1U,r8
+ mtspr IBAT2U,r8
+ mtspr IBAT3U,r8
+
+ blr
+hang:
+ b hang
+
+/*
+ * Delay for a number of microseconds
+ * -- Use the BUS timer (assumes 66MHz)
+ */
+ .globl udelay
+udelay:
+ mfspr r4,PVR
+ srwi r4,r4,16
+ cmpi 0,r4,1 /* 601 ? */
+ bne .udelay_not_601
+00: li r0,86 /* Instructions / microsecond? */
+ mtctr r0
+10: addi r0,r0,0 /* NOP */
+ bdnz 10b
+ subic. r3,r3,1
+ bne 00b
+ blr
+
+.udelay_not_601:
+ mulli r4,r3,1000 /* nanoseconds */
+ addi r4,r4,59
+ li r5,60
+ divw r4,r4,r5 /* BUS ticks */
+1: mftbu r5
+ mftb r6
+ mftbu r7
+ cmp 0,r5,r7
+ bne 1b /* Get [synced] base time */
+ addc r9,r6,r4 /* Compute end time */
+ addze r8,r5
+2: mftbu r5
+ cmp 0,r5,r8
+ blt 2b
+ bgt 3f
+ mftb r6
+ cmp 0,r6,r9
+ blt 2b
+3: blr
+
+.globl _get_HID0
+_get_HID0:
+ mfspr r3,HID0
+ blr
+
+.globl _put_HID0
+_put_HID0:
+ mtspr HID0,r3
+ blr
+
+.globl _get_MSR
+_get_MSR:
+ mfmsr r3
+ blr
+
+.globl _put_MSR
+_put_MSR:
+ mtmsr r3
+ blr
+
+/*
+ * Flush instruction cache
+ * *** I'm really paranoid here!
+ */
+_GLOBAL(flush_instruction_cache)
+ mflr r5
+ bl flush_data_cache
+ mfspr r3,HID0 /* Caches are controlled by this register */
+ li r4,0
+ ori r4,r4,(HID0_ICE|HID0_ICFI)
+ or r3,r3,r4 /* Need to enable+invalidate to clear */
+ mtspr HID0,r3
+ andc r3,r3,r4
+ ori r3,r3,HID0_ICE /* Enable cache */
+ mtspr HID0,r3
+ mtlr r5
+ blr
+
+#define NUM_CACHE_LINES 128*8
+#define CACHE_LINE_SIZE 32
+#define cache_flush_buffer 0x1000
+
+/*
+ * Flush data cache
+ * *** I'm really paranoid here!
+ */
+_GLOBAL(flush_data_cache)
+ lis r3,cache_flush_buffer@h
+ ori r3,r3,cache_flush_buffer@l
+ li r4,NUM_CACHE_LINES
+ mtctr r4
+00: lwz r4,0(r3)
+ addi r3,r3,CACHE_LINE_SIZE /* Next line, please */
+ bdnz 00b
+10: blr
+ .comm .stack,4096*2,4
diff --git a/arch/ppc/mbxboot/iic.c b/arch/ppc/mbxboot/iic.c
index 7775350d5..27de804a6 100644
--- a/arch/ppc/mbxboot/iic.c
+++ b/arch/ppc/mbxboot/iic.c
@@ -43,6 +43,15 @@ iic_init()
*/
while (cp->cp_cpcr & (CPM_CR_RST | CPM_CR_FLG));
+ /* Remove any microcode patches. We will install our own
+ * later.
+ */
+ cp->cp_cpmcr1 = 0;
+ cp->cp_cpmcr2 = 0;
+ cp->cp_cpmcr3 = 0;
+ cp->cp_cpmcr4 = 0;
+ cp->cp_rccr = 0;
+
iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
i2c = (i2c8xx_t *)&(immap->im_i2c);
diff --git a/arch/ppc/mbxboot/m8260_tty.c b/arch/ppc/mbxboot/m8260_tty.c
new file mode 100644
index 000000000..1340577ab
--- /dev/null
+++ b/arch/ppc/mbxboot/m8260_tty.c
@@ -0,0 +1,201 @@
+
+
+/* Minimal serial functions needed to send messages out the serial
+ * port on SMC1.
+ */
+#include <linux/types.h>
+#include "asm/mpc8260.h"
+#include "asm/cpm_8260.h"
+
+uint no_print;
+extern char *params[];
+extern int nparams;
+static u_char cons_hold[128], *sgptr;
+static int cons_hold_cnt;
+
+void
+serial_init(bd_t *bd)
+{
+ volatile smc_t *sp;
+ volatile smc_uart_t *up;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile immap_t *ip;
+ volatile iop8260_t *io;
+ volatile cpm8260_t *cp;
+ uint dpaddr, memaddr;
+
+ ip = (immap_t *)IMAP_ADDR;
+
+ sp = (smc_t*)&(ip->im_smc[0]);
+ *(ushort *)(&ip->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
+ up = (smc_uart_t *)&ip->im_dprambase[PROFF_SMC1];
+
+ cp = &ip->im_cpm;
+ io = &ip->im_ioport;
+
+ /* Disable transmitter/receiver.
+ */
+ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+ /* Use Port D for SMC1 instead of other functions.
+ */
+ io->iop_ppard |= 0x00c00000;
+ io->iop_pdird |= 0x00400000;
+ io->iop_pdird &= ~0x00800000;
+ io->iop_psord &= ~0x00c00000;
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * For now, this address seems OK, but it may have to
+ * change with newer versions of the firmware.
+ */
+ dpaddr = 0x0800;
+
+ /* Grab a few bytes from the top of memory.
+ */
+#if 1
+ memaddr = (bd->bi_memsize - 256) & ~15;
+#else
+ memaddr = 0x0f002c00;
+#endif
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ rbdf = (cbd_t *)&ip->im_dprambase[dpaddr];
+ rbdf->cbd_bufaddr = memaddr;
+ rbdf->cbd_sc = 0;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = memaddr+128;
+ tbdf->cbd_sc = 0;
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+ up->smc_rbase = dpaddr;
+ up->smc_tbase = dpaddr+sizeof(cbd_t);
+ up->smc_rfcr = SMC_EB;
+ up->smc_tfcr = SMC_EB;
+ up->smc_brklen = 0;
+ up->smc_brkec = 0;
+ up->smc_brkcr = 0;
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ sp->smc_smcm = 0;
+ sp->smc_smce = 0xff;
+
+ /* Set up the baud rate generator.
+ */
+ ip->im_clkrst.car_sccr = 0; /* DIV 4 BRG */
+ ip->im_cpmux.cmx_smr = 0;
+ ip->im_brgc1 =
+ ((((bd->bi_brgfreq * 1000000)/16) / bd->bi_baudrate) << 1) |
+ CPM_BRG_EN;
+
+ /* Make the first buffer the only buffer.
+ */
+ tbdf->cbd_sc |= BD_SC_WRAP;
+ rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+#if 0
+ /* Single character receive.
+ */
+ up->smc_mrblr = 1;
+ up->smc_maxidl = 0;
+#else
+ up->smc_mrblr = 128;
+ up->smc_maxidl = 8;
+#endif
+
+ /* Initialize Tx/Rx parameters.
+ */
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* Enable transmitter/receiver.
+ */
+ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+}
+
+void
+serial_putchar(const char c)
+{
+ volatile cbd_t *tbdf;
+ volatile char *buf;
+ volatile smc_uart_t *up;
+ volatile immap_t *ip;
+ extern bd_t *board_info;
+
+ ip = (immap_t *)IMAP_ADDR;
+ up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
+ tbdf = (cbd_t *)&ip->im_dprambase[up->smc_tbase];
+
+ /* Wait for last character to go.
+ */
+ buf = (char *)tbdf->cbd_bufaddr;
+ while (tbdf->cbd_sc & BD_SC_READY);
+
+ *buf = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+}
+
+char
+serial_getc()
+{
+ char c;
+
+ if (cons_hold_cnt <= 0) {
+ cons_hold_cnt = serial_readbuf(cons_hold);
+ sgptr = cons_hold;
+ }
+ c = *sgptr++;
+ cons_hold_cnt--;
+
+ return(c);
+}
+
+int
+serial_readbuf(u_char *cbuf)
+{
+ volatile cbd_t *rbdf;
+ volatile char *buf;
+ volatile smc_uart_t *up;
+ volatile immap_t *ip;
+ int i, nc;
+
+ ip = (immap_t *)IMAP_ADDR;
+
+ up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
+ rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase];
+
+ /* Wait for character to show up.
+ */
+ buf = (char *)rbdf->cbd_bufaddr;
+ while (rbdf->cbd_sc & BD_SC_EMPTY);
+ nc = rbdf->cbd_datlen;
+ for (i=0; i<nc; i++)
+ *cbuf++ = *buf++;
+ rbdf->cbd_sc |= BD_SC_EMPTY;
+
+ return(nc);
+}
+
+int
+serial_tstc()
+{
+ volatile cbd_t *rbdf;
+ volatile smc_uart_t *up;
+ volatile immap_t *ip;
+
+ ip = (immap_t *)IMAP_ADDR;
+ up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
+ rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase];
+
+ return(!(rbdf->cbd_sc & BD_SC_EMPTY));
+}
+
diff --git a/arch/ppc/mbxboot/misc.c b/arch/ppc/mbxboot/misc.c
index 7ecf18512..683f53491 100644
--- a/arch/ppc/mbxboot/misc.c
+++ b/arch/ppc/mbxboot/misc.c
@@ -20,6 +20,9 @@
#ifdef CONFIG_8xx
#include <asm/mpc8xx.h>
#endif
+#ifdef CONFIG_8260
+#include <asm/mpc8260.h>
+#endif
/*
* Please send me load/board info and such data for hardware not
@@ -231,6 +234,13 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, b
unsigned long i;
char *dp;
+#ifdef CONFIG_8260
+ /* I don't know why I didn't do it this way on the 8xx.......
+ */
+ embed_config(bp);
+ serial_init(bp);
+#endif
+
/* These values must be variables. If not, the compiler optimizer
* will remove some code, causing the size of the code to vary
* when these values are zero. This is bad because we first
diff --git a/arch/ppc/mbxboot/pci.c b/arch/ppc/mbxboot/pci.c
index 72a8aa0e7..4c3332ef8 100644
--- a/arch/ppc/mbxboot/pci.c
+++ b/arch/ppc/mbxboot/pci.c
@@ -1,6 +1,7 @@
/* Stand alone funtions for QSpan Tundra support.
*/
-#include <sys/types.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
#include <linux/pci.h>
#include <asm/mpc8xx.h>
diff --git a/arch/ppc/mbxboot/qspan_pci.c b/arch/ppc/mbxboot/qspan_pci.c
index b4f332a9b..f94105b2a 100644
--- a/arch/ppc/mbxboot/qspan_pci.c
+++ b/arch/ppc/mbxboot/qspan_pci.c
@@ -9,7 +9,8 @@
* I don't know what to do about interrupts (yet).
*/
-#include <sys/types.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
#include <linux/pci.h>
#include <asm/mpc8xx.h>
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
index 562ce0295..076ee56e5 100644
--- a/arch/ppc/mm/fault.c
+++ b/arch/ppc/mm/fault.c
@@ -216,7 +216,7 @@ unsigned long va_to_phys(unsigned long address)
pte = find_pte(current->mm, address);
if (pte)
- return((unsigned long)(pte_page(*pte)) | (address & ~(PAGE_MASK-1)));
+ return(((unsigned long)(pte_val(*pte)) & PAGE_MASK) | (address & ~(PAGE_MASK-1)));
return (0);
}
@@ -237,7 +237,7 @@ print_8xx_pte(struct mm_struct *mm, unsigned long addr)
printk(" (0x%08lx)->(0x%08lx)->0x%08lx\n",
(long)pgd, (long)pte, (long)pte_val(*pte));
#define pp ((long)pte_val(*pte))
- printk(" RPN: %05x PP: %x SPS: %x SH: %lx "
+ printk(" RPN: %05lx PP: %lx SPS: %lx SH: %lx "
"CI: %lx v: %lx\n",
pp>>12, /* rpn */
(pp>>10)&3, /* pp */
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index c92abef90..80fb7575e 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -48,8 +48,14 @@
#include <asm/mmu.h>
#include <asm/residual.h>
#include <asm/uaccess.h>
+#ifdef CONFIG_8xx
#include <asm/8xx_immap.h>
#include <asm/mpc8xx.h>
+#endif
+#ifdef CONFIG_8260
+#include <asm/immap_8260.h>
+#include <asm/mpc8260.h>
+#endif
#include <asm/smp.h>
#include <asm/bootx.h>
#include <asm/machdep.h>
@@ -104,6 +110,9 @@ unsigned long *m8xx_find_end_of_memory(void);
#ifdef CONFIG_4xx
unsigned long *oak_find_end_of_memory(void);
#endif
+#ifdef CONFIG_8260
+unsigned long *m8260_find_end_of_memory(void);
+#endif /* CONFIG_8260 */
static void mapin_ram(void);
void map_page(unsigned long va, unsigned long pa, int flags);
extern void die_if_kernel(char *,struct pt_regs *,long);
@@ -725,7 +734,7 @@ static void __init mapin_ram(void)
* don't get ASID compares on kernel space.
*/
f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED;
-#ifdef CONFIG_KGDB
+#if defined(CONFIG_KGDB) || defined(CONFIG_XMON)
/* Allows stub to set breakpoints everywhere */
f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE;
#else
@@ -896,6 +905,9 @@ MMU_init(void)
mtspr(SPRN_ICCR, 0x80000000); /* 128 MB of instr. space at 0x0. */
}
#else
+ /* How about ppc_md.md_find_end_of_memory instead of these
+ * ifdefs? -- Dan.
+ */
void __init MMU_init(void)
{
if ( ppc_md.progress ) ppc_md.progress("MMU:enter", 0x111);
@@ -910,8 +922,13 @@ void __init MMU_init(void)
else if ( _machine == _MACH_gemini )
end_of_DRAM = gemini_find_end_of_memory();
#endif /* CONFIG_GEMINI */
+#if defined(CONFIG_8260)
+ else
+ end_of_DRAM = m8260_find_end_of_memory();
+#else
else /* prep */
end_of_DRAM = prep_find_end_of_memory();
+#endif
if ( ppc_md.progress ) ppc_md.progress("MMU:hash init", 0x300);
hash_init();
@@ -960,11 +977,6 @@ void __init MMU_init(void)
setbat(0, base, base, 0x100000, IO_PAGE);
}
#endif
-#if 0
-// This is bogus, BAT must be aligned.
-// setbat(0, disp_bi->dispDeviceBase, disp_bi->dispDeviceBase, 0x100000, IO_PAGE);
-// disp_bi->logicalDisplayBase = disp_bi->dispDeviceBase;
-#endif
ioremap_base = 0xf0000000;
break;
case _MACH_apus:
@@ -977,6 +989,16 @@ void __init MMU_init(void)
setbat(0, 0xf0000000, 0xf0000000, 0x10000000, IO_PAGE);
setbat(1, 0x80000000, 0x80000000, 0x10000000, IO_PAGE);
break;
+ case _MACH_8260:
+ /* Map the IMMR, plus anything else we can cover
+ * in that upper space according to the memory controller
+ * chip select mapping. Grab another bunch of space
+ * below that for stuff we can't cover in the upper.
+ */
+ setbat(0, 0xf0000000, 0xf0000000, 0x10000000, IO_PAGE);
+ setbat(1, 0xe0000000, 0xe0000000, 0x10000000, IO_PAGE);
+ ioremap_base = 0xe0000000;
+ break;
}
ioremap_bot = ioremap_base;
#else /* CONFIG_8xx */
@@ -1295,6 +1317,28 @@ unsigned long __init *gemini_find_end_of_memory(void)
}
#endif /* defined(CONFIG_GEMINI) */
+#ifdef CONFIG_8260
+/*
+ * Same hack as 8xx.
+ */
+unsigned long __init *m8260_find_end_of_memory(void)
+{
+ bd_t *binfo;
+ unsigned long *ret;
+ extern unsigned char __res[];
+
+ binfo = (bd_t *)__res;
+
+ phys_mem.regions[0].address = 0;
+ phys_mem.regions[0].size = binfo->bi_memsize;
+ phys_mem.n_regions = 1;
+
+ ret = __va(phys_mem.regions[0].size);
+ set_phys_avail(&phys_mem);
+ return ret;
+}
+#endif /* CONFIG_8260 */
+
#ifdef CONFIG_APUS
#define HARDWARE_MAPPED_SIZE (512*1024)
unsigned long __init *apus_find_end_of_memory(void)
@@ -1396,6 +1440,7 @@ static void __init hash_init(void)
case 3: /* 603 */
case 6: /* 603e */
case 7: /* 603ev */
+ case 0x0081: /* 82xx */
Hash_size = 0;
Hash_mask = 0;
break;
diff --git a/arch/ppc/xmon/Makefile b/arch/ppc/xmon/Makefile
index ba501cf35..614f3b7eb 100644
--- a/arch/ppc/xmon/Makefile
+++ b/arch/ppc/xmon/Makefile
@@ -1,6 +1,10 @@
# Makefile for xmon
O_TARGET = x.o
+ifeq ($(CONFIG_8xx),y)
+O_OBJS = start_8xx.o xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o
+else
O_OBJS = start.o xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o
+endif
include $(TOPDIR)/Rules.make
diff --git a/arch/ppc/xmon/privinst.h b/arch/ppc/xmon/privinst.h
index ec281a154..93978c027 100644
--- a/arch/ppc/xmon/privinst.h
+++ b/arch/ppc/xmon/privinst.h
@@ -1,6 +1,7 @@
/*
* Copyright (C) 1996 Paul Mackerras.
*/
+#include <linux/config.h>
#define GETREG(reg) \
static inline int get_ ## reg (void) \
@@ -38,6 +39,7 @@ GSETSPR(274, sprg2)
GSETSPR(275, sprg3)
GSETSPR(282, ear)
GSETSPR(287, pvr)
+#ifndef CONFIG_8xx
GSETSPR(528, bat0u)
GSETSPR(529, bat0l)
GSETSPR(530, bat1u)
@@ -51,6 +53,13 @@ GSETSPR(1009, hid1)
GSETSPR(1010, iabr)
GSETSPR(1013, dabr)
GSETSPR(1023, pir)
+#else
+GSETSPR(144, cmpa)
+GSETSPR(145, cmpb)
+GSETSPR(146, cmpc)
+GSETSPR(147, cmpd)
+GSETSPR(158, ictrl)
+#endif
static inline int get_sr(int n)
{
diff --git a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c
index 95b19ba47..77b6f3548 100644
--- a/arch/ppc/xmon/start.c
+++ b/arch/ppc/xmon/start.c
@@ -43,6 +43,8 @@ void buf_access(void)
sccd[3] &= ~0x80; /* reset DLAB */
}
+extern int adb_init(void);
+
void
xmon_map_scc(void)
{
@@ -59,12 +61,13 @@ xmon_map_scc(void)
/* needs to be hacked if xmon_printk is to be used
from within find_via_pmu() */
+#ifdef CONFIG_ADB_PMU
if (!via_modem && disp_bi && find_via_pmu()) {
prom_drawstring("xmon uses screen and keyboard\n");
use_screen = 1;
- return;
}
#endif
+#endif
#ifdef CHRP_ESCC
addr = 0xc1013020;
@@ -77,18 +80,11 @@ xmon_map_scc(void)
np = find_devices("mac-io");
if (np && np->n_addrs) {
macio_node = np;
- addr = np->addrs[0].address + 0x13000;
- /* use the B channel on the iMac */
- if (!xmon_use_sccb)
- addr += 0x20; /* use A channel */
+ addr = np->addrs[0].address + 0x13020;
}
base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE);
sccc = base + (addr & ~PAGE_MASK);
-#ifdef CHRP_ESCC
- sccd = sccc + (0xc1013030 - 0xc1013020);
-#else
- sccd = sccc + (0xf3013030 - 0xf3013020);
-#endif
+ sccd = sccc + 0x10;
}
else if ( _machine & _MACH_gemini )
{
@@ -133,10 +129,10 @@ xmon_write(void *handle, void *ptr, int nb)
ct = 0;
for (i = 0; i < nb; ++i) {
while ((*sccc & TXRDY) == 0) {
-#ifdef CONFIG_ADB
+#ifdef CONFIG_ADB_PMU
if (sys_ctrler == SYS_CTRLER_PMU)
pmu_poll();
-#endif /* CONFIG_ADB */
+#endif /* CONFIG_ADB_PMU */
}
c = p[i];
if (c == '\n' && !ct) {
@@ -144,7 +140,6 @@ xmon_write(void *handle, void *ptr, int nb)
ct = 1;
--i;
} else {
- prom_drawchar(c);
if (console)
printk("%c", c);
ct = 0;
@@ -156,10 +151,10 @@ xmon_write(void *handle, void *ptr, int nb)
}
int xmon_wants_key;
-int xmon_pmu_keycode;
+int xmon_adb_keycode;
#ifdef CONFIG_BOOTX_TEXT
-static int xmon_pmu_shiftstate;
+static int xmon_adb_shiftstate;
static unsigned char xmon_keytab[128] =
"asdfhgzxcv\000bqwer" /* 0x00 - 0x0f */
@@ -178,13 +173,13 @@ static unsigned char xmon_shift_keytab[128] =
"\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
static int
-xmon_get_pmu_key(void)
+xmon_get_adb_key(void)
{
int k, t, on;
xmon_wants_key = 1;
for (;;) {
- xmon_pmu_keycode = -1;
+ xmon_adb_keycode = -1;
t = 0;
on = 0;
do {
@@ -194,20 +189,22 @@ xmon_get_pmu_key(void)
prom_drawchar('\b');
t = 200000;
}
+#ifdef CONFIG_ADB_PMU
pmu_poll();
- } while (xmon_pmu_keycode == -1);
- k = xmon_pmu_keycode;
+#endif /* CONFIG_ADB_PMU */
+ } while (xmon_adb_keycode == -1);
+ k = xmon_adb_keycode;
if (on)
prom_drawstring(" \b");
/* test for shift keys */
if ((k & 0x7f) == 0x38 || (k & 0x7f) == 0x7b) {
- xmon_pmu_shiftstate = (k & 0x80) == 0;
+ xmon_adb_shiftstate = (k & 0x80) == 0;
continue;
}
if (k >= 0x80)
continue; /* ignore up transitions */
- k = (xmon_pmu_shiftstate? xmon_shift_keytab: xmon_keytab)[k];
+ k = (xmon_adb_shiftstate? xmon_shift_keytab: xmon_keytab)[k];
if (k != 0)
break;
}
@@ -225,7 +222,7 @@ xmon_read(void *handle, void *ptr, int nb)
#ifdef CONFIG_BOOTX_TEXT
if (use_screen) {
for (i = 0; i < nb; ++i)
- *p++ = xmon_get_pmu_key();
+ *p++ = xmon_get_adb_key();
return i;
}
#endif
@@ -233,12 +230,12 @@ xmon_read(void *handle, void *ptr, int nb)
xmon_init_scc();
for (i = 0; i < nb; ++i) {
while ((*sccc & RXRDY) == 0)
-#ifdef CONFIG_ADB
+#ifdef CONFIG_ADB_PMU
if (sys_ctrler == SYS_CTRLER_PMU)
pmu_poll();
#else
;
-#endif /* CONFIG_ADB */
+#endif /* CONFIG_ADB_PMU */
buf_access();
*p++ = *sccd;
}
@@ -249,12 +246,10 @@ int
xmon_read_poll(void)
{
if ((*sccc & RXRDY) == 0) {
-#ifdef CONFIG_ADB
+#ifdef CONFIG_ADB_PMU
if (sys_ctrler == SYS_CTRLER_PMU)
pmu_poll();
-#else
- ;
-#endif
+#endif /* CONFIG_ADB_PMU */
return -1;
}
buf_access();
@@ -297,6 +292,12 @@ xmon_init_scc()
while (readtb() - t0 < 3*TB_SPEED)
eieio();
}
+ /* use the B channel if requested */
+ if (xmon_use_sccb) {
+ sccc = (volatile unsigned char *)
+ ((unsigned long)sccc & ~0x20);
+ sccd = sccc + 0x10;
+ }
for (i = 20000; i != 0; --i) {
x = *sccc; eieio();
}
diff --git a/arch/ppc/xmon/start_8xx.c b/arch/ppc/xmon/start_8xx.c
new file mode 100644
index 000000000..e698d9575
--- /dev/null
+++ b/arch/ppc/xmon/start_8xx.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 1996 Paul Mackerras.
+ * Copyright (C) 2000 Dan Malek.
+ * Quick hack of Paul's code to make XMON work on 8xx processors. Lots
+ * of assumptions, like the SMC1 is used, it has been initialized by the
+ * loader at some point, and we can just stuff and suck bytes.
+ * We rely upon the 8xx uart driver to support us, as the interface
+ * changes between boot up and operational phases of the kernel.
+ */
+#include <linux/string.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <linux/kernel.h>
+#include <asm/processor.h>
+#include <asm/8xx_immap.h>
+#include <asm/mpc8xx.h>
+#include "commproc.h"
+
+extern void xmon_printf(const char *fmt, ...);
+extern int xmon_8xx_write(char *str, int nb);
+extern int xmon_8xx_read_poll(void);
+extern int xmon_8xx_read_char(void);
+void prom_drawhex(uint);
+void prom_drawstring(const char *str);
+
+static int use_screen = 1; /* default */
+
+#define TB_SPEED 25000000
+
+static inline unsigned int readtb(void)
+{
+ unsigned int ret;
+
+ asm volatile("mftb %0" : "=r" (ret) :);
+ return ret;
+}
+
+void buf_access(void)
+{
+}
+
+void
+xmon_map_scc(void)
+{
+
+ cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
+ use_screen = 0;
+
+ prom_drawstring("xmon uses serial port\n");
+}
+
+static int scc_initialized = 0;
+
+void xmon_init_scc(void);
+
+int
+xmon_write(void *handle, void *ptr, int nb)
+{
+ char *p = ptr;
+ int i, c, ct;
+
+ if (!scc_initialized)
+ xmon_init_scc();
+
+ return(xmon_8xx_write(ptr, nb));
+}
+
+int xmon_wants_key;
+
+int
+xmon_read(void *handle, void *ptr, int nb)
+{
+ char *p = ptr;
+ int i;
+
+ if (!scc_initialized)
+ xmon_init_scc();
+
+ for (i = 0; i < nb; ++i) {
+ *p++ = xmon_8xx_read_char();
+ }
+ return i;
+}
+
+int
+xmon_read_poll(void)
+{
+ return(xmon_8xx_read_poll());
+}
+
+void
+xmon_init_scc()
+{
+ scc_initialized = 1;
+}
+
+#if 0
+extern int (*prom_entry)(void *);
+
+int
+xmon_exit(void)
+{
+ struct prom_args {
+ char *service;
+ } args;
+
+ for (;;) {
+ args.service = "exit";
+ (*prom_entry)(&args);
+ }
+}
+#endif
+
+void *xmon_stdin;
+void *xmon_stdout;
+void *xmon_stderr;
+
+void
+xmon_init(void)
+{
+}
+
+int
+xmon_putc(int c, void *f)
+{
+ char ch = c;
+
+ if (c == '\n')
+ xmon_putc('\r', f);
+ return xmon_write(f, &ch, 1) == 1? c: -1;
+}
+
+int
+xmon_putchar(int c)
+{
+ return xmon_putc(c, xmon_stdout);
+}
+
+int
+xmon_fputs(char *str, void *f)
+{
+ int n = strlen(str);
+
+ return xmon_write(f, str, n) == n? 0: -1;
+}
+
+int
+xmon_readchar(void)
+{
+ char ch;
+
+ for (;;) {
+ switch (xmon_read(xmon_stdin, &ch, 1)) {
+ case 1:
+ return ch;
+ case -1:
+ xmon_printf("read(stdin) returned -1\r\n", 0, 0);
+ return -1;
+ }
+ }
+}
+
+static char line[256];
+static char *lineptr;
+static int lineleft;
+
+#if 0
+int xmon_expect(const char *str, unsigned int timeout)
+{
+ int c;
+ unsigned int t0;
+
+ timeout *= TB_SPEED;
+ t0 = readtb();
+ do {
+ lineptr = line;
+ for (;;) {
+ c = xmon_read_poll();
+ if (c == -1) {
+ if (readtb() - t0 > timeout)
+ return 0;
+ continue;
+ }
+ if (c == '\n')
+ break;
+ if (c != '\r' && lineptr < &line[sizeof(line) - 1])
+ *lineptr++ = c;
+ }
+ *lineptr = 0;
+ } while (strstr(line, str) == NULL);
+ return 1;
+}
+#endif
+
+int
+xmon_getchar(void)
+{
+ int c;
+
+ if (lineleft == 0) {
+ lineptr = line;
+ for (;;) {
+ c = xmon_readchar();
+ if (c == -1 || c == 4)
+ break;
+ if (c == '\r' || c == '\n') {
+ *lineptr++ = '\n';
+ xmon_putchar('\n');
+ break;
+ }
+ switch (c) {
+ case 0177:
+ case '\b':
+ if (lineptr > line) {
+ xmon_putchar('\b');
+ xmon_putchar(' ');
+ xmon_putchar('\b');
+ --lineptr;
+ }
+ break;
+ case 'U' & 0x1F:
+ while (lineptr > line) {
+ xmon_putchar('\b');
+ xmon_putchar(' ');
+ xmon_putchar('\b');
+ --lineptr;
+ }
+ break;
+ default:
+ if (lineptr >= &line[sizeof(line) - 1])
+ xmon_putchar('\a');
+ else {
+ xmon_putchar(c);
+ *lineptr++ = c;
+ }
+ }
+ }
+ lineleft = lineptr - line;
+ lineptr = line;
+ }
+ if (lineleft == 0)
+ return -1;
+ --lineleft;
+ return *lineptr++;
+}
+
+char *
+xmon_fgets(char *str, int nb, void *f)
+{
+ char *p;
+ int c;
+
+ for (p = str; p < str + nb - 1; ) {
+ c = xmon_getchar();
+ if (c == -1) {
+ if (p == str)
+ return 0;
+ break;
+ }
+ *p++ = c;
+ if (c == '\n')
+ break;
+ }
+ *p = 0;
+ return str;
+}
+
+void
+prom_drawhex(uint val)
+{
+ unsigned char buf[10];
+
+ int i;
+ for (i = 7; i >= 0; i--)
+ {
+ buf[i] = "0123456789abcdef"[val & 0x0f];
+ val >>= 4;
+ }
+ buf[8] = '\0';
+ xmon_fputs(buf, xmon_stdout);
+}
+
+void
+prom_drawstring(const char *str)
+{
+ xmon_fputs(str, xmon_stdout);
+}
diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c
index b81e21890..9cc302840 100644
--- a/arch/ppc/xmon/xmon.c
+++ b/arch/ppc/xmon/xmon.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 1996 Paul Mackerras.
*/
+#include <linux/config.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <asm/ptrace.h>
@@ -120,8 +121,7 @@ void
xmon(struct pt_regs *excp)
{
struct pt_regs regs;
- int msr, cmd, i;
- unsigned *sp;
+ int msr, cmd;
if (excp == NULL) {
asm volatile ("stw 0,0(%0)\n\
@@ -137,29 +137,6 @@ xmon(struct pt_regs *excp)
excp = &regs;
}
- prom_drawstring("xmon pc="); prom_drawhex(excp->nip);
- prom_drawstring(" lr="); prom_drawhex(excp->link);
- prom_drawstring(" msr="); prom_drawhex(excp->msr);
- prom_drawstring(" trap="); prom_drawhex(excp->trap);
- prom_drawstring(" sp="); prom_drawhex(excp->gpr[1]);
- sp = (unsigned *)&excp->gpr[0];
- for (i = 0; i < 32; ++i) {
- if ((i & 7) == 0)
- prom_drawstring("\n");
- prom_drawstring(" ");
- prom_drawhex(sp[i]);
- }
- sp = (unsigned *) excp->gpr[1];
- for (i = 0; i < 64; ++i) {
- if ((i & 7) == 0) {
- prom_drawstring("\n");
- prom_drawhex(sp);
- prom_drawstring(" ");
- }
- prom_drawstring(" ");
- prom_drawhex(sp[i]);
- }
- prom_drawstring("\n");
msr = get_msr();
set_msr(msr & ~0x8000); /* disable interrupts */
remove_bpts();
@@ -284,10 +261,12 @@ insert_bpts()
bp->enabled = 0;
}
}
+#ifndef CONFIG_8xx
if (dabr.enabled)
set_dabr(dabr.address);
if (iabr.enabled)
set_iabr(iabr.address);
+#endif
}
static void
@@ -297,8 +276,10 @@ remove_bpts()
struct bpt *bp;
unsigned instr;
+#ifndef CONFIG_8xx
set_dabr(0);
set_iabr(0);
+#endif
bp = bpts;
for (i = 0; i < NBPTS; ++i, ++bp) {
if (!bp->enabled)
@@ -412,6 +393,7 @@ bpt_cmds(void)
cmd = inchar();
switch (cmd) {
+#ifndef CONFIG_8xx
case 'd':
mode = 7;
cmd = inchar();
@@ -436,6 +418,7 @@ bpt_cmds(void)
iabr.address |= 3;
scanhex(&iabr.count);
break;
+#endif
case 'c':
if (!scanhex(&a)) {
/* clear all breakpoints */
@@ -1406,6 +1389,7 @@ static char *lookup_name(unsigned long addr)
return NULL;
#if 0
cmp = simple_strtoul(c, &c, 8);
+ /* XXX crap, we don't want the whole of the rest of the map - paulus */
strcpy( last, strsep( &c, "\n"));
while ( c < (sysmap+sysmap_size) )
{
@@ -1414,7 +1398,7 @@ return NULL;
break;
strcpy( last, strsep( &c, "\n"));
}
- return NULLlast;
+ return last;
#endif
}