summaryrefslogtreecommitdiffstats
path: root/arch/ppc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc')
-rw-r--r--arch/ppc/8260_io/Config.in15
-rw-r--r--arch/ppc/8260_io/Makefile4
-rw-r--r--arch/ppc/8260_io/commproc.c34
-rw-r--r--arch/ppc/8260_io/enet.c21
-rw-r--r--arch/ppc/8260_io/fcc_enet.c1601
-rw-r--r--arch/ppc/8260_io/uart.c23
-rw-r--r--arch/ppc/8xx_io/enet.c11
-rw-r--r--arch/ppc/8xx_io/fec.c9
-rw-r--r--arch/ppc/amiga/time.c36
-rw-r--r--arch/ppc/chrpboot/Makefile6
-rw-r--r--arch/ppc/chrpboot/addnote.c13
-rw-r--r--arch/ppc/coffboot/Makefile2
-rw-r--r--arch/ppc/coffboot/chrpmain.c65
-rw-r--r--arch/ppc/config.in58
-rw-r--r--arch/ppc/configs/common_defconfig207
-rw-r--r--arch/ppc/configs/est8260_defconfig70
-rw-r--r--arch/ppc/configs/gemini_defconfig93
-rw-r--r--arch/ppc/configs/rpxcllf_defconfig68
-rw-r--r--arch/ppc/defconfig210
-rw-r--r--arch/ppc/kernel/Makefile6
-rw-r--r--arch/ppc/kernel/apus_setup.c16
-rw-r--r--arch/ppc/kernel/chrp_pci.c95
-rw-r--r--arch/ppc/kernel/chrp_setup.c144
-rw-r--r--arch/ppc/kernel/chrp_time.c50
-rw-r--r--arch/ppc/kernel/entry.S49
-rw-r--r--arch/ppc/kernel/feature.c175
-rw-r--r--arch/ppc/kernel/gemini_setup.c4
-rw-r--r--arch/ppc/kernel/hashtable.S6
-rw-r--r--arch/ppc/kernel/head.S180
-rw-r--r--arch/ppc/kernel/head_8xx.S45
-rw-r--r--arch/ppc/kernel/idle.c1
-rw-r--r--arch/ppc/kernel/irq.c28
-rw-r--r--arch/ppc/kernel/m8260_setup.c23
-rw-r--r--arch/ppc/kernel/m8xx_setup.c62
-rw-r--r--arch/ppc/kernel/misc.S103
-rw-r--r--arch/ppc/kernel/mol.h68
-rw-r--r--arch/ppc/kernel/oak_setup.c3
-rw-r--r--arch/ppc/kernel/open_pic.c12
-rw-r--r--arch/ppc/kernel/pci.c427
-rw-r--r--arch/ppc/kernel/pmac_backlight.c18
-rw-r--r--arch/ppc/kernel/pmac_nvram.c14
-rw-r--r--arch/ppc/kernel/pmac_pci.c32
-rw-r--r--arch/ppc/kernel/pmac_pic.c9
-rw-r--r--arch/ppc/kernel/pmac_setup.c83
-rw-r--r--arch/ppc/kernel/pmac_time.c65
-rw-r--r--arch/ppc/kernel/ppc-stub.c6
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c44
-rw-r--r--arch/ppc/kernel/prep_setup.c107
-rw-r--r--arch/ppc/kernel/prep_time.c46
-rw-r--r--arch/ppc/kernel/process.c31
-rw-r--r--arch/ppc/kernel/prom.c230
-rw-r--r--arch/ppc/kernel/setup.c14
-rw-r--r--arch/ppc/kernel/signal.c13
-rw-r--r--arch/ppc/kernel/smp.c343
-rw-r--r--arch/ppc/kernel/syscalls.c24
-rw-r--r--arch/ppc/kernel/time.c357
-rw-r--r--arch/ppc/kernel/traps.c144
-rw-r--r--arch/ppc/kernel/walnut_setup.c3
-rw-r--r--arch/ppc/kernel/xics.c2
-rw-r--r--arch/ppc/lib/string.S247
-rw-r--r--arch/ppc/mbxboot/misc.c5
-rw-r--r--arch/ppc/mm/extable.c48
-rw-r--r--arch/ppc/mm/fault.c4
-rw-r--r--arch/ppc/mm/init.c322
-rw-r--r--arch/ppc/xmon/start.c66
-rw-r--r--arch/ppc/xmon/xmon.c180
66 files changed, 4829 insertions, 1671 deletions
diff --git a/arch/ppc/8260_io/Config.in b/arch/ppc/8260_io/Config.in
index 8cdd8c615..4db16a068 100644
--- a/arch/ppc/8260_io/Config.in
+++ b/arch/ppc/8260_io/Config.in
@@ -11,12 +11,15 @@ if [ "$CONFIG_NET_ETHERNET" = "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
+#
+# CONFIG_FEC_ENET is only used to get netdevices to call our init
+# function. Any combination of FCC1,2,3 are supported.
+#
+ bool 'FCC Ethernet' CONFIG_FEC_ENET
+ if [ "$CONFIG_FEC_ENET" = "y" ]; then
+ bool 'Ethernet on FCC1' CONFIG_FCC1_ENET
+ bool 'Ethernet on FCC2' CONFIG_FCC2_ENET
+ bool 'Ethernet on FCC3' CONFIG_FCC3_ENET
fi
endmenu
fi
diff --git a/arch/ppc/8260_io/Makefile b/arch/ppc/8260_io/Makefile
index 240a85628..8de47b144 100644
--- a/arch/ppc/8260_io/Makefile
+++ b/arch/ppc/8260_io/Makefile
@@ -10,8 +10,8 @@
O_TARGET := 8260_io.a
O_OBJS = commproc.o uart.o
-ifdef CONFIG_FCC_ENET
-O_OBJS += fcc.o
+ifdef CONFIG_FEC_ENET
+O_OBJS += fcc_enet.o
endif
ifdef CONFIG_SCC_ENET
O_OBJS += enet.o
diff --git a/arch/ppc/8260_io/commproc.c b/arch/ppc/8260_io/commproc.c
index 8642fa420..b7c13b167 100644
--- a/arch/ppc/8260_io/commproc.c
+++ b/arch/ppc/8260_io/commproc.c
@@ -69,17 +69,27 @@ m8260_cpm_reset(void)
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.
+/* Allocate some memory from the dual ported ram.
+ * To help protocols with object alignment restrictions, we do that
+ * if they ask.
*/
uint
-m8260_cpm_dpalloc(uint size)
+m8260_cpm_dpalloc(uint size, uint align)
{
uint retloc;
+ uint align_mask, off;
+ uint savebase;
- if ((dp_alloc_base + size) >= dp_alloc_top)
+ align_mask = align - 1;
+ savebase = dp_alloc_base;
+
+ if ((off = (dp_alloc_base & align_mask)) != 0)
+ dp_alloc_base += (align - off);
+
+ if ((dp_alloc_base + size) >= dp_alloc_top) {
+ dp_alloc_base = savebase;
return(CPM_DP_NOSPACE);
+ }
retloc = dp_alloc_base;
dp_alloc_base += size;
@@ -91,12 +101,22 @@ m8260_cpm_dpalloc(uint size)
* UART "fifos" and the like.
*/
uint
-m8260_cpm_hostalloc(uint size)
+m8260_cpm_hostalloc(uint size, uint align)
{
uint retloc;
+ uint align_mask, off;
+ uint savebase;
- if ((host_buffer + size) >= host_end)
+ align_mask = align - 1;
+ savebase = host_buffer;
+
+ if ((off = (host_buffer & align_mask)) != 0)
+ host_buffer += (align - off);
+
+ if ((host_buffer + size) >= host_end) {
+ host_buffer = savebase;
return(0);
+ }
retloc = host_buffer;
host_buffer += size;
diff --git a/arch/ppc/8260_io/enet.c b/arch/ppc/8260_io/enet.c
index 4c8c672fd..e1ff3c092 100644
--- a/arch/ppc/8260_io/enet.c
+++ b/arch/ppc/8260_io/enet.c
@@ -466,8 +466,11 @@ for (;;) {
cep->stats.rx_bytes += pkt_len;
/* This does 16 byte alignment, much more than we need.
- */
- skb = dev_alloc_skb(pkt_len);
+ * The packet length includes FCS, but we don't want to
+ * include that when passing upstream as it messes up
+ * bridging applications.
+ */
+ skb = dev_alloc_skb(pkt_len-4);
if (skb == NULL) {
printk("%s: Memory squeeze, dropping packet.\n", dev->name);
@@ -475,10 +478,10 @@ for (;;) {
}
else {
skb->dev = dev;
- skb_put(skb,pkt_len); /* Make room */
+ skb_put(skb,pkt_len-4); /* Make room */
eth_copy_and_sum(skb,
(unsigned char *)__va(bdp->cbd_bufaddr),
- pkt_len, 0);
+ pkt_len-4, 0);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
}
@@ -549,10 +552,10 @@ static void set_multicast_list(struct net_device *dev)
/* Log any net taps. */
printk("%s: Promiscuous mode enabled.\n", dev->name);
- cep->sccp->scc_pmsr |= SCC_PMSR_PRO;
+ cep->sccp->scc_pmsr |= SCC_PSMR_PRO;
} else {
- cep->sccp->scc_pmsr &= ~SCC_PMSR_PRO;
+ cep->sccp->scc_pmsr &= ~SCC_PSMR_PRO;
if (dev->flags & IFF_ALLMULTI) {
/* Catch all multicast addresses, so set the
@@ -678,11 +681,11 @@ int __init scc_enet_init(void)
* 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);
+ i = m8260_cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
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);
+ i = m8260_cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
ep->sen_genscc.scc_tbase = i;
cep->tx_bd_base = (cbd_t *)&immap->im_dprambase[i];
@@ -816,7 +819,7 @@ int __init scc_enet_init(void)
/* 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);
+ sccp->scc_pmsr = (SCC_PSMR_ENCRC | SCC_PSMR_NIB22);
/* It is now OK to enable the Ethernet transmitter.
* Unfortunately, there are board implementation differences here.
diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
new file mode 100644
index 000000000..da3991ae3
--- /dev/null
+++ b/arch/ppc/8260_io/fcc_enet.c
@@ -0,0 +1,1601 @@
+/*
+ * Fast Ethernet Controller (FCC) driver for Motorola MPC8260.
+ * Copyright (c) 2000 MontaVista Software, Inc. Dan Malek (dmalek@jlc.net)
+ *
+ * This version of the driver is a combination of the 8xx fec and
+ * 8260 SCC Ethernet drivers. People seem to be choosing common I/O
+ * configurations, so this driver will work on the EST8260 boards and
+ * others yet to be announced.
+ *
+ * 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/config.h>
+#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/irq.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/cpm_8260.h>
+
+/* 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 it best
+ * to keep them that size.
+ * We don't need to allocate pages for the transmitter. We just use
+ * the skbuffer directly.
+ */
+#define FCC_ENET_RX_PAGES 16
+#define FCC_ENET_RX_FRSIZE 2048
+#define FCC_ENET_RX_FRPPG (PAGE_SIZE / FCC_ENET_RX_FRSIZE)
+#define RX_RING_SIZE (FCC_ENET_RX_FRPPG * FCC_ENET_RX_PAGES)
+#define TX_RING_SIZE 16 /* Must be power of two */
+#define TX_RING_MOD_MASK 15 /* for this to work */
+
+/* The FCC stores dest/src/type, data, and checksum for receive packets.
+ */
+#define PKT_MAXBUF_SIZE 1518
+#define PKT_MINBUF_SIZE 64
+
+/* Maximum input DMA size. Must be a should(?) be a multiple of 4.
+*/
+#define PKT_MAXDMA_SIZE 1520
+
+/* Maximum input buffer size. Must be a multiple of 32.
+*/
+#define PKT_MAXBLR_SIZE 1536
+
+static int fcc_enet_open(struct net_device *dev);
+static int fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int fcc_enet_rx(struct net_device *dev);
+static void fcc_enet_mii(struct net_device *dev);
+static void fcc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
+static int fcc_enet_close(struct net_device *dev);
+static struct net_device_stats *fcc_enet_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+static void restart_fcc(struct net_device *dev);
+
+/* These will be configurable for the FCC choice.
+ * Multiple ports can be configured. There is little choice among the
+ * I/O pins to the PHY, except the clocks. We will need some board
+ * dependent clock selection.
+ * Why in the hell did I put these inside #ifdef's? I dunno, maybe to
+ * help show what pins are used for each device.
+ */
+
+/* I/O Pin assignment for FCC1. I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PA1_COL ((uint)0x00000001)
+#define PA1_CRS ((uint)0x00000002)
+#define PA1_TXER ((uint)0x00000004)
+#define PA1_TXEN ((uint)0x00000008)
+#define PA1_RXDV ((uint)0x00000010)
+#define PA1_RXER ((uint)0x00000020)
+#define PA1_TXDAT ((uint)0x00003c00)
+#define PA1_RXDAT ((uint)0x0003c000)
+#define PA1_PSORA0 (PA1_RXDAT | PA1_TXDAT)
+#define PA1_PSORA1 (PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
+ PA1_RXDV | PA1_RXER)
+#define PA1_DIRA0 (PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV)
+#define PA1_DIRA1 (PA1_TXDAT | PA1_TXEN | PA1_TXER)
+
+/* CLK12 is receive, CLK11 is transmit. These are board specific.
+*/
+#define PC_F1RXCLK ((uint)0x00000800)
+#define PC_F1TXCLK ((uint)0x00000400)
+#define CMX1_CLK_ROUTE ((uint)0x3e000000)
+#define CMX1_CLK_MASK ((uint)0xff000000)
+
+/* I/O Pin assignment for FCC2. I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PB2_TXER ((uint)0x00000001)
+#define PB2_RXDV ((uint)0x00000002)
+#define PB2_TXEN ((uint)0x00000004)
+#define PB2_RXER ((uint)0x00000008)
+#define PB2_COL ((uint)0x00000010)
+#define PB2_CRS ((uint)0x00000020)
+#define PB2_TXDAT ((uint)0x000003c0)
+#define PB2_RXDAT ((uint)0x00003c00)
+#define PB2_PSORB0 (PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
+ PB2_RXER | PB2_RXDV | PB2_TXER)
+#define PB2_PSORB1 (PB2_TXEN)
+#define PB2_DIRB0 (PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV)
+#define PB2_DIRB1 (PB2_TXDAT | PB2_TXEN | PB2_TXER)
+
+/* CLK13 is receive, CLK14 is transmit. These are board dependent.
+*/
+#define PC_F2RXCLK ((uint)0x00001000)
+#define PC_F2TXCLK ((uint)0x00002000)
+#define CMX2_CLK_ROUTE ((uint)0x00250000)
+#define CMX2_CLK_MASK ((uint)0x00ff0000)
+
+/* I/O Pin assignment for FCC3. I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PB3_RXDV ((uint)0x00004000)
+#define PB3_RXER ((uint)0x00008000)
+#define PB3_TXER ((uint)0x00010000)
+#define PB3_TXEN ((uint)0x00020000)
+#define PB3_COL ((uint)0x00040000)
+#define PB3_CRS ((uint)0x00080000)
+#define PB3_TXDAT ((uint)0x0f000000)
+#define PB3_RXDAT ((uint)0x00f00000)
+#define PB3_PSORB0 (PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
+ PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN)
+#define PB3_PSORB1 (0)
+#define PB3_DIRB0 (PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV)
+#define PB3_DIRB1 (PB3_TXDAT | PB3_TXEN | PB3_TXER)
+
+/* CLK15 is receive, CLK16 is transmit. These are board dependent.
+*/
+#define PC_F3RXCLK ((uint)0x00004000)
+#define PC_F3TXCLK ((uint)0x00008000)
+#define CMX3_CLK_ROUTE ((uint)0x00003700)
+#define CMX3_CLK_MASK ((uint)0x0000ff00)
+
+/* MII status/control serial interface.
+*/
+#define PC_MDIO ((uint)0x00400000)
+#define PC_MDCK ((uint)0x00200000)
+
+/* A table of information for supporting FCCs. This does two things.
+ * First, we know how many FCCs we have and they are always externally
+ * numbered from zero. Second, it holds control register and I/O
+ * information that could be different among board designs.
+ */
+typedef struct fcc_info {
+ uint fc_fccnum;
+ uint fc_cpmblock;
+ uint fc_cpmpage;
+ uint fc_proff;
+ uint fc_interrupt;
+ uint fc_trxclocks;
+ uint fc_clockroute;
+ uint fc_clockmask;
+ uint fc_mdio;
+ uint fc_mdck;
+} fcc_info_t;
+
+static fcc_info_t fcc_ports[] = {
+#ifdef CONFIG_FCC1_ENET
+ { 0, CPM_CR_FCC1_SBLOCK, CPM_CR_FCC1_PAGE, PROFF_FCC1, SIU_INT_FCC1,
+ (PC_F1RXCLK | PC_F1TXCLK), CMX1_CLK_ROUTE, CMX1_CLK_MASK,
+ PC_MDIO, PC_MDCK },
+#endif
+#ifdef CONFIG_FCC2_ENET
+ { 1, CPM_CR_FCC2_SBLOCK, CPM_CR_FCC2_PAGE, PROFF_FCC2, SIU_INT_FCC2,
+ (PC_F2RXCLK | PC_F2TXCLK), CMX2_CLK_ROUTE, CMX2_CLK_MASK,
+ PC_MDIO, PC_MDCK },
+#endif
+#ifdef CONFIG_FCC3_ENET
+ { 2, CPM_CR_FCC3_SBLOCK, CPM_CR_FCC3_PAGE, PROFF_FCC3, SIU_INT_FCC3,
+ (PC_F3RXCLK | PC_F3TXCLK), CMX3_CLK_ROUTE, CMX3_CLK_MASK,
+ PC_MDIO, PC_MDCK },
+#endif
+};
+
+/* The FCC 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 fcc_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. */
+ volatile fcc_t *fccp;
+ volatile fcc_enet_t *ep;
+ struct net_device_stats stats;
+ uint tx_full;
+ spinlock_t lock;
+ uint phy_address;
+ uint phy_type;
+ uint phy_duplex;
+ fcc_info_t *fip;
+};
+
+static void init_fcc_shutdown(fcc_info_t *fip, struct fcc_enet_private *cep,
+ volatile immap_t *immap);
+static void init_fcc_startup(fcc_info_t *fip, struct net_device *dev);
+static void init_fcc_ioports(fcc_info_t *fip, volatile iop8260_t *io,
+ volatile immap_t *immap);
+static void init_fcc_param(fcc_info_t *fip, struct net_device *dev,
+ volatile immap_t *immap);
+
+/* MII processing. We keep this as simple as possible. Requests are
+ * placed on the list (if there is room). When the request is finished
+ * by the MII, an optional function may be called.
+ */
+typedef struct mii_list {
+ uint mii_regval;
+ void (*mii_func)(uint val, struct net_device *dev);
+ struct mii_list *mii_next;
+} mii_list_t;
+
+#define NMII 20
+mii_list_t mii_cmds[NMII];
+mii_list_t *mii_free;
+mii_list_t *mii_head;
+mii_list_t *mii_tail;
+
+static int phyaddr;
+static uint phytype;
+
+static int mii_queue(int request, void (*func)(uint, struct net_device *));
+static void mii_startup_cmds(void);
+static uint mii_send_receive(fcc_info_t *fip, uint cmd);
+
+/* Make MII read/write commands for the FCC.
+*/
+
+#define mk_mii_phyaddr(ADDR) (0x60020000 | ((ADDR) << 23) | (2 << 18))
+
+#define mk_mii_read(REG) (0x60020000 | ((phyaddr << 23) | \
+ (REG & 0x1f) << 18))
+
+#define mk_mii_write(REG, VAL) (0x50020000 | ((phyaddr << 23) | \
+ (REG & 0x1f) << 18) | \
+ (VAL & 0xffff))
+
+
+static int
+fcc_enet_open(struct net_device *dev)
+{
+ netif_start_queue(dev);
+ return 0; /* Always succeed */
+}
+
+static int
+fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct fcc_enet_private *cep = (struct fcc_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_full 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;
+
+ 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);
+
+#if 0
+ /* Errata says don't do this.
+ */
+ cep->fccp->fcc_ftodr = 0x8000;
+#endif
+ 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->tx_full = 1;
+ }
+
+ cep->cur_tx = (cbd_t *)bdp;
+
+ spin_unlock_irq(&cep->lock);
+
+ return 0;
+}
+
+
+static void
+fcc_enet_timeout(struct net_device *dev)
+{
+ struct fcc_enet_private *cep = (struct fcc_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;
+ printk(" Tx @base %p :\n", bdp);
+ 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;
+ printk(" Rx @base %p :\n", bdp);
+ 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.
+ */
+static void
+fcc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+ struct net_device *dev = dev_id;
+ volatile struct fcc_enet_private *cep;
+ volatile cbd_t *bdp;
+ ushort int_events;
+ int must_restart;
+
+ cep = (struct fcc_enet_private *)dev->priv;
+
+ /* Get the interrupt events that caused us to be here.
+ */
+ int_events = cep->fccp->fcc_fcce;
+ cep->fccp->fcc_fcce = int_events;
+ must_restart = 0;
+
+ /* Handle receive event in its own function.
+ */
+ if (int_events & FCC_ENET_RXF)
+ fcc_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 & (FCC_ENET_TXE | FCC_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) {
+ cep->tx_full = 0;
+ 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(cep->fip->fc_cpmpage, cep->fip->fc_cpmblock,
+ 0x0c, 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.
+ */
+ if (int_events & FCC_ENET_BSY) {
+ cep->stats.rx_dropped++;
+ }
+ 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
+fcc_enet_rx(struct net_device *dev)
+{
+ struct fcc_enet_private *cep;
+ volatile cbd_t *bdp;
+ struct sk_buff *skb;
+ ushort pkt_len;
+
+ cep = (struct fcc_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.
+ * The packet length includes FCS, but we don't want to
+ * include that when passing upstream as it messes up
+ * bridging applications.
+ */
+ skb = dev_alloc_skb(pkt_len-4);
+
+ 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-4); /* Make room */
+ eth_copy_and_sum(skb,
+ (unsigned char *)__va(bdp->cbd_bufaddr),
+ pkt_len-4, 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
+fcc_enet_close(struct net_device *dev)
+{
+ /* Don't know what to do yet.
+ */
+ netif_stop_queue(dev);
+
+ return 0;
+}
+
+static struct net_device_stats *fcc_enet_get_stats(struct net_device *dev)
+{
+ struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
+
+ return &cep->stats;
+}
+
+/* The MII is simulated from the 8xx FEC implementation. The FCC
+ * is not responsible for the MII control/status interface.
+ */
+static void
+fcc_enet_mii(struct net_device *dev)
+{
+ struct fcc_enet_private *fep;
+ mii_list_t *mip;
+ uint mii_reg;
+
+ fep = (struct fcc_enet_private *)dev->priv;
+#if 0
+ ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec);
+ mii_reg = ep->fec_mii_data;
+#endif
+
+ if ((mip = mii_head) == NULL) {
+ printk("MII and no head!\n");
+ return;
+ }
+
+ if (mip->mii_func != NULL)
+ (*(mip->mii_func))(mii_reg, dev);
+
+ mii_head = mip->mii_next;
+ mip->mii_next = mii_free;
+ mii_free = mip;
+
+#if 0
+ if ((mip = mii_head) != NULL)
+ ep->fec_mii_data = mip->mii_regval;
+#endif
+}
+
+static int
+mii_queue(int regval, void (*func)(uint, struct net_device *))
+{
+ unsigned long flags;
+ mii_list_t *mip;
+ int retval;
+
+ retval = 0;
+
+ save_flags(flags);
+ cli();
+
+ if ((mip = mii_free) != NULL) {
+ mii_free = mip->mii_next;
+ mip->mii_regval = regval;
+ mip->mii_func = func;
+ mip->mii_next = NULL;
+ if (mii_head) {
+ mii_tail->mii_next = mip;
+ mii_tail = mip;
+ }
+ else {
+ mii_head = mii_tail = mip;
+#if 0
+ (&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec))->fec_mii_data = regval;
+#endif
+ }
+ }
+ else {
+ retval = 1;
+ }
+
+ restore_flags(flags);
+
+ return(retval);
+}
+
+static volatile uint full_duplex;
+
+static void
+mii_status(uint mii_reg, struct net_device *dev)
+{
+ volatile uint prev_duplex;
+
+ if (((mii_reg >> 18) & 0x1f) == 1) {
+ /* status register.
+ */
+ printk("fec: ");
+ if (mii_reg & 0x0004)
+ printk("link up");
+ else
+ printk("link down");
+
+ if (mii_reg & 0x0010)
+ printk(",remote fault");
+ if (mii_reg & 0x0020)
+ printk(",auto complete");
+ printk("\n");
+ }
+ if (((mii_reg >> 18) & 0x1f) == 0x14) {
+ /* Extended chip status register.
+ */
+ prev_duplex = full_duplex;
+ printk("fec: ");
+ if (mii_reg & 0x0800)
+ printk("100 Mbps");
+ else
+ printk("10 Mbps");
+
+ if (mii_reg & 0x1000) {
+ printk(", Full-Duplex\n");
+ full_duplex = 1;
+ }
+ else {
+ printk(", Half-Duplex\n");
+ full_duplex = 0;
+ }
+#if 0
+ if (prev_duplex != full_duplex)
+ restart_fec(dev);
+#endif
+ }
+ if (((mii_reg >> 18) & 0x1f) == 31) {
+ /* QS6612 PHY Control/Status.
+ * OK, now we have it all, so figure out what is going on.
+ */
+ prev_duplex = full_duplex;
+ printk("fec: ");
+
+ mii_reg = (mii_reg >> 2) & 7;
+
+ if (mii_reg & 1)
+ printk("10 Mbps");
+ else
+ printk("100 Mbps");
+
+ if (mii_reg > 4) {
+ printk(", Full-Duplex\n");
+ full_duplex = 1;
+ }
+ else {
+ printk(", Half-Duplex\n");
+ full_duplex = 0;
+ }
+
+#if 0
+ if (prev_duplex != full_duplex)
+ restart_fec(dev);
+#endif
+ }
+}
+
+static uint phyno;
+
+static void
+mii_discover_phy3(uint mii_reg, struct net_device *dev)
+{
+ phytype <<= 16;
+ phytype |= (mii_reg & 0xffff);
+ printk("fec: Phy @ 0x%x, type 0x%08x\n", phyno, phytype);
+ mii_startup_cmds();
+}
+
+static void
+mii_discover_phy(uint mii_reg, struct net_device *dev)
+{
+ if (phyno < 32) {
+ if ((phytype = (mii_reg & 0xffff)) != 0xffff) {
+ phyaddr = phyno;
+ mii_queue(mk_mii_read(3), mii_discover_phy3);
+ }
+ else {
+ phyno++;
+ mii_queue(mk_mii_phyaddr(phyno), mii_discover_phy);
+ }
+ }
+ else {
+ printk("FEC: No PHY device found.\n");
+ }
+}
+
+static void
+mii_discover_phy_poll(fcc_info_t *fip)
+{
+ uint rv;
+ int i;
+
+ for (i=0; i<32; i++) {
+ rv = mii_send_receive(fip, mk_mii_phyaddr(i));
+ if ((phytype = (rv & 0xffff)) != 0xffff) {
+ phyaddr = i;
+ rv = mii_send_receive(fip, mk_mii_read(3));
+ phytype <<= 16;
+ phytype |= (rv & 0xffff);
+ printk("fec: Phy @ 0x%x, type 0x%08x\n", phyaddr, phytype);
+ }
+ }
+}
+
+static void
+mii_startup_cmds(void)
+{
+
+#if 1
+ /* Level One PHY.
+ */
+
+ /* Read status registers to clear any pending interrupt.
+ */
+ mii_queue(mk_mii_read(1), mii_status);
+ mii_queue(mk_mii_read(18), mii_status);
+
+ /* Read extended chip status register.
+ */
+ mii_queue(mk_mii_read(0x14), mii_status);
+
+ /* Set default operation of 100-TX....for some reason
+ * some of these bits are set on power up, which is wrong.
+ */
+ mii_queue(mk_mii_write(0x13, 0), NULL);
+
+ /* Enable Link status change interrupts.
+ */
+ mii_queue(mk_mii_write(0x11, 0x0002), NULL);
+
+ /* Don't advertize Full duplex.
+ mii_queue(mk_mii_write(0x04, 0x0021), NULL);
+ */
+#endif
+
+}
+
+/* This supports the mii_link interrupt below.
+ * We should get called three times. Once for register 1, once for
+ * register 18, and once for register 20.
+ */
+static uint mii_saved_reg1;
+
+static void
+mii_relink(uint mii_reg, struct net_device *dev)
+{
+ volatile uint prev_duplex;
+ unsigned long flags;
+
+ if (((mii_reg >> 18) & 0x1f) == 1) {
+ /* Just save the status register and get out.
+ */
+ mii_saved_reg1 = mii_reg;
+ return;
+ }
+ if (((mii_reg >> 18) & 0x1f) == 18) {
+ /* Not much here, but has to be read to clear the
+ * interrupt condition.
+ */
+ if ((mii_reg & 0x8000) == 0)
+ printk("fec: re-link and no IRQ?\n");
+ if ((mii_reg & 0x4000) == 0)
+ printk("fec: no PHY power?\n");
+ }
+ if (((mii_reg >> 18) & 0x1f) == 20) {
+ /* Extended chip status register.
+ * OK, now we have it all, so figure out what is going on.
+ */
+ prev_duplex = full_duplex;
+ printk("fec: ");
+ if (mii_saved_reg1 & 0x0004)
+ printk("link up");
+ else
+ printk("link down");
+
+ if (mii_saved_reg1 & 0x0010)
+ printk(", remote fault");
+ if (mii_saved_reg1 & 0x0020)
+ printk(", auto complete");
+
+ if (mii_reg & 0x0800)
+ printk(", 100 Mbps");
+ else
+ printk(", 10 Mbps");
+
+ if (mii_reg & 0x1000) {
+ printk(", Full-Duplex\n");
+ full_duplex = 1;
+ }
+ else {
+ printk(", Half-Duplex\n");
+ full_duplex = 0;
+ }
+ if (prev_duplex != full_duplex) {
+ save_flags(flags);
+ cli();
+#if 0
+ restart_fec(dev);
+#endif
+ restore_flags(flags);
+ }
+ }
+ if (((mii_reg >> 18) & 0x1f) == 31) {
+ /* QS6612 PHY Control/Status.
+ * OK, now we have it all, so figure out what is going on.
+ */
+ prev_duplex = full_duplex;
+ printk("fec: ");
+ if (mii_saved_reg1 & 0x0004)
+ printk("link up");
+ else
+ printk("link down");
+
+ if (mii_saved_reg1 & 0x0010)
+ printk(", remote fault");
+ if (mii_saved_reg1 & 0x0020)
+ printk(", auto complete");
+
+ mii_reg = (mii_reg >> 2) & 7;
+
+ if (mii_reg & 1)
+ printk(", 10 Mbps");
+ else
+ printk(", 100 Mbps");
+
+ if (mii_reg > 4) {
+ printk(", Full-Duplex\n");
+ full_duplex = 1;
+ }
+ else {
+ printk(", Half-Duplex\n");
+ full_duplex = 0;
+ }
+
+#if 0
+ if (prev_duplex != full_duplex) {
+ save_flags(flags);
+ cli();
+ restart_fec(dev);
+ restore_flags(flags);
+ }
+#endif
+ }
+}
+
+/* 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 fcc_enet_private *cep;
+ struct dev_mc_list *dmi;
+ u_char *mcptr, *tdptr;
+ volatile fcc_enet_t *ep;
+ int i, j;
+
+ cep = (struct fcc_enet_private *)dev->priv;
+
+return;
+ /* Get pointer to FCC area in parameter RAM.
+ */
+ ep = (fcc_enet_t *)dev->base_addr;
+
+ if (dev->flags&IFF_PROMISC) {
+
+ /* Log any net taps. */
+ printk("%s: Promiscuous mode enabled.\n", dev->name);
+ cep->fccp->fcc_fpsmr |= FCC_PSMR_PRO;
+ } else {
+
+ cep->fccp->fcc_fpsmr &= ~FCC_PSMR_PRO;
+
+ if (dev->flags & IFF_ALLMULTI) {
+ /* Catch all multicast addresses, so set the
+ * filter to all 1's.
+ */
+ ep->fen_gaddrh = 0xffffffff;
+ ep->fen_gaddrl = 0xffffffff;
+ }
+ else {
+ /* Clear filter and add the addresses in the list.
+ */
+ ep->fen_gaddrh = 0;
+ ep->fen_gaddrl = 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->fen_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(cep->fip->fc_cpmpage,
+ cep->fip->fc_cpmblock, 0x0c,
+ CPM_CR_SET_GADDR) | CPM_CR_FLG;
+ udelay(10);
+ while (cpmp->cp_cpcr & CPM_CR_FLG);
+ }
+ }
+ }
+}
+
+/* Initialize the CPM Ethernet on FCC.
+ */
+int __init fec_enet_init(void)
+{
+ struct net_device *dev;
+ struct fcc_enet_private *cep;
+ fcc_info_t *fip;
+ int i, np;
+ volatile immap_t *immap;
+ volatile iop8260_t *io;
+
+ immap = (immap_t *)IMAP_ADDR; /* and to internal registers */
+ io = &immap->im_ioport;
+
+ np = sizeof(fcc_ports) / sizeof(fcc_info_t);
+ fip = fcc_ports;
+
+ while (np-- > 0) {
+
+ /* Allocate some private information.
+ */
+ cep = (struct fcc_enet_private *)
+ kmalloc(sizeof(*cep), GFP_KERNEL);
+ __clear_user(cep,sizeof(*cep));
+ spin_lock_init(&cep->lock);
+ cep->fip = fip;
+
+ /* Create an Ethernet device instance.
+ */
+ dev = init_etherdev(0, 0);
+ dev->priv = cep;
+
+ init_fcc_shutdown(fip, cep, immap);
+ init_fcc_ioports(fip, io, immap);
+ init_fcc_param(fip, dev, immap);
+
+ dev->base_addr = (unsigned long)(cep->ep);
+
+ /* The CPM Ethernet specific entries in the device
+ * structure.
+ */
+ dev->open = fcc_enet_open;
+ dev->hard_start_xmit = fcc_enet_start_xmit;
+ dev->tx_timeout = fcc_enet_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+ dev->stop = fcc_enet_close;
+ dev->get_stats = fcc_enet_get_stats;
+ dev->set_multicast_list = set_multicast_list;
+
+ init_fcc_startup(fip, dev);
+
+ printk("%s: FCC ENET Version 0.2, ", dev->name);
+ for (i=0; i<5; i++)
+ printk("%02x:", dev->dev_addr[i]);
+ printk("%02x\n", dev->dev_addr[5]);
+
+ /* This is just a hack for now that works only on the EST
+ * board, or anything else that has MDIO/CK configured.
+ * It is mainly to test the MII software clocking.
+ */
+ mii_discover_phy_poll(fip);
+
+ fip++;
+ }
+
+ return 0;
+}
+
+/* Make sure the device is shut down during initialization.
+*/
+static void __init
+init_fcc_shutdown(fcc_info_t *fip, struct fcc_enet_private *cep,
+ volatile immap_t *immap)
+{
+ volatile fcc_enet_t *ep;
+ volatile fcc_t *fccp;
+
+ /* Get pointer to FCC area in parameter RAM.
+ */
+ ep = (fcc_enet_t *)(&immap->im_dprambase[fip->fc_proff]);
+
+ /* And another to the FCC register area.
+ */
+ fccp = (volatile fcc_t *)(&immap->im_fcc[fip->fc_fccnum]);
+ cep->fccp = fccp; /* Keep the pointers handy */
+ cep->ep = ep;
+
+ /* Disable receive and transmit in case someone left it running.
+ */
+ fccp->fcc_gfmr &= ~(FCC_GFMR_ENR | FCC_GFMR_ENT);
+}
+
+/* Initialize the I/O pins for the FCC Ethernet.
+*/
+static void __init
+init_fcc_ioports(fcc_info_t *fip, volatile iop8260_t *io,
+ volatile immap_t *immap)
+{
+
+ /* FCC1 pins are on port A/C. FCC2/3 are port B/C.
+ */
+ if (fip->fc_proff == PROFF_FCC1) {
+ /* Configure port A and C pins for FCC1 Ethernet.
+ */
+ io->iop_pdira &= ~PA1_DIRA0;
+ io->iop_pdira |= PA1_DIRA1;
+ io->iop_psora &= ~PA1_PSORA0;
+ io->iop_psora |= PA1_PSORA1;
+ io->iop_ppara |= (PA1_DIRA0 | PA1_DIRA1);
+ }
+ if (fip->fc_proff == PROFF_FCC2) {
+ /* Configure port B and C pins for FCC Ethernet.
+ */
+ io->iop_pdirb &= ~PB2_DIRB0;
+ io->iop_pdirb |= PB2_DIRB1;
+ io->iop_psorb &= ~PB2_PSORB0;
+ io->iop_psorb |= PB2_PSORB1;
+ io->iop_pparb |= (PB2_DIRB0 | PB2_DIRB1);
+ }
+ if (fip->fc_proff == PROFF_FCC3) {
+ /* Configure port B and C pins for FCC Ethernet.
+ */
+ io->iop_pdirb &= ~PB3_DIRB0;
+ io->iop_pdirb |= PB3_DIRB1;
+ io->iop_psorb &= ~PB3_PSORB0;
+ io->iop_psorb |= PB3_PSORB1;
+ io->iop_pparb |= (PB3_DIRB0 | PB3_DIRB1);
+ }
+
+ /* Port C has clocks......
+ */
+ io->iop_psorc &= ~(fip->fc_trxclocks);
+ io->iop_pdirc &= ~(fip->fc_trxclocks);
+ io->iop_pparc |= fip->fc_trxclocks;
+
+ /* ....and the MII serial clock/data.
+ */
+ io->iop_pdatc |= (fip->fc_mdio | fip->fc_mdck);
+ io->iop_podrc |= fip->fc_mdio;
+ io->iop_pdirc |= (fip->fc_mdio | fip->fc_mdck);
+ io->iop_pparc &= ~(fip->fc_mdio | fip->fc_mdck);
+
+ /* Configure Serial Interface clock routing.
+ * First, clear all FCC bits to zero,
+ * then set the ones we want.
+ */
+ immap->im_cpmux.cmx_fcr &= ~(fip->fc_clockmask);
+ immap->im_cpmux.cmx_fcr |= fip->fc_clockroute;
+}
+
+static void __init
+init_fcc_param(fcc_info_t *fip, struct net_device *dev,
+ volatile immap_t *immap)
+{
+ unsigned char *eap;
+ unsigned long mem_addr;
+ bd_t *bd;
+ int i, j;
+ struct fcc_enet_private *cep;
+ volatile fcc_enet_t *ep;
+ volatile cbd_t *bdp;
+ volatile cpm8260_t *cp;
+
+ cep = (struct fcc_enet_private *)(dev->priv);
+ ep = cep->ep;
+ cp = cpmp;
+
+ bd = (bd_t *)__res;
+
+ /* Zero the whole thing.....I must have missed some individually.
+ * It works when I do this.
+ */
+ memset((char *)ep, 0, sizeof(fcc_enet_t));
+
+ /* 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.
+ */
+#if 0
+ /* I really want to do this, but for some reason it doesn't
+ * work with the data cache enabled, so I allocate from the
+ * main memory instead.
+ */
+ i = m8260_cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
+ ep->fen_genfcc.fcc_rbase = (uint)&immap->im_dprambase[i];
+ cep->rx_bd_base = (cbd_t *)&immap->im_dprambase[i];
+
+ i = m8260_cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
+ ep->fen_genfcc.fcc_tbase = (uint)&immap->im_dprambase[i];
+ cep->tx_bd_base = (cbd_t *)&immap->im_dprambase[i];
+#else
+ cep->rx_bd_base = (cbd_t *)m8260_cpm_hostalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
+ ep->fen_genfcc.fcc_rbase = __pa(cep->rx_bd_base);
+ cep->tx_bd_base = (cbd_t *)m8260_cpm_hostalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
+ ep->fen_genfcc.fcc_tbase = __pa(cep->tx_bd_base);
+#endif
+
+ cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
+ cep->cur_rx = cep->rx_bd_base;
+
+ ep->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
+ ep->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
+
+ /* Set maximum bytes per receive buffer.
+ * It must be a multiple of 32.
+ */
+ ep->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE;
+
+ /* Allocate space in the reserved FCC area of DPRAM for the
+ * internal buffers. No one uses this space (yet), so we
+ * can do this. Later, we will add resource management for
+ * this area.
+ */
+ mem_addr = CPM_FCC_SPECIAL_BASE + (fip->fc_fccnum * 128);
+ ep->fen_genfcc.fcc_riptr = mem_addr;
+ ep->fen_genfcc.fcc_tiptr = mem_addr+32;
+ ep->fen_padptr = mem_addr+64;
+ memset((char *)(&(immap->im_dprambase[(mem_addr+64)])), 0x88, 32);
+
+ ep->fen_genfcc.fcc_rbptr = 0;
+ ep->fen_genfcc.fcc_tbptr = 0;
+ ep->fen_genfcc.fcc_rcrc = 0;
+ ep->fen_genfcc.fcc_tcrc = 0;
+ ep->fen_genfcc.fcc_res1 = 0;
+ ep->fen_genfcc.fcc_res2 = 0;
+
+ ep->fen_camptr = 0; /* CAM isn't used in this driver */
+
+ /* Set CRC preset and mask.
+ */
+ ep->fen_cmask = 0xdebb20e3;
+ ep->fen_cpres = 0xffffffff;
+
+ ep->fen_crcec = 0; /* CRC Error counter */
+ ep->fen_alec = 0; /* alignment error counter */
+ ep->fen_disfc = 0; /* discard frame counter */
+ ep->fen_retlim = 15; /* Retry limit threshold */
+ ep->fen_pper = 0; /* Normal persistence */
+
+ /* Clear hash filter tables.
+ */
+ ep->fen_gaddrh = 0;
+ ep->fen_gaddrl = 0;
+ ep->fen_iaddrh = 0;
+ ep->fen_iaddrl = 0;
+
+ /* Clear the Out-of-sequence TxBD.
+ */
+ ep->fen_tfcstat = 0;
+ ep->fen_tfclen = 0;
+ ep->fen_tfcptr = 0;
+
+ ep->fen_mflr = PKT_MAXBUF_SIZE; /* maximum frame length register */
+ ep->fen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register */
+
+ /* Set Ethernet station address.
+ *
+ * This is supplied in the board information structure, so we
+ * copy that into the controller.
+ * So, far we have only been given one Ethernet address. We make
+ * it unique by setting a few bits in the upper byte of the
+ * non-static part of the address.
+ */
+ eap = (unsigned char *)&(ep->fen_paddrh);
+ for (i=5; i>=0; i--) {
+ if (i == 3) {
+ dev->dev_addr[i] = bd->bi_enetaddr[i];
+ dev->dev_addr[i] |= (1 << (7 - fip->fc_fccnum));
+ *eap++ = dev->dev_addr[i];
+ }
+ else {
+ *eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
+ }
+ }
+
+ ep->fen_taddrh = 0;
+ ep->fen_taddrm = 0;
+ ep->fen_taddrl = 0;
+
+ ep->fen_maxd1 = PKT_MAXDMA_SIZE; /* maximum DMA1 length */
+ ep->fen_maxd2 = PKT_MAXDMA_SIZE; /* maximum DMA2 length */
+
+ /* Clear stat counters, in case we ever enable RMON.
+ */
+ ep->fen_octc = 0;
+ ep->fen_colc = 0;
+ ep->fen_broc = 0;
+ ep->fen_mulc = 0;
+ ep->fen_uspc = 0;
+ ep->fen_frgc = 0;
+ ep->fen_ospc = 0;
+ ep->fen_jbrc = 0;
+ ep->fen_p64c = 0;
+ ep->fen_p65c = 0;
+ ep->fen_p128c = 0;
+ ep->fen_p256c = 0;
+ ep->fen_p512c = 0;
+ ep->fen_p1024c = 0;
+
+ ep->fen_rfthr = 0; /* Suggested by manual */
+ ep->fen_rfcnt = 0;
+ ep->fen_cftype = 0;
+
+ /* 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_datlen = 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<FCC_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<FCC_ENET_RX_FRPPG; j++) {
+ bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
+ bdp->cbd_datlen = 0;
+ bdp->cbd_bufaddr = __pa(mem_addr);
+ mem_addr += FCC_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.
+ */
+ cp->cp_cpcr = mk_cr_cmd(fip->fc_cpmpage, fip->fc_cpmblock, 0x0c,
+ CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ cep->skb_cur = cep->skb_dirty = 0;
+}
+
+/* Let 'er rip.
+*/
+static void __init
+init_fcc_startup(fcc_info_t *fip, struct net_device *dev)
+{
+ volatile fcc_t *fccp;
+ struct fcc_enet_private *cep;
+
+ cep = (struct fcc_enet_private *)(dev->priv);
+ fccp = cep->fccp;
+
+ fccp->fcc_fcce = 0xffff; /* Clear any pending events */
+
+ /* Enable interrupts for transmit error, complete frame
+ * received, and any transmit buffer we have also set the
+ * interrupt flag.
+ */
+ fccp->fcc_fccm = (FCC_ENET_TXE | FCC_ENET_RXF | FCC_ENET_TXB);
+
+ /* Install our interrupt handler.
+ */
+ if (request_8xxirq(fip->fc_interrupt, fcc_enet_interrupt, 0,
+ "fenet", dev) < 0)
+ printk("Can't get FCC IRQ %d\n", fip->fc_interrupt);
+
+ /* Set GFMR to enable Ethernet operating mode.
+ */
+ fccp->fcc_gfmr = (FCC_GFMR_TCI | FCC_GFMR_MODE_ENET);
+
+ /* Set sync/delimiters.
+ */
+ fccp->fcc_fdsr = 0xd555;
+
+ /* Set protocol specific processing mode for Ethernet.
+ * This has to be adjusted for Full Duplex operation after we can
+ * determine how to detect that.
+ */
+ fccp->fcc_fpsmr = FCC_PSMR_ENCRC;
+
+ /* And last, enable the transmit and receive processing.
+ */
+ fccp->fcc_gfmr |= (FCC_GFMR_ENR | FCC_GFMR_ENT);
+}
+
+/* MII command/status interface.
+ * I'm not going to describe all of the details. You can find the
+ * protocol definition in many other places, including the data sheet
+ * of most PHY parts.
+ * I wonder what "they" were thinking (maybe weren't) when they leave
+ * the I2C in the CPM but I have to toggle these bits......
+ */
+static uint
+mii_send_receive(fcc_info_t *fip, uint cmd)
+{
+ unsigned long flags;
+ uint retval;
+ int read_op, i;
+ volatile immap_t *immap;
+ volatile iop8260_t *io;
+
+ immap = (immap_t *)IMAP_ADDR;
+ io = &immap->im_ioport;
+
+ /* When we get here, both clock and data are high, outputs.
+ * Output is open drain.
+ * Data transitions on high->low clock, is valid on low->high clock.
+ * Spec says edge transitions no closer than 160 nSec, minimum clock
+ * cycle 400 nSec. I could only manage about 500 nSec edges with
+ * an XOR loop, so I won't worry about delays yet.
+ * I disable interrupts during bit flipping to ensure atomic
+ * updates of the registers. I do lots of interrupt disable/enable
+ * to ensure we don't hang out too long with interrupts disabled.
+ */
+
+ /* First, crank out 32 1-bits as preamble.
+ * This is 64 transitions to clock the bits, with clock/data
+ * left high.
+ */
+ save_flags(flags);
+ cli();
+ for (i=0; i<64; i++) {
+ io->iop_pdatc ^= fip->fc_mdck;
+ udelay(0);
+ }
+ restore_flags(flags);
+
+ read_op = ((cmd & 0xf0000000) == 0x60000000);
+
+ /* We return the command word on a write op, or the command portion
+ * plus the new data on a read op. This is what the 8xx FEC does,
+ * and it allows the functions to simply look at the returned value
+ * and know the PHY/register as well.
+ */
+ if (read_op)
+ retval = cmd;
+ else
+ retval = (cmd >> 16);
+
+ /* Clock out the first 16 MS bits of the command.
+ */
+ save_flags(flags);
+ cli();
+ for (i=0; i<16; i++) {
+ io->iop_pdatc &= ~(fip->fc_mdck);
+ if (cmd & 0x80000000)
+ io->iop_pdatc |= fip->fc_mdio;
+ else
+ io->iop_pdatc &= ~(fip->fc_mdio);
+ cmd <<= 1;
+ io->iop_pdatc |= fip->fc_mdck;
+ udelay(0);
+ }
+
+ /* Do the turn-around. If read op, we make the IO and input.
+ * If write op, do the 1/0 thing.
+ */
+ io->iop_pdatc &= ~(fip->fc_mdck);
+ if (read_op)
+ io->iop_pdirc &= ~(fip->fc_mdio);
+ else
+ io->iop_pdatc |= fip->fc_mdio;
+ io->iop_pdatc |= fip->fc_mdck;
+
+ /* I do this mainly to get just a little delay.
+ */
+ restore_flags(flags);
+ save_flags(flags);
+ cli();
+ io->iop_pdatc &= ~(fip->fc_mdck);
+ io->iop_pdirc &= ~(fip->fc_mdio);
+ io->iop_pdatc |= fip->fc_mdck;
+
+ restore_flags(flags);
+ save_flags(flags);
+ cli();
+
+ /* For read, clock in 16 bits. For write, clock out
+ * rest of command.
+ */
+ if (read_op) {
+ io->iop_pdatc &= ~(fip->fc_mdck);
+ udelay(0);
+ for (i=0; i<16; i++) {
+ io->iop_pdatc |= fip->fc_mdck;
+ udelay(0);
+ retval <<= 1;
+ if (io->iop_pdatc & fip->fc_mdio)
+ retval |= 1;
+ io->iop_pdatc &= ~(fip->fc_mdck);
+ udelay(0);
+ }
+ }
+ else {
+ for (i=0; i<16; i++) {
+ io->iop_pdatc &= ~(fip->fc_mdck);
+ if (cmd & 0x80000000)
+ io->iop_pdatc |= fip->fc_mdio;
+ else
+ io->iop_pdatc &= ~(fip->fc_mdio);
+ cmd <<= 1;
+ io->iop_pdatc |= fip->fc_mdck;
+ udelay(0);
+ }
+ io->iop_pdatc &= ~(fip->fc_mdck);
+ }
+ restore_flags(flags);
+
+ /* Some diagrams show two 1 bits for "idle". I don't know if
+ * this is really necessary or if it was just to indicate nothing
+ * is going to happen for a while.
+ * Make the data pin an output, set the data high, and clock it.
+ */
+ save_flags(flags);
+ cli();
+ io->iop_pdatc |= fip->fc_mdio;
+ io->iop_pdirc |= fip->fc_mdio;
+ for (i=0; i<3; i++)
+ io->iop_pdatc ^= fip->fc_mdck;
+ restore_flags(flags);
+
+ /* We exit with the same conditions as entry.
+ */
+ return(retval);
+}
diff --git a/arch/ppc/8260_io/uart.c b/arch/ppc/8260_io/uart.c
index caa5ca8b0..97c4cb880 100644
--- a/arch/ppc/8260_io/uart.c
+++ b/arch/ppc/8260_io/uart.c
@@ -977,8 +977,7 @@ 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)) {
+ if (copy_from_user(__va(bdp->cbd_bufaddr), buf, c)) {
if (!ret)
ret = -EFAULT;
break;
@@ -2396,10 +2395,10 @@ int __init rs_8xx_init(void)
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;
+ io->iop_ppara |= 0x00c00000;
+ io->iop_pdira |= 0x00400000;
+ io->iop_pdira &= ~0x00800000;
+ io->iop_psora &= ~0x00c00000;
#endif
/* Configure SCC2 and SCC3. Be careful about the fine print.
@@ -2473,11 +2472,11 @@ int __init rs_8xx_init(void)
* descriptors from dual port ram, and a character
* buffer area from host mem.
*/
- dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * RX_NUM_FIFO);
+ dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * RX_NUM_FIFO, 8);
/* Allocate space for FIFOs in the host memory.
*/
- mem_addr = m8260_cpm_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE);
+ mem_addr = m8260_cpm_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE, 1);
/* Set the physical address of the host memory
* buffers in the buffer descriptors, and the
@@ -2506,11 +2505,11 @@ int __init rs_8xx_init(void)
sup->scc_genscc.scc_rbase = dp_addr;
}
- dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * TX_NUM_FIFO);
+ dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * TX_NUM_FIFO, 8);
/* Allocate space for FIFOs in the host memory.
*/
- mem_addr = m8260_cpm_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE);
+ mem_addr = m8260_cpm_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE, 1);
/* Set the physical address of the host memory
* buffers in the buffer descriptors, and the
@@ -2716,11 +2715,11 @@ static int __init serial_console_setup(struct console *co, char *options)
/* Allocate space for two buffer descriptors in the DP ram.
*/
- dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * 2);
+ dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * 2, 8);
/* Allocate space for two 2 byte FIFOs in the host memory.
*/
- mem_addr = m8260_cpm_hostalloc(4);
+ mem_addr = m8260_cpm_hostalloc(4, 1);
/* Set the physical address of the host memory buffers in
* the buffer descriptors.
diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c
index 730453bbb..b77cf32da 100644
--- a/arch/ppc/8xx_io/enet.c
+++ b/arch/ppc/8xx_io/enet.c
@@ -484,8 +484,11 @@ for (;;) {
cep->stats.rx_bytes += pkt_len;
/* This does 16 byte alignment, much more than we need.
- */
- skb = dev_alloc_skb(pkt_len);
+ * The packet length includes FCS, but we don't want to
+ * include that when passing upstream as it messes up
+ * bridging applications.
+ */
+ skb = dev_alloc_skb(pkt_len-4);
if (skb == NULL) {
printk("%s: Memory squeeze, dropping packet.\n", dev->name);
@@ -493,10 +496,10 @@ for (;;) {
}
else {
skb->dev = dev;
- skb_put(skb,pkt_len); /* Make room */
+ skb_put(skb,pkt_len-4); /* Make room */
eth_copy_and_sum(skb,
(unsigned char *)__va(bdp->cbd_bufaddr),
- pkt_len, 0);
+ pkt_len-4, 0);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
}
diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c
index f69d0dfbd..45f10b635 100644
--- a/arch/ppc/8xx_io/fec.c
+++ b/arch/ppc/8xx_io/fec.c
@@ -669,18 +669,21 @@ while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) {
#endif
/* This does 16 byte alignment, exactly what we need.
+ * The packet length includes FCS, but we don't want to
+ * include that when passing upstream as it messes up
+ * bridging applications.
*/
- skb = dev_alloc_skb(pkt_len);
+ skb = dev_alloc_skb(pkt_len-4);
if (skb == NULL) {
printk("%s: Memory squeeze, dropping packet.\n", dev->name);
fep->stats.rx_dropped++;
} else {
skb->dev = dev;
- skb_put(skb,pkt_len); /* Make room */
+ skb_put(skb,pkt_len-4); /* Make room */
eth_copy_and_sum(skb,
(unsigned char *)__va(bdp->cbd_bufaddr),
- pkt_len, 0);
+ pkt_len-4, 0);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
}
diff --git a/arch/ppc/amiga/time.c b/arch/ppc/amiga/time.c
index a78f8aa41..0073527a7 100644
--- a/arch/ppc/amiga/time.c
+++ b/arch/ppc/amiga/time.c
@@ -11,10 +11,6 @@
#include <linux/timex.h>
-static inline unsigned long mktime(unsigned int year, unsigned int mon,
- unsigned int day, unsigned int hour,
- unsigned int min, unsigned int sec);
-
unsigned long m68k_get_rtc_time(void)
{
unsigned int year, mon, day, hour, min, sec;
@@ -37,38 +33,6 @@ int m68k_set_rtc_time(unsigned long nowtime)
return -1;
}
-/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
- * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
- * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
- *
- * [For the Julian calendar (which was used in Russia before 1917,
- * Britain & colonies before 1752, anywhere else before 1582,
- * and is still in use by some communities) leave out the
- * -year/100+year/400 terms, and add 10.]
- *
- * This algorithm was first published by Gauss (I think).
- *
- * WARNING: this function will overflow on 2106-02-07 06:28:16 on
- * machines were long is 32-bit! (However, as time_t is signed, we
- * will already get problems at other places on 2038-01-19 03:14:08)
- */
-static inline unsigned long mktime(unsigned int year, unsigned int mon,
- unsigned int day, unsigned int hour,
- unsigned int min, unsigned int sec)
-{
- if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
- mon += 12; /* Puts Feb last since it has leap day */
- year -= 1;
- }
- return (((
- (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
- year*365 - 719499
- )*24 + hour /* now have hours */
- )*60 + min /* now have minutes */
- )*60 + sec; /* finally seconds */
-}
-
-
void apus_heartbeat (void)
{
#ifdef CONFIG_HEARTBEAT
diff --git a/arch/ppc/chrpboot/Makefile b/arch/ppc/chrpboot/Makefile
index 48750982e..f7ea3a3fa 100644
--- a/arch/ppc/chrpboot/Makefile
+++ b/arch/ppc/chrpboot/Makefile
@@ -67,11 +67,13 @@ initrd.o: ramdisk.image.gz piggyback
zImage: $(OBJS) no_initrd.o addnote
$(LD) $(LD_ARGS) -o $@ $(OBJS) no_initrd.o $(LIBS)
- ./addnote $@
+ cp $@ $@.rs6k
+ ./addnote $@.rs6k
zImage.initrd: $(OBJS) initrd.o addnote
$(LD) $(LD_ARGS) -o $@ $(OBJS) initrd.o $(LIBS)
- ./addnote $@
+ cp $@ $@.rs6k
+ ./addnote $@.rs6k
else
znetboot:
diff --git a/arch/ppc/chrpboot/addnote.c b/arch/ppc/chrpboot/addnote.c
index 5f0934f6e..b2374df7c 100644
--- a/arch/ppc/chrpboot/addnote.c
+++ b/arch/ppc/chrpboot/addnote.c
@@ -22,12 +22,23 @@ char arch[] = "PowerPC";
#define N_DESCR 6
unsigned int descr[N_DESCR] = {
+#if 1
+ /* values for IBM RS/6000 machines */
0xffffffff, /* real-mode = true */
0x00c00000, /* real-base, i.e. where we expect OF to be */
0xffffffff, /* real-size */
0xffffffff, /* virt-base */
0xffffffff, /* virt-size */
0x4000, /* load-base */
+#else
+ /* values for longtrail CHRP */
+ 0, /* real-mode = false */
+ 0xffffffff, /* real-base */
+ 0xffffffff, /* real-size */
+ 0xffffffff, /* virt-base */
+ 0xffffffff, /* virt-size */
+ 0x00600000, /* load-base */
+#endif
};
unsigned char buf[512];
@@ -63,7 +74,7 @@ unsigned char buf[512];
unsigned char elf_magic[4] = { 0x7f, 'E', 'L', 'F' };
-main(int ac, char **av)
+int main(int ac, char **av)
{
int fd, n, i;
int ph, ps, np;
diff --git a/arch/ppc/coffboot/Makefile b/arch/ppc/coffboot/Makefile
index 23afda4a8..494026e42 100644
--- a/arch/ppc/coffboot/Makefile
+++ b/arch/ppc/coffboot/Makefile
@@ -8,7 +8,7 @@ HOSTCFLAGS = -O -I$(TOPDIR)/include
CFLAGS = $(CPPFLAGS) -O -fno-builtin
OBJCOPY_ARGS = -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment
COFF_LD_ARGS = -e _start -T ld.script -Ttext 500000 -Tdata 510000 -Bstatic
-CHRP_LD_ARGS = -Ttext 0x00400000
+CHRP_LD_ARGS = -Ttext 0x01000000
COFFOBJS = coffcrt0.o start.o coffmain.o misc.o string.o zlib.o image.o
CHRPOBJS = crt0.o start.o chrpmain.o misc.o string.o zlib.o image.o
diff --git a/arch/ppc/coffboot/chrpmain.c b/arch/ppc/coffboot/chrpmain.c
index 4d994d17e..08b238b16 100644
--- a/arch/ppc/coffboot/chrpmain.c
+++ b/arch/ppc/coffboot/chrpmain.c
@@ -22,13 +22,18 @@ void stop_imac_usb(void);
#define get_16be(x) (*(unsigned short *)(x))
#define get_32be(x) (*(unsigned *)(x))
-#define RAM_START 0x00000000
-#define RAM_END (8<<20)
+#define RAM_END (16 << 20)
#define PROG_START 0x00010000
+#define PROG_SIZE 0x003f0000
+
+#define SCRATCH_SIZE (128 << 10)
char *avail_ram;
-char *end_avail;
+char *begin_avail, *end_avail;
+char *avail_high;
+unsigned int heap_use;
+unsigned int heap_max;
extern char _end[];
extern char image_data[];
@@ -60,29 +65,30 @@ boot(int a1, int a2, void *prom)
im = image_data;
len = image_len;
/* claim 3MB starting at PROG_START */
- claim(PROG_START, 3 << 20, 0);
+ claim(PROG_START, PROG_SIZE, 0);
dst = (void *) PROG_START;
if (im[0] == 0x1f && im[1] == 0x8b) {
- /* claim 512kB for scratch space */
- avail_ram = (char *) claim(0, 512 << 10, 0x10);
- end_avail = avail_ram + (512 << 10);
- printf("avail_ram = %x\n", avail_ram);
+ /* claim some memory for scratch space */
+ avail_ram = (char *) claim(0, SCRATCH_SIZE, 0x10);
+ begin_avail = avail_high = avail_ram;
+ end_avail = avail_ram + SCRATCH_SIZE;
+ printf("heap at 0x%x\n", avail_ram);
printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len);
- gunzip(dst, 3 << 20, im, &len);
+ gunzip(dst, PROG_SIZE, im, &len);
printf("done %u bytes\n", len);
+ printf("%u bytes of heap consumed, max in use %u\n",
+ avail_high - begin_avail, heap_max);
} else {
memmove(dst, im, len);
}
flush_cache(dst, len);
- stop_imac_ethernet();
- stop_imac_usb();
make_bi_recs((unsigned long) dst + len);
sa = (unsigned long)PROG_START;
printf("start address = 0x%x\n", sa);
- (*(void (*)())sa)(0, 0, prom, a1, a2);
+ (*(void (*)())sa)(a1, a2, prom);
printf("returned?\n");
@@ -122,6 +128,7 @@ void make_bi_recs(unsigned long addr)
rec = (struct bi_record *)((unsigned long)rec + rec->size);
}
+#if 0
#define eieio() asm volatile("eieio");
void stop_imac_ethernet(void)
@@ -172,14 +179,35 @@ void stop_imac_usb(void)
*usb_ctrl = 0x01000000; /* cpu_to_le32(1) */
eieio();
}
+#endif
+
+struct memchunk {
+ unsigned int size;
+ struct memchunk *next;
+};
+
+static struct memchunk *freechunks;
void *zalloc(void *x, unsigned items, unsigned size)
{
- void *p = avail_ram;
+ void *p;
+ struct memchunk **mpp, *mp;
size *= items;
size = (size + 7) & -8;
+ heap_use += size;
+ if (heap_use > heap_max)
+ heap_max = heap_use;
+ for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) {
+ if (mp->size == size) {
+ *mpp = mp->next;
+ return mp;
+ }
+ }
+ p = avail_ram;
avail_ram += size;
+ if (avail_ram > avail_high)
+ avail_high = avail_ram;
if (avail_ram > end_avail) {
printf("oops... out of memory\n");
pause();
@@ -189,6 +217,17 @@ void *zalloc(void *x, unsigned items, unsigned size)
void zfree(void *x, void *addr, unsigned nb)
{
+ struct memchunk *mp = addr;
+
+ nb = (nb + 7) & -8;
+ heap_use -= nb;
+ if (avail_ram == addr + nb) {
+ avail_ram = addr;
+ return;
+ }
+ mp->size = nb;
+ mp->next = freechunks;
+ freechunks = mp;
}
#define HEAD_CRC 2
diff --git a/arch/ppc/config.in b/arch/ppc/config.in
index 950118eb2..0a217d4c9 100644
--- a/arch/ppc/config.in
+++ b/arch/ppc/config.in
@@ -88,11 +88,15 @@ fi
if [ "$CONFIG_4xx" = "y" -o "$CONFIG_8xx" = "y" ]; then
bool 'Math emulation' CONFIG_MATH_EMULATION
fi
+
endmenu
mainmenu_option next_comment
comment 'General setup'
+bool 'High memory support (experimental)' CONFIG_HIGHMEM
+bool 'Mac-on-Linux support' CONFIG_MOL
+
define_bool CONFIG_ISA n
define_bool CONFIG_SBUS n
@@ -140,20 +144,6 @@ if [ "$CONFIG_4xx" != "y" -a "$CONFIG_8xx" != "y" ]; then
bool 'Backward compatibility mode for Xpmac' CONFIG_FB_COMPAT_XPMAC
fi
- bool 'Power management support for PowerBooks' CONFIG_PMAC_PBOOK
- bool 'Support for PowerMac floppy' CONFIG_MAC_FLOPPY
- tristate 'Support for PowerMac serial ports' CONFIG_MAC_SERIAL
- if [ "$CONFIG_MAC_SERIAL" = "y" ]; then
- bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE
- fi
- bool 'Apple Desktop Bus (ADB) support' CONFIG_ADB
- if [ "$CONFIG_ADB" = "y" ]; then
- bool ' Include CUDA ADB driver' CONFIG_ADB_CUDA
- bool ' Include MacIO ADB driver' CONFIG_ADB_MACIO
- bool ' Include PMU (Powerbook) ADB driver' CONFIG_ADB_PMU
- bool 'Support for ADB keyboard' CONFIG_ADB_KEYBOARD
- bool 'Support for ADB mouse' CONFIG_ADBMOUSE
- fi
tristate 'Support for /dev/rtc' CONFIG_PPC_RTC
bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE
bool 'Support for early boot text console (BootX only)' CONFIG_BOOTX_TEXT
@@ -192,7 +182,7 @@ endmenu
source drivers/mtd/Config.in
source drivers/pnp/Config.in
source drivers/block/Config.in
-#source drivers.new/Config.in
+source drivers/md/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
@@ -262,6 +252,43 @@ comment 'Console drivers'
source drivers/video/Config.in
endmenu
+source drivers/input/Config.in
+
+mainmenu_option next_comment
+comment 'Macintosh device drivers'
+
+if [ "$CONFIG_ALL_PPC" = "y" ]; then
+ # we want to change this to something like CONFIG_SYSCTRL_CUDA/PMU
+ bool 'Support for CUDA based PowerMacs' CONFIG_ADB_CUDA
+ bool 'Support for PMU based PowerMacs' CONFIG_ADB_PMU
+ if [ "$CONFIG_ADB_PMU" = "y" ]; then
+ bool ' Power management support for PowerBooks' CONFIG_PMAC_PBOOK
+ # made a separate option since backlight may end up beeing used
+ # on non-powerbook machines (but only on PMU based ones AFAIK)
+ bool ' Backlight control for LCD screens' CONFIG_PMAC_BACKLIGHT
+ fi
+ bool 'Support for PowerMac floppy' CONFIG_MAC_FLOPPY
+ tristate 'Support for PowerMac serial ports' CONFIG_MAC_SERIAL
+ if [ "$CONFIG_MAC_SERIAL" = "y" ]; then
+ bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE
+ fi
+ bool 'Apple Desktop Bus (ADB) support' CONFIG_ADB
+ if [ "$CONFIG_ADB" = "y" ]; then
+ bool ' Include MacIO (CHRP) ADB driver' CONFIG_ADB_MACIO
+ fi
+fi
+if [ "$CONFIG_ADB" = "y" ]; then
+ dep_bool ' Use input layer for ADB devices' CONFIG_INPUT_ADBHID $CONFIG_INPUT
+ if [ "$CONFIG_INPUT_ADBHID" = "y" ]; then
+ define_bool CONFIG_MAC_HID y
+ bool ' Support for ADB raw keycodes' CONFIG_MAC_ADBKEYCODES
+ bool ' Support for mouse button 2+3 emulation' CONFIG_MAC_EMUMOUSEBTN
+ else
+ bool ' Support for ADB keyboard (old driver)' CONFIG_ADB_KEYBOARD
+ fi
+fi
+endmenu
+
source drivers/char/Config.in
source drivers/media/Config.in
@@ -287,7 +314,6 @@ source arch/ppc/8260_io/Config.in
fi
source drivers/usb/Config.in
-source drivers/input/Config.in
mainmenu_option next_comment
comment 'Kernel hacking'
diff --git a/arch/ppc/configs/common_defconfig b/arch/ppc/configs/common_defconfig
index 68e49c148..a9ae80db0 100644
--- a/arch/ppc/configs/common_defconfig
+++ b/arch/ppc/configs/common_defconfig
@@ -1,5 +1,5 @@
#
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
#
# CONFIG_UID16 is not set
@@ -9,12 +9,20 @@
CONFIG_EXPERIMENTAL=y
#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
# Platform support
#
CONFIG_PPC=y
CONFIG_6xx=y
# CONFIG_4xx is not set
-# CONFIG_PPC64BRIDGE is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
# CONFIG_8260 is not set
# CONFIG_8xx is not set
CONFIG_ALL_PPC=y
@@ -25,15 +33,9 @@ CONFIG_ALL_PPC=y
CONFIG_ALTIVEC=y
#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
# General setup
#
+# CONFIG_HIGHMEM is not set
# CONFIG_ISA is not set
# CONFIG_SBUS is not set
CONFIG_PCI=y
@@ -44,8 +46,8 @@ CONFIG_SYSVIPC=y
CONFIG_KCORE_ELF=y
CONFIG_BINFMT_ELF=y
CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_PCI_NAMES is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_PCI_NAMES=y
# CONFIG_HOTPLUG is not set
# CONFIG_PCMCIA is not set
@@ -57,21 +59,18 @@ CONFIG_VGA_CONSOLE=y
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_ADBMOUSE=y
+CONFIG_PPC_RTC=y
CONFIG_PROC_DEVICETREE=y
CONFIG_BOOTX_TEXT=y
# CONFIG_MOTOROLA_HOTSWAP is not set
# CONFIG_CMDLINE_BOOL is not set
#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
# Plug and Play configuration
#
# CONFIG_PNP is not set
@@ -90,8 +89,11 @@ CONFIG_BLK_DEV_LOOP=y
# 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_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
#
@@ -109,22 +111,24 @@ 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_INET_ECN is not set
CONFIG_SYN_COOKIES=y
-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_BRIDGE 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
@@ -145,26 +149,42 @@ 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_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO 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_IDEFLOPPY=y
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_IDEPCI_SHARE_IRQ=y
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_IDEDMA_PCI_AUTO=y
CONFIG_BLK_DEV_IDEDMA=y
-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
@@ -173,37 +193,40 @@ CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
# 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_CMD64X=y
# 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_SL82C105=y
CONFIG_BLK_DEV_IDE_PMAC=y
CONFIG_BLK_DEV_IDEDMA_PMAC=y
-CONFIG_IDEDMA_PMAC_AUTO=y
+CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO=y
CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_BLK_DEV_IDEPCI=y
# CONFIG_IDE_CHIPSETS is not set
CONFIG_IDEDMA_AUTO=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_DMA_NONPCI is not set
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
@@ -211,6 +234,10 @@ 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
@@ -296,6 +323,7 @@ CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
# CONFIG_ETHERTAP is not set
# CONFIG_NET_SB1000 is not set
@@ -327,8 +355,9 @@ CONFIG_DE4X5=y
# CONFIG_DM9102 is not set
# CONFIG_EEPRO100 is not set
# CONFIG_LNE390 is not set
-# CONFIG_NE3210 is not set
+# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
+# CONFIG_NE3210 is not set
# CONFIG_RTL8129 is not set
# CONFIG_8139TOO is not set
# CONFIG_SIS900 is not set
@@ -347,11 +376,13 @@ 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_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=y
# CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
+CONFIG_PPP_DEFLATE=y
# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
# CONFIG_SLIP is not set
#
@@ -404,12 +435,13 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_FB_RIVA is not set
# CONFIG_FB_CLGEN is not set
# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 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_IMSTT=y
# CONFIG_FB_S3TRIO is not set
# CONFIG_FB_VGA16 is not set
CONFIG_FB_MATROX=y
@@ -420,6 +452,7 @@ CONFIG_FB_MATROX_G100=y
CONFIG_FB_ATY=y
CONFIG_FB_ATY128=y
CONFIG_FB_3DFX=y
+# CONFIG_FB_SIS is not set
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FBCON_ADVANCED is not set
CONFIG_FBCON_CFB8=y
@@ -437,6 +470,32 @@ CONFIG_FONT_SUN12x22=y
# CONFIG_FONT_ACORN_8x8 is not set
#
+# Input core support
+#
+CONFIG_INPUT=y
+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=y
+
+#
+# Macintosh device drivers
+#
+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_INPUT_ADBHID=y
+CONFIG_MAC_HID=y
+CONFIG_MAC_ADBKEYCODES=y
+CONFIG_MAC_EMUMOUSEBTN=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -459,7 +518,6 @@ 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=y
CONFIG_PSMOUSE=y
# CONFIG_82C710_MOUSE is not set
@@ -469,19 +527,19 @@ CONFIG_PSMOUSE=y
# Joysticks
#
# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
# CONFIG_QIC02_TAPE is not set
#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
CONFIG_NVRAM=y
# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -490,26 +548,31 @@ CONFIG_NVRAM=y
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
#
# File systems
#
# CONFIG_QUOTA is not set
CONFIG_AUTOFS_FS=y
-# CONFIG_AUTOFS4_FS is not set
+CONFIG_AUTOFS4_FS=y
# CONFIG_ADFS_FS is not set
# CONFIG_ADFS_FS_RW is not set
# CONFIG_AFFS_FS is not set
-CONFIG_HFS_FS=y
+# CONFIG_HFS_FS is not set
# CONFIG_BFS_FS is not set
CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y
# CONFIG_UMSDOS_FS is not set
CONFIG_VFAT_FS=y
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_RAMFS is not set
CONFIG_ISO9660_FS=y
@@ -519,7 +582,8 @@ CONFIG_ISO9660_FS=y
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
+CONFIG_DEVFS_FS=y
+# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
@@ -571,12 +635,14 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
CONFIG_NLS=y
#
# Native Language Support
#
+CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_437 is not set
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
@@ -593,6 +659,10 @@ CONFIG_NLS=y
# CONFIG_NLS_CODEPAGE_866 is not set
# CONFIG_NLS_CODEPAGE_869 is not set
# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
# CONFIG_NLS_ISO8859_1 is not set
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
@@ -605,6 +675,7 @@ CONFIG_NLS=y
# CONFIG_NLS_ISO8859_14 is not set
# CONFIG_NLS_ISO8859_15 is not set
# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_UTF8 is not set
#
# Sound
@@ -614,6 +685,7 @@ CONFIG_DMASOUND_AWACS=y
CONFIG_DMASOUND=y
# CONFIG_SOUND_CMPCI is not set
# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
# CONFIG_SOUND_ES1370 is not set
# CONFIG_SOUND_ES1371 is not set
# CONFIG_SOUND_ESSSOLO1 is not set
@@ -622,6 +694,7 @@ CONFIG_DMASOUND=y
# CONFIG_SOUND_TRIDENT is not set
# CONFIG_SOUND_MSNDCLAS is not set
# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
CONFIG_SOUND_OSS=y
# CONFIG_SOUND_TRACEINIT is not set
# CONFIG_SOUND_DMAP is not set
@@ -647,24 +720,39 @@ CONFIG_SOUND_CS4232=m
# CONFIG_SOUND_AWE32_SYNTH is not set
# CONFIG_SOUND_WAVEFRONT is not set
# CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_VIA82CXXX is not set
# CONFIG_SOUND_YM3812 is not set
# CONFIG_SOUND_OPL3SA1 is not set
# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_YMPCI is not set
# CONFIG_SOUND_UART6850 is not set
# CONFIG_SOUND_AEDSP16 is not set
+# CONFIG_SOUND_TVMIXER is not set
#
# USB support
#
CONFIG_USB=y
CONFIG_USB_DEBUG=y
-# CONFIG_USB_DEVICEFS is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+
+#
+# USB Controllers
+#
# CONFIG_USB_UHCI is not set
# CONFIG_USB_UHCI_ALT is not set
CONFIG_USB_OHCI=y
+
+#
+# USB Devices
+#
# CONFIG_USB_PRINTER is not set
# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_MICROTEK is not set
# CONFIG_USB_AUDIO is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_SERIAL is not set
@@ -679,15 +767,13 @@ CONFIG_USB_OHCI=y
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_DSBR is not set
+# CONFIG_USB_BLUETOOTH is not set
+
+#
+# USB Human Interface Devices (HID)
+#
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
@@ -695,4 +781,3 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
CONFIG_MAGIC_SYSRQ=y
# CONFIG_KGDB is not set
CONFIG_XMON=y
-
diff --git a/arch/ppc/configs/est8260_defconfig b/arch/ppc/configs/est8260_defconfig
index 972820d21..d317c8517 100644
--- a/arch/ppc/configs/est8260_defconfig
+++ b/arch/ppc/configs/est8260_defconfig
@@ -9,12 +9,18 @@
CONFIG_EXPERIMENTAL=y
#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
# Platform support
#
CONFIG_PPC=y
# CONFIG_6xx is not set
# CONFIG_4xx is not set
-# CONFIG_PPC64BRIDGE is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
CONFIG_8260=y
# CONFIG_8xx is not set
CONFIG_6xx=y
@@ -29,13 +35,9 @@ CONFIG_EST8260=y
CONFIG_MACH_SPECIFIC=y
#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
# General setup
#
+# CONFIG_HIGHMEM is not set
# CONFIG_ISA is not set
# CONFIG_SBUS is not set
# CONFIG_PCI is not set
@@ -56,15 +58,17 @@ CONFIG_KERNEL_ELF=y
# CONFIG_PARPORT is not set
# CONFIG_VGA_CONSOLE is not set
# CONFIG_FB is not set
-# CONFIG_PMAC_PBOOK is not set
-# CONFIG_MAC_FLOPPY is not set
-# CONFIG_MAC_SERIAL is not set
-# CONFIG_ADB is not set
+# CONFIG_PPC_RTC is not set
# CONFIG_PROC_DEVICETREE is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_MOTOROLA_HOTSWAP is not set
#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
# Plug and Play configuration
#
# CONFIG_PNP is not set
@@ -84,8 +88,10 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_MD is not set
# CONFIG_MD_LINEAR is not set
# CONFIG_MD_RAID0 is not set
-# CONFIG_RAID15_DANGEROUS is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
#
@@ -105,17 +111,11 @@ CONFIG_IP_MULTICAST=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP 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_INET_ECN is not set
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
@@ -126,9 +126,9 @@ CONFIG_SKB_LARGE=y
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_DECNET is not set
+# CONFIG_BRIDGE 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
@@ -164,6 +164,7 @@ CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
# CONFIG_ETHERTAP is not set
# CONFIG_NET_SB1000 is not set
@@ -245,6 +246,15 @@ CONFIG_NET_ETHERNET=y
# CONFIG_FB is not set
#
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
# Character devices
#
# CONFIG_VT is not set
@@ -269,19 +279,19 @@ CONFIG_UNIX98_PTY_COUNT=256
# Joysticks
#
# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
# CONFIG_QIC02_TAPE is not set
#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -290,9 +300,13 @@ CONFIG_UNIX98_PTY_COUNT=256
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
#
# File systems
@@ -310,6 +324,7 @@ CONFIG_UNIX98_PTY_COUNT=256
# CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_RAMFS is not set
# CONFIG_ISO9660_FS is not set
@@ -369,6 +384,7 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_MAC_PARTITION is not set
# CONFIG_MSDOS_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
# CONFIG_NLS is not set
@@ -382,7 +398,7 @@ CONFIG_PARTITION_ADVANCED=y
#
CONFIG_SCC_ENET=y
CONFIG_SCC1_ENET=y
-# CONFIG_FCC_ENET is not set
+# CONFIG_FEC_ENET is not set
#
# USB support
diff --git a/arch/ppc/configs/gemini_defconfig b/arch/ppc/configs/gemini_defconfig
index e141e8f54..522bd5d5d 100644
--- a/arch/ppc/configs/gemini_defconfig
+++ b/arch/ppc/configs/gemini_defconfig
@@ -14,14 +14,12 @@ CONFIG_EXPERIMENTAL=y
CONFIG_PPC=y
CONFIG_6xx=y
# CONFIG_4xx is not set
-# CONFIG_PPC64BRIDGE is not set
-# CONFIG_82xx is not set
+# CONFIG_PPC64 is not set
+# CONFIG_8260 is not set
# CONFIG_8xx is not set
-# CONFIG_PMAC is not set
-# CONFIG_PREP is not set
-# CONFIG_CHRP is not set
# CONFIG_ALL_PPC is not set
CONFIG_GEMINI=y
+# CONFIG_EST8260 is not set
# CONFIG_APUS is not set
# CONFIG_SMP is not set
CONFIG_ALTIVEC=y
@@ -37,7 +35,8 @@ CONFIG_KMOD=y
#
# General setup
#
-# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_SBUS is not set
CONFIG_PCI=y
CONFIG_NET=y
CONFIG_SYSCTL=y
@@ -47,8 +46,12 @@ CONFIG_KCORE_ELF=y
CONFIG_BINFMT_ELF=y
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
+#
# CONFIG_PARPORT is not set
# CONFIG_VGA_CONSOLE is not set
# CONFIG_FB is not set
@@ -57,7 +60,6 @@ CONFIG_KERNEL_ELF=y
# CONFIG_MAC_SERIAL is not set
# CONFIG_ADB is not set
# CONFIG_PROC_DEVICETREE is not set
-# CONFIG_TOTALMP is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_MOTOROLA_HOTSWAP is not set
@@ -70,22 +72,16 @@ CONFIG_KERNEL_ELF=y
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_IDE is not set
#
-# Please see Documentation/ide.txt for help/info on IDE drives
+# Additional Block Devices
#
-# CONFIG_BLK_DEV_HD_ONLY is not set
-# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_LVM is not set
# CONFIG_BLK_DEV_MD is not set
+# CONFIG_RAID15_DANGEROUS is not set
# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
-# CONFIG_BLK_DEV_HD is not set
#
# Networking options
@@ -138,6 +134,13 @@ CONFIG_SKB_LARGE=y
# CONFIG_NET_SCHED is not set
#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
# SCSI support
#
CONFIG_SCSI=y
@@ -148,7 +151,6 @@ CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_SD_EXTRA_DEVS=40
# CONFIG_CHR_DEV_ST is not set
-CONFIG_ST_EXTRA_DEVS=2
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_SR_EXTRA_DEVS=2
@@ -171,7 +173,6 @@ CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_AHA1542 is not set
# CONFIG_SCSI_AHA1740 is not set
# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
# CONFIG_SCSI_AM53C974 is not set
@@ -184,43 +185,22 @@ CONFIG_SCSI_CONSTANTS=y
# 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_SIM710 is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-# CONFIG_SCSI_NCR53C8XX is not set
-CONFIG_SCSI_SYM53C8XX=y
-CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
-CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
-CONFIG_SCSI_NCR53C8XX_SYNC=20
-# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set
-# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
+# CONFIG_SCSI_NCR53C7xx_sync is not set
+# CONFIG_SCSI_NCR53C7xx_FAST is not set
+# CONFIG_SCSI_NCR53C7xx_DISCONNECT 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_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 is not set
# CONFIG_SCSI_MAC53C94 is not set
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
#
# Network device support
@@ -232,6 +212,7 @@ CONFIG_NETDEVICES=y
#
# CONFIG_ARCNET is not set
# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_ETHERTAP is not set
# CONFIG_NET_SB1000 is not set
@@ -249,12 +230,10 @@ CONFIG_NCR885E=y
# 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_DM9102 is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
# CONFIG_NET_ISA is not set
-# CONFIG_NET_EISA is not set
+# CONFIG_NET_PCI is not set
# CONFIG_NET_POCKET is not set
#
@@ -274,7 +253,7 @@ CONFIG_NCR885E=y
# CONFIG_NET_RADIO is not set
#
-# Token Ring driver support
+# Token Ring devices
#
# CONFIG_TR is not set
# CONFIG_NET_FC is not set
@@ -292,6 +271,11 @@ CONFIG_NCR885E=y
# CONFIG_HAMRADIO is not set
#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -361,12 +345,7 @@ CONFIG_UNIX98_PTY_COUNT=256
# CONFIG_AGP is not set
#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# Filesystems
+# File systems
#
# CONFIG_QUOTA is not set
# CONFIG_AUTOFS_FS is not set
@@ -378,12 +357,14 @@ CONFIG_UNIX98_PTY_COUNT=256
# CONFIG_FAT_FS is not set
# 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_HPFS_FS is not set
CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -397,6 +378,7 @@ CONFIG_EXT2_FS=y
#
# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
# CONFIG_NFSD is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
@@ -416,6 +398,11 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SOUND is not set
#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
# Kernel hacking
#
# CONFIG_MAGIC_SYSRQ is not set
diff --git a/arch/ppc/configs/rpxcllf_defconfig b/arch/ppc/configs/rpxcllf_defconfig
index 9aaa80530..4dda3d93f 100644
--- a/arch/ppc/configs/rpxcllf_defconfig
+++ b/arch/ppc/configs/rpxcllf_defconfig
@@ -9,18 +9,27 @@
CONFIG_EXPERIMENTAL=y
#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
# Platform support
#
CONFIG_PPC=y
# CONFIG_6xx is not set
# CONFIG_4xx is not set
-# CONFIG_PPC64BRIDGE is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
# CONFIG_8260 is not set
CONFIG_8xx=y
CONFIG_SERIAL_CONSOLE=y
# CONFIG_RPXLITE is not set
CONFIG_RPXCLASSIC=y
# CONFIG_BSEIP is not set
+# CONFIG_TQM8xxL is not set
+# CONFIG_TQM860L is not set
+# CONFIG_TQM860 is not set
# CONFIG_MBX is not set
# CONFIG_WINCEPT is not set
# CONFIG_ALL_PPC is not set
@@ -29,13 +38,9 @@ CONFIG_MACH_SPECIFIC=y
CONFIG_MATH_EMULATION=y
#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
# General setup
#
+# CONFIG_HIGHMEM is not set
# CONFIG_ISA is not set
# CONFIG_SBUS is not set
# CONFIG_PCI is not set
@@ -56,6 +61,11 @@ CONFIG_KERNEL_ELF=y
# CONFIG_PARPORT is not set
#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
# Plug and Play configuration
#
# CONFIG_PNP is not set
@@ -75,8 +85,10 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_MD is not set
# CONFIG_MD_LINEAR is not set
# CONFIG_MD_RAID0 is not set
-# CONFIG_RAID15_DANGEROUS is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
#
@@ -96,17 +108,11 @@ CONFIG_IP_MULTICAST=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP 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_INET_ECN is not set
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
@@ -117,9 +123,9 @@ CONFIG_SKB_LARGE=y
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_DECNET is not set
+# CONFIG_BRIDGE 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
@@ -155,6 +161,7 @@ CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
# CONFIG_ETHERTAP is not set
# CONFIG_NET_SB1000 is not set
@@ -236,6 +243,15 @@ CONFIG_NET_ETHERNET=y
# CONFIG_FB is not set
#
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
# Character devices
#
# CONFIG_VT is not set
@@ -260,19 +276,19 @@ CONFIG_UNIX98_PTY_COUNT=256
# Joysticks
#
# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
# CONFIG_QIC02_TAPE is not set
#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -281,9 +297,13 @@ CONFIG_UNIX98_PTY_COUNT=256
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
#
# File systems
@@ -301,6 +321,7 @@ CONFIG_UNIX98_PTY_COUNT=256
# CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_RAMFS is not set
# CONFIG_ISO9660_FS is not set
@@ -360,6 +381,7 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_MAC_PARTITION is not set
# CONFIG_MSDOS_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
# CONFIG_NLS is not set
@@ -374,7 +396,9 @@ CONFIG_PARTITION_ADVANCED=y
CONFIG_SCC_ENET=y
CONFIG_SCC1_ENET=y
CONFIG_FEC_ENET=y
+CONFIG_ENET_BIG_BUFFERS=y
CONFIG_8xxSMC2=y
+# CONFIG_8xx_ALTSMC2 is not set
CONFIG_8xxSCC=y
#
diff --git a/arch/ppc/defconfig b/arch/ppc/defconfig
index e1854fad6..9b3d88212 100644
--- a/arch/ppc/defconfig
+++ b/arch/ppc/defconfig
@@ -1,5 +1,5 @@
#
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
#
# CONFIG_UID16 is not set
@@ -9,12 +9,20 @@
CONFIG_EXPERIMENTAL=y
#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
# Platform support
#
CONFIG_PPC=y
CONFIG_6xx=y
# CONFIG_4xx is not set
-# CONFIG_PPC64BRIDGE is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
# CONFIG_8260 is not set
# CONFIG_8xx is not set
CONFIG_ALL_PPC=y
@@ -25,15 +33,9 @@ CONFIG_ALL_PPC=y
CONFIG_ALTIVEC=y
#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
# General setup
#
+# CONFIG_HIGHMEM is not set
# CONFIG_ISA is not set
# CONFIG_SBUS is not set
CONFIG_PCI=y
@@ -44,8 +46,8 @@ CONFIG_SYSVIPC=y
CONFIG_KCORE_ELF=y
CONFIG_BINFMT_ELF=y
CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_PCI_NAMES is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_PCI_NAMES=y
# CONFIG_HOTPLUG is not set
# CONFIG_PCMCIA is not set
@@ -57,21 +59,18 @@ CONFIG_VGA_CONSOLE=y
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_ADBMOUSE=y
+CONFIG_PPC_RTC=y
CONFIG_PROC_DEVICETREE=y
CONFIG_BOOTX_TEXT=y
# CONFIG_MOTOROLA_HOTSWAP is not set
# CONFIG_CMDLINE_BOOL is not set
#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
# Plug and Play configuration
#
# CONFIG_PNP is not set
@@ -90,8 +89,11 @@ CONFIG_BLK_DEV_LOOP=y
# 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_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
#
@@ -109,22 +111,24 @@ 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_INET_ECN is not set
CONFIG_SYN_COOKIES=y
-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_BRIDGE 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
@@ -145,26 +149,42 @@ 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_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO 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_IDEFLOPPY=y
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_IDEPCI_SHARE_IRQ=y
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_IDEDMA_PCI_AUTO=y
CONFIG_BLK_DEV_IDEDMA=y
-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
@@ -173,37 +193,40 @@ CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
# 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_CMD64X=y
# 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_SL82C105=y
CONFIG_BLK_DEV_IDE_PMAC=y
CONFIG_BLK_DEV_IDEDMA_PMAC=y
-CONFIG_IDEDMA_PMAC_AUTO=y
+CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO=y
CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_BLK_DEV_IDEPCI=y
# CONFIG_IDE_CHIPSETS is not set
CONFIG_IDEDMA_AUTO=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_DMA_NONPCI is not set
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
@@ -211,6 +234,10 @@ 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
@@ -296,6 +323,7 @@ CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
# CONFIG_ETHERTAP is not set
# CONFIG_NET_SB1000 is not set
@@ -327,8 +355,9 @@ CONFIG_DE4X5=y
# CONFIG_DM9102 is not set
# CONFIG_EEPRO100 is not set
# CONFIG_LNE390 is not set
-# CONFIG_NE3210 is not set
+# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
+# CONFIG_NE3210 is not set
# CONFIG_RTL8129 is not set
# CONFIG_8139TOO is not set
# CONFIG_SIS900 is not set
@@ -347,11 +376,13 @@ 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_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=y
# CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
+CONFIG_PPP_DEFLATE=y
# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
# CONFIG_SLIP is not set
#
@@ -404,12 +435,13 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_FB_RIVA is not set
# CONFIG_FB_CLGEN is not set
# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 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_IMSTT=y
# CONFIG_FB_S3TRIO is not set
# CONFIG_FB_VGA16 is not set
CONFIG_FB_MATROX=y
@@ -420,6 +452,7 @@ CONFIG_FB_MATROX_G100=y
CONFIG_FB_ATY=y
CONFIG_FB_ATY128=y
CONFIG_FB_3DFX=y
+# CONFIG_FB_SIS is not set
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FBCON_ADVANCED is not set
CONFIG_FBCON_CFB8=y
@@ -437,6 +470,32 @@ CONFIG_FONT_SUN12x22=y
# CONFIG_FONT_ACORN_8x8 is not set
#
+# Input core support
+#
+CONFIG_INPUT=y
+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=y
+
+#
+# Macintosh device drivers
+#
+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_INPUT_ADBHID=y
+CONFIG_MAC_HID=y
+CONFIG_MAC_ADBKEYCODES=y
+CONFIG_MAC_EMUMOUSEBTN=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -459,7 +518,6 @@ 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=y
CONFIG_PSMOUSE=y
# CONFIG_82C710_MOUSE is not set
@@ -469,19 +527,19 @@ CONFIG_PSMOUSE=y
# Joysticks
#
# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
# CONFIG_QIC02_TAPE is not set
#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
CONFIG_NVRAM=y
# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -490,26 +548,31 @@ CONFIG_NVRAM=y
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
#
# File systems
#
# CONFIG_QUOTA is not set
CONFIG_AUTOFS_FS=y
-# CONFIG_AUTOFS4_FS is not set
+CONFIG_AUTOFS4_FS=y
# CONFIG_ADFS_FS is not set
# CONFIG_ADFS_FS_RW is not set
# CONFIG_AFFS_FS is not set
-CONFIG_HFS_FS=y
+# CONFIG_HFS_FS is not set
# CONFIG_BFS_FS is not set
CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y
# CONFIG_UMSDOS_FS is not set
CONFIG_VFAT_FS=y
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_RAMFS is not set
CONFIG_ISO9660_FS=y
@@ -519,7 +582,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
+CONFIG_DEVFS_FS=y
# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
@@ -572,12 +635,14 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
CONFIG_NLS=y
#
# Native Language Support
#
+CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_437 is not set
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
@@ -594,6 +659,10 @@ CONFIG_NLS=y
# CONFIG_NLS_CODEPAGE_866 is not set
# CONFIG_NLS_CODEPAGE_869 is not set
# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
# CONFIG_NLS_ISO8859_1 is not set
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
@@ -606,6 +675,7 @@ CONFIG_NLS=y
# CONFIG_NLS_ISO8859_14 is not set
# CONFIG_NLS_ISO8859_15 is not set
# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_UTF8 is not set
#
# Sound
@@ -615,6 +685,7 @@ CONFIG_DMASOUND_AWACS=y
CONFIG_DMASOUND=y
# CONFIG_SOUND_CMPCI is not set
# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
# CONFIG_SOUND_ES1370 is not set
# CONFIG_SOUND_ES1371 is not set
# CONFIG_SOUND_ESSSOLO1 is not set
@@ -623,6 +694,7 @@ CONFIG_DMASOUND=y
# CONFIG_SOUND_TRIDENT is not set
# CONFIG_SOUND_MSNDCLAS is not set
# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
CONFIG_SOUND_OSS=y
# CONFIG_SOUND_TRACEINIT is not set
# CONFIG_SOUND_DMAP is not set
@@ -648,24 +720,39 @@ CONFIG_SOUND_CS4232=m
# CONFIG_SOUND_AWE32_SYNTH is not set
# CONFIG_SOUND_WAVEFRONT is not set
# CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_VIA82CXXX is not set
# CONFIG_SOUND_YM3812 is not set
# CONFIG_SOUND_OPL3SA1 is not set
# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_YMPCI is not set
# CONFIG_SOUND_UART6850 is not set
# CONFIG_SOUND_AEDSP16 is not set
+# CONFIG_SOUND_TVMIXER is not set
#
# USB support
#
CONFIG_USB=y
CONFIG_USB_DEBUG=y
-# CONFIG_USB_DEVICEFS is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+
+#
+# USB Controllers
+#
# CONFIG_USB_UHCI is not set
# CONFIG_USB_UHCI_ALT is not set
CONFIG_USB_OHCI=y
+
+#
+# USB Devices
+#
# CONFIG_USB_PRINTER is not set
# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_MICROTEK is not set
# CONFIG_USB_AUDIO is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_SERIAL is not set
@@ -680,15 +767,18 @@ CONFIG_USB_OHCI=y
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_DSBR is not set
+# CONFIG_USB_BLUETOOTH is not set
+
+#
+# USB Human Interface Devices (HID)
+#
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
+
+#
+# Mac-on-Linux (MOL) support
+#
+# CONFIG_MOL is not set
#
# Kernel hacking
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index 0369ad800..a539083bd 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -99,8 +99,10 @@ endif
ifeq ($(CONFIG_ALL_PPC),y)
O_OBJS += pmac_pic.o pmac_setup.o pmac_time.o feature.o pmac_pci.o prom.o \
chrp_setup.o chrp_time.o chrp_pci.o open_pic.o indirect_pci.o \
- prep_pci.o i8259.o prep_nvram.o prep_time.o residual.o \
- pmac_backlight.o
+ prep_pci.o i8259.o prep_nvram.o prep_time.o residual.o
+ ifeq ($(CONFIG_PMAC_BACKLIGHT),y)
+ O_OBJS += pmac_backlight.o
+ endif
OX_OBJS += prep_setup.o
endif
ifeq ($(CONFIG_GEMINI),y)
diff --git a/arch/ppc/kernel/apus_setup.c b/arch/ppc/kernel/apus_setup.c
index b93bd8193..d75663be5 100644
--- a/arch/ppc/kernel/apus_setup.c
+++ b/arch/ppc/kernel/apus_setup.c
@@ -304,7 +304,7 @@ __apus
void apus_calibrate_decr(void)
{
#ifdef CONFIG_APUS
- int freq, divisor;
+ unsigned long freq;
/* This algorithm for determining the bus speed was
contributed by Ralph Schmidt. */
@@ -335,8 +335,8 @@ void apus_calibrate_decr(void)
bus_speed = 60;
freq = 15000000;
} else if ((bus_speed >= 63) && (bus_speed < 69)) {
- bus_speed = 66;
- freq = 16500000;
+ bus_speed = 67;
+ freq = 16666667;
} else {
printk ("APUS: Unable to determine bus speed (%d). "
"Defaulting to 50MHz", bus_speed);
@@ -375,12 +375,10 @@ void apus_calibrate_decr(void)
}
- freq *= 60; /* try to make freq/1e6 an integer */
- divisor = 60;
- printk("time_init: decrementer frequency = %d/%d\n", freq, divisor);
- decrementer_count = freq / HZ / divisor;
- count_period_num = divisor;
- count_period_den = freq / 1000000;
+ printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ freq/1000000, freq%1000000);
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
__bus_speed = bus_speed;
__speed_test_failed = speed_test_failed;
diff --git a/arch/ppc/kernel/chrp_pci.c b/arch/ppc/kernel/chrp_pci.c
index c43296c42..43b678861 100644
--- a/arch/ppc/kernel/chrp_pci.c
+++ b/arch/ppc/kernel/chrp_pci.c
@@ -284,13 +284,38 @@ hydra_init(void)
return 1;
}
+#ifdef CONFIG_POWER4
+static void
+power4_fixup_dev(struct pci_dev *dev)
+{
+ int i;
+ unsigned long offset;
+
+ for (i = 0; i < 6; ++i) {
+ if (dev->resource[i].start == 0)
+ continue;
+ offset = pci_address_offset(dev->bus->number,
+ dev->resource[i].flags);
+ if (offset) {
+ dev->resource[i].start += offset;
+ dev->resource[i].end += offset;
+ printk("device %x.%x[%d] now [%lx..%lx]\n",
+ dev->bus->number, dev->devfn, i,
+ dev->resource[i].start,
+ dev->resource[i].end);
+ }
+ /* zap the 2nd function of the winbond chip */
+ if (dev->resource[i].flags & IORESOURCE_IO
+ && dev->bus->number == 0 && dev->devfn == 0x81)
+ dev->resource[i].flags &= ~IORESOURCE_IO;
+ }
+}
+#endif /* CONFIG_POWER4 */
+
void __init
chrp_pcibios_fixup(void)
{
struct pci_dev *dev;
-#ifdef CONFIG_POWER4
- int i;
-#endif
int *brp;
struct device_node *np;
extern struct pci_ops generic_pci_ops;
@@ -316,10 +341,8 @@ chrp_pcibios_fixup(void)
/* PCI interrupts are controlled by the OpenPIC */
pci_for_each_dev(dev) {
np = find_pci_device_OFnode(dev->bus->number, dev->devfn);
- if ( (np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0))
+ if ((np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0))
dev->irq = np->intrs[0].line;
- if ( dev->irq )
- dev->irq = openpic_to_irq( dev->irq );
/* these need to be absolute addrs for OF and Matrox FB -- Cort */
if ( dev->vendor == PCI_VENDOR_ID_MATROX )
{
@@ -337,25 +360,7 @@ chrp_pcibios_fixup(void)
dev->devfn, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
}
#ifdef CONFIG_POWER4
- for (i = 0; i < 6; ++i) {
- unsigned long offset;
- if (dev->resource[i].start == 0)
- continue;
- offset = pci_address_offset(dev->bus->number,
- dev->resource[i].flags);
- if (offset) {
- dev->resource[i].start += offset;
- dev->resource[i].end += offset;
- printk("device %x.%x[%d] now [%lx..%lx]\n",
- dev->bus->number, dev->devfn, i,
- dev->resource[i].start,
- dev->resource[i].end);
- }
- /* zap the 2nd function of the winbond chip */
- if (dev->resource[i].flags & IORESOURCE_IO
- && dev->bus->number == 0 && dev->devfn == 0x81)
- dev->resource[i].flags &= ~IORESOURCE_IO;
- }
+ power4_fixup_dev(dev);
#else
if (dev->bus->number > 0 && python_busnr > 0)
dev->resource[0].start += dev->bus->number*0x01000000;
@@ -363,6 +368,40 @@ chrp_pcibios_fixup(void)
}
}
+static struct {
+ /* parent is iomem */
+ struct resource ram, pci_mem, isa_mem, pci_io, pci_cfg, rom_exp, flash;
+ /* parent is isa_mem */
+ struct resource nvram;
+} gg2_resources = {
+ ram: { "RAM", 0x00000000, 0xbfffffff, IORESOURCE_MEM },
+ pci_mem: { "GG2 PCI mem", 0xc0000000, 0xf6ffffff, IORESOURCE_MEM },
+ isa_mem: { "GG2 ISA mem", 0xf7000000, 0xf7ffffff },
+ pci_io: { "GG2 PCI I/O", 0xf8000000, 0xf8ffffff },
+ pci_cfg: { "GG2 PCI cfg", 0xfec00000, 0xfec7ffff },
+ rom_exp: { "ROM exp", 0xff000000, 0xff7fffff, },
+ flash: { "Flash ROM", 0xfff80000, 0xffffffff },
+ nvram: { "NVRAM", 0xf70e0000, 0xf70e7fff },
+};
+
+static void __init gg2_pcibios_fixup(void)
+{
+ int i;
+ extern unsigned long *end_of_DRAM;
+
+ chrp_pcibios_fixup();
+ gg2_resources.ram.end = (unsigned long)end_of_DRAM-PAGE_OFFSET;
+ for (i = 0; i < 7; i++)
+ request_resource(&iomem_resource,
+ &((struct resource *)&gg2_resources)[i]);
+ request_resource(&gg2_resources.isa_mem, &gg2_resources.nvram);
+}
+
+static void __init gg2_pcibios_fixup_bus(struct pci_bus *bus)
+{
+ bus->resource[1] = &gg2_resources.pci_mem;
+}
+
decl_config_access_method(grackle);
decl_config_access_method(indirect);
decl_config_access_method(rtas);
@@ -372,6 +411,7 @@ chrp_setup_pci_ptrs(void)
{
struct device_node *py;
+ ppc_md.pcibios_fixup = chrp_pcibios_fixup;
#ifdef CONFIG_POWER4
set_config_access_method(rtas);
pci_dram_offset = 0;
@@ -428,16 +468,17 @@ chrp_setup_pci_ptrs(void)
}
else
{
+ /* LongTrail */
pci_dram_offset = 0;
isa_mem_base = 0xf7000000;
isa_io_base = 0xf8000000;
set_config_access_method(gg2);
+ ppc_md.pcibios_fixup = gg2_pcibios_fixup;
+ ppc_md.pcibios_fixup_bus = gg2_pcibios_fixup_bus;
}
}
}
#endif /* CONFIG_POWER4 */
-
- ppc_md.pcibios_fixup = chrp_pcibios_fixup;
}
#ifdef CONFIG_PPC64BRIDGE
diff --git a/arch/ppc/kernel/chrp_setup.c b/arch/ppc/kernel/chrp_setup.c
index 8d6649231..ccc6621de 100644
--- a/arch/ppc/kernel/chrp_setup.c
+++ b/arch/ppc/kernel/chrp_setup.c
@@ -62,11 +62,13 @@ extern volatile unsigned char *chrp_int_ack_special;
unsigned long chrp_get_rtc_time(void);
int chrp_set_rtc_time(unsigned long nowtime);
void chrp_calibrate_decr(void);
-void chrp_time_init(void);
+long chrp_time_init(void);
void chrp_setup_pci_ptrs(void);
-extern void chrp_progress(char *, unsigned short);
void chrp_event_scan(void);
+void rtas_display_progress(char *, unsigned short);
+void rtas_indicator_progress(char *, unsigned short);
+void bootx_text_progress(char *, unsigned short);
extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
extern int pckbd_getkeycode(unsigned int scancode);
@@ -91,6 +93,8 @@ extern PTE *Hash, *Hash_end;
extern unsigned long Hash_size, Hash_mask;
extern int probingmem;
extern unsigned long loops_per_sec;
+extern int bootx_text_mapped;
+static int max_width;
unsigned long empty_zero_page[1024];
@@ -252,13 +256,6 @@ chrp_setup_arch(void)
#endif
ROOT_DEV = to_kdev_t(0x0802); /* sda2 (sda1 is for the kernel) */
printk("Boot arguments: %s\n", cmd_line);
-
- request_region(0x20,0x20,"pic1");
- request_region(0xa0,0x20,"pic2");
- request_region(0x00,0x20,"dma1");
- request_region(0x40,0x20,"timer");
- request_region(0x80,0x10,"dma page reg");
- request_region(0xc0,0x20,"dma2");
#ifndef CONFIG_PPC64BRIDGE
/* PCI bridge config space access area -
@@ -446,11 +443,43 @@ void __init chrp_init_IRQ(void)
void __init
chrp_init2(void)
{
+#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD)
+ struct device_node *kbd;
+#endif
#ifdef CONFIG_NVRAM
pmac_nvram_init();
#endif
+
+ request_region(0x20,0x20,"pic1");
+ request_region(0xa0,0x20,"pic2");
+ request_region(0x00,0x20,"dma1");
+ request_region(0x40,0x20,"timer");
+ request_region(0x80,0x10,"dma page reg");
+ request_region(0xc0,0x20,"dma2");
+
if (ppc_md.progress)
ppc_md.progress(" Have fun! ", 0x7777);
+
+#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD)
+ /* see if there is a keyboard in the device tree
+ with a parent of type "adb" */
+ for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next)
+ if (kbd->parent && kbd->parent->type
+ && strcmp(kbd->parent->type, "adb") == 0)
+ break;
+ if (kbd) {
+ ppc_md.kbd_setkeycode = mackbd_setkeycode;
+ ppc_md.kbd_getkeycode = mackbd_getkeycode;
+ ppc_md.kbd_translate = mackbd_translate;
+ ppc_md.kbd_unexpected_up = mackbd_unexpected_up;
+ ppc_md.kbd_leds = mackbd_leds;
+ ppc_md.kbd_init_hw = mackbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.ppc_kbd_sysrq_xlate = mackbd_sysrq_xlate;
+ SYSRQ_KEY = 0x69;
+#endif /* CONFIG_MAGIC_SYSRQ */
+ }
+#endif /* CONFIG_VT && CONFIG_ADB_KEYBOARD */
}
#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
@@ -598,40 +627,40 @@ void __init
ppc_md.calibrate_decr = chrp_calibrate_decr;
#ifdef CONFIG_VT
-#ifdef CONFIG_MAC_KEYBOARD
- if (adb_driver == NULL)
- {
-#endif /* CONFIG_MAC_KEYBOAD */
- ppc_md.kbd_setkeycode = pckbd_setkeycode;
- ppc_md.kbd_getkeycode = pckbd_getkeycode;
- 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.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate;
- SYSRQ_KEY = 0x54;
-#endif /* CONFIG_MAGIC_SYSRQ */
-#ifdef CONFIG_MAC_KEYBOARD
- }
- else
- {
- ppc_md.kbd_setkeycode = mackbd_setkeycode;
- ppc_md.kbd_getkeycode = mackbd_getkeycode;
- ppc_md.kbd_translate = mackbd_translate;
- ppc_md.kbd_unexpected_up = mackbd_unexpected_up;
- ppc_md.kbd_leds = mackbd_leds;
- ppc_md.kbd_init_hw = mackbd_init_hw;
+ /* these are adjusted in chrp_init2 if we have an ADB keyboard */
+ ppc_md.kbd_setkeycode = pckbd_setkeycode;
+ ppc_md.kbd_getkeycode = pckbd_getkeycode;
+ 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.ppc_kbd_sysrq_xlate = mackbd_sysrq_xlate;
- SYSRQ_KEY = 0x69;
+ ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate;
+ SYSRQ_KEY = 0x54;
#endif /* CONFIG_MAGIC_SYSRQ */
- }
-#endif /* CONFIG_MAC_KEYBOARD */
#endif /* CONFIG_VT */
- if ( rtas_data )
- ppc_md.progress = chrp_progress;
-
+
+ if (rtas_data) {
+ struct device_node *rtas;
+ unsigned int *p;
+
+ rtas = find_devices("rtas");
+ if (rtas != NULL) {
+ if (get_property(rtas, "display-character", NULL)) {
+ ppc_md.progress = rtas_display_progress;
+ p = (unsigned int *) get_property
+ (rtas, "ibm,display-line-length", NULL);
+ if (p)
+ max_width = *p;
+ } else if (get_property(rtas, "set-indicator", NULL))
+ ppc_md.progress = rtas_indicator_progress;
+ }
+ }
+#ifdef CONFIG_BOOTX_TEXT
+ if (ppc_md.progress == NULL && bootx_text_mapped)
+ ppc_md.progress = bootx_text_progress;
+#endif
+
#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
ppc_ide_md.insw = chrp_ide_insw;
ppc_ide_md.outsw = chrp_ide_outsw;
@@ -653,30 +682,13 @@ void __init
}
void __chrp
-chrp_progress(char *s, unsigned short hex)
+rtas_display_progress(char *s, unsigned short hex)
{
- extern unsigned int rtas_data;
- int max_width, width;
- struct device_node *root;
+ int width;
char *os = s;
- unsigned long *p;
- if ( (root = find_path_device("/rtas")) &&
- (p = (unsigned long *)get_property(root,
- "ibm,display-line-length",
- NULL)) )
- max_width = *p;
- else
- max_width = 0x10;
-
- if ( (_machine != _MACH_chrp) || !rtas_data )
- return;
if ( call_rtas( "display-character", 1, 1, NULL, '\r' ) )
- {
- /* assume no display-character RTAS method - use hex display */
- call_rtas("set-indicator", 3, 1, NULL, 6, 0, hex);
return;
- }
width = max_width;
while ( *os )
@@ -696,3 +708,17 @@ chrp_progress(char *s, unsigned short hex)
call_rtas( "display-character", 1, 1, NULL, ' ' );
}
+void __chrp
+rtas_indicator_progress(char *s, unsigned short hex)
+{
+ call_rtas("set-indicator", 3, 1, NULL, 6, 0, hex);
+}
+
+#ifdef CONFIG_BOOTX_TEXT
+void
+bootx_text_progress(char *s, unsigned short hex)
+{
+ prom_print(s);
+ prom_print("\n");
+}
+#endif /* CONFIG_BOOTX_TEXT */
diff --git a/arch/ppc/kernel/chrp_time.c b/arch/ppc/kernel/chrp_time.c
index 54b4a76bb..67325c685 100644
--- a/arch/ppc/kernel/chrp_time.c
+++ b/arch/ppc/kernel/chrp_time.c
@@ -15,6 +15,7 @@
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
+#include <linux/time.h>
#include <linux/timex.h>
#include <linux/kernel_stat.h>
#include <linux/mc146818rtc.h>
@@ -32,18 +33,20 @@ static int nvram_as1 = NVRAM_AS1;
static int nvram_as0 = NVRAM_AS0;
static int nvram_data = NVRAM_DATA;
-void __init chrp_time_init(void)
+long __init chrp_time_init(void)
{
struct device_node *rtcs;
int base;
rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
if (rtcs == NULL || rtcs->addrs == NULL)
- return;
+ return 0;
base = rtcs->addrs[0].address;
nvram_as1 = 0;
nvram_as0 = base;
nvram_data = base + 1;
+
+ return 0;
}
int __chrp chrp_cmos_clock_read(int addr)
@@ -115,28 +118,34 @@ int __chrp chrp_set_rtc_time(unsigned long nowtime)
unsigned long __chrp chrp_get_rtc_time(void)
{
unsigned int year, mon, day, hour, min, sec;
- int i;
+ int uip, i;
/* The Linux interpretation of the CMOS clock register contents:
* When the Update-In-Progress (UIP) flag goes from 1 to 0, the
* RTC registers show the second which has precisely just started.
* Let's hope other operating systems interpret the RTC the same way.
*/
- /* read RTC exactly on falling edge of update flag */
- for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (chrp_cmos_clock_read(RTC_FREQ_SELECT) & RTC_UIP)
- break;
- for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
- if (!(chrp_cmos_clock_read(RTC_FREQ_SELECT) & RTC_UIP))
- break;
- do { /* Isn't this overkill ? UIP above should guarantee consistency */
+
+ /* Since the UIP flag is set for about 2.2 ms and the clock
+ * is typically written with a precision of 1 jiffy, trying
+ * to obtain a precision better than a few milliseconds is
+ * an illusion. Only consistency is interesting, this also
+ * allows to use the routine for /dev/rtc without a potential
+ * 1 second kernel busy loop triggered by any reader of /dev/rtc.
+ */
+
+ for ( i = 0; i<1000000; i++) {
+ uip = chrp_cmos_clock_read(RTC_FREQ_SELECT);
sec = chrp_cmos_clock_read(RTC_SECONDS);
min = chrp_cmos_clock_read(RTC_MINUTES);
hour = chrp_cmos_clock_read(RTC_HOURS);
day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH);
mon = chrp_cmos_clock_read(RTC_MONTH);
year = chrp_cmos_clock_read(RTC_YEAR);
- } while (sec != chrp_cmos_clock_read(RTC_SECONDS));
+ uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT);
+ if ((uip & RTC_UIP)==0) break;
+ }
+
if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
{
BCD_TO_BIN(sec);
@@ -155,8 +164,7 @@ unsigned long __chrp chrp_get_rtc_time(void)
void __init chrp_calibrate_decr(void)
{
struct device_node *cpu;
- int *fp, divisor;
- unsigned long freq;
+ unsigned int freq, *fp;
if (via_calibrate_decr())
return;
@@ -168,15 +176,13 @@ void __init chrp_calibrate_decr(void)
freq = 16666000; /* hardcoded default */
cpu = find_type_devices("cpu");
if (cpu != 0) {
- fp = (int *) get_property(cpu, "timebase-frequency", NULL);
+ fp = (unsigned int *)
+ get_property(cpu, "timebase-frequency", NULL);
if (fp != 0)
freq = *fp;
}
- freq *= 30;
- divisor = 30;
- printk("time_init: decrementer frequency = %lu/%d (%ld MHz)\n", freq,
- divisor, (freq/divisor)>>20);
- decrementer_count = freq / HZ / divisor;
- count_period_num = divisor;
- count_period_den = freq / 1000000;
+ printk("time_init: decrementer frequency = %u.%.6u MHz\n",
+ freq/1000000, freq%1000000);
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
}
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index d40a54cf1..627cd7a2a 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -30,6 +30,7 @@
#include <linux/errno.h>
#include <linux/sys.h>
#include <linux/config.h>
+#include "mol.h"
#undef SHOW_SYSCALLS
#undef SHOW_SYSCALLS_TASK
@@ -85,7 +86,7 @@ _GLOBAL(DoSyscall)
beq- 10f
cmpi 0,r0,0x6666 /* Special case for 'sys_rt_sigreturn' */
beq- 16f
- lwz r10,TASK_FLAGS(r2)
+ lwz r10,TASK_PTRACE(r2)
andi. r10,r10,PT_TRACESYS
bne- 50f
cmpli 0,r0,NR_syscalls
@@ -241,6 +242,13 @@ _GLOBAL(_switch)
/* XXX it would be nice to find a SPRGx for this on 6xx,7xx too */
lwz r9,PGDIR(r4) /* cache the page table root */
tophys(r9,r9) /* convert to phys addr */
+#ifdef CONFIG_8xx_CPU6
+ lis r6, cpu6_errata_word@h
+ ori r6, r6, cpu6_errata_word@l
+ li r5, 0x3980
+ stw r5, 8(r6)
+ lwz r5, 8(r6)
+#endif
mtspr M_TWB,r9 /* Update MMU base address */
tlbia
SYNC
@@ -349,21 +357,18 @@ ret_to_user_hook:
beq+ restore
li r3,0
addi r4,r1,STACK_FRAME_OVERHEAD
+ MOL_HOOK_MMU(8,r8)
bl do_signal
.globl do_signal_ret
do_signal_ret:
-restore:
- lwz r3,_CTR(r1)
- lwz r0,_LINK(r1)
- mtctr r3
- mtlr r0
+restore:
lwz r3,_XER(r1)
mtspr XER,r3
- REST_10GPRS(3, r1)
- REST_10GPRS(13, r1)
- REST_8GPRS(23, r1)
- REST_GPR(31, r1)
-
+ REST_10GPRS(9,r1)
+ REST_10GPRS(19,r1)
+ REST_2GPRS(29,r1)
+ REST_GPR(31,r1)
+
/* make sure we hard disable here, even if rtl is active, to protect
* SRR[01] and SPRG2 -- Cort
*/
@@ -376,12 +381,28 @@ restore:
lwz r0,_MSR(r1)
andi. r0,r0,MSR_PR
beq+ 1f
+#ifdef CONFIG_ALTIVEC
+ mfpvr r8 /* check if we are on a G4 */
+ srwi r8,r8,16
+ cmpwi r8,PVR_7400@h
+ bne 2f
+ lwz r0,THREAD+THREAD_VRSAVE(r2)
+ mtspr SPRN_VRSAVE,r0 /* if so, restore VRSAVE reg */
+2:
+#endif /* CONFIG_ALTIVEC */
addi r0,r1,INT_FRAME_SIZE /* size of frame */
stw r0,THREAD+KSP(r2) /* save kernel stack pointer */
- tophys(r2,r1)
- CLR_TOP32(r2)
- mtspr SPRG2,r2 /* phys exception stack pointer */
+ tophys(r8,r1)
+ CLR_TOP32(r8)
+ MOL_HOOK_MMU(9, r4) /* mod. r0,r2-r7, lr, ctr */
+ mtspr SPRG2,r8 /* phys exception stack pointer */
1:
+ lwz r3,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r3
+ mtlr r0
+ REST_4GPRS(3, r1)
+ REST_2GPRS(7, r1)
lwz r0,_MSR(r1)
FIX_SRR1(r0,r2)
mtspr SRR1,r0
diff --git a/arch/ppc/kernel/feature.c b/arch/ppc/kernel/feature.c
index 4b63d5dc0..57599917a 100644
--- a/arch/ppc/kernel/feature.c
+++ b/arch/ppc/kernel/feature.c
@@ -24,6 +24,8 @@
#include <asm/errno.h>
#include <asm/ohare.h>
#include <asm/heathrow.h>
+#include <asm/keylargo.h>
+#include <asm/uninorth.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/feature.h>
@@ -34,6 +36,20 @@
#define MAX_FEATURE_OFFSET 0x100
#define FREG(c,r) (&(((c)->reg)[(r)>>2]))
+/* Keylargo reg. access. */
+#define KL_FCR(r) (keylargo_base + ((r) >> 2))
+#define KL_IN(r) (in_le32(KL_FCR(r)))
+#define KL_OUT(r,v) (out_le32(KL_FCR(r), (v)))
+#define KL_BIS(r,v) (KL_OUT((r), KL_IN(r) | (v)))
+#define KL_BIC(r,v) (KL_OUT((r), KL_IN(r) & ~(v)))
+
+/* Uni-N reg. access. Note that Uni-N regs are big endian */
+#define UN_REG(r) (uninorth_base + ((r) >> 2))
+#define UN_IN(r) (in_be32(UN_REG(r)))
+#define UN_OUT(r,v) (out_be32(UN_REG(r), (v)))
+#define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v)))
+#define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v)))
+
typedef struct feature_bit {
int reg; /* reg. offset from mac-io base */
unsigned int polarity; /* 0 = normal, 1 = inverse */
@@ -74,11 +90,45 @@ static fbit feature_bits_ohare_pbook[] = {
{0x38,0,0}, /* FEATURE_Airport_reset */
};
-/* Those bits are from a PowerBook. It's possible that desktop machines
- * based on heathrow need a different definition or some bits removed
+/* Those bits concern heathrow-based desktop machines (Beige G3s). We have removed
+ * the SCC related bits and init them once. They have proven to occasionally cause
+ * problems with the desktop units.
*/
static fbit feature_bits_heathrow[] = {
{0x38,0,0}, /* FEATURE_null */
+ {0x38,0,0}, /* FEATURE_Serial_reset */
+ {0x38,0,0}, /* FEATURE_Serial_enable */
+ {0x38,0,0}, /* FEATURE_Serial_IO_A */
+ {0x38,0,0}, /* 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,0}, /* FEATURE_Mediabay_reset */
+ {0x38,1,0}, /* FEATURE_Mediabay_power */
+ {0x38,0,0}, /* FEATURE_Mediabay_PCI_enable */
+ {0x38,0,HRW_BAY_IDE_ENABLE}, /* FEATURE_IDE1_enable */
+ {0x38,1,HRW_IDE1_RESET_N}, /* FEATURE_IDE1_reset */
+ {0x38,0,0}, /* FEATURE_Mediabay_floppy_enable */
+ {0x38,0,HRW_BMAC_RESET}, /* FEATURE_BMac_reset */
+ {0x38,0,HRW_BMAC_IO_ENABLE}, /* FEATURE_BMac_IO_enable */
+ {0x38,1,0}, /* FEATURE_Modem_power */
+ {0x38,0,HRW_SLOW_SCC_PCLK}, /* FEATURE_Slow_SCC_PCLK */
+ {0x38,1,0}, /* FEATURE_Sound_Power */
+ {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 */
+ {0x38,0,0}, /* FEATURE_Airport_reset */
+};
+
+/* Those bits concern heathrow-based PowerBooks (wallstreet/mainstreet).
+ * Heathrow-based desktop macs (Beige G3s) are _not_ handled here
+ */
+static fbit feature_bits_wallstreet[] = {
+ {0x38,0,0}, /* FEATURE_null */
{0x38,0,HRW_RESET_SCC}, /* FEATURE_Serial_reset */
{0x38,0,HRW_SCC_ENABLE}, /* FEATURE_Serial_enable */
{0x38,0,HRW_SCCA_IO}, /* FEATURE_Serial_IO_A */
@@ -145,32 +195,32 @@ static fbit feature_bits_paddington[] = {
*/
static fbit feature_bits_keylargo[] = {
{0x38,0,0}, /* FEATURE_null */
- {0x38,0,0}, /* FEATURE_Serial_reset */
- {0x38,0,0x00000054}, /* FEATURE_Serial_enable */
- {0x38,0,0}, /* FEATURE_Serial_IO_A */
- {0x38,0,0}, /* FEATURE_Serial_IO_B */
+ {0x38,0,KL0_SCC_RESET}, /* FEATURE_Serial_reset */
+ {0x38,0,KL0_SERIAL_ENABLE}, /* FEATURE_Serial_enable */
+ {0x38,0,KL0_SCC_A_INTF_ENABLE}, /* FEATURE_Serial_IO_A */
+ {0x38,0,KL0_SCC_B_INTF_ENABLE}, /* FEATURE_Serial_IO_B */
{0x38,0,0}, /* FEATURE_SWIM3_enable */
{0x38,0,0}, /* FEATURE_MESH_enable */
{0x3c,0,0}, /* FEATURE_IDE0_enable */
- {0x3c,1,0x01000000}, /* FEATURE_IDE0_reset */
+ {0x3c,1,KL1_EIDE0_RESET_N}, /* FEATURE_IDE0_reset */
{0x38,0,0}, /* FEATURE_IOBUS_enable */
{0x34,1,0x00000200}, /* FEATURE_Mediabay_reset */
{0x34,1,0x00000400}, /* FEATURE_Mediabay_power */
{0x38,0,0}, /* FEATURE_Mediabay_PCI_enable */
{0x3c,0,0x0}, /* FEATURE_IDE1_enable */
- {0x3c,1,0x08000000}, /* FEATURE_IDE1_reset */
+ {0x3c,1,KL1_EIDE1_RESET_N}, /* FEATURE_IDE1_reset */
{0x38,0,0}, /* FEATURE_Mediabay_floppy_enable */
{0x38,0,0}, /* FEATURE_BMac_reset */
{0x38,0,0}, /* FEATURE_BMac_IO_enable */
- {0x40,1,0x02000000}, /* FEATURE_Modem_power */
+ {0x40,1,KL2_MODEM_POWER_N}, /* FEATURE_Modem_power */
{0x38,0,0}, /* FEATURE_Slow_SCC_PCLK */
{0x38,0,0}, /* FEATURE_Sound_Power */
{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 */
+ {0x3c,1,KL1_UIDE_RESET_N}, /* FEATURE_IDE2_reset */
+ {0x34,0,KL_MBCR_MBDEV_ENABLE}, /* FEATURE_Mediabay_IDE_switch */
{0x34,0,0x00000100}, /* FEATURE_Mediabay_content */
- {0x40,1,0x08000000}, /* FEATURE_Airport_reset */
+ {0x40,1,KL2_AIRPORT_RESET_N}, /* FEATURE_Airport_reset */
};
/* definition of a feature controller object */
@@ -190,6 +240,8 @@ feature_lookup_controller(struct device_node *device);
static void heathrow_prepare_for_sleep(struct feature_controller* ctrler);
static void heathrow_wakeup(struct feature_controller* ctrler);
+static void keylargo_init(void);
+static void uninorth_init(void);
static void core99_prepare_for_sleep(struct feature_controller* ctrler);
static void core99_wake_up(struct feature_controller* ctrler);
@@ -228,8 +280,15 @@ feature_init(void)
}
} else if (device_is_compatible(np, "paddington")) {
feature_add_controller(np, feature_bits_paddington);
+ } else if (machine_is_compatible("AAPL,PowerBook1998")) {
+ feature_add_controller(np, feature_bits_wallstreet);
} else {
- feature_add_controller(np, feature_bits_heathrow);
+ struct feature_controller* ctrler =
+ feature_add_controller(np, feature_bits_heathrow);
+ if (ctrler)
+ out_le32(FREG(ctrler,HEATHROW_FEATURE_REG),
+ in_le32(FREG(ctrler,HEATHROW_FEATURE_REG)) | HRW_DEFAULTS);
+
}
np = np->next;
}
@@ -249,14 +308,17 @@ feature_init(void)
np = find_devices("uni-n");
if (np && np->n_addrs > 0) {
uninorth_base = ioremap(np->addrs[0].address, 0x1000);
- rev = (u32 *)get_property(np, "device-rev", NULL);
- if (rev)
- uninorth_rev = *rev;
+ uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
}
if (uninorth_base && keylargo_base)
printk("Uni-N revision: %d, KeyLargo revision: %d\n",
uninorth_rev, keylargo_rev);
+ if (uninorth_base)
+ uninorth_init();
+ if (keylargo_base)
+ keylargo_init();
+
if (controller_count)
printk(KERN_INFO "Registered %d feature controller(s)\n", controller_count);
@@ -440,14 +502,21 @@ feature_set_gmac_power(struct device_node* device, int power)
if (!uninorth_base)
return;
if (power)
- out_le32(uninorth_base + 0x20/4,
- in_le32(uninorth_base + 0x20/4) | 0x02000000);
+ UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
else
- out_le32(uninorth_base + 0x20/4,
- in_le32(uninorth_base + 0x20/4) & ~0x02000000);
+ UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
udelay(20);
}
+void
+feature_set_gmac_phy_reset(struct device_node* device, int reset)
+{
+ if (!keylargo_base)
+ return;
+ out_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET), reset);
+ (void)in_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET));
+}
+
/* Pass the node of the correct controller, please */
void
feature_set_usb_power(struct device_node* device, int power)
@@ -460,6 +529,53 @@ feature_set_firewire_power(struct device_node* device, int power)
{
}
+/* Initialize the Core99 UniNorth host bridge and memory controller
+ */
+static void
+uninorth_init(void)
+{
+ struct device_node* gmac;
+ unsigned long actrl;
+
+ /* Set the arbitrer QAck delay according to what Apple does
+ */
+ actrl = in_be32(UN_REG(UNI_N_ARB_CTRL)) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
+ actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 : UNI_N_ARB_CTRL_QACK_DELAY)
+ << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
+ UN_OUT(UNI_N_ARB_CTRL, actrl);
+
+ /*
+ * Turns OFF the gmac clock. The gmac driver will turn
+ * it back ON when the interface is enabled. This save
+ * power on portables.
+ *
+ * Note: We could also try to turn OFF the PHY. Since this
+ * has to be done by both the gmac driver and this code,
+ * I'll probably end-up moving some of this out of the
+ * modular gmac driver into a non-modular stub containing
+ * some basic PHY management and power management stuffs
+ */
+ gmac = find_devices("ethernet");
+
+ while(gmac) {
+ if (device_is_compatible(gmac, "gmac"))
+ break;
+ gmac = gmac->next;
+ }
+ if (gmac)
+ feature_set_gmac_power(gmac, 0);
+}
+
+/* Initialize the Core99 KeyLargo ASIC. Currently, we just make sure
+ * OpenPIC is enabled
+ */
+static void
+keylargo_init(void)
+{
+ KL_BIS(KEYLARGO_FCR2, KL2_MPIC_ENABLE);
+}
+
+#ifdef CONFIG_PMAC_PBOOK
void
feature_prepare_for_sleep(void)
{
@@ -506,27 +622,28 @@ feature_wake_up(void)
}
}
-static u32 save_fcr0;
-//static u32 save_fcr1;
-//static u32 save_fcr2;
+static u32 save_fcr[5];
static u32 save_mbcr;
static void
heathrow_prepare_for_sleep(struct feature_controller* ctrler)
{
save_mbcr = in_le32(FREG(ctrler, 0x34));
- save_fcr0 = in_le32(FREG(ctrler, 0x38));
+ save_fcr[0] = in_le32(FREG(ctrler, 0x38));
+ save_fcr[1] = in_le32(FREG(ctrler, 0x3c));
- out_le32(FREG(ctrler, 0x38), save_fcr0 & ~HRW_IOBUS_ENABLE);
+ out_le32(FREG(ctrler, 0x38), save_fcr[0] & ~HRW_IOBUS_ENABLE);
}
static void
heathrow_wakeup(struct feature_controller* ctrler)
{
- out_le32(FREG(ctrler, 0x38), save_fcr0);
+ out_le32(FREG(ctrler, 0x38), save_fcr[0]);
+ out_le32(FREG(ctrler, 0x3c), save_fcr[1]);
out_le32(FREG(ctrler, 0x34), save_mbcr);
-
- out_le32(FREG(ctrler, 0x38), save_fcr0 | HRW_IOBUS_ENABLE);
+ mdelay(1);
+ out_le32(FREG(ctrler, 0x38), save_fcr[0] | HRW_IOBUS_ENABLE);
+ mdelay(1);
}
static void
@@ -540,4 +657,4 @@ core99_wake_up(struct feature_controller* ctrler)
{
/* Not yet implemented */
}
-
+#endif /* CONFIG_PMAC_PBOOK */
diff --git a/arch/ppc/kernel/gemini_setup.c b/arch/ppc/kernel/gemini_setup.c
index 7be4675c2..a01ff9eca 100644
--- a/arch/ppc/kernel/gemini_setup.c
+++ b/arch/ppc/kernel/gemini_setup.c
@@ -15,6 +15,7 @@
#include <linux/errno.h>
#include <linux/reboot.h>
#include <linux/pci.h>
+#include <linux/time.h>
#include <linux/kdev_t.h>
#include <linux/types.h>
#include <linux/major.h>
@@ -335,7 +336,7 @@ void __init gemini_init_IRQ(void)
#define gemini_rtc_write(val,x) (writeb((val),(GEMINI_RTC+(x))))
/* ensure that the RTC is up and running */
-void __init gemini_time_init(void)
+long __init gemini_time_init(void)
{
unsigned char reg;
@@ -346,6 +347,7 @@ void __init gemini_time_init(void)
gemini_rtc_write((reg & ~(M48T35_RTC_STOPPED)), M48T35_RTC_CONTROL);
gemini_rtc_write((reg | M48T35_RTC_SET), M48T35_RTC_CONTROL);
}
+ return 0;
}
#undef DEBUG_RTC
diff --git a/arch/ppc/kernel/hashtable.S b/arch/ppc/kernel/hashtable.S
index be86a1503..1129dd40e 100644
--- a/arch/ppc/kernel/hashtable.S
+++ b/arch/ppc/kernel/hashtable.S
@@ -27,6 +27,7 @@
#include <asm/processor.h>
#include <asm/page.h>
#include <linux/config.h>
+#include "mol.h"
/*
* Load a PTE into the hash table, if possible.
@@ -593,6 +594,11 @@ _GLOBAL(flush_hash_segments)
* flush_hash_page(unsigned context, unsigned long va)
*/
_GLOBAL(flush_hash_page)
+#ifdef CONFIG_MOL
+ mflr r10
+ MOL_HOOK_MMU(10, r6)
+ mtlr r10
+#endif
lis r6,Hash@ha
lwz r6,Hash@l(r6) /* hash table base */
cmpwi 0,r6,0 /* hash table in use? */
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index 067581f5d..5d26e2917 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -31,6 +31,7 @@
#include <asm/page.h>
#include <linux/config.h>
#include <asm/mmu.h>
+#include "mol.h"
#ifdef CONFIG_APUS
#include <asm/amigappc.h>
@@ -78,7 +79,7 @@ CACHELINE_WORDS = 32
mtspr DBAT##n##L,RB; \
1:
#endif /* CONFIG_PPC64BRIDGE */
-
+
.text
.globl _stext
_stext:
@@ -162,8 +163,8 @@ __start:
/* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
* the physical address we are running at, returned by prom_init()
*/
-__after_prom_start:
bl mmu_off
+__after_mmu_off:
bl clear_bats
bl flush_tlbs
#endif
@@ -202,15 +203,7 @@ __after_prom_start:
mr r26,r3
addis r4,r3,KERNELBASE@h /* current address of _start */
cmpwi 0,r4,0 /* are we already running at 0? */
- beq 2f /* assume it's OK if so */
- li r3,0
- mfmsr r0
- andi. r0,r0,MSR_DR /* MMU enabled? */
- beq relocate_kernel
- lis r3,KERNELBASE@h /* if so, are we */
- cmpw 0,r4,r3 /* already running at KERNELBASE? */
bne relocate_kernel
-2:
#endif /* CONFIG_APUS */
/*
* we now have the 1st 16M of ram mapped with the bats.
@@ -300,6 +293,17 @@ label: \
.long hdlr; \
.long ret_from_except
+#define STD_MOL_EXCEPTION(n, label, hdlr, hook) \
+ . = n; \
+label: \
+ EXCEPTION_PROLOG; \
+ MOL_HOOK(hook); \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ li r20,MSR_KERNEL; \
+ bl transfer_to_handler; \
+ .long hdlr; \
+ .long ret_from_except
+
/* System reset */
#ifdef CONFIG_SMP /* MVME/MTX and gemini start the secondary here */
#ifdef CONFIG_GEMINI
@@ -324,6 +328,7 @@ DataAccessCont:
DataAccess:
EXCEPTION_PROLOG
#endif /* CONFIG_PPC64BRIDGE */
+ MOL_HOOK(0)
mfspr r20,DSISR
andis. r0,r20,0xa470 /* weird error? */
bne 1f /* if not, try to put a PTE */
@@ -366,6 +371,7 @@ InstructionAccessCont:
InstructionAccess:
EXCEPTION_PROLOG
#endif /* CONFIG_PPC64BRIDGE */
+ MOL_HOOK(1)
andis. r0,r23,0x4000 /* no pte found? */
beq 1f /* if so, try to put a PTE */
mr r3,r22 /* into the hash table */
@@ -430,6 +436,7 @@ Alignment:
. = 0x700
ProgramCheck:
EXCEPTION_PROLOG
+ MOL_HOOK(2)
addi r3,r1,STACK_FRAME_OVERHEAD
li r20,MSR_KERNEL
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
@@ -441,6 +448,7 @@ ProgramCheck:
. = 0x800
FPUnavailable:
EXCEPTION_PROLOG
+ MOL_HOOK_RESTORE(3)
bne load_up_fpu /* if from user, just load it up */
li r20,MSR_KERNEL
bl transfer_to_handler /* if from kernel, take a trap */
@@ -450,6 +458,7 @@ FPUnavailable:
. = 0x900
Decrementer:
EXCEPTION_PROLOG
+ MOL_HOOK(4)
addi r3,r1,STACK_FRAME_OVERHEAD
li r20,MSR_KERNEL
bl transfer_to_handler
@@ -473,12 +482,9 @@ SystemCall:
.long ret_from_except
/* Single step - not used on 601 */
- STD_EXCEPTION(0xd00, SingleStep, SingleStepException)
-
+ STD_MOL_EXCEPTION(0xd00, SingleStep, SingleStepException, 5)
STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
-#ifndef CONFIG_ALTIVEC
- STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
-#else
+
/*
* The Altivec unavailable trap is at 0x0f20. Foo.
* We effectively remap it to 0x3000.
@@ -493,15 +499,20 @@ trap_0f_cont:
.long ret_from_except
. = 0xf20
+#ifdef CONFIG_ALTIVEC
b AltiVecUnavailable
-#endif /* CONFIG_ALTIVEC */
-
+#endif
+Trap_0f:
+ EXCEPTION_PROLOG
+ b trap_0f_cont
+
/*
* Handle TLB miss for instruction on 603/603e.
* Note: we get an alternate set of r0 - r3 to use automatically.
*/
. = 0x1000
InstructionTLBMiss:
+ MOL_HOOK_TLBMISS( 14 )
/*
* r0: stored ctr
* r1: linux style pte ( later becomes ppc hardware pte )
@@ -568,6 +579,7 @@ InstructionAddressInvalid:
*/
. = 0x1100
DataLoadTLBMiss:
+ MOL_HOOK_TLBMISS( 15 )
/*
* r0: stored ctr
* r1: linux style pte ( later becomes ppc hardware pte )
@@ -633,6 +645,7 @@ DataAddressInvalid:
*/
. = 0x1200
DataStoreTLBMiss:
+ MOL_HOOK_TLBMISS( 16 )
/*
* r0: stored ctr
* r1: linux style pte ( later becomes ppc hardware pte )
@@ -674,7 +687,7 @@ DataStoreTLBMiss:
mtcrf 0x80,r3
rfi
- STD_EXCEPTION(0x1300, Trap_13, InstructionBreakpoint)
+ STD_MOL_EXCEPTION(0x1300, Trap_13, InstructionBreakpoint, 11)
STD_EXCEPTION(0x1400, SMI, SMIException)
STD_EXCEPTION(0x1500, Trap_15, UnknownException)
STD_EXCEPTION(0x1600, Trap_16, UnknownException)
@@ -687,7 +700,7 @@ DataStoreTLBMiss:
STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
- STD_EXCEPTION(0x2000, RunMode, RunModeException)
+ STD_MOL_EXCEPTION(0x2000, RunMode, RunModeException, 5)
STD_EXCEPTION(0x2100, Trap_21, UnknownException)
STD_EXCEPTION(0x2200, Trap_22, UnknownException)
STD_EXCEPTION(0x2300, Trap_23, UnknownException)
@@ -709,16 +722,12 @@ DataStoreTLBMiss:
#ifdef CONFIG_ALTIVEC
AltiVecUnavailable:
EXCEPTION_PROLOG
+ MOL_HOOK_RESTORE(12)
bne load_up_altivec /* if from user, just load it up */
li r20,MSR_KERNEL
bl transfer_to_handler /* if from kernel, take a trap */
.long KernelAltiVec
.long ret_from_except
-
-/* here are the bits of trap 0xf00 which got displaced */
-Trap_0f:
- EXCEPTION_PROLOG
- b trap_0f_cont
#endif /* CONFIG_ALTIVEC */
#ifdef CONFIG_PPC64BRIDGE
@@ -753,6 +762,14 @@ transfer_to_handler:
beq 2f
addi r24,r1,STACK_FRAME_OVERHEAD
stw r24,PT_REGS(r23)
+#ifdef CONFIG_ALTIVEC
+ mfpvr r24 /* check if we are on a G4 */
+ srwi r24,r24,16
+ cmpwi r24,PVR_7400@h
+ bne 2f
+ mfspr r22,SPRN_VRSAVE /* if so, save vrsave register value */
+ stw r22,THREAD_VRSAVE(r23)
+#endif /* CONFIG_ALTIVEC */
2: addi r2,r23,-THREAD /* set r2 to current */
tovirt(r2,r2)
mflr r23
@@ -771,6 +788,7 @@ transfer_to_handler:
lwz r24,0(r23) /* virtual address of handler */
lwz r23,4(r23) /* where to go when done */
FIX_SRR1(r20,r22)
+ MOL_HOOK(6)
mtspr SRR0,r24
mtspr SRR1,r20
mtlr r23
@@ -981,6 +999,11 @@ KernelAltiVec:
.globl giveup_altivec
giveup_altivec:
+#ifdef CONFIG_MOL
+ mflr r4
+ MOL_HOOK_MMU(13, r5)
+ mtlr r4
+#endif
mfmsr r5
oris r5,r5,MSR_VEC@h
SYNC
@@ -1017,6 +1040,11 @@ giveup_altivec:
*/
.globl giveup_fpu
giveup_fpu:
+#ifdef CONFIG_MOL
+ mflr r4
+ MOL_HOOK_MMU(7, r5)
+ mtlr r4
+#endif
mfmsr r5
ori r5,r5,MSR_FP
SYNC
@@ -1048,19 +1076,10 @@ giveup_fpu:
* the kernel image to physical address 0.
*/
relocate_kernel:
-#if 0 /* Is this still needed ? I don't think so. It breaks new
- * boot-with-mmu-off stuff
- */
- lis r9,0x426f /* if booted from BootX, don't */
- addi r9,r9,0x6f58 /* translate source addr */
- cmpw r31,r9 /* (we have to on chrp) */
- beq 7f
- rlwinm r4,r4,0,8,31 /* translate source address */
- add r4,r4,r3 /* to region mapped with BATs */
-#endif
-7: addis r9,r26,klimit@ha /* fetch klimit */
+ addis r9,r26,klimit@ha /* fetch klimit */
lwz r25,klimit@l(r9)
addis r25,r25,-KERNELBASE@h
+ li r3,0 /* Destination base address */
li r6,0 /* Destination offset */
li r5,0x4000 /* # bytes of memory to copy */
bl copy_and_flush /* copy the first 0x4000 bytes */
@@ -1307,7 +1326,7 @@ enable_caches:
mfspr r9,PVR
rlwinm r9,r9,16,16,31
cmpi 0,r9,1
- beq 4f /* not needed for 601 */
+ beq 6f /* not needed for 601 */
mfspr r11,HID0
andi. r0,r11,HID0_DCE
ori r11,r11,HID0_ICE|HID0_DCE
@@ -1323,26 +1342,33 @@ enable_caches:
isync
cmpi 0,r9,4 /* check for 604 */
cmpi 1,r9,9 /* or 604e */
- cmpi 2,r9,10 /* or mach5 */
+ cmpi 2,r9,10 /* or mach5 / 604r */
cmpi 3,r9,8 /* check for 750 (G3) */
cmpi 4,r9,12 /* or 7400 (G4) */
cror 2,2,6
cror 2,2,10
bne 4f
- ori r11,r11,HID0_SIED|HID0_BHTE /* for 604[e], enable */
+ ori r11,r11,HID0_SIED|HID0_BHTE /* for 604[e|r], enable */
bne 2,5f
- ori r11,r11,HID0_BTCD
+ ori r11,r11,HID0_BTCD /* superscalar exec & br history tbl */
b 5f
4:
cror 14,14,18
bne 3,6f
- /* We should add ABE here if we want to use Store Gathering
- * and other nifty bridge features
+ /* for G3/G4:
+ * enable Store Gathering (SGE), Address Brodcast (ABE),
+ * Branch History Table (BHTE), Branch Target ICache (BTIC)
*/
- ori r11,r11,HID0_SGE|HID0_BHTE|HID0_BTIC /* for g3/g4, enable */
+ ori r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC
+ oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */
+ li r3,HID0_SPD
+ andc r11,r11,r3 /* clear SPD: enable speculative */
li r3,0
- mtspr ICTC,r3
-5: mtspr HID0,r11 /* superscalar exec & br history tbl */
+ mtspr ICTC,r3 /* Instruction Cache Throttling off */
+5: isync
+ mtspr HID0,r11
+ sync
+ isync
6: blr
/*
@@ -1548,12 +1574,11 @@ flush_tlbs:
blr
mmu_off:
- addi r4, r3, __after_prom_start - _start
+ addi r4, r3, __after_mmu_off - _start
mfmsr r3
andi. r0,r3,MSR_DR|MSR_IR /* MMU enabled? */
beqlr
- ori r3,r3,MSR_DR|MSR_IR
- xori r3,r3,MSR_DR|MSR_IR
+ andc r3,r3,r0
mtspr SRR0,r4
mtspr SRR1,r3
sync
@@ -1617,23 +1642,19 @@ setup_disp_bat:
mflr r8
bl reloc_offset
mtlr r8
- lis r8, disp_BATL@h
- ori r8, r8, disp_BATL@l
- add r8, r3, r8
- lwz r8, 0(r8)
- lis r11, disp_BATU@h
- ori r11, r11, disp_BATU@l
- add r11, r3, r11
- lwz r11, 0(r11)
- mtspr IBAT3L,r8
- mtspr IBAT3U,r11
+ addis r8,r3,disp_BAT@ha
+ addi r8,r8,disp_BAT@l
+ lwz r11,0(r8)
+ lwz r8,4(r8)
mfspr r9,PVR
rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
cmpi 0,r9,1
beq 1f
mtspr DBAT3L,r8
mtspr DBAT3U,r11
-1:
+ blr
+1: mtspr IBAT3L,r8
+ mtspr IBAT3U,r11
blr
#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
@@ -1649,18 +1670,43 @@ setup_disp_bat:
*/
.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
+ mfmsr r0
+ rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */
+ sync
+ mtmsr r0
+ sync
+ mfspr r11, HID0
+ lis r10, 0
+ ori r10,r10,HID0_ICE|HID0_DCE
+ andc r11, r11, r10
+ mtspr HID0, r11
+ isync
+ li r5, MSR_
+ lis r6,2f@h
+ addis r6,r6,-KERNELBASE@h
+ ori r6,r6,2f@l
+ mtspr SRR0,r6
+ mtspr SRR1,r5
+ isync
+ sync
+ rfi
2:
- mtlr r4
- blr
+ mtlr r4
+ blr
+#endif
+
+#ifdef CONFIG_MOL
+/*
+ * Mac-on-linux hook_table. Don't put this in the data section -
+ * the base address must be within the first 32KB of RAM.
+ */
+ .globl mol_interface
+mol_interface:
+ .long MOL_INTERFACE_VERSION
+ .fill 24,4,0 /* space for 24 hooks */
#endif
+
/*
* We put a few things here that have to be page-aligned.
* This stuff goes at the beginning of the data segment,
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index a35f6e2a1..40579ce63 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -874,6 +874,13 @@ start_here:
lis r6, swapper_pg_dir@h
tophys(r6,r6)
ori r6, r6, swapper_pg_dir@l
+#ifdef CONFIG_8xx_CPU6
+ lis r4, cpu6_errata_word@h
+ ori r4, r4, cpu6_errata_word@l
+ li r3, 0x3980
+ stw r3, 12(r4)
+ lwz r3, 12(r4)
+#endif
mtspr M_TWB, r6
lis r4,2f@h
ori r4,r4,2f@l
@@ -940,9 +947,23 @@ start_here:
* ASID compare register with the new "context".
*/
_GLOBAL(set_context)
+#ifdef CONFIG_8xx_CPU6
+ lis r6, cpu6_errata_word@h
+ ori r6, r6, cpu6_errata_word@l
+ tophys (r4, r4)
+ li r7, 0x3980
+ stw r7, 12(r6)
+ lwz r7, 12(r6)
+ mtspr M_TWB, r4 /* Update MMU base address */
+ li r7, 0x3380
+ stw r7, 12(r6)
+ lwz r7, 12(r6)
+ mtspr M_CASID, r3 /* Update context */
+#else
mtspr M_CASID,r3 /* Update context */
tophys (r4, r4)
mtspr M_TWB, r4 /* and pgd */
+#endif
tlbia
SYNC
blr
@@ -966,6 +987,24 @@ m8xx_gorom:
2:
mtlr r4
blr
+
+#ifdef CONFIG_8xx_CPU6
+/* It's here because it is unique to the 8xx.
+ * It is important we get called with interrupts disabled. I used to
+ * do that, but it appears that all code that calls this already had
+ * interrupt disabled.
+ */
+ .globl set_dec_cpu6
+set_dec_cpu6:
+ lis r7, cpu6_errata_word@h
+ ori r7, r7, cpu6_errata_word@l
+ li r4, 0x2c00
+ stw r4, 8(r7)
+ lwz r4, 8(r7)
+ mtspr 22, r3 /* Update Decrementer */
+ SYNC
+ blr
+#endif
/*
* We put a few things here that have to be page-aligned.
@@ -991,3 +1030,9 @@ swapper_pg_dir:
cmd_line:
.space 512
+#ifdef CONFIG_8xx_CPU6
+ .globl cpu6_errata_word
+cpu6_errata_word:
+ .space 16
+#endif
+
diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
index d29f7bd20..a363a0e34 100644
--- a/arch/ppc/kernel/idle.c
+++ b/arch/ppc/kernel/idle.c
@@ -286,6 +286,7 @@ void power_save(void)
case 6: /* 603e */
case 7: /* 603ev */
case 8: /* 750 */
+ case 12: /* 7400 */
save_flags(msr);
__cli();
if (!current->need_resched) {
diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
index 64ef4b4dc..eef89f352 100644
--- a/arch/ppc/kernel/irq.c
+++ b/arch/ppc/kernel/irq.c
@@ -137,17 +137,21 @@ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *)
if (!handler)
{
/* Free */
- for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next)
- {
- /* Found it - now free it */
- save_flags(flags);
- cli();
- *p = action->next;
- restore_flags(flags);
- irq_kfree(action);
- return 0;
- }
- return -ENOENT;
+ p = &irq_desc[irq].action;
+ while ((action = *p) != NULL && action->dev_id != dev_id)
+ p = &action->next;
+ if (action == NULL)
+ return -ENOENT;
+
+ /* Found it - now free it */
+ save_flags(flags);
+ cli();
+ *p = action->next;
+ if (irq_desc[irq].action == NULL)
+ disable_irq(irq);
+ restore_flags(flags);
+ irq_kfree(action);
+ return 0;
}
action = (struct irqaction *)
@@ -300,7 +304,7 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
}
}
-asmlinkage int do_IRQ(struct pt_regs *regs, int isfake)
+int do_IRQ(struct pt_regs *regs, int isfake)
{
int cpu = smp_processor_id();
int irq;
diff --git a/arch/ppc/kernel/m8260_setup.c b/arch/ppc/kernel/m8260_setup.c
index 891b0ca44..6e006a867 100644
--- a/arch/ppc/kernel/m8260_setup.c
+++ b/arch/ppc/kernel/m8260_setup.c
@@ -112,11 +112,10 @@ 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;
+ freq = (binfo->bi_busfreq * 1000000);
+ divisor = 4;
+ tb_ticks_per_jiffy = freq / HZ / divisor;
+ tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
}
/* The 8260 has an internal 1-second timer update register that
@@ -143,8 +142,20 @@ void
m8260_restart(char *cmd)
{
extern void m8260_gorom(bd_t *bi, uint addr);
+ uint startaddr;
- m8260_gorom(NULL, 0xff000100);
+ /* Most boot roms have a warmstart as the second instruction
+ * of the reset vector. If that doesn't work for you, change this
+ * or the reboot program to send a proper address.
+ */
+ startaddr = 0xff000104;
+
+ if (cmd != NULL) {
+ if (!strncmp(cmd, "startaddr=", 10))
+ startaddr = simple_strtoul(&cmd[10], NULL, 0);
+ }
+
+ m8260_gorom((uint)__pa(__res), startaddr);
}
void
diff --git a/arch/ppc/kernel/m8xx_setup.c b/arch/ppc/kernel/m8xx_setup.c
index a00a8c452..7dc408a13 100644
--- a/arch/ppc/kernel/m8xx_setup.c
+++ b/arch/ppc/kernel/m8xx_setup.c
@@ -135,6 +135,13 @@ abort(void)
machine_restart(NULL);
}
+/* A place holder for time base interrupts, if they are ever enabled.
+*/
+void timebase_interrupt(int irq, void * dev, struct pt_regs * regs)
+{
+ printk("timebase_interrupt()\n");
+}
+
/* The decrementer counts at the system (internal) clock frequency divided by
* sixteen, or external oscillator divided by four. We force the processor
* to use system clock divided by sixteen.
@@ -160,35 +167,14 @@ void __init m8xx_calibrate_decr(void)
freq = fp*60; /* try to make freq/1e6 an integer */
divisor = 60;
printk("time_init: decrementer frequency = %d/%d\n", freq, divisor);
- decrementer_count = freq / HZ / divisor;
- count_period_num = divisor;
- count_period_den = freq / 1000000;
-}
-
-/* A place holder for time base interrupts, if they are ever enabled.
-*/
-void timebase_interrupt(int irq, void * dev, struct pt_regs * regs)
-{
- printk("timebase_interrupt()\n");
-}
-
-/* The RTC on the MPC8xx is an internal register.
- * We want to protect this during power down, so we need to unlock,
- * modify, and re-lock.
- */
-static int
-m8xx_set_rtc_time(unsigned long time)
-{
- ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY;
- ((volatile immap_t *)IMAP_ADDR)->im_sit.sit_rtc = time;
- ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY;
- return(0);
-}
-
-unsigned long __init
-m8xx_get_rtc_time(void)
-{
- /* First, unlock all of the registers we are going to modify.
+ tb_ticks_per_jiffy = freq / HZ / divisor;
+ tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
+
+ /* Perform some more timer/timebase initialization. This used
+ * to be done elsewhere, but other changes caused it to get
+ * called more than once....that is a bad thing.
+ *
+ * First, unlock all of the registers we are going to modify.
* To protect them from corruption during power down, registers
* that are maintained by keep alive power are "locked". To
* modify these registers we have to write the key value to
@@ -219,9 +205,27 @@ m8xx_get_rtc_time(void)
((volatile immap_t *)IMAP_ADDR)->im_sit.sit_tbscr =
((mk_int_int_mask(DEC_INTERRUPT) << 8) |
(TBSCR_TBF | TBSCR_TBE));
+
if (request_8xxirq(DEC_INTERRUPT, timebase_interrupt, 0, "tbint", NULL) != 0)
panic("Could not allocate timer IRQ!");
+}
+/* The RTC on the MPC8xx is an internal register.
+ * We want to protect this during power down, so we need to unlock,
+ * modify, and re-lock.
+ */
+static int
+m8xx_set_rtc_time(unsigned long time)
+{
+ ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY;
+ ((volatile immap_t *)IMAP_ADDR)->im_sit.sit_rtc = time;
+ ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY;
+ return(0);
+}
+
+unsigned long __init
+m8xx_get_rtc_time(void)
+{
/* Get time from the RTC.
*/
return((unsigned long)(((immap_t *)IMAP_ADDR)->im_sit.sit_rtc));
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index 081dda7f3..e3826293b 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -24,12 +24,15 @@
#if defined(CONFIG_4xx) || defined(CONFIG_8xx)
#define CACHE_LINE_SIZE 16
#define LG_CACHE_LINE_SIZE 4
+#define MAX_COPY_PREFETCH 1
#elif !defined(CONFIG_PPC64BRIDGE)
#define CACHE_LINE_SIZE 32
#define LG_CACHE_LINE_SIZE 5
+#define MAX_COPY_PREFETCH 4
#else
#define CACHE_LINE_SIZE 128
#define LG_CACHE_LINE_SIZE 7
+#define MAX_COPY_PREFETCH 1
#endif /* CONFIG_4xx || CONFIG_8xx */
.text
@@ -339,7 +342,15 @@ _GLOBAL(__flush_icache_page)
_GLOBAL(clear_page)
li r0,4096/CACHE_LINE_SIZE
mtctr r0
+#ifdef CONFIG_8xx
+ li r4, 0
+1: stw r4, 0(r3)
+ stw r4, 4(r3)
+ stw r4, 8(r3)
+ stw r4, 12(r3)
+#else
1: dcbz 0,r3
+#endif
addi r3,r3,CACHE_LINE_SIZE
bdnz 1b
blr
@@ -361,12 +372,31 @@ _GLOBAL(clear_page)
stwu r9,16(r3)
_GLOBAL(copy_page)
- li r0,4096/CACHE_LINE_SIZE
- mtctr r0
addi r3,r3,-4
addi r4,r4,-4
li r5,4
-1: dcbz r5,r3
+
+#ifndef CONFIG_8xx
+#if MAX_COPY_PREFETCH > 1
+ li r0,MAX_COPY_PREFETCH
+ li r11,4
+ mtctr r0
+11: dcbt r11,r4
+ addi r11,r11,CACHE_LINE_SIZE
+ bdnz 11b
+#else /* MAX_COPY_PREFETCH == 1 */
+ dcbt r5,r4
+ li r11,CACHE_LINE_SIZE+4
+#endif /* MAX_COPY_PREFETCH */
+#endif /* CONFIG_8xx */
+
+ li r0,4096/CACHE_LINE_SIZE
+ mtctr r0
+1:
+#ifndef CONFIG_8xx
+ dcbt r11,r4
+ dcbz r5,r3
+#endif
COPY_16_BYTES
#if CACHE_LINE_SIZE >= 32
COPY_16_BYTES
@@ -484,7 +514,7 @@ _GLOBAL(atomic_dec_and_test)
stwcx. r5,0,r3 /* Update with new value */
bne- 10b /* Retry if "reservation" (i.e. lock) lost */
cntlzw r3,r5
- srwi r3,r3,5
+ srwi r3,r3,5
blr
#endif /* 0 */
_GLOBAL(atomic_clear_mask)
@@ -629,48 +659,59 @@ _GLOBAL(_outsl_ns)
blr
/*
- * Extended precision shifts
+ * Extended precision shifts.
+ *
+ * Updated to be valid for shift counts from 0 to 63 inclusive.
+ * -- Gabriel
*
* R3/R4 has 64 bit value
* R5 has shift count
* result in R3/R4
*
- * ashrdi3: XXXYYY/ZZZAAA -> SSSXXX/YYYZZZ
- * ashldi3: XXXYYY/ZZZAAA -> YYYZZZ/AAA000
- * lshrdi3: XXXYYY/ZZZAAA -> 000XXX/YYYZZZ
+ * ashrdi3: arithmetic right shift (sign propagation)
+ * lshrdi3: logical right shift
+ * ashldi3: left shift
*/
_GLOBAL(__ashrdi3)
- li r6,32
- sub r6,r6,r5
- slw r7,r3,r6 /* isolate YYY */
- srw r4,r4,r5 /* isolate ZZZ */
- or r4,r4,r7 /* YYYZZZ */
- sraw r3,r3,r5 /* SSSXXX */
+ subfic r6,r5,32
+ srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
+ addi r7,r5,32 # could be xori, or addi with -32
+ slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
+ rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0
+ sraw r7,r3,r7 # t2 = MSW >> (count-32)
+ or r4,r4,r6 # LSW |= t1
+ slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2
+ sraw r3,r3,r5 # MSW = MSW >> count
+ or r4,r4,r7 # LSW |= t2
blr
_GLOBAL(__ashldi3)
- li r6,32
- sub r6,r6,r5
- srw r7,r4,r6 /* isolate ZZZ */
- slw r4,r4,r5 /* AAA000 */
- slw r3,r3,r5 /* YYY--- */
- or r3,r3,r7 /* YYYZZZ */
+ subfic r6,r5,32
+ slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count
+ addi r7,r5,32 # could be xori, or addi with -32
+ srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
+ slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
+ or r3,r3,r6 # MSW |= t1
+ slw r4,r4,r5 # LSW = LSW << count
+ or r3,r3,r7 # MSW |= t2
blr
_GLOBAL(__lshrdi3)
- li r6,32
- sub r6,r6,r5
- slw r7,r3,r6 /* isolate YYY */
- srw r4,r4,r5 /* isolate ZZZ */
- or r4,r4,r7 /* YYYZZZ */
- srw r3,r3,r5 /* 000XXX */
+ subfic r6,r5,32
+ srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
+ addi r7,r5,32 # could be xori, or addi with -32
+ slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
+ srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
+ or r4,r4,r6 # LSW |= t1
+ srw r3,r3,r5 # MSW = MSW >> count
+ or r4,r4,r7 # LSW |= t2
blr
_GLOBAL(abs)
- cmpi 0,r3,0
- bge 10f
- neg r3,r3
-10: blr
+ srawi r4,r3,31
+ xor r3,r3,r4
+ sub r3,r3,r4
+ blr
_GLOBAL(_get_SP)
mr r3,r1 /* Close enough */
@@ -1217,6 +1258,6 @@ _GLOBAL(sys_call_table)
.long sys_pciconfig_iobase /* 200 */
.long sys_ni_syscall /* 201 - reserved - MacOnLinux - new */
.long sys_getdents64 /* 202 */
- .rept NR_syscalls-201
+ .rept NR_syscalls-(.-sys_call_table)/4
.long sys_ni_syscall
.endr
diff --git a/arch/ppc/kernel/mol.h b/arch/ppc/kernel/mol.h
new file mode 100644
index 000000000..6105867e1
--- /dev/null
+++ b/arch/ppc/kernel/mol.h
@@ -0,0 +1,68 @@
+/*
+ * arch/ppc/kernel/mol.h
+ *
+ * <mol.h>
+ *
+ * Mac-on-Linux hook macros
+ * <http://www.maconlinux.org>
+ *
+ * Copyright (C) 2000 Samuel Rydh (samuel@ibrium.se)
+ *
+ * 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
+ *
+ */
+
+#ifndef _PPC_KERNEL_MOL
+#define _PPC_KERNEL_MOL
+
+#include <linux/config.h>
+
+#ifdef CONFIG_MOL
+#define MOL_INTERFACE_VERSION 3
+
+#define MOL_HOOK(hook_num) \
+ lwz r0,(mol_interface + 4 * hook_num + 4)@l(0); \
+ cmpwi cr1,r0,0; \
+ beq+ cr1,777f; \
+ mtctr r0; \
+ bctrl; \
+777: lwz r0,GPR0(r21)
+
+#define MOL_HOOK_RESTORE(hook_num) \
+ mfcr r2; \
+ MOL_HOOK(hook_num); \
+ mtcrf 0x80,r2; \
+ lwz r2,_CTR(r21); \
+ mtctr r2; \
+ lwz r2,GPR2(r21)
+
+#define MOL_HOOK_MMU(hook_num, scr) \
+ lis scr,(mol_interface + 4 * hook_num + 4)@ha; \
+ lwz scr,(mol_interface + 4 * hook_num + 4)@l(scr); \
+ cmpwi cr1,scr,0; \
+ beq+ cr1,778f; \
+ mtctr scr; \
+ bctrl; \
+778:
+
+#define MOL_HOOK_TLBMISS(hook_num) \
+ lwz r0,(mol_interface + 4 * hook_num + 4)@l(0); \
+ cmpwi r0,0; \
+ beq+ 779f; \
+ mflr r3; \
+ mtlr r0; \
+ blrl; \
+ mtlr r3; \
+779:
+
+#else
+#define MOL_HOOK(num)
+#define MOL_HOOK_RESTORE(num)
+#define MOL_HOOK_MMU(num, scr)
+#define MOL_HOOK_TLBMISS(num)
+#endif
+
+
+#endif /* _PPC_KERNEL_MOL */
diff --git a/arch/ppc/kernel/oak_setup.c b/arch/ppc/kernel/oak_setup.c
index 09e6e6e6f..ef5a7a0fe 100644
--- a/arch/ppc/kernel/oak_setup.c
+++ b/arch/ppc/kernel/oak_setup.c
@@ -231,10 +231,11 @@ oak_halt(void)
/*
* Document me.
*/
-void __init
+long __init
oak_time_init(void)
{
/* XXX - Implement me */
+ return 0;
}
/*
diff --git a/arch/ppc/kernel/open_pic.c b/arch/ppc/kernel/open_pic.c
index 416137934..5ca365b1c 100644
--- a/arch/ppc/kernel/open_pic.c
+++ b/arch/ppc/kernel/open_pic.c
@@ -100,7 +100,7 @@ struct hw_interrupt_type open_pic = {
#ifdef CONFIG_SMP
void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
{
- smp_message_recv(cpl-OPENPIC_VEC_IPI);
+ smp_message_recv(cpl-OPENPIC_VEC_IPI, regs);
}
#endif /* CONFIG_SMP */
@@ -262,11 +262,11 @@ void __init openpic_init(int main_pic)
int j, pri;
pri = strcmp(np->name, "programmer-switch") ? 2 : 7;
for (j=0;j<np->n_intrs;j++) {
- openpic_initirq( np->intrs[j].line,
- pri,
- np->intrs[j].line,
- 0,
- np->intrs[j].sense);
+ openpic_initirq(np->intrs[j].line,
+ pri,
+ np->intrs[j].line,
+ 0,
+ np->intrs[j].sense);
if (np->intrs[j].sense)
irq_desc[np->intrs[j].line].status = IRQ_LEVEL;
}
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 6233e5f9b..84faa0e1d 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -25,7 +25,13 @@
#include "pci.h"
-static void __init pcibios_claim_resources(struct list_head *);
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
unsigned long isa_io_base = 0;
unsigned long isa_mem_base = 0;
@@ -70,59 +76,280 @@ struct pci_ops generic_pci_ops =
generic_pcibios_write_dword
};
-void __init pcibios_init(void)
-{
- printk("PCI: Probing PCI hardware\n");
- pci_scan_bus(0, &generic_pci_ops, NULL);
- if (ppc_md.pcibios_fixup)
- ppc_md.pcibios_fixup();
- pcibios_claim_resources(&pci_root_buses);
-}
-void __init
-pcibios_fixup_pbus_ranges(struct pci_bus * bus, struct pbus_set_ranges_data * ranges)
+
+void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+ struct resource *res, int resource)
{
- ranges->io_start -= bus->resource[0]->start;
- ranges->io_end -= bus->resource[0]->start;
- ranges->mem_start -= bus->resource[1]->start;
- ranges->mem_end -= bus->resource[1]->start;
+ u32 new, check;
+ int reg;
+
+ new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
+ if (resource < 6) {
+ reg = PCI_BASE_ADDRESS_0 + 4*resource;
+ } else if (resource == PCI_ROM_RESOURCE) {
+ res->flags |= PCI_ROM_ADDRESS_ENABLE;
+ reg = dev->rom_base_reg;
+ } else {
+ /* Somebody might have asked allocation of a non-standard resource */
+ return;
+ }
+
+ pci_write_config_dword(dev, reg, new);
+ pci_read_config_dword(dev, reg, &check);
+ if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
+ printk(KERN_ERR "PCI: Error while updating region "
+ "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+ new, check);
+ }
}
-unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
- unsigned long start, unsigned long size)
+/*
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might have be mirrored at 0x0100-0x03ff..
+ */
+void
+pcibios_align_resource(void *data, struct resource *res, unsigned long size)
{
- return start;
+ struct pci_dev *dev = data;
+
+ if (res->flags & IORESOURCE_IO) {
+ unsigned long start = res->start;
+
+ if (size > 0x100) {
+ printk(KERN_ERR "PCI: I/O Region %s/%d too large"
+ " (%ld bytes)\n", dev->slot_name,
+ dev->resource - res, size);
+ }
+
+ if (start & 0x300) {
+ start = (start + 0x3ff) & ~0x3ff;
+ res->start = start;
+ }
+ }
}
-static void __init pcibios_claim_resources(struct list_head *bus_list)
+
+/*
+ * Handle resources of PCI devices. If the world were perfect, we could
+ * just allocate all the resource regions and do nothing more. It isn't.
+ * On the other hand, we cannot just re-allocate all devices, as it would
+ * require us to know lots of host bridge internals. So we attempt to
+ * keep as much of the original configuration as possible, but tweak it
+ * when it's found to be wrong.
+ *
+ * Known BIOS problems we have to work around:
+ * - I/O or memory regions not configured
+ * - regions configured, but not enabled in the command register
+ * - bogus I/O addresses above 64K used
+ * - expansion ROMs left enabled (this may sound harmless, but given
+ * the fact the PCI specs explicitly allow address decoders to be
+ * shared between expansion ROMs and other resource regions, it's
+ * at least dangerous)
+ *
+ * Our solution:
+ * (1) Allocate resources for all buses behind PCI-to-PCI bridges.
+ * This gives us fixed barriers on where we can allocate.
+ * (2) Allocate resources for all enabled devices. If there is
+ * a collision, just mark the resource as unallocated. Also
+ * disable expansion ROMs during this step.
+ * (3) Try to allocate resources for disabled devices. If the
+ * resources were assigned correctly, everything goes well,
+ * if they weren't, they won't disturb allocation of other
+ * resources.
+ * (4) Assign new addresses to resources which were either
+ * not configured at all or misconfigured. If explicitly
+ * requested by the user, configure expansion ROM address
+ * as well.
+ */
+
+static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
{
- struct list_head *ln, *dn;
+ struct list_head *ln;
struct pci_bus *bus;
struct pci_dev *dev;
int idx;
+ struct resource *r, *pr;
+ /* Depth-First Search on bus tree */
for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
bus = pci_bus_b(ln);
- for (dn=bus->devices.next; dn != &bus->devices; dn=dn->next) {
- dev = pci_dev_b(dn);
- for (idx = 0; idx < PCI_NUM_RESOURCES; idx++)
- {
- struct resource *r = &dev->resource[idx];
- struct resource *pr;
+ if ((dev = bus->self)) {
+ for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
+ r = &dev->resource[idx];
if (!r->start)
continue;
pr = pci_find_parent_resource(dev, r);
if (!pr || request_resource(pr, r) < 0)
- {
- printk(KERN_ERR "PCI: Address space collision on region %d of device %s\n", idx, dev->name);
- /* We probably should disable the region, shouldn't we? */
+ printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, dev->slot_name);
+ }
+ }
+ pcibios_allocate_bus_resources(&bus->children);
+ }
+}
+
+static void __init pcibios_allocate_resources(int pass)
+{
+ struct pci_dev *dev;
+ int idx, disabled;
+ u16 command;
+ struct resource *r, *pr;
+
+ pci_for_each_dev(dev) {
+ pci_read_config_word(dev, PCI_COMMAND, &command);
+ for(idx = 0; idx < 6; idx++) {
+ r = &dev->resource[idx];
+ if (r->parent) /* Already allocated */
+ continue;
+ if (!r->start) /* Address not assigned at all */
+ continue;
+ if (r->end == 0xffffffff) {
+ /* LongTrail OF quirk: unassigned */
+ DBG("PCI: Resource %08lx-%08lx was unassigned\n", r->start, r->end);
+ r->end -= r->start;
+ r->start = 0;
+ continue;
+ }
+
+ if (r->flags & IORESOURCE_IO)
+ disabled = !(command & PCI_COMMAND_IO);
+ else
+ disabled = !(command & PCI_COMMAND_MEMORY);
+ if (pass == disabled) {
+ DBG("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n",
+ r->start, r->end, r->flags, disabled, pass);
+ pr = pci_find_parent_resource(dev, r);
+ if (!pr || request_resource(pr, r) < 0) {
+ printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n", idx, dev->slot_name);
+ /* We'll assign a new address later */
+ r->end -= r->start;
+ r->start = 0;
}
}
}
- pcibios_claim_resources(&bus->children);
+ if (!pass) {
+ r = &dev->resource[PCI_ROM_RESOURCE];
+ if (r->flags & PCI_ROM_ADDRESS_ENABLE) {
+ /* Turn the ROM off, leave the resource region, but keep it unregistered. */
+ u32 reg;
+ DBG("PCI: Switching off ROM of %s\n", dev->slot_name);
+ r->flags &= ~PCI_ROM_ADDRESS_ENABLE;
+ pci_read_config_dword(dev, dev->rom_base_reg, &reg);
+ pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE);
+ }
+ }
+ }
+}
+
+static void __init pcibios_assign_resources(void)
+{
+ struct pci_dev *dev;
+ int idx;
+ struct resource *r;
+
+ pci_for_each_dev(dev) {
+ int class = dev->class >> 8;
+
+ /* Don't touch classless devices and host bridges */
+ if (!class || class == PCI_CLASS_BRIDGE_HOST)
+ continue;
+
+ for(idx=0; idx<6; idx++) {
+ r = &dev->resource[idx];
+
+ /*
+ * Don't touch IDE controllers and I/O ports of video cards!
+ */
+ if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) ||
+ (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
+ continue;
+
+ /*
+ * We shall assign a new address to this resource, either because
+ * the BIOS forgot to do so or because we have decided the old
+ * address was unusable for some reason.
+ */
+ if (!r->start && r->end)
+ pci_assign_resource(dev, idx);
+ }
+
+ if (0) { /* don't assign ROMs */
+ r = &dev->resource[PCI_ROM_RESOURCE];
+ r->end -= r->start;
+ r->start = 0;
+ if (r->end)
+ pci_assign_resource(dev, PCI_ROM_RESOURCE);
+ }
}
}
+
+int pcibios_enable_resources(struct pci_dev *dev)
+{
+ u16 cmd, old_cmd;
+ int idx;
+ struct resource *r;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ old_cmd = cmd;
+ for(idx=0; idx<6; idx++) {
+ r = &dev->resource[idx];
+ if (!r->start && r->end) {
+ printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
+ return -EINVAL;
+ }
+ if (r->flags & IORESOURCE_IO)
+ cmd |= PCI_COMMAND_IO;
+ if (r->flags & IORESOURCE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+ if (dev->resource[PCI_ROM_RESOURCE].start)
+ cmd |= PCI_COMMAND_MEMORY;
+ if (cmd != old_cmd) {
+ printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+ return 0;
+}
+
+
+
+void __init pcibios_init(void)
+{
+ printk("PCI: Probing PCI hardware\n");
+ pci_scan_bus(0, &generic_pci_ops, NULL);
+ if (ppc_md.pcibios_fixup)
+ ppc_md.pcibios_fixup();
+ pcibios_allocate_bus_resources(&pci_root_buses);
+ pcibios_allocate_resources(0);
+ pcibios_allocate_resources(1);
+ pcibios_assign_resources();
+}
+
+void __init
+pcibios_fixup_pbus_ranges(struct pci_bus * bus, struct pbus_set_ranges_data * ranges)
+{
+ ranges->io_start -= bus->resource[0]->start;
+ ranges->io_end -= bus->resource[0]->start;
+ ranges->mem_start -= bus->resource[1]->start;
+ ranges->mem_end -= bus->resource[1]->start;
+}
+
+unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
+ unsigned long start, unsigned long size)
+{
+ return start;
+}
+
void __init pcibios_fixup_bus(struct pci_bus *bus)
{
if ( ppc_md.pcibios_fixup_bus )
@@ -134,21 +361,7 @@ char __init *pcibios_setup(char *str)
return str;
}
-/* the next two are stolen from the alpha port... */
-void __init
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
- struct resource *res, int resource)
-{
- unsigned long where, size;
- u32 reg;
-
- where = PCI_BASE_ADDRESS_0 + (resource * 4);
- size = res->end - res->start;
- pci_read_config_dword(dev, where, &reg);
- reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
- pci_write_config_dword(dev, where, reg);
-}
-
+/* the next one is stolen from the alpha port... */
void __init
pcibios_update_irq(struct pci_dev *dev, int irq)
{
@@ -156,11 +369,6 @@ pcibios_update_irq(struct pci_dev *dev, int irq)
/* XXX FIXME - update OF device tree node interrupt property */
}
-void __init
-pcibios_align_resource(void *data, struct resource *res, unsigned long size)
-{
-}
-
int pcibios_enable_device(struct pci_dev *dev)
{
u16 cmd, old_cmd;
@@ -188,114 +396,26 @@ int pcibios_enable_device(struct pci_dev *dev)
return 0;
}
-/*
- * Those syscalls are derived from the Alpha versions, they
- * allow userland apps to retreive the per-device iobase and
- * mem-base. They also provide wrapper for userland to do
- * config space accesses.
- * The "host_number" returns the number of the Uni-N sub bridge
- */
-
-asmlinkage int
-sys_pciconfig_read(unsigned long bus, unsigned long dfn,
- unsigned long off, unsigned long len,
- unsigned char *buf)
-{
- unsigned char ubyte;
- unsigned short ushort;
- unsigned int uint;
- long err = 0;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (!pcibios_present())
- return -ENOSYS;
-
- switch (len) {
- case 1:
- err = pcibios_read_config_byte(bus, dfn, off, &ubyte);
- put_user(ubyte, buf);
- break;
- case 2:
- err = pcibios_read_config_word(bus, dfn, off, &ushort);
- put_user(ushort, (unsigned short *)buf);
- break;
- case 4:
- err = pcibios_read_config_dword(bus, dfn, off, &uint);
- put_user(uint, (unsigned int *)buf);
- break;
- default:
- err = -EINVAL;
- break;
- }
- return err;
-}
-
-asmlinkage int
-sys_pciconfig_write(unsigned long bus, unsigned long dfn,
- unsigned long off, unsigned long len,
- unsigned char *buf)
-{
- unsigned char ubyte;
- unsigned short ushort;
- unsigned int uint;
- long err = 0;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (!pcibios_present())
- return -ENOSYS;
-
- switch (len) {
- case 1:
- err = get_user(ubyte, buf);
- if (err)
- break;
- err = pcibios_write_config_byte(bus, dfn, off, ubyte);
- if (err != PCIBIOS_SUCCESSFUL) {
- err = -EFAULT;
- }
- break;
- case 2:
- err = get_user(ushort, (unsigned short *)buf);
- if (err)
- break;
- err = pcibios_write_config_word(bus, dfn, off, ushort);
- if (err != PCIBIOS_SUCCESSFUL) {
- err = -EFAULT;
- }
- break;
- case 4:
- err = get_user(uint, (unsigned int *)buf);
- if (err)
- break;
- err = pcibios_write_config_dword(bus, dfn, off, uint);
- if (err != PCIBIOS_SUCCESSFUL) {
- err = -EFAULT;
- }
- break;
- default:
- err = -EINVAL;
- break;
- }
- return err;
-}
-
void *
-pci_dev_io_base(unsigned char bus, unsigned char devfn)
+pci_dev_io_base(unsigned char bus, unsigned char devfn, int physical)
{
- /* Defaults to old way */
- if (!ppc_md.pci_dev_io_base)
- return pci_io_base(bus);
- return ppc_md.pci_dev_io_base(bus, devfn);
+ if (!ppc_md.pci_dev_io_base) {
+ /* Please, someone fix this for non-pmac machines, we
+ * need either the virtual or physical PCI IO base
+ */
+ return 0;
+ }
+ return ppc_md.pci_dev_io_base(bus, devfn, physical);
}
void *
pci_dev_mem_base(unsigned char bus, unsigned char devfn)
{
/* Default memory base is 0 (1:1 mapping) */
- if (!ppc_md.pci_dev_mem_base)
+ if (!ppc_md.pci_dev_mem_base) {
+ /* Please, someone fix this for non-pmac machines.*/
return 0;
+ }
return ppc_md.pci_dev_mem_base(bus, devfn);
}
@@ -318,15 +438,20 @@ pci_dev_root_bridge(unsigned char bus, unsigned char devfn)
asmlinkage long
sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
{
+ long result = -EOPNOTSUPP;
+
switch (which) {
case IOBASE_BRIDGE_NUMBER:
return (long)pci_dev_root_bridge(bus, devfn);
case IOBASE_MEMORY:
return (long)pci_dev_mem_base(bus, devfn);
case IOBASE_IO:
- return (long)pci_dev_io_base(bus, devfn);
+ result = (long)pci_dev_io_base(bus, devfn, 1);
+ if (result == 0)
+ result = -EOPNOTSUPP;
+ break;
}
- return -EOPNOTSUPP;
+ return result;
}
diff --git a/arch/ppc/kernel/pmac_backlight.c b/arch/ppc/kernel/pmac_backlight.c
index 8c6244632..30ad5f416 100644
--- a/arch/ppc/kernel/pmac_backlight.c
+++ b/arch/ppc/kernel/pmac_backlight.c
@@ -41,16 +41,16 @@ register_backlight_controller(struct backlight_controller *ctrler, void *data, c
#ifdef CONFIG_ADB_PMU
/* Special case for the old PowerBook since I can't test on it */
- if ((machine_is_compatible("AAPL,3400/2400") || machine_is_compatible("AAPL,3500")
- || machine_is_compatible("AAPL,PowerBook1998")
- || machine_is_compatible("AAPL,PowerBook1999"))
- && !strcmp(type, "pmu"))
+ backlight_autosave = machine_is_compatible("AAPL,3400/2400")
+ || machine_is_compatible("AAPL,3500");
+ if ((backlight_autosave
+ || machine_is_compatible("AAPL,PowerBook1998")
+ || machine_is_compatible("PowerBook1,1"))
+ && !strcmp(type, "pmu"))
valid = 1;
- else
#endif
- {
- if (bk_node)
- prop = get_property(bk_node, "backlight-control", NULL);
+ if (bk_node) {
+ prop = get_property(bk_node, "backlight-control", NULL);
if (prop && !strncmp(prop, type, strlen(type)))
valid = 1;
}
@@ -70,8 +70,6 @@ register_backlight_controller(struct backlight_controller *ctrler, void *data, c
}
#ifdef CONFIG_ADB_PMU
- backlight_autosave = machine_is_compatible("AAPL,3400/2400")
- || machine_is_compatible("AAPL,3500");
if (backlight_autosave) {
struct adb_request req;
pmu_request(&req, NULL, 2, 0xd9, 0);
diff --git a/arch/ppc/kernel/pmac_nvram.c b/arch/ppc/kernel/pmac_nvram.c
index d8de113ec..1c4c1eea1 100644
--- a/arch/ppc/kernel/pmac_nvram.c
+++ b/arch/ppc/kernel/pmac_nvram.c
@@ -312,17 +312,18 @@ pmac_nvram_update(void)
__openfirmware
unsigned char nvram_read_byte(int addr)
{
- struct adb_request req;
-
switch (nvram_naddrs) {
#ifdef CONFIG_ADB_PMU
- case -1:
+ case -1: {
+ struct adb_request req;
+
if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM,
(addr >> 8) & 0xff, addr & 0xff))
break;
while (!req.complete)
pmu_poll();
return req.reply[1];
+ }
#endif
case 1:
if (is_core_99)
@@ -339,17 +340,18 @@ unsigned char nvram_read_byte(int addr)
__openfirmware
void nvram_write_byte(unsigned char val, int addr)
{
- struct adb_request req;
-
switch (nvram_naddrs) {
#ifdef CONFIG_ADB_PMU
- case -1:
+ case -1: {
+ struct adb_request req;
+
if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM,
(addr >> 8) & 0xff, addr & 0xff, val))
break;
while (!req.complete)
pmu_poll();
break;
+ }
#endif
case 1:
if (is_core_99) {
diff --git a/arch/ppc/kernel/pmac_pci.c b/arch/ppc/kernel/pmac_pci.c
index ced029722..8f7b3d7c2 100644
--- a/arch/ppc/kernel/pmac_pci.c
+++ b/arch/ppc/kernel/pmac_pci.c
@@ -35,6 +35,7 @@ struct uninorth_data {
volatile unsigned int* cfg_addr;
volatile unsigned int* cfg_data;
void* iobase;
+ unsigned long iobase_phys;
};
static struct uninorth_data uninorth_bridges[3];
@@ -133,15 +134,20 @@ pmac_pci_dev_root_bridge(unsigned char bus, unsigned char dev_fn)
__pmac
void *
-pmac_pci_dev_io_base(unsigned char bus, unsigned char devfn)
+pmac_pci_dev_io_base(unsigned char bus, unsigned char devfn, int physical)
{
- int bridge;
- if (uninorth_count == 0)
- return pci_io_base(bus);
- bridge = pmac_pci_dev_root_bridge(bus, devfn);
- if (bridge == -1)
- return pci_io_base(bus);
- return uninorth_bridges[bridge].iobase;
+ int bridge = -1;
+ if (uninorth_count != 0)
+ bridge = pmac_pci_dev_root_bridge(bus, devfn);
+ if (bridge == -1) {
+ struct bridge_data *bp;
+
+ if (bus > max_bus || (bp = bridges[bus]) == 0)
+ return 0;
+ return physical ? (void *) bp->io_base_phys : bp->io_base;
+ }
+ return physical ? (void *) uninorth_bridges[bridge].iobase_phys
+ : uninorth_bridges[bridge].iobase;
}
__pmac
@@ -649,7 +655,9 @@ static void __init add_bridges(struct device_node *dev)
uninorth_bridges[i].cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
uninorth_bridges[i].cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
uninorth_bridges[i].node = dev;
- uninorth_bridges[i].iobase = (void *)addr->address;
+ uninorth_bridges[i].iobase_phys = addr->address;
+ /* is 0x10000 enough for io space ? */
+ uninorth_bridges[i].iobase = (void *)ioremap(addr->address, 0x10000);
/* XXX This is the bridge with the PCI expansion bus. This is also the
* address of the bus that will receive type 1 config accesses and io
* accesses. Appears to be correct for iMac DV and G4 Sawtooth too.
@@ -667,14 +675,15 @@ static void __init add_bridges(struct device_node *dev)
if (device_is_compatible(dev, "uni-north")) {
bp->cfg_addr = 0;
bp->cfg_data = 0;
- /* is 0x10000 enough for io space ? */
- bp->io_base = (void *)ioremap(addr->address, 0x10000);
+ bp->io_base = uninorth_bridges[uninorth_count-1].iobase;
+ bp->io_base_phys = uninorth_bridges[uninorth_count-1].iobase_phys;
} else if (strcmp(dev->name, "pci") == 0) {
/* XXX assume this is a mpc106 (grackle) */
bp->cfg_addr = (volatile unsigned int *)
ioremap(0xfec00000, 0x1000);
bp->cfg_data = (volatile unsigned char *)
ioremap(0xfee00000, 0x1000);
+ bp->io_base_phys = 0xfe000000;
bp->io_base = (void *) ioremap(0xfe000000, 0x20000);
if (machine_is_compatible("AAPL,PowerBook1998"))
grackle_set_loop_snoop(bp, 1);
@@ -687,6 +696,7 @@ static void __init add_bridges(struct device_node *dev)
ioremap(addr->address + 0x800000, 0x1000);
bp->cfg_data = (volatile unsigned char *)
ioremap(addr->address + 0xc00000, 0x1000);
+ bp->io_base_phys = addr->address;
bp->io_base = (void *) ioremap(addr->address, 0x10000);
}
if (isa_io_base == 0)
diff --git a/arch/ppc/kernel/pmac_pic.c b/arch/ppc/kernel/pmac_pic.c
index e0e654305..efd767482 100644
--- a/arch/ppc/kernel/pmac_pic.c
+++ b/arch/ppc/kernel/pmac_pic.c
@@ -204,17 +204,12 @@ pmac_get_irq(struct pt_regs *regs)
unsigned long bits = 0;
#ifdef CONFIG_SMP
- void pmac_smp_message_recv(void);
+ void pmac_smp_message_recv(struct pt_regs *);
/* IPI's are a hack on the powersurge -- Cort */
if ( smp_processor_id() != 0 )
{
-#ifdef CONFIG_XMON
- static int xmon_2nd;
- if (xmon_2nd)
- xmon(regs);
-#endif
- pmac_smp_message_recv();
+ pmac_smp_message_recv(regs);
return -2; /* ignore, already handled */
}
#endif /* CONFIG_SMP */
diff --git a/arch/ppc/kernel/pmac_setup.c b/arch/ppc/kernel/pmac_setup.c
index 658d7c226..b5bf03abc 100644
--- a/arch/ppc/kernel/pmac_setup.c
+++ b/arch/ppc/kernel/pmac_setup.c
@@ -68,7 +68,7 @@
#undef SHOW_GATWICK_IRQS
-extern void pmac_time_init(void);
+extern long pmac_time_init(void);
extern unsigned long pmac_get_rtc_time(void);
extern int pmac_set_rtc_time(unsigned long nowtime);
extern void pmac_read_rtc_time(void);
@@ -77,24 +77,29 @@ extern void pmac_setup_pci_ptrs(void);
extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
extern int mackbd_getkeycode(unsigned int scancode);
-extern int mackbd_translate(unsigned char scancode, unsigned char *keycode,
- char raw_mode);
-extern char mackbd_unexpected_up(unsigned char keycode);
+extern int mackbd_translate(unsigned char keycode, unsigned char *keycodep,
+ char raw_mode);
+extern int mackbd_unexpected_up(unsigned char keycode);
extern void mackbd_leds(unsigned char leds);
-extern void mackbd_init_hw(void);
+extern void __init mackbd_init_hw(void);
+extern int mac_hid_kbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode);
+extern char mac_hid_kbd_unexpected_up(unsigned char keycode);
+extern void mac_hid_init_hw(void);
#ifdef CONFIG_MAGIC_SYSRQ
-unsigned char mackbd_sysrq_xlate[128];
+extern unsigned char mac_hid_kbd_sysrq_xlate[128];
+extern unsigned char pckbd_sysrq_xlate[128];
+extern unsigned char mackbd_sysrq_xlate[128];
#endif /* CONFIG_MAGIC_SYSRQ */
extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
extern int pckbd_getkeycode(unsigned int scancode);
extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
char raw_mode);
extern char pckbd_unexpected_up(unsigned char keycode);
-extern void pckbd_leds(unsigned char leds);
-extern void pckbd_init_hw(void);
+extern int keyboard_sends_linux_keycodes;
extern void pmac_nvram_update(void);
-extern void *pmac_pci_dev_io_base(unsigned char bus, unsigned char devfn);
+extern void *pmac_pci_dev_io_base(unsigned char bus, unsigned char devfn, int physical);
extern void *pmac_pci_dev_mem_base(unsigned char bus, unsigned char devfn);
extern int pmac_pci_dev_root_bridge(unsigned char bus, unsigned char devfn);
@@ -115,7 +120,6 @@ extern int pmac_newworld;
extern void zs_kgdb_hook(int tty_num);
static void ohare_init(void);
static void init_p2pbridge(void);
-static void init_uninorth(void);
#ifdef CONFIG_BOOTX_TEXT
void pmac_progress(char *s, unsigned short hex);
#endif
@@ -276,7 +280,6 @@ pmac_setup_arch(void)
pmac_find_bridges();
init_p2pbridge();
- init_uninorth();
/* Checks "l2cr-value" property in the registry */
if ( (_get_PVR() >> 16) == 8 || (_get_PVR() >> 16) == 12 ) {
@@ -372,31 +375,6 @@ static void __init ohare_init(void)
}
}
-static void __init
-init_uninorth(void)
-{
- /*
- * Turns OFF the gmac clock. The gmac driver will turn
- * it back ON when the interface is enabled. This save
- * power on portables.
- *
- * Note: We could also try to turn OFF the PHY. Since this
- * has to be done by both the gmac driver and this code,
- * I'll probably end-up moving some of this out of the
- * modular gmac driver into a non-modular stub containing
- * some basic PHY management and power management stuffs
- */
- struct device_node* gmac = find_devices("ethernet");
-
- while(gmac) {
- if (device_is_compatible(gmac, "gmac"))
- break;
- gmac = gmac->next;
- }
- if (gmac)
- feature_set_gmac_power(gmac, 0);
-}
-
extern char *bootpath;
extern char *bootdevice;
void *boot_host;
@@ -404,14 +382,15 @@ int boot_target;
int boot_part;
kdev_t boot_dev;
-extern void via_pmu_start(void);
-
void __init
pmac_init2(void)
{
#ifdef CONFIG_ADB_PMU
via_pmu_start();
#endif
+#ifdef CONFIG_ADB_CUDA
+ via_cuda_start();
+#endif
#ifdef CONFIG_PMAC_PBOOK
media_bay_init();
#endif
@@ -683,7 +662,26 @@ pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.pci_dev_mem_base = pmac_pci_dev_mem_base;
ppc_md.pci_dev_root_bridge = pmac_pci_dev_root_bridge;
-#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD)
+#ifdef CONFIG_VT
+#ifdef CONFIG_INPUT_ADBHID
+ ppc_md.kbd_init_hw = mac_hid_init_hw;
+ ppc_md.kbd_translate = mac_hid_kbd_translate;
+ ppc_md.kbd_unexpected_up = mac_hid_kbd_unexpected_up;
+ ppc_md.kbd_setkeycode = 0;
+ ppc_md.kbd_getkeycode = 0;
+#ifdef CONFIG_MAGIC_SYSRQ
+#ifdef CONFIG_MAC_ADBKEYCODES
+ if (!keyboard_sends_linux_keycodes) {
+ ppc_md.ppc_kbd_sysrq_xlate = mac_hid_kbd_sysrq_xlate;
+ SYSRQ_KEY = 0x69;
+ } else
+#endif /* CONFIG_MAC_ADBKEYCODES */
+ {
+ ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate;
+ SYSRQ_KEY = 0x54;
+ }
+#endif /* CONFIG_MAGIC_SYSRQ */
+#elif defined(CONFIG_ADB_KEYBOARD)
ppc_md.kbd_setkeycode = mackbd_setkeycode;
ppc_md.kbd_getkeycode = mackbd_getkeycode;
ppc_md.kbd_translate = mackbd_translate;
@@ -691,10 +689,11 @@ pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.kbd_leds = mackbd_leds;
ppc_md.kbd_init_hw = mackbd_init_hw;
#ifdef CONFIG_MAGIC_SYSRQ
- ppc_md.ppc_kbd_sysrq_xlate = mackbd_sysrq_xlate;
+ ppc_md.ppc_kbd_sysrq_xlate = mackbd_sysrq_xlate;
SYSRQ_KEY = 0x69;
-#endif
-#endif
+#endif /* CONFIG_MAGIC_SYSRQ */
+#endif /* CONFIG_INPUT_ADBHID/CONFIG_ADB_KEYBOARD */
+#endif /* CONFIG_VT */
#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
ppc_ide_md.insw = pmac_ide_insw;
diff --git a/arch/ppc/kernel/pmac_time.c b/arch/ppc/kernel/pmac_time.c
index 9eb326bf9..00b6302a7 100644
--- a/arch/ppc/kernel/pmac_time.c
+++ b/arch/ppc/kernel/pmac_time.c
@@ -25,7 +25,7 @@
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/machdep.h>
-
+#include <asm/hardirq.h>
#include <asm/time.h>
#include <asm/nvram.h>
@@ -58,7 +58,7 @@ extern rwlock_t xtime_lock;
extern struct timezone sys_tz;
__init
-void pmac_time_init(void)
+long pmac_time_init(void)
{
#ifdef CONFIG_NVRAM
s32 delta = 0;
@@ -72,17 +72,18 @@ void pmac_time_init(void)
dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0);
printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60,
dst ? "on" : "off");
- sys_tz.tz_minuteswest = -delta/60;
- /* I _suppose_ this is 0:off, 1:on */
- sys_tz.tz_dsttime = dst;
+ return delta;
+#else
+ return 0;
#endif
}
__pmac
unsigned long pmac_get_rtc_time(void)
{
-#ifdef CONFIG_ADB
+#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
struct adb_request req;
+ unsigned long now;
#endif
/* Get the time from the RTC */
@@ -96,8 +97,9 @@ unsigned long pmac_get_rtc_time(void)
if (req.reply_len != 7)
printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
req.reply_len);
- return (req.reply[3] << 24) + (req.reply[4] << 16)
- + (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET;
+ now = (req.reply[3] << 24) + (req.reply[4] << 16)
+ + (req.reply[5] << 8) + req.reply[6];
+ return now - RTC_OFFSET;
#endif /* CONFIG_ADB_CUDA */
#ifdef CONFIG_ADB_PMU
case SYS_CTRLER_PMU:
@@ -108,21 +110,25 @@ unsigned long pmac_get_rtc_time(void)
if (req.reply_len != 5)
printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
req.reply_len);
- return (req.reply[1] << 24) + (req.reply[2] << 16)
- + (req.reply[3] << 8) + req.reply[4] - RTC_OFFSET;
+ now = (req.reply[1] << 24) + (req.reply[2] << 16)
+ + (req.reply[3] << 8) + req.reply[4];
+ return now - RTC_OFFSET;
#endif /* CONFIG_ADB_PMU */
default:
- return 0;
}
+ return 0;
}
int pmac_set_rtc_time(unsigned long nowtime)
{
+#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
struct adb_request req;
+#endif
- nowtime += RTC_OFFSET - sys_tz.tz_minuteswest * 60;
+ nowtime += RTC_OFFSET;
switch (sys_ctrler) {
+#ifdef CONFIG_ADB_CUDA
case SYS_CTRLER_CUDA:
if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
@@ -133,16 +139,19 @@ int pmac_set_rtc_time(unsigned long nowtime)
printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
req.reply_len);
return 1;
+#endif /* CONFIG_ADB_CUDA */
+#ifdef CONFIG_ADB_PMU
case SYS_CTRLER_PMU:
if (pmu_request(&req, NULL, 5, PMU_SET_RTC,
nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
return 0;
while (!req.complete)
pmu_poll();
- if (req.reply_len != 5)
+ if (req.reply_len != 0)
printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
req.reply_len);
return 1;
+#endif /* CONFIG_ADB_PMU */
default:
return 0;
}
@@ -186,12 +195,11 @@ int __init via_calibrate_decr(void)
;
dend = get_dec();
- decrementer_count = (dstart - dend) / 6;
- count_period_num = 60;
- count_period_den = decrementer_count * 6 * HZ / 100000;
+ tb_ticks_per_jiffy = (dstart - dend) / 6;
+ tb_to_us = mulhwu_scale_factor(dstart - dend, 60000);
- printk(KERN_INFO "via_calibrate_decr: decrementer_count = %u (%u ticks)\n",
- decrementer_count, dstart - dend);
+ printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n",
+ tb_ticks_per_jiffy, dstart - dend);
return 1;
}
@@ -214,8 +222,11 @@ static int time_sleep_notify(struct pmu_sleep_notifier *self, int when)
case PBOOK_WAKE:
write_lock_irqsave(&xtime_lock, flags);
xtime.tv_sec = pmac_get_rtc_time() + time_diff;
+ set_dec(tb_ticks_per_jiffy);
+ /* No currently-supported powerbook has a 601,
+ so use get_tbl, not native */
+ last_jiffy_stamp(0) = tb_last_stamp = get_tbl();
xtime.tv_usec = 0;
- set_dec(decrementer_count);
last_rtc_update = xtime.tv_sec;
write_unlock_irqrestore(&xtime_lock, flags);
break;
@@ -236,7 +247,7 @@ static struct pmu_sleep_notifier time_sleep_notifier = {
void __init pmac_calibrate_decr(void)
{
struct device_node *cpu;
- int freq, *fp, divisor;
+ unsigned int freq, *fp;
#ifdef CONFIG_PMAC_PBOOK
pmu_register_sleep_notifier(&time_sleep_notifier);
@@ -252,15 +263,13 @@ void __init pmac_calibrate_decr(void)
cpu = find_type_devices("cpu");
if (cpu == 0)
panic("can't find cpu node in time_init");
- fp = (int *) get_property(cpu, "timebase-frequency", NULL);
+ fp = (unsigned int *) get_property(cpu, "timebase-frequency", NULL);
if (fp == 0)
panic("can't get cpu timebase frequency");
- freq = *fp * 60; /* try to make freq/1e6 an integer */
- divisor = 60;
- printk("time_init: decrementer frequency = %d/%d\n",
- freq, divisor);
- decrementer_count = freq / HZ / divisor;
- count_period_num = divisor;
- count_period_den = freq / 1000000;
+ freq = *fp;
+ printk("time_init: decrementer frequency = %u.%.6u MHz\n",
+ freq/1000000, freq%1000000);
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
}
diff --git a/arch/ppc/kernel/ppc-stub.c b/arch/ppc/kernel/ppc-stub.c
index 7a673fb70..1b865ef96 100644
--- a/arch/ppc/kernel/ppc-stub.c
+++ b/arch/ppc/kernel/ppc-stub.c
@@ -122,9 +122,9 @@ void breakinst(void);
static char remcomInBuffer[BUFMAX];
static char remcomOutBuffer[BUFMAX];
-static int initialized = 0;
-static int kgdb_active = 0;
-static int kgdb_started = 0;
+static int initialized;
+static int kgdb_active;
+static int kgdb_started;
static u_int fault_jmp_buf[100];
static int kdebug;
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 1317359e7..9240431e6 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -37,6 +37,7 @@
#include <asm/hw_irq.h>
#include <asm/nvram.h>
#include <asm/mmu_context.h>
+#include <asm/backlight.h>
#ifdef CONFIG_SMP
#include <asm/smplock.h>
#endif /* CONFIG_SMP */
@@ -184,6 +185,10 @@ EXPORT_SYMBOL(giveup_fpu);
EXPORT_SYMBOL(enable_kernel_fp);
EXPORT_SYMBOL(flush_icache_range);
EXPORT_SYMBOL(xchg_u32);
+#ifdef CONFIG_ALTIVEC
+EXPORT_SYMBOL(last_task_used_altivec);
+EXPORT_SYMBOL(giveup_altivec);
+#endif /* CONFIG_ALTIVEC */
#ifdef CONFIG_SMP
EXPORT_SYMBOL(__global_cli);
EXPORT_SYMBOL(__global_sti);
@@ -204,26 +209,34 @@ EXPORT_SYMBOL(_machine);
EXPORT_SYMBOL(ppc_md);
#ifdef CONFIG_ADB
-/*
- * This could be more fine-grained, but for now assume if we have
- * ADB we have it all -- Cort
- */
EXPORT_SYMBOL(adb_request);
EXPORT_SYMBOL(adb_register);
+EXPORT_SYMBOL(adb_unregister);
+EXPORT_SYMBOL(adb_poll);
+EXPORT_SYMBOL(adb_try_handler_change);
+#endif /* CONFIG_ADB */
+#ifdef CONFIG_ADB_CUDA
EXPORT_SYMBOL(cuda_request);
EXPORT_SYMBOL(cuda_poll);
+#endif /* CONFIG_ADB_CUDA */
#ifdef CONFIG_ADB_PMU
EXPORT_SYMBOL(pmu_request);
EXPORT_SYMBOL(pmu_poll);
#endif /* CONFIG_ADB_PMU */
-#endif /* CONFIG_ADB */
#ifdef CONFIG_PMAC_PBOOK
EXPORT_SYMBOL(pmu_register_sleep_notifier);
EXPORT_SYMBOL(pmu_unregister_sleep_notifier);
EXPORT_SYMBOL(pmu_enable_irled);
-#endif CONFIG_PMAC_PBOOK
+#endif /* CONFIG_PMAC_PBOOK */
+#ifdef CONFIG_PMAC_BACKLIGHT
+EXPORT_SYMBOL(get_backlight_level);
+EXPORT_SYMBOL(set_backlight_level);
+#endif /* CONFIG_PMAC_BACKLIGHT */
#if defined(CONFIG_ALL_PPC)
EXPORT_SYMBOL_NOVERS(sys_ctrler);
+#ifndef CONFIG_MACH_SPECIFIC
+EXPORT_SYMBOL_NOVERS(have_of);
+#endif /* CONFIG_MACH_SPECIFIC */
EXPORT_SYMBOL(find_devices);
EXPORT_SYMBOL(find_type_devices);
EXPORT_SYMBOL(find_compatible_devices);
@@ -253,10 +266,7 @@ EXPORT_SYMBOL(nvram_write_byte);
EXPORT_SYMBOL(pmac_xpram_read);
EXPORT_SYMBOL(pmac_xpram_write);
#endif /* CONFIG_NVRAM */
-#ifdef CONFIG_PPC_RTC
-EXPORT_SYMBOL(mktime);
EXPORT_SYMBOL(to_tm);
-#endif
EXPORT_SYMBOL_NOVERS(__ashrdi3);
EXPORT_SYMBOL_NOVERS(__ashldi3);
@@ -280,7 +290,7 @@ EXPORT_SYMBOL(do_IRQ_intercept);
EXPORT_SYMBOL(irq_desc);
void ppc_irq_dispatch_handler(struct pt_regs *, int);
EXPORT_SYMBOL(ppc_irq_dispatch_handler);
-EXPORT_SYMBOL(decrementer_count);
+EXPORT_SYMBOL(tb_ticks_per_jiffy);
EXPORT_SYMBOL(get_wchan);
EXPORT_SYMBOL(console_drivers);
EXPORT_SYMBOL(console_lock);
@@ -310,3 +320,17 @@ EXPORT_SYMBOL(do_softirq);
EXPORT_SYMBOL(next_mmu_context);
EXPORT_SYMBOL(set_context);
EXPORT_SYMBOL(mmu_context_overflow);
+
+#ifdef CONFIG_MOL
+extern ulong mol_interface[];
+extern PTE *Hash;
+extern unsigned long Hash_mask;
+extern void (*ret_from_except)(void);
+extern struct task_struct *last_task_used_altivec;
+EXPORT_SYMBOL_NOVERS(mol_interface);
+EXPORT_SYMBOL(Hash);
+EXPORT_SYMBOL(Hash_mask);
+EXPORT_SYMBOL(handle_mm_fault);
+EXPORT_SYMBOL(last_task_used_math);
+EXPORT_SYMBOL(ret_from_except);
+#endif /* CONFIG_MOL */
diff --git a/arch/ppc/kernel/prep_setup.c b/arch/ppc/kernel/prep_setup.c
index a09b4cf81..d72e74735 100644
--- a/arch/ppc/kernel/prep_setup.c
+++ b/arch/ppc/kernel/prep_setup.c
@@ -365,14 +365,13 @@ prep_setup_arch(void)
*/
void __init prep_res_calibrate_decr(void)
{
- int freq, divisor;
+ unsigned long freq, divisor=4;
freq = res->VitalProductData.ProcessorBusHz;
- divisor = 4;
- printk("time_init: decrementer frequency = %d/%d\n", freq, divisor);
- decrementer_count = freq / HZ / divisor;
- count_period_num = divisor;
- count_period_den = freq / 1000000;
+ printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ (freq/divisor)/1000000, (freq/divisor)%1000000);
+ tb_ticks_per_jiffy = freq / HZ / divisor;
+ tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
}
/*
@@ -381,32 +380,30 @@ void __init prep_res_calibrate_decr(void)
* but on prep we have to figure it out.
* -- Cort
*/
-int calibrate_done = 0;
-volatile int *done_ptr = &calibrate_done;
+/* Done with 3 interrupts: the first one primes the cache and the
+ * 2 following ones measure the interval. The precision of the method
+ * is still doubtful due to the short interval sampled.
+ */
+static __initdata volatile int calibrate_steps = 3;
+static __initdata unsigned tbstamp;
void __init
prep_calibrate_decr_handler(int irq,
void *dev,
struct pt_regs *regs)
{
- unsigned long freq, divisor;
- static unsigned long t1 = 0, t2 = 0;
-
- if ( !t1 )
- t1 = get_dec();
- else if (!t2)
- {
- t2 = get_dec();
- t2 = t1-t2; /* decr's in 1/HZ */
- t2 = t2*HZ; /* # decrs in 1s - thus in Hz */
- freq = t2 * 60; /* try to make freq/1e6 an integer */
- divisor = 60;
- printk("time_init: decrementer frequency = %lu/%lu (%luMHz)\n",
- freq, divisor,t2>>20);
- decrementer_count = freq / HZ / divisor;
- count_period_num = divisor;
- count_period_den = freq / 1000000;
- *done_ptr = 1;
+ unsigned long t, freq;
+ int step=--calibrate_steps;
+
+ t = get_tbl();
+ if (step > 0) {
+ tbstamp = t;
+ } else {
+ freq = (t - tbstamp)*HZ;
+ printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ freq/1000000, freq%1000000);
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
}
}
@@ -428,17 +425,43 @@ void __init prep_calibrate_decr(void)
if (request_irq(0, prep_calibrate_decr_handler, 0, "timer", NULL) != 0)
panic("Could not allocate timer IRQ!");
__sti();
- while ( ! *done_ptr ) /* nothing */; /* wait for calibrate */
+ while ( calibrate_steps ) /* nothing */; /* wait for calibrate */
restore_flags(flags);
free_irq( 0, NULL);
}
-/* We use the NVRAM RTC to time a second to calibrate the decrementer. */
+static long __init mk48t59_init(void) {
+ unsigned char tmp;
+
+ tmp = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB);
+ if (tmp & MK48T59_RTC_CB_STOP) {
+ printk("Warning: RTC was stopped, date will be wrong.\n");
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLB,
+ tmp & ~MK48T59_RTC_CB_STOP);
+ /* Low frequency crystal oscillators may take a very long
+ * time to startup and stabilize. For now just ignore the
+ * the issue, but attempting to calibrate the decrementer
+ * from the RTC just after this wakeup is likely to be very
+ * inaccurate. Firmware should not allow to load
+ * the OS with the clock stopped anyway...
+ */
+ }
+ /* Ensure that the clock registers are updated */
+ tmp = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
+ tmp &= ~(MK48T59_RTC_CA_READ | MK48T59_RTC_CA_WRITE);
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, tmp);
+ return 0;
+}
+
+/* We use the NVRAM RTC to time a second to calibrate the decrementer,
+ * the RTC registers have just been set up in the right state by the
+ * preceding routine.
+ */
void __init mk48t59_calibrate_decr(void)
{
- unsigned long freq, divisor;
- unsigned long t1, t2;
+ unsigned long freq;
+ unsigned long t1;
unsigned char save_control;
long i;
unsigned char sec;
@@ -458,29 +481,31 @@ void __init mk48t59_calibrate_decr(void)
/* Read the seconds value to see when it changes. */
sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
+ /* Actually this is bad for precision, we should have a loop in
+ * which we only read the seconds counter. nvram_read_val writes
+ * the address bytes on every call and this takes a lot of time.
+ * Perhaps an nvram_wait_change method returning a time
+ * stamp with a loop count as parameter would be the solution.
+ */
for (i = 0 ; i < 1000000 ; i++) { /* may take up to 1 second... */
+ t1 = get_tbl();
if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) {
break;
}
}
- t1 = get_dec();
sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
for (i = 0 ; i < 1000000 ; i++) { /* Should take up 1 second... */
+ freq = get_tbl()-t1;
if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) {
break;
}
}
- t2 = t1 - get_dec();
-
- freq = t2 * 60; /* try to make freq/1e6 an integer */
- divisor = 60;
- printk("time_init: decrementer frequency = %lu/%lu (%luMHz)\n",
- freq, divisor,t2>>20);
- decrementer_count = freq / HZ / divisor;
- count_period_num = divisor;
- count_period_den = freq / 1000000;
+ printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ freq/1000000, freq%1000000);
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
}
void __prep
@@ -788,6 +813,7 @@ prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
{
ppc_md.set_rtc_time = mk48t59_set_rtc_time;
ppc_md.get_rtc_time = mk48t59_get_rtc_time;
+ ppc_md.time_init = mk48t59_init;
}
else
{
@@ -808,6 +834,7 @@ prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.set_rtc_time = mk48t59_set_rtc_time;
ppc_md.get_rtc_time = mk48t59_get_rtc_time;
ppc_md.calibrate_decr = mk48t59_calibrate_decr;
+ ppc_md.time_init = mk48t59_init;
}
#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
diff --git a/arch/ppc/kernel/prep_time.c b/arch/ppc/kernel/prep_time.c
index 7274dfd0b..78634c6e2 100644
--- a/arch/ppc/kernel/prep_time.c
+++ b/arch/ppc/kernel/prep_time.c
@@ -15,6 +15,7 @@
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
+#include <linux/time.h>
#include <linux/timex.h>
#include <linux/kernel_stat.h>
#include <linux/init.h>
@@ -99,28 +100,34 @@ __prep
unsigned long mc146818_get_rtc_time(void)
{
unsigned int year, mon, day, hour, min, sec;
- int i;
+ int uip, i;
/* The Linux interpretation of the CMOS clock register contents:
* When the Update-In-Progress (UIP) flag goes from 1 to 0, the
* RTC registers show the second which has precisely just started.
* Let's hope other operating systems interpret the RTC the same way.
*/
- /* read RTC exactly on falling edge of update flag */
- for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
- break;
- for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
- if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
- break;
- do { /* Isn't this overkill ? UIP above should guarantee consistency */
+
+ /* Since the UIP flag is set for about 2.2 ms and the clock
+ * is typically written with a precision of 1 jiffy, trying
+ * to obtain a precision better than a few milliseconds is
+ * an illusion. Only consistency is interesting, this also
+ * allows to use the routine for /dev/rtc without a potential
+ * 1 second kernel busy loop triggered by any reader of /dev/rtc.
+ */
+
+ for ( i = 0; i<1000000; i++) {
+ uip = CMOS_READ(RTC_FREQ_SELECT);
sec = CMOS_READ(RTC_SECONDS);
min = CMOS_READ(RTC_MINUTES);
hour = CMOS_READ(RTC_HOURS);
day = CMOS_READ(RTC_DAY_OF_MONTH);
mon = CMOS_READ(RTC_MONTH);
year = CMOS_READ(RTC_YEAR);
- } while (sec != CMOS_READ(RTC_SECONDS));
+ uip |= CMOS_READ(RTC_FREQ_SELECT);
+ if ((uip & RTC_UIP)==0) break;
+ }
+
if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
|| RTC_ALWAYS_BCD)
{
@@ -177,29 +184,12 @@ unsigned long mk48t59_get_rtc_time(void)
{
unsigned char save_control;
unsigned int year, mon, day, hour, min, sec;
- int i;
- /* Make sure the time is not stopped. */
- save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB);
-
- ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
- (save_control & (~MK48T59_RTC_CB_STOP)));
-
- /* Now make sure the read bit is off so the value will change. */
+ /* Simple: freeze the clock, read it and allow updates again */
save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
save_control &= ~MK48T59_RTC_CA_READ;
ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
- /* Read the seconds value to see when it changes. */
- sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
-
- /* Wait until the seconds value changes, then read the value. */
- for (i = 0 ; i < 1000000 ; i++) { /* may take up to 1 second... */
- if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) {
- break;
- }
- }
-
/* Set the register to read the value. */
ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
(save_control | MK48T59_RTC_CA_READ));
diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
index 7bc5cb82f..27adc9958 100644
--- a/arch/ppc/kernel/process.c
+++ b/arch/ppc/kernel/process.c
@@ -234,7 +234,6 @@ _switch_to(struct task_struct *prev, struct task_struct *new,
prev->thread.vrsave )
giveup_altivec(prev);
#endif /* CONFIG_ALTIVEC */
- prev->last_processor = prev->processor;
current_set[smp_processor_id()] = new;
#endif /* CONFIG_SMP */
/* Avoid the trap. On smp this this never happens since
@@ -266,7 +265,7 @@ void show_regs(struct pt_regs * regs)
last_task_used_altivec);
#ifdef CONFIG_SMP
- printk(" CPU: %d last CPU: %d", current->processor,current->last_processor);
+ printk(" CPU: %d", current->processor);
#endif /* CONFIG_SMP */
printk("\n");
@@ -315,6 +314,7 @@ release_thread(struct task_struct *t)
*/
int
copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+ unsigned long unused,
struct task_struct * p, struct pt_regs * regs)
{
unsigned long msr;
@@ -378,9 +378,6 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
childregs->msr &= ~MSR_VEC;
#endif /* CONFIG_ALTIVEC */
-#ifdef CONFIG_SMP
- p->last_processor = NO_PROC_ID;
-#endif /* CONFIG_SMP */
return 0;
}
@@ -440,13 +437,13 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
current->thread.fpscr = 0;
}
-asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
- struct pt_regs *regs)
+int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
+ struct pt_regs *regs)
{
unsigned long clone_flags = p1;
int res;
lock_kernel();
- res = do_fork(clone_flags, regs->gpr[1], regs);
+ res = do_fork(clone_flags, regs->gpr[1], regs, 0);
#ifdef CONFIG_SMP
/* When we clone the idle task we keep the same pid but
* the return value of 0 for both causes problems.
@@ -459,13 +456,13 @@ asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
return res;
}
-asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
- struct pt_regs *regs)
+int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
+ struct pt_regs *regs)
{
int res;
- res = do_fork(SIGCHLD, regs->gpr[1], regs);
+ res = do_fork(SIGCHLD, regs->gpr[1], regs, 0);
#ifdef CONFIG_SMP
/* When we clone the idle task we keep the same pid but
* the return value of 0 for both causes problems.
@@ -477,15 +474,15 @@ asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
return res;
}
-asmlinkage int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6,
- struct pt_regs *regs)
+int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6,
+ struct pt_regs *regs)
{
- return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs);
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0);
}
-asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
- unsigned long a3, unsigned long a4, unsigned long a5,
- struct pt_regs *regs)
+int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
+ unsigned long a3, unsigned long a4, unsigned long a5,
+ struct pt_regs *regs)
{
int error;
char * filename;
diff --git a/arch/ppc/kernel/prom.c b/arch/ppc/kernel/prom.c
index 1d661fa71..5494f2f52 100644
--- a/arch/ppc/kernel/prom.c
+++ b/arch/ppc/kernel/prom.c
@@ -140,8 +140,7 @@ static long g_loc_Y = 0;
static long g_max_loc_X = 0;
static long g_max_loc_Y = 0;
-unsigned long disp_BATL = 0;
-unsigned long disp_BATU = 0;
+unsigned long disp_BAT[2] = {0, 0};
#define cmapsz (16*256)
@@ -276,8 +275,7 @@ prom_print(const char *msg)
prom_drawstring(msg);
#endif
return;
- }
-
+ }
for (p = msg; *p != 0; p = q) {
for (q = p; *q != 0 && *q != '\n'; ++q)
@@ -362,7 +360,7 @@ prom_hold_cpus(unsigned long mem)
/* copy the holding pattern code to someplace safe (0) */
/* the holding pattern is now within the first 0x100
bytes of the kernel image -- paulus */
- memcpy((void *)0, KERNELBASE + offset, 0x100);
+ memcpy((void *)0, (void *)(KERNELBASE + offset), 0x100);
flush_icache_range(0, 0x100);
/* look for cpus */
@@ -556,6 +554,54 @@ prom_alloc_htab(void)
}
#endif /* CONFIG_PPC64BRIDGE */
+static __init void
+prom_instantiate_rtas(void)
+{
+ ihandle prom_rtas;
+ unsigned int i;
+ struct prom_args prom_args;
+ unsigned long offset = reloc_offset();
+
+ prom_rtas = call_prom(RELOC("finddevice"), 1, 1, RELOC("/rtas"));
+ if (prom_rtas == (void *) -1)
+ return;
+
+ RELOC(rtas_size) = 0;
+ call_prom(RELOC("getprop"), 4, 1, prom_rtas,
+ RELOC("rtas-size"), &RELOC(rtas_size), sizeof(rtas_size));
+ prom_print(RELOC("instantiating rtas"));
+ if (RELOC(rtas_size) == 0) {
+ RELOC(rtas_data) = 0;
+ } else {
+ /*
+ * Ask OF for some space for RTAS.
+ * Actually OF has bugs so we just arbitrarily
+ * use memory at the 6MB point.
+ */
+ RELOC(rtas_data) = 6 << 20;
+ prom_print(RELOC(" at "));
+ prom_print_hex(RELOC(rtas_data));
+ }
+
+ prom_rtas = call_prom(RELOC("open"), 1, 1, RELOC("/rtas"));
+ prom_print(RELOC("..."));
+ prom_args.service = RELOC("call-method");
+ prom_args.nargs = 3;
+ prom_args.nret = 2;
+ prom_args.args[0] = RELOC("instantiate-rtas");
+ prom_args.args[1] = prom_rtas;
+ prom_args.args[2] = (void *) RELOC(rtas_data);
+ RELOC(prom)(&prom_args);
+ i = 0;
+ if (prom_args.args[3] == 0)
+ i = (unsigned int)prom_args.args[4];
+ RELOC(rtas_entry) = i;
+ if ((RELOC(rtas_entry) == -1) || (RELOC(rtas_entry) == 0))
+ prom_print(RELOC(" failed\n"));
+ else
+ prom_print(RELOC(" done\n"));
+}
+
/*
* We enter here early on, when the Open Firmware prom is still
* handling exceptions and the MMU hash table for us.
@@ -566,7 +612,7 @@ prom_init(int r3, int r4, prom_entry pp)
{
int chrp = 0;
unsigned long mem;
- ihandle prom_rtas, prom_mmu, prom_op;
+ ihandle prom_mmu, prom_op;
unsigned long offset = reloc_offset();
int l;
char *p, *d;
@@ -650,47 +696,7 @@ prom_init(int r3, int r4, prom_entry pp)
mem = ALIGN(mem + strlen(d) + 1);
}
- prom_rtas = call_prom(RELOC("finddevice"), 1, 1, RELOC("/rtas"));
- if (prom_rtas != (void *) -1) {
- int i, nargs;
- struct prom_args prom_args;
-
- RELOC(rtas_size) = 0;
- call_prom(RELOC("getprop"), 4, 1, prom_rtas,
- RELOC("rtas-size"), &RELOC(rtas_size), sizeof(rtas_size));
- prom_print(RELOC("instantiating rtas"));
- if (RELOC(rtas_size) == 0) {
- RELOC(rtas_data) = 0;
- } else {
- /*
- * Ask OF for some space for RTAS.
- * Actually OF has bugs so we just arbitrarily
- * use memory at the 6MB point.
- */
- RELOC(rtas_data) = 6 << 20;
- prom_print(RELOC(" at "));
- prom_print_hex(RELOC(rtas_data));
- }
- prom_rtas = call_prom(RELOC("open"), 1, 1, RELOC("/rtas"));
- prom_print(RELOC("..."));
- nargs = 3;
- prom_args.service = RELOC("call-method");
- prom_args.nargs = nargs;
- prom_args.nret = 2;
- prom_args.args[0] = RELOC("instantiate-rtas");
- prom_args.args[1] = prom_rtas;
- prom_args.args[2] = (void *) RELOC(rtas_data);
- RELOC(prom)(&prom_args);
- if (prom_args.args[nargs] != 0)
- i = 0;
- else
- i = (int)prom_args.args[nargs+1];
- RELOC(rtas_entry) = i;
- if ((RELOC(rtas_entry) == -1) || (RELOC(rtas_entry) == 0))
- prom_print(RELOC(" failed\n"));
- else
- prom_print(RELOC(" done\n"));
- }
+ prom_instantiate_rtas();
#ifdef CONFIG_PPC64BRIDGE
/*
@@ -737,7 +743,7 @@ prom_init(int r3, int r4, prom_entry pp)
/* We assume the phys. address size is 3 cells */
if (prom_args.args[nargs] != 0)
- prom_print(RELOC(" (translate failed) "));
+ prom_print(RELOC(" (translate failed)\n"));
else
phys = (unsigned long)prom_args.args[nargs+3];
}
@@ -752,8 +758,6 @@ prom_init(int r3, int r4, prom_entry pp)
if (prom_version >= 3) {
prom_print(RELOC("Calling quiesce ...\n"));
call_prom(RELOC("quiesce"), 0, 0);
- offset = reloc_offset();
- phys = offset + KERNELBASE;
}
#ifdef CONFIG_BOOTX_TEXT
@@ -769,7 +773,9 @@ prom_init(int r3, int r4, prom_entry pp)
}
#endif
- prom_print(RELOC("returning from prom_init\n"));
+ prom_print(RELOC("returning "));
+ prom_print_hex(phys);
+ prom_print(RELOC(" from prom_init\n"));
RELOC(prom_stdout) = 0;
return phys;
}
@@ -836,9 +842,8 @@ prom_welcome(boot_infos_t* bi, unsigned long phys)
}
/* Calc BAT values for mapping the display and store them
- * in disp_BATH and disp_BATL. Those values are then used
- * from head.S to map the display during identify_machine()
- * and MMU_Init()
+ * in disp_BAT. Those values are then used from head.S to map
+ * the display during identify_machine() and MMU_Init()
*
* For now, the display is mapped in place (1:1). This should
* be changed if the display physical address overlaps
@@ -862,13 +867,13 @@ prepare_disp_BAT(void)
if ((_get_PVR() >> 16) != 1) {
/* 603, 604, G3, G4, ... */
addr &= 0xFF000000UL;
- RELOC(disp_BATU) = addr | (BL_16M<<2) | 2;
- RELOC(disp_BATL) = addr | (_PAGE_NO_CACHE | _PAGE_GUARDED | BPP_RW);
+ RELOC(disp_BAT[0]) = addr | (BL_16M<<2) | 2;
+ RELOC(disp_BAT[1]) = addr | (_PAGE_NO_CACHE | _PAGE_GUARDED | BPP_RW);
} else {
/* 601 */
addr &= 0xFF800000UL;
- RELOC(disp_BATU) = addr | (_PAGE_NO_CACHE | PP_RWXX) | 4;
- RELOC(disp_BATL) = addr | BL_8M | 0x40;
+ RELOC(disp_BAT[0]) = addr | (_PAGE_NO_CACHE | PP_RWXX) | 4;
+ RELOC(disp_BAT[1]) = addr | BL_8M | 0x40;
}
bi->logicalDisplayBase = bi->dispDeviceBase;
}
@@ -1003,34 +1008,52 @@ setup_disp_fake_bi(ihandle dp)
unsigned address;
boot_infos_t* bi;
unsigned long offset = reloc_offset();
-
- prom_print(RELOC("Initializing fake screen\n"));
-
- call_prom(RELOC("getprop"), 4, 1, dp, RELOC("width"),
- &width, sizeof(width));
- call_prom(RELOC("getprop"), 4, 1, dp, RELOC("height"),
- &height, sizeof(height));
- call_prom(RELOC("getprop"), 4, 1, dp, RELOC("depth"),
- &depth, sizeof(depth));
+ struct pci_reg_property addrs[8];
+ int i, naddrs;
+ char name[32];
+ char *getprop = RELOC("getprop");
+
+ prom_print(RELOC("Initializing fake screen: "));
+
+ memset(name, 0, sizeof(name));
+ call_prom(getprop, 4, 1, dp, RELOC("name"), name, sizeof(name));
+ name[sizeof(name)-1] = 0;
+ prom_print(name);
+ prom_print(RELOC("\n"));
+ call_prom(getprop, 4, 1, dp, RELOC("width"), &width, sizeof(width));
+ call_prom(getprop, 4, 1, dp, RELOC("height"), &height, sizeof(height));
+ call_prom(getprop, 4, 1, dp, RELOC("depth"), &depth, sizeof(depth));
pitch = width * ((depth + 7) / 8);
- call_prom(RELOC("getprop"), 4, 1, dp, RELOC("linebytes"),
+ call_prom(getprop, 4, 1, dp, RELOC("linebytes"),
&pitch, sizeof(pitch));
- address = 0;
- if (pitch == 1) {
- address = 0xfa000000;
+ if (pitch == 1)
pitch = 0x1000; /* for strange IBM display */
- }
- call_prom(RELOC("getprop"), 4, 1, dp, RELOC("address"),
+ address = 0;
+ call_prom(getprop, 4, 1, dp, RELOC("address"),
&address, sizeof(address));
if (address == 0) {
- prom_print(RELOC("Failed to get address\n"));
- return;
+ /* look for an assigned address with a size of >= 1MB */
+ naddrs = (int) call_prom(getprop, 4, 1, dp,
+ RELOC("assigned-addresses"),
+ addrs, sizeof(addrs));
+ naddrs /= sizeof(struct pci_reg_property);
+ for (i = 0; i < naddrs; ++i) {
+ if (addrs[i].size_lo >= (1 << 20)) {
+ address = addrs[i].addr.a_lo;
+ /* use the BE aperture if possible */
+ if (addrs[i].size_lo >= (16 << 20))
+ address += (8 << 20);
+ break;
+ }
+ }
+ if (address == 0) {
+ prom_print(RELOC("Failed to get address\n"));
+ return;
+ }
}
-#if 0
/* kludge for valkyrie */
- if (strcmp(dp->name, "valkyrie") == 0)
- address += 0x1000;
-#endif
+ if (strcmp(name, RELOC("valkyrie")) == 0)
+ address += 0x1000;
RELOC(disp_bi) = &fake_bi;
bi = PTRRELOC((&fake_bi));
@@ -1334,11 +1357,19 @@ finish_node_interrupts(struct device_node *np, unsigned long mem_start)
*/
if (get_property(node, "interrupt-controller", &l)) {
int i,j;
+ int cvt_irq;
+
+ /* XXX on chrp, offset interrupt numbers for the
+ 8259 by 0, those for the openpic by 16 */
+ cvt_irq = _machine == _MACH_chrp
+ && get_property(node, "interrupt-parent", NULL) == 0;
np->intrs = (struct interrupt_info *) mem_start;
np->n_intrs = ipsize / isize;
mem_start += np->n_intrs * sizeof(struct interrupt_info);
for (i = 0; i < np->n_intrs; ++i) {
np->intrs[i].line = *interrupts++;
+ if (cvt_irq)
+ np->intrs[i].line = openpic_to_irq(np->intrs[i].line);
np->intrs[i].sense = 0;
if (isize > 1)
np->intrs[i].sense = *interrupts++;
@@ -2072,7 +2103,6 @@ abort()
* changes.
*/
-__init
void
map_bootx_text(void)
{
@@ -2083,7 +2113,10 @@ map_bootx_text(void)
offset = ((unsigned long) disp_bi->dispDeviceBase) - base;
size = disp_bi->dispDeviceRowBytes * disp_bi->dispDeviceRect[3] + offset
+ disp_bi->dispDeviceRect[0];
- disp_bi->logicalDisplayBase = ioremap(base, size) + offset;
+ disp_bi->logicalDisplayBase = ioremap(base, size);
+ if (disp_bi->logicalDisplayBase == 0)
+ return;
+ disp_bi->logicalDisplayBase += offset;
bootx_text_mapped = 1;
}
@@ -2102,6 +2135,35 @@ calc_base(boot_infos_t *bi, int x, int y)
return base;
}
+/* Adjust the display to a new resolution */
+void
+bootx_update_display(unsigned long phys, int width, int height,
+ int depth, int pitch)
+{
+ if (disp_bi == 0)
+ return;
+ /* check it's the same frame buffer (within 16MB) */
+ if ((phys ^ (unsigned long)disp_bi->dispDeviceBase) & 0xff000000)
+ return;
+
+ disp_bi->dispDeviceBase = (__u8 *) phys;
+ disp_bi->dispDeviceRect[0] = 0;
+ disp_bi->dispDeviceRect[1] = 0;
+ disp_bi->dispDeviceRect[2] = width;
+ disp_bi->dispDeviceRect[3] = height;
+ disp_bi->dispDeviceDepth = depth;
+ disp_bi->dispDeviceRowBytes = pitch;
+ if (bootx_text_mapped) {
+ iounmap(disp_bi->logicalDisplayBase);
+ bootx_text_mapped = 0;
+ }
+ map_bootx_text();
+ g_loc_X = 0;
+ g_loc_Y = 0;
+ g_max_loc_X = width / 8;
+ g_max_loc_Y = height / 16;
+}
+
__pmac
static void
clearscreen(void)
@@ -2162,6 +2224,9 @@ scrollscreen(void)
(bi->dispDeviceDepth >> 3)) >> 2;
int i,j;
+#ifdef CONFIG_ADB_PMU
+ pmu_suspend(); /* PMU will not shut us down ! */
+#endif
for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++)
{
unsigned long *src_ptr = src;
@@ -2178,6 +2243,9 @@ scrollscreen(void)
*(dst_ptr++) = 0;
dst += (bi->dispDeviceRowBytes >> 2);
}
+#ifdef CONFIG_ADB_PMU
+ pmu_resume(); /* PMU will not shut us down ! */
+#endif
}
#endif /* ndef NO_SCROLL */
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 67387cca0..6bafa57c1 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -35,6 +35,8 @@
#include <asm/bootx.h>
#include <asm/machdep.h>
#include <asm/feature.h>
+#include <asm/uaccess.h>
+
#ifdef CONFIG_OAK
#include "oak_setup.h"
#endif /* CONFIG_OAK */
@@ -655,16 +657,18 @@ int parse_bootinfo(void)
}
/* Checks "l2cr=xxxx" command-line option */
-void ppc_setup_l2cr(char *str, int *ints)
+int ppc_setup_l2cr(char *str)
{
if ( ((_get_PVR() >> 16) == 8) || ((_get_PVR() >> 16) == 12) )
{
unsigned long val = simple_strtoul(str, NULL, 0);
printk(KERN_INFO "l2cr set to %lx\n", val);
- _set_L2CR(0);
- _set_L2CR(val);
+ _set_L2CR(0); /* force invalidate by disable cache */
+ _set_L2CR(val); /* and enable it */
}
+ return 1;
}
+__setup("l2cr=", ppc_setup_l2cr);
void __init ppc_init(void)
{
@@ -683,6 +687,9 @@ void __init setup_arch(char **cmdline_p)
extern char *klimit;
extern void do_init_bootmem(void);
+ /* so udelay does something sensible, assume <= 1000 bogomips */
+ loops_per_sec = 500000000;
+
#ifdef CONFIG_ALL_PPC
feature_init();
#endif
@@ -737,6 +744,7 @@ void __init setup_arch(char **cmdline_p)
if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
paging_init();
+ sort_exception_table();
}
void ppc_generic_ide_fix_driveid(struct hd_driveid *id)
diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
index 79847fa0d..dd3d1ae1b 100644
--- a/arch/ppc/kernel/signal.c
+++ b/arch/ppc/kernel/signal.c
@@ -154,7 +154,7 @@ sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, int p3, int p4, int p6,
}
-asmlinkage int
+int
sys_sigaltstack(const stack_t *uss, stack_t *uoss)
{
struct pt_regs *regs = (struct pt_regs *) &uss;
@@ -232,7 +232,7 @@ struct rt_sigframe
* Each of these things must be a multiple of 16 bytes in size.
*
*/
-asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+int sys_rt_sigreturn(struct pt_regs *regs)
{
struct rt_sigframe *rt_sf;
struct sigcontext_struct sigctx;
@@ -301,7 +301,6 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
return ret;
badframe:
- lock_kernel();
do_exit(SIGSEGV);
}
@@ -351,7 +350,6 @@ badframe:
printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n",
regs, frame, newsp);
#endif
- lock_kernel();
do_exit(SIGSEGV);
}
@@ -418,7 +416,6 @@ int sys_sigreturn(struct pt_regs *regs)
return ret;
badframe:
- lock_kernel();
do_exit(SIGSEGV);
}
@@ -460,7 +457,6 @@ badframe:
printk("badframe in setup_frame, regs=%p frame=%p newsp=%lx\n",
regs, frame, newsp);
#endif
- lock_kernel();
do_exit(SIGSEGV);
}
@@ -541,7 +537,6 @@ badframe:
regs, frame, *newspp);
printk("sc=%p sig=%d ka=%p info=%p oldset=%p\n", sc, sig, ka, info, oldset);
#endif
- lock_kernel();
do_exit(SIGSEGV);
}
@@ -645,8 +640,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
/* FALLTHRU */
default:
- lock_kernel();
- sigaddset(&current->signal, signr);
+ sigaddset(&current->pending.signal, signr);
recalc_sigpending(current);
current->flags |= PF_SIGNALED;
do_exit(exit_code);
@@ -663,6 +657,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
/* Whee! Actually deliver the signal. */
handle_signal(signr, ka, &info, oldset, regs, &newsp, frame);
+ break;
}
if (regs->trap == 0x0C00 /* System Call! */ &&
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index 8cb68c6b2..0a66d6c6b 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -62,72 +62,62 @@ volatile unsigned long cpu_callin_map[NR_CPUS] = {0,};
int start_secondary(void *);
extern int cpu_idle(void *unused);
u_int openpic_read(volatile u_int *addr);
+void smp_call_function_interrupt(void);
+void smp_message_pass(int target, int msg, unsigned long data, int wait);
+/* register for interrupting the primary processor on the powersurge */
+/* N.B. this is actually the ethernet ROM! */
+#define PSURGE_PRI_INTR 0xf3019000
/* register for interrupting the secondary processor on the powersurge */
-#define PSURGE_INTR ((volatile unsigned *)0xf80000c0)
+#define PSURGE_SEC_INTR 0xf80000c0
+/* register for storing the start address for the secondary processor */
+#define PSURGE_START 0xf2800000
+/* virtual addresses for the above */
+volatile u32 *psurge_pri_intr;
+volatile u32 *psurge_sec_intr;
+volatile u32 *psurge_start;
+
+/* Since OpenPIC has only 4 IPIs, we use slightly different message numbers. */
+#define PPC_MSG_CALL_FUNCTION 0
+#define PPC_MSG_RESCHEDULE 1
+#define PPC_MSG_INVALIDATE_TLB 2
+#define PPC_MSG_XMON_BREAK 3
+
+static inline void set_tb(unsigned int upper, unsigned int lower)
+{
+ mtspr(SPRN_TBWU, upper);
+ mtspr(SPRN_TBWL, lower);
+}
void smp_local_timer_interrupt(struct pt_regs * regs)
{
int cpu = smp_processor_id();
- extern void update_one_process(struct task_struct *,unsigned long,
- unsigned long,unsigned long,int);
- if (!--prof_counter[cpu]) {
- int user=0,system=0;
- struct task_struct * p = current;
-
- /*
- * After doing the above, we need to make like
- * a normal interrupt - otherwise timer interrupts
- * ignore the global interrupt lock, which is the
- * WrongThing (tm) to do.
- */
-
- if (user_mode(regs))
- user=1;
- else
- system=1;
-
- if (p->pid) {
- update_one_process(p, 1, user, system, cpu);
-
- p->counter -= 1;
- if (p->counter <= 0) {
- p->counter = 0;
- current->need_resched = 1;
- }
- if (p->nice > 0) {
- kstat.cpu_nice += user;
- kstat.per_cpu_nice[cpu] += user;
- } else {
- kstat.cpu_user += user;
- kstat.per_cpu_user[cpu] += user;
- }
- kstat.cpu_system += system;
- kstat.per_cpu_system[cpu] += system;
-
- }
+ if (!--prof_counter[cpu]) {
+ update_process_times(user_mode(regs));
prof_counter[cpu]=prof_multiplier[cpu];
}
}
-void smp_message_recv(int msg)
+void smp_message_recv(int msg, struct pt_regs *regs)
{
ipi_count++;
- switch( msg )
- {
- case MSG_STOP_CPU:
- __cli();
- while (1) ;
+ switch( msg ) {
+ case PPC_MSG_CALL_FUNCTION:
+ smp_call_function_interrupt();
break;
- case MSG_RESCHEDULE:
+ case PPC_MSG_RESCHEDULE:
current->need_resched = 1;
break;
- case MSG_INVALIDATE_TLB:
+ case PPC_MSG_INVALIDATE_TLB:
_tlbia();
- case 0xf0f0: /* pmac syncing time bases - just return */
break;
+#ifdef CONFIG_XMON
+ case PPC_MSG_XMON_BREAK:
+ xmon(regs);
+ break;
+#endif /* CONFIG_XMON */
default:
printk("SMP %d: smp_message_recv(): unknown msg %d\n",
smp_processor_id(), msg);
@@ -142,25 +132,38 @@ void smp_message_recv(int msg)
* smp_message[].
*
* This is because don't have several IPI's on the PowerSurge even though
- * we do on the chrp. It would be nice to use actual IPI's such as with openpic
- * rather than this.
+ * we do on the chrp. It would be nice to use actual IPI's such as with
+ * openpic rather than this.
* -- Cort
*/
int pmac_smp_message[NR_CPUS];
-void pmac_smp_message_recv(void)
+void pmac_smp_message_recv(struct pt_regs *regs)
{
- int msg = pmac_smp_message[smp_processor_id()];
-
+ int cpu = smp_processor_id();
+ int msg;
+
/* clear interrupt */
- out_be32(PSURGE_INTR, ~0);
-
- /* make sure msg is for us */
- if ( msg == -1 ) return;
+ if (cpu == 1)
+ out_be32(psurge_sec_intr, ~0);
+
+ if (smp_num_cpus < 2)
+ return;
+
+ /* make sure there is a message there */
+ msg = pmac_smp_message[cpu];
+ if (msg == 0)
+ return;
- smp_message_recv(msg);
-
/* reset message */
- pmac_smp_message[smp_processor_id()] = -1;
+ pmac_smp_message[cpu] = 0;
+
+ smp_message_recv(msg - 1, regs);
+}
+
+void
+pmac_primary_intr(int irq, void *d, struct pt_regs *regs)
+{
+ pmac_smp_message_recv(regs);
}
/*
@@ -171,7 +174,7 @@ void pmac_smp_message_recv(void)
void smp_send_tlb_invalidate(int cpu)
{
if ( (_get_PVR()>>16) == 8 )
- smp_message_pass(MSG_ALL_BUT_SELF, MSG_INVALIDATE_TLB, 0, 0);
+ smp_message_pass(MSG_ALL_BUT_SELF, PPC_MSG_INVALIDATE_TLB, 0, 0);
}
void smp_send_reschedule(int cpu)
@@ -187,18 +190,135 @@ void smp_send_reschedule(int cpu)
*/
/* This is only used if `cpu' is running an idle task,
so it will reschedule itself anyway... */
- smp_message_pass(cpu, MSG_RESCHEDULE, 0, 0);
+ smp_message_pass(cpu, PPC_MSG_RESCHEDULE, 0, 0);
+}
+
+#ifdef CONFIG_XMON
+void smp_send_xmon_break(int cpu)
+{
+ smp_message_pass(cpu, PPC_MSG_XMON_BREAK, 0, 0);
+}
+#endif /* CONFIG_XMON */
+
+static void stop_this_cpu(void *dummy)
+{
+ __cli();
+ while (1)
+ ;
}
void smp_send_stop(void)
{
- smp_message_pass(MSG_ALL_BUT_SELF, MSG_STOP_CPU, 0, 0);
+ smp_call_function(stop_this_cpu, NULL, 1, 0);
+ smp_num_cpus = 1;
+}
+
+/*
+ * Structure and data for smp_call_function(). This is designed to minimise
+ * static memory requirements. It also looks cleaner.
+ * Stolen from the i386 version.
+ */
+static spinlock_t call_lock = SPIN_LOCK_UNLOCKED;
+
+static volatile struct call_data_struct {
+ void (*func) (void *info);
+ void *info;
+ atomic_t started;
+ atomic_t finished;
+ int wait;
+} *call_data = NULL;
+
+/*
+ * this function sends a 'generic call function' IPI to all other CPUs
+ * in the system.
+ */
+
+int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
+ int wait)
+/*
+ * [SUMMARY] Run a function on all other CPUs.
+ * <func> The function to run. This must be fast and non-blocking.
+ * <info> An arbitrary pointer to pass to the function.
+ * <nonatomic> currently unused.
+ * <wait> If true, wait (atomically) until function has completed on other CPUs.
+ * [RETURNS] 0 on success, else a negative status code. Does not return until
+ * remote CPUs are nearly ready to execute <<func>> or are or have executed.
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler, you may call it from a bottom half handler.
+ */
+{
+ struct call_data_struct data;
+ int ret = -1, cpus = smp_num_cpus-1;
+ int timeout;
+
+ if (!cpus)
+ return 0;
+
+ data.func = func;
+ data.info = info;
+ atomic_set(&data.started, 0);
+ data.wait = wait;
+ if (wait)
+ atomic_set(&data.finished, 0);
+
+ spin_lock_bh(&call_lock);
+ call_data = &data;
+ /* Send a message to all other CPUs and wait for them to respond */
+ smp_message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION, 0, 0);
+
+ /* Wait for response */
+ timeout = 1000000;
+ while (atomic_read(&data.started) != cpus) {
+ if (--timeout == 0) {
+ printk("smp_call_function on cpu %d: other cpus not responding (%d)\n",
+ smp_processor_id(), atomic_read(&data.started));
+ goto out;
+ }
+ barrier();
+ udelay(1);
+ }
+
+ if (wait) {
+ timeout = 1000000;
+ while (atomic_read(&data.finished) != cpus) {
+ if (--timeout == 0) {
+ printk("smp_call_function on cpu %d: other cpus not finishing (%d/%d)\n",
+ smp_processor_id(), atomic_read(&data.finished), atomic_read(&data.started));
+ goto out;
+ }
+ barrier();
+ udelay(1);
+ }
+ }
+ ret = 0;
+
+ out:
+ spin_unlock_bh(&call_lock);
+ return ret;
+}
+
+void smp_call_function_interrupt(void)
+{
+ void (*func) (void *info) = call_data->func;
+ void *info = call_data->info;
+ int wait = call_data->wait;
+
+ /*
+ * Notify initiating CPU that I've grabbed the data and am
+ * about to execute the function
+ */
+ atomic_inc(&call_data->started);
+ /*
+ * At this point the info structure may be out of scope unless wait==1
+ */
+ (*func)(info);
+ if (wait)
+ atomic_inc(&call_data->finished);
}
void smp_message_pass(int target, int msg, unsigned long data, int wait)
{
- int i;
-
if ( !(_machine & (_MACH_Pmac|_MACH_chrp|_MACH_prep|_MACH_gemini)) )
return;
@@ -212,31 +332,29 @@ void smp_message_pass(int target, int msg, unsigned long data, int wait)
* the recipient won't know the message was destined
* for it. -- Cort
*/
- for ( i = 0; i <= smp_num_cpus ; i++ )
- pmac_smp_message[i] = -1;
- switch( target )
- {
- case MSG_ALL:
- pmac_smp_message[smp_processor_id()] = msg;
- /* fall through */
- case MSG_ALL_BUT_SELF:
- for ( i = 0 ; i < smp_num_cpus ; i++ )
- if ( i != smp_processor_id () )
- pmac_smp_message[i] = msg;
- break;
- default:
- pmac_smp_message[target] = msg;
- break;
+ if (smp_processor_id() == 0) {
+ /* primary cpu */
+ if (target == 1 || target == MSG_ALL_BUT_SELF
+ || target == MSG_ALL) {
+ pmac_smp_message[1] = msg + 1;
+ /* interrupt secondary processor */
+ out_be32(psurge_sec_intr, ~0);
+ out_be32(psurge_sec_intr, 0);
+ }
+ } else {
+ /* secondary cpu */
+ if (target == 0 || target == MSG_ALL_BUT_SELF
+ || target == MSG_ALL) {
+ pmac_smp_message[0] = msg + 1;
+ /* interrupt primary processor */
+ in_be32(psurge_pri_intr);
+ }
+ }
+ if (target == smp_processor_id() || target == MSG_ALL) {
+ /* sending a message to ourself */
+ /* XXX maybe we shouldn't do this if ints are off */
+ smp_message_recv(msg, NULL);
}
- /* interrupt secondary processor */
- out_be32(PSURGE_INTR, ~0);
- out_be32(PSURGE_INTR, 0);
- /*
- * Assume for now that the secondary doesn't send
- * IPI's -- Cort
- */
- /* interrupt primary */
- /**(volatile unsigned long *)(0xf3019000);*/
break;
case _MACH_chrp:
case _MACH_prep:
@@ -261,7 +379,7 @@ void smp_message_pass(int target, int msg, unsigned long data, int wait)
#else /* CONFIG_POWER4 */
/* for now, only do reschedule messages
since we only have one IPI */
- if (msg != MSG_RESCHEDULE)
+ if (msg != PPC_MSG_RESCHEDULE)
break;
for (i = 0; i < smp_num_cpus; ++i) {
if (target == MSG_ALL || target == i
@@ -319,7 +437,10 @@ void __init smp_boot_cpus(void)
{
case _MACH_Pmac:
/* assume powersurge board - 2 processors -- Cort */
- cpu_nr = 2;
+ cpu_nr = 2;
+ psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4);
+ psurge_sec_intr = ioremap(PSURGE_SEC_INTR, 4);
+ psurge_start = ioremap(PSURGE_START, 4);
break;
case _MACH_chrp:
if (OpenPIC)
@@ -347,7 +468,7 @@ void __init smp_boot_cpus(void)
/* create a process for the processor */
/* we don't care about the values in regs since we'll
never reschedule the forked task. */
- if (do_fork(CLONE_VM|CLONE_PID, 0, &regs) < 0)
+ if (do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0) < 0)
panic("failed fork for CPU %d", i);
p = init_task.prev_task;
if (!p)
@@ -370,13 +491,11 @@ void __init smp_boot_cpus(void)
{
case _MACH_Pmac:
/* setup entry point of secondary processor */
- *(volatile unsigned long *)(0xf2800000) =
- (unsigned long)__secondary_start_psurge-KERNELBASE;
- eieio();
+ out_be32(psurge_start, __pa(__secondary_start_psurge));
/* interrupt secondary to begin executing code */
- out_be32(PSURGE_INTR, ~0);
+ out_be32(psurge_sec_intr, ~0);
udelay(1);
- out_be32(PSURGE_INTR, 0);
+ out_be32(psurge_sec_intr, 0);
break;
case _MACH_chrp:
*(unsigned long *)KERNELBASE = i;
@@ -399,9 +518,6 @@ void __init smp_boot_cpus(void)
if ( cpu_callin_map[i] )
{
printk("Processor %d found.\n", i);
- /* this sync's the decr's -- Cort */
- if ( _machine == _MACH_Pmac )
- set_dec(decrementer_count);
smp_num_cpus++;
} else {
printk("Processor %d is stuck.\n", i);
@@ -415,9 +531,25 @@ void __init smp_boot_cpus(void)
{
/* reset the entry point so if we get another intr we won't
* try to startup again */
- *(volatile unsigned long *)(0xf2800000) = 0x100;
- /* send interrupt to other processors to start decr's on all cpus */
- smp_message_pass(1,0xf0f0, 0, 0);
+ out_be32(psurge_start, 0x100);
+ if (request_irq(30, pmac_primary_intr, 0, "primary IPI", 0))
+ printk(KERN_ERR "Couldn't get primary IPI interrupt");
+ /*
+ * The decrementers of both cpus are frozen at this point
+ * until we give the secondary cpu another interrupt.
+ * We set them both to decrementer_count and then send
+ * the interrupt. This should get the decrementers
+ * synchronized.
+ * -- paulus.
+ */
+ set_dec(tb_ticks_per_jiffy);
+ if ((_get_PVR() >> 16) != 1) {
+ set_tb(0, 0); /* set timebase if not 601 */
+ last_jiffy_stamp(0) = 0;
+ }
+ out_be32(psurge_sec_intr, ~0);
+ udelay(1);
+ out_be32(psurge_sec_intr, 0);
}
}
@@ -447,8 +579,11 @@ int __init start_secondary(void *unused)
void __init smp_callin(void)
{
smp_store_cpu_info(current->processor);
- set_dec(decrementer_count);
-
+ set_dec(tb_ticks_per_jiffy);
+ if (_machine == _MACH_Pmac && (_get_PVR() >> 16) != 1) {
+ set_tb(0, 0); /* set timebase if not 601 */
+ last_jiffy_stamp(current->processor) = 0;
+ }
init_idle();
cpu_callin_map[current->processor] = 1;
diff --git a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c
index 314c1240c..d0fee4344 100644
--- a/arch/ppc/kernel/syscalls.c
+++ b/arch/ppc/kernel/syscalls.c
@@ -45,7 +45,7 @@ check_bugs(void)
{
}
-asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
+int sys_ioperm(unsigned long from, unsigned long num, int on)
{
printk(KERN_ERR "sys_ioperm()\n");
return -EIO;
@@ -74,7 +74,7 @@ int sys_modify_ldt(int a1, int a2, int a3, int a4)
*
* This is really horribly ugly.
*/
-asmlinkage int
+int
sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
{
int version, ret;
@@ -172,7 +172,7 @@ sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
* sys_pipe() is the normal C calling standard for creating
* a pipe. It's not the way unix traditionally does this, though.
*/
-asmlinkage int sys_pipe(int *fildes)
+int sys_pipe(int *fildes)
{
int fd[2];
int error;
@@ -185,19 +185,19 @@ asmlinkage int sys_pipe(int *fildes)
return error;
}
-asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, off_t offset)
+unsigned long sys_mmap(unsigned long addr, size_t len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, off_t offset)
{
struct file * file = NULL;
int ret = -EBADF;
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
if (!(flags & MAP_ANONYMOUS)) {
if (!(file = fget(fd)))
goto out;
}
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
down(&current->mm->mmap_sem);
ret = do_mmap(file, addr, len, prot, flags, offset);
up(&current->mm->mmap_sem);
@@ -207,7 +207,7 @@ out:
return ret;
}
-extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+extern int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
/*
* Due to some executables calling the wrong select we sometimes
@@ -215,7 +215,7 @@ extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timev
* (a single ptr to them all args passed) then calls
* sys_select() with the appropriate args. -- Cort
*/
-asmlinkage int
+int
ppc_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
{
if ( (unsigned long)n >= 4096 )
@@ -232,14 +232,14 @@ ppc_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
return sys_select(n, inp, outp, exp, tvp);
}
-asmlinkage int sys_pause(void)
+int sys_pause(void)
{
current->state = TASK_INTERRUPTIBLE;
schedule();
return -ERESTARTNOHAND;
}
-asmlinkage int sys_uname(struct old_utsname * name)
+int sys_uname(struct old_utsname * name)
{
int err = -EFAULT;
@@ -250,7 +250,7 @@ asmlinkage int sys_uname(struct old_utsname * name)
return err;
}
-asmlinkage int sys_olduname(struct oldold_utsname * name)
+int sys_olduname(struct oldold_utsname * name)
{
int error;
diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
index aff4838b3..f71c8cbbf 100644
--- a/arch/ppc/kernel/time.c
+++ b/arch/ppc/kernel/time.c
@@ -6,6 +6,27 @@
* Paul Mackerras' version and mine for PReP and Pmac.
* MPC8xx/MBX changes by Dan Malek (dmalek@jlc.net).
*
+ * First round of bugfixes by Gabriel Paubert (paubert@iram.es)
+ * to make clock more stable (2.4.0-test5). The only thing
+ * that this code assumes is that the timebases have been synchronized
+ * by firmware on SMP and are never stopped (never do sleep
+ * on SMP then, nap and doze are OK).
+ *
+ * TODO (not necessarily in this file):
+ * - improve precision and reproducibility of timebase frequency
+ * measurement at boot time.
+ * - get rid of xtime_lock for gettimeofday (generic kernel problem
+ * to be implemented on all architectures for SMP scalability and
+ * eventually implementing gettimeofday without entering the kernel).
+ * - put all time/clock related variables in a single structure
+ * to minimize number of cache lines touched by gettimeofday()
+ * - for astronomical applications: add a new function to get
+ * non ambiguous timestamps even around leap seconds. This needs
+ * a new timestamp format and a good name.
+ *
+ *
+ * The following comment is partially obsolete (at least the long wait
+ * is no more a valid reason):
* Since the MPC8xx has a programmable interrupt timer, I decided to
* use that rather than the decrementer. Two reasons: 1.) the clock
* frequency is low, causing 2.) a long wait in the timer interrupt
@@ -49,18 +70,32 @@
void smp_local_timer_interrupt(struct pt_regs *);
/* keep track of when we need to update the rtc */
-time_t last_rtc_update = 0;
+time_t last_rtc_update;
extern rwlock_t xtime_lock;
/* The decrementer counts down by 128 every 128ns on a 601. */
#define DECREMENTER_COUNT_601 (1000000000 / HZ)
-#define COUNT_PERIOD_NUM_601 1
-#define COUNT_PERIOD_DEN_601 1000
-unsigned decrementer_count; /* count value for 1e6/HZ microseconds */
-unsigned count_period_num; /* 1 decrementer count equals */
-unsigned count_period_den; /* count_period_num / count_period_den us */
-unsigned long last_tb;
+unsigned tb_ticks_per_jiffy;
+unsigned tb_to_us;
+unsigned tb_last_stamp;
+
+extern unsigned long wall_jiffies;
+
+static long time_offset;
+
+/* Timer interrupt helper function */
+static inline int tb_delta(unsigned *jiffy_stamp) {
+ int delta;
+ if (__USE_RTC()) {
+ delta = get_rtcl();
+ if (delta < *jiffy_stamp) *jiffy_stamp -= 1000000000;
+ delta -= *jiffy_stamp;
+ } else {
+ delta = get_tbl() - *jiffy_stamp;
+ }
+ return delta;
+}
/*
* timer_interrupt - gets called when the decrementer overflows,
@@ -69,88 +104,56 @@ unsigned long last_tb;
*/
int timer_interrupt(struct pt_regs * regs)
{
- int dval, d;
-#if 0
- unsigned long flags;
-#endif
+ int next_dec;
unsigned long cpu = smp_processor_id();
-
+ unsigned jiffy_stamp = last_jiffy_stamp(cpu);
+
hardirq_enter(cpu);
-#ifdef CONFIG_SMP
- {
- unsigned int loops = 100000000;
- while (test_bit(0, &global_irq_lock)) {
- if (smp_processor_id() == global_irq_holder) {
- printk("uh oh, interrupt while we hold global irq lock!\n");
-#ifdef CONFIG_XMON
- xmon(0);
-#endif
- break;
- }
- if (loops-- == 0) {
- printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
-#ifdef CONFIG_XMON
- xmon(0);
-#endif
- }
- }
- }
-#endif /* CONFIG_SMP */
- dval = get_dec();
- /*
- * Wait for the decrementer to change, then jump
- * in and add decrementer_count to its value
- * (quickly, before it changes again!)
- */
- while ((d = get_dec()) == dval)
- ;
- asm volatile("mftb %0" : "=r" (last_tb) );
- /*
- * Don't play catchup between the call to time_init()
- * and sti() in init/main.c.
- *
- * This also means if we're delayed for > HZ
- * we lose those ticks. If we're delayed for > HZ
- * then we have something wrong anyway, though.
- *
- * -- Cort
- */
- if ( d < (-1*decrementer_count) )
- d = 0;
- set_dec(d + decrementer_count);
- if ( !smp_processor_id() )
- {
+ do {
+ jiffy_stamp += tb_ticks_per_jiffy;
+ if (smp_processor_id()) continue;
+ /* We are in an interrupt, no need to save/restore flags */
+ write_lock(&xtime_lock);
+ tb_last_stamp = jiffy_stamp;
do_timer(regs);
-#if 0
- /* -- BenH -- I'm removing this for now since it can cause various
- * troubles with local-time RTCs. Now that we have a
- * /dev/rtc that uses ppc_md.set_rtc_time() on mac, it
- * should be possible to program the RTC from userland
- * in all cases.
- */
+
/*
- * update the rtc when needed
+ * update the rtc when needed, this should be performed on the
+ * right fraction of a second. Half or full second ?
+ * Full second works on mk48t59 clocks, others need testing.
+ * Note that this update is basically only used through
+ * the adjtimex system calls. Setting the HW clock in
+ * any other way is a /dev/rtc and userland business.
+ * This is still wrong by -0.5/+1.5 jiffies because of the
+ * timer interrupt resolution and possible delay, but here we
+ * hit a quantization limit which can only be solved by higher
+ * resolution timers and decoupling time management from timer
+ * interrupts. This is also wrong on the clocks
+ * which require being written at the half second boundary.
+ * We should have an rtc call that only sets the minutes and
+ * seconds like on Intel to avoid problems with non UTC clocks.
*/
- read_lock_irqsave(&xtime_lock, flags);
- if ( (time_status & STA_UNSYNC) &&
- ((xtime.tv_sec > last_rtc_update + 60) ||
- (xtime.tv_sec < last_rtc_update)) )
- {
- if (ppc_md.set_rtc_time(xtime.tv_sec) == 0)
- last_rtc_update = xtime.tv_sec;
+ if ( (time_status & STA_UNSYNC) == 0 &&
+ xtime.tv_sec - last_rtc_update >= 659 &&
+ abs(xtime.tv_usec - (1000000-1000000/HZ)) < 500000/HZ &&
+ jiffies - wall_jiffies == 1) {
+ if (ppc_md.set_rtc_time(xtime.tv_sec+1 + time_offset) == 0)
+ last_rtc_update = xtime.tv_sec+1;
else
- /* do it again in 60 s */
- last_rtc_update = xtime.tv_sec;
+ /* Try again one minute later */
+ last_rtc_update += 60;
}
- read_unlock_irqrestore(&xtime_lock, flags);
-#endif
- }
+ write_unlock(&xtime_lock);
+ } while((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) < 0);
+ set_dec(next_dec);
+ last_jiffy_stamp(cpu) = jiffy_stamp;
+
#ifdef CONFIG_SMP
smp_local_timer_interrupt(regs);
#endif
- if ( ppc_md.heartbeat && !ppc_md.heartbeat_count--)
+ if (ppc_md.heartbeat && !ppc_md.heartbeat_count--)
ppc_md.heartbeat();
hardirq_exit(cpu);
@@ -162,106 +165,138 @@ int timer_interrupt(struct pt_regs * regs)
*/
void do_gettimeofday(struct timeval *tv)
{
- unsigned long flags, diff;
+ unsigned long flags;
+ unsigned delta, lost_ticks, usec, sec;
- save_flags(flags);
- cli();
read_lock_irqsave(&xtime_lock, flags);
- *tv = xtime;
+ sec = xtime.tv_sec;
+ usec = xtime.tv_usec;
+ delta = tb_ticks_since(tb_last_stamp);
+#ifdef CONFIG_SMP
+ /* As long as timebases are not in sync, gettimeofday can only
+ * have jiffy resolution on SMP.
+ */
+ if (_machine != _MACH_Pmac)
+ delta = 0;
+#endif /* CONFIG_SMP */
+ lost_ticks = jiffies - wall_jiffies;
read_unlock_irqrestore(&xtime_lock, flags);
- /* XXX we don't seem to have the decrementers synced properly yet */
-#ifndef CONFIG_SMP
- asm volatile("mftb %0" : "=r" (diff) );
- diff -= last_tb;
- tv->tv_usec += diff * count_period_num / count_period_den;
- tv->tv_sec += tv->tv_usec / 1000000;
- tv->tv_usec = tv->tv_usec % 1000000;
-#endif
-
- restore_flags(flags);
+
+ usec += mulhwu(tb_to_us, tb_ticks_per_jiffy * lost_ticks + delta);
+ while (usec > 1000000) {
+ sec++;
+ usec -= 1000000;
+ }
+ tv->tv_sec = sec;
+ tv->tv_usec = usec;
}
void do_settimeofday(struct timeval *tv)
{
unsigned long flags;
- int frac_tick;
-
- last_rtc_update = 0; /* so the rtc gets updated soon */
-
- frac_tick = tv->tv_usec % (1000000 / HZ);
- save_flags(flags);
- cli();
+ int tb_delta, new_usec, new_sec;
+
write_lock_irqsave(&xtime_lock, flags);
- xtime.tv_sec = tv->tv_sec;
- xtime.tv_usec = tv->tv_usec - frac_tick;
- write_unlock_irqrestore(&xtime_lock, flags);
- set_dec(frac_tick * count_period_den / count_period_num);
+ /* Updating the RTC is not the job of this code. If the time is
+ * stepped under NTP, the RTC will be update after STA_UNSYNC
+ * is cleared. Tool like clock/hwclock either copy the RTC
+ * to the system time, in which case there is no point in writing
+ * to the RTC again, or write to the RTC but then they don't call
+ * settimeofday to perform this operation. Note also that
+ * we don't touch the decrementer since:
+ * a) it would lose timer interrupt synchronization on SMP
+ * (if it is working one day)
+ * b) it could make one jiffy spuriously shorter or longer
+ * which would introduce another source of uncertainty potentially
+ * harmful to relatively short timers.
+ */
+
+ /* This works perfectly on SMP only if the tb are in sync but
+ * guarantees an error < 1 jiffy even if they are off by eons,
+ * still reasonable when gettimeofday resolution is 1 jiffy.
+ */
+ tb_delta = tb_ticks_since(last_jiffy_stamp(smp_processor_id()));
+ tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
+ new_sec = tv->tv_sec;
+ new_usec = tv->tv_usec - mulhwu(tb_to_us, tb_delta);
+ while (new_usec <0) {
+ new_sec--;
+ new_usec += 1000000;
+ }
+ xtime.tv_usec = new_usec;
+ xtime.tv_sec = new_sec;
+
+ /* In case of a large backwards jump in time with NTP, we want the
+ * clock to be updated as soon as the PLL is again in lock.
+ */
+ last_rtc_update = new_sec - 658;
+
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_state = TIME_ERROR; /* p. 24, (a) */
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
- restore_flags(flags);
+ write_unlock_irqrestore(&xtime_lock, flags);
}
void __init time_init(void)
{
+ time_t sec, old_sec;
+ unsigned old_stamp, stamp, elapsed;
+ /* This function is only called on the boot processor */
unsigned long flags;
+
if (ppc_md.time_init != NULL)
- {
- ppc_md.time_init();
- }
+ time_offset = ppc_md.time_init();
- if ((_get_PVR() >> 16) == 1) {
+ if (__USE_RTC()) {
/* 601 processor: dec counts down by 128 every 128ns */
- decrementer_count = DECREMENTER_COUNT_601;
- count_period_num = COUNT_PERIOD_NUM_601;
- count_period_den = COUNT_PERIOD_DEN_601;
- } else if (!smp_processor_id()) {
+ tb_ticks_per_jiffy = DECREMENTER_COUNT_601;
+ /* mulhwu_scale_factor(1000000000, 1000000) is 0x418937 */
+ tb_to_us = 0x418937;
+ } else {
ppc_md.calibrate_decr();
}
+ /* Now that the decrementer is calibrated, it can be used in case the
+ * clock is stuck, but the fact that we have to handle the 601
+ * makes things more complex. Repeatedly read the RTC until the
+ * next second boundary to try to achieve some precision...
+ */
+ stamp = get_native_tbl();
+ sec = ppc_md.get_rtc_time();
+ elapsed = 0;
+ do {
+ old_stamp = stamp;
+ old_sec = sec;
+ stamp = get_native_tbl();
+ if (__USE_RTC() && stamp < old_stamp) old_stamp -= 1000000000;
+ elapsed += stamp - old_stamp;
+ sec = ppc_md.get_rtc_time();
+ } while ( sec == old_sec && elapsed < 2*HZ*tb_ticks_per_jiffy);
+ if (sec==old_sec) {
+ printk("Warning: real time clock seems stuck!\n");
+ }
write_lock_irqsave(&xtime_lock, flags);
- xtime.tv_sec = ppc_md.get_rtc_time();
+ xtime.tv_sec = sec;
+ last_jiffy_stamp(0) = tb_last_stamp = stamp;
xtime.tv_usec = 0;
+ /* No update now, we just read the time from the RTC ! */
+ last_rtc_update = xtime.tv_sec;
write_unlock_irqrestore(&xtime_lock, flags);
+ /* Not exact, but the timer interrupt takes care of this */
+ set_dec(tb_ticks_per_jiffy);
- set_dec(decrementer_count);
- /* allow setting the time right away */
- last_rtc_update = 0;
-}
-
-/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
- * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
- * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
- *
- * [For the Julian calendar (which was used in Russia before 1917,
- * Britain & colonies before 1752, anywhere else before 1582,
- * and is still in use by some communities) leave out the
- * -year/100+year/400 terms, and add 10.]
- *
- * This algorithm was first published by Gauss (I think).
- *
- * WARNING: this function will overflow on 2106-02-07 06:28:16 on
- * machines were long is 32-bit! (However, as time_t is signed, we
- * will already get problems at other places on 2038-01-19 03:14:08)
- */
-unsigned long mktime(unsigned int year, unsigned int mon,
- unsigned int day, unsigned int hour,
- unsigned int min, unsigned int sec)
-{
-
- if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
- mon += 12; /* Puts Feb last since it has leap day */
- year -= 1;
- }
- return (((
- (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
- year*365 - 719499
- )*24 + hour /* now have hours */
- )*60 + min /* now have minutes */
- )*60 + sec; /* finally seconds */
+ /* If platform provided a timezone (pmac), we correct the time
+ * using do_sys_settimeofday() which in turn calls warp_clock()
+ */
+ if (time_offset) {
+ struct timezone tz;
+ tz.tz_minuteswest = -time_offset / 60;
+ tz.tz_dsttime = 0;
+ do_sys_settimeofday(NULL, &tz);
+ }
}
#define TICK_SIZE tick
@@ -354,3 +389,31 @@ void to_tm(int tim, struct rtc_time * tm)
*/
GregorianDay(tm);
}
+
+/* Auxiliary function to compute scaling factors */
+/* Actually the choice of a timebase running at 1/4 the of the bus
+ * frequency giving resolution of a few tens of nanoseconds is quite nice.
+ * It makes this computation very precise (27-28 bits typically) which
+ * is optimistic considering the stability of most processor clock
+ * oscillators and the precision with which the timebase frequency
+ * is measured but does not harm.
+ */
+unsigned mulhwu_scale_factor(unsigned inscale, unsigned outscale) {
+ unsigned mlt=0, tmp, err;
+ /* No concern for performance, it's done once: use a stupid
+ * but safe and compact method to find the multiplier.
+ */
+ for (tmp = 1U<<31; tmp != 0; tmp >>= 1) {
+ if (mulhwu(inscale, mlt|tmp) < outscale) mlt|=tmp;
+ }
+ /* We might still be off by 1 for the best approximation.
+ * A side effect of this is that if outscale is too large
+ * the returned value will be zero.
+ * Many corner cases have been checked and seem to work,
+ * some might have been forgotten in the test however.
+ */
+ err = inscale*(mlt+1);
+ if (err <= inscale/2) mlt++;
+ return mlt;
+}
+
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index 0701f7118..3b7473dda 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -87,45 +87,76 @@ _exception(int signr, struct pt_regs *regs)
void
MachineCheckException(struct pt_regs *regs)
{
- if ( !user_mode(regs) )
- {
-#if defined(CONFIG_8xx) && defined(CONFIG_PCI)
- /* the qspan pci read routines can cause machine checks -- Cort */
- bad_page_fault(regs, regs->dar);
+#ifdef CONFIG_ALL_PPC
+ unsigned long fixup;
+#endif /* CONFIG_ALL_PPC */
+
+ if (user_mode(regs)) {
+ _exception(SIGSEGV, regs);
return;
+ }
+
+#if defined(CONFIG_8xx) && defined(CONFIG_PCI)
+ /* the qspan pci read routines can cause machine checks -- Cort */
+ bad_page_fault(regs, regs->dar);
+ return;
#endif
#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
- if (debugger_fault_handler) {
- debugger_fault_handler(regs);
- return;
- }
+ if (debugger_fault_handler) {
+ debugger_fault_handler(regs);
+ return;
+ }
#endif
- printk("Machine check in kernel mode.\n");
- printk("Caused by (from SRR1=%lx): ", regs->msr);
- switch (regs->msr & 0xF0000) {
- case 0x80000:
- printk("Machine check signal\n");
- break;
- case 0x40000:
- printk("Transfer error ack signal\n");
- break;
- case 0x20000:
- printk("Data parity error signal\n");
- break;
- case 0x10000:
- printk("Address parity error signal\n");
- break;
- default:
- printk("Unknown values in msr\n");
+
+#ifdef CONFIG_ALL_PPC
+ /*
+ * I/O accesses can cause machine checks on powermacs.
+ * Check if the NIP corresponds to the address of a sync
+ * instruction for which there is an entry in the exception
+ * table.
+ */
+ if (regs->msr & (0x80000 | 0x40000)
+ && (fixup = search_exception_table(regs->nip)) != 0) {
+ /*
+ * Check that it's a sync instruction.
+ * As the address is in the exception table
+ * we should be able to read the instr there.
+ */
+ if (*(unsigned int *)regs->nip == 0x7c0004ac) {
+ unsigned int lsi = ((unsigned int *)regs->nip)[-1];
+ int rb = (lsi >> 11) & 0x1f;
+ printk(KERN_DEBUG "%s bad port %lx at %lx\n",
+ (lsi & 0x100)? "OUT to": "IN from",
+ regs->gpr[rb] - _IO_BASE, regs->nip);
+ regs->nip = fixup;
+ return;
}
- show_regs(regs);
+ }
+#endif /* CONFIG_ALL_PPC */
+ printk("Machine check in kernel mode.\n");
+ printk("Caused by (from SRR1=%lx): ", regs->msr);
+ switch (regs->msr & 0xF0000) {
+ case 0x80000:
+ printk("Machine check signal\n");
+ break;
+ case 0x40000:
+ printk("Transfer error ack signal\n");
+ break;
+ case 0x20000:
+ printk("Data parity error signal\n");
+ break;
+ case 0x10000:
+ printk("Address parity error signal\n");
+ break;
+ default:
+ printk("Unknown values in msr\n");
+ }
+ show_regs(regs);
#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
- debugger(regs);
+ debugger(regs);
#endif
- print_backtrace((unsigned long *)regs->gpr[1]);
- panic("machine check");
- }
- _exception(SIGSEGV, regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("machine check");
}
void
@@ -166,6 +197,46 @@ RunModeException(struct pt_regs *regs)
_exception(SIGTRAP, regs);
}
+/* Illegal instruction emulation support. Originally written to
+ * provide the PVR to user applications using the mfspr rd, PVR.
+ * Return non-zero if we can't emulate, or EFAULT if the associated
+ * memory access caused an access fault. Return zero on success.
+ *
+ * There are a couple of ways to do this, either "decode" the instruction
+ * or directly match lots of bits. In this case, matching lots of
+ * bits is faster and easier.
+ *
+ */
+#define INST_MFSPR_PVR 0x7c1f42a6
+#define INST_MFSPR_PVR_MASK 0xfc1fffff
+
+static int
+emulate_instruction(struct pt_regs *regs)
+{
+ uint instword;
+ uint rd;
+ uint retval;
+
+ retval = EFAULT;
+
+ if (!user_mode(regs))
+ return retval;
+
+ if (get_user(instword, (uint *)(regs->nip)))
+ return retval;
+
+ /* Emulate the mfspr rD, PVR.
+ */
+ if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) {
+ rd = (instword >> 21) & 0x1f;
+ regs->gpr[rd] = _get_PVR();
+ retval = 0;
+ }
+ if (retval == 0)
+ regs->nip += 4;
+ return(retval);
+}
+
void
ProgramCheckException(struct pt_regs *regs)
{
@@ -193,7 +264,14 @@ ProgramCheckException(struct pt_regs *regs)
#endif
_exception(SIGTRAP, regs);
} else {
- _exception(SIGILL, regs);
+ /* Try to emulate it if we should. */
+ int errcode;
+ if ((errcode = emulate_instruction(regs))) {
+ if (errcode == EFAULT)
+ _exception(SIGBUS, regs);
+ else
+ _exception(SIGILL, regs);
+ }
}
#endif
}
diff --git a/arch/ppc/kernel/walnut_setup.c b/arch/ppc/kernel/walnut_setup.c
index 768c36a94..e48a3e61a 100644
--- a/arch/ppc/kernel/walnut_setup.c
+++ b/arch/ppc/kernel/walnut_setup.c
@@ -226,10 +226,11 @@ walnut_halt(void)
/*
* Document me.
*/
-void __init
+long __init
walnut_time_init(void)
{
/* XXX - Implement me */
+ return 0;
}
/*
diff --git a/arch/ppc/kernel/xics.c b/arch/ppc/kernel/xics.c
index a9772821b..2b277f952 100644
--- a/arch/ppc/kernel/xics.c
+++ b/arch/ppc/kernel/xics.c
@@ -166,7 +166,7 @@ xics_get_irq(struct pt_regs *regs)
void xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
{
qirr_info(smp_processor_id()) = 0xff;
- smp_message_recv(MSG_RESCHEDULE);
+ smp_message_recv(MSG_RESCHEDULE, regs);
}
void xics_cause_IPI(int cpu)
diff --git a/arch/ppc/lib/string.S b/arch/ppc/lib/string.S
index 1c4f1f78e..a922b4361 100644
--- a/arch/ppc/lib/string.S
+++ b/arch/ppc/lib/string.S
@@ -9,13 +9,74 @@
* 2 of the License, or (at your option) any later version.
*/
#include "../kernel/ppc_asm.tmpl"
+#include <linux/config.h>
#include <asm/processor.h>
#include <asm/errno.h>
-CACHELINE_BYTES = 32
-LG_CACHELINE_BYTES = 5
-CACHELINE_MASK = 0x1f
-CACHELINE_WORDS = 8
+#if defined(CONFIG_4xx) || defined(CONFIG_8xx)
+#define CACHE_LINE_SIZE 16
+#define LG_CACHE_LINE_SIZE 4
+#define MAX_COPY_PREFETCH 1
+#elif !defined(CONFIG_PPC64BRIDGE)
+#define CACHE_LINE_SIZE 32
+#define LG_CACHE_LINE_SIZE 5
+#define MAX_COPY_PREFETCH 4
+#else
+#define CACHE_LINE_SIZE 128
+#define LG_CACHE_LINE_SIZE 7
+#define MAX_COPY_PREFETCH 1
+#endif /* CONFIG_4xx || CONFIG_8xx */
+
+#define COPY_16_BYTES \
+ lwz r7,4(r4); \
+ lwz r8,8(r4); \
+ lwz r9,12(r4); \
+ lwzu r10,16(r4); \
+ stw r7,4(r6); \
+ stw r8,8(r6); \
+ stw r9,12(r6); \
+ stwu r10,16(r6)
+
+#define COPY_16_BYTES_WITHEX(n) \
+8 ## n ## 0: \
+ lwz r7,4(r4); \
+8 ## n ## 1: \
+ lwz r8,8(r4); \
+8 ## n ## 2: \
+ lwz r9,12(r4); \
+8 ## n ## 3: \
+ lwzu r10,16(r4); \
+8 ## n ## 4: \
+ stw r7,4(r6); \
+8 ## n ## 5: \
+ stw r8,8(r6); \
+8 ## n ## 6: \
+ stw r9,12(r6); \
+8 ## n ## 7: \
+ stwu r10,16(r6)
+
+#define COPY_16_BYTES_EXCODE(n) \
+9 ## n ## 0: \
+ addi r5,r5,-(16 * n); \
+ b 104f; \
+9 ## n ## 1: \
+ addi r5,r5,-(16 * n); \
+ b 105f; \
+.section __ex_table,"a"; \
+ .align 2; \
+ .long 8 ## n ## 0b,9 ## n ## 0b; \
+ .long 8 ## n ## 1b,9 ## n ## 0b; \
+ .long 8 ## n ## 2b,9 ## n ## 0b; \
+ .long 8 ## n ## 3b,9 ## n ## 0b; \
+ .long 8 ## n ## 4b,9 ## n ## 1b; \
+ .long 8 ## n ## 5b,9 ## n ## 1b; \
+ .long 8 ## n ## 6b,9 ## n ## 1b; \
+ .long 8 ## n ## 7b,9 ## n ## 1b; \
+.text
+
+CACHELINE_BYTES = CACHE_LINE_SIZE
+LG_CACHELINE_BYTES = LG_CACHE_LINE_SIZE
+CACHELINE_MASK = (CACHE_LINE_SIZE-1)
.globl strcpy
strcpy:
@@ -105,7 +166,14 @@ cacheable_memzero:
bdnz 4b
3: mtctr r9
li r7,4
+#if !defined(CONFIG_8xx)
10: dcbz r7,r6
+#else
+10: stw r4, 4(r6)
+ stw r4, 8(r6)
+ stw r4, 12(r6)
+ stw r4, 16(r6)
+#endif
addi r6,r6,CACHELINE_BYTES
bdnz 10b
clrlwi r5,r8,32-LG_CACHELINE_BYTES
@@ -202,23 +270,24 @@ cacheable_memcpy:
li r11,4
mtctr r0
beq 63f
-53: dcbz r11,r6
- lwz r7,4(r4)
- lwz r8,8(r4)
- lwz r9,12(r4)
- lwzu r10,16(r4)
- stw r7,4(r6)
- stw r8,8(r6)
- stw r9,12(r6)
- stwu r10,16(r6)
- lwz r7,4(r4)
- lwz r8,8(r4)
- lwz r9,12(r4)
- lwzu r10,16(r4)
- stw r7,4(r6)
- stw r8,8(r6)
- stw r9,12(r6)
- stwu r10,16(r6)
+53:
+#if !defined(CONFIG_8xx)
+ dcbz r11,r6
+#endif
+ COPY_16_BYTES
+#if CACHE_LINE_SIZE >= 32
+ COPY_16_BYTES
+#if CACHE_LINE_SIZE >= 64
+ COPY_16_BYTES
+ COPY_16_BYTES
+#if CACHE_LINE_SIZE >= 128
+ COPY_16_BYTES
+ COPY_16_BYTES
+ COPY_16_BYTES
+ COPY_16_BYTES
+#endif
+#endif
+#endif
bdnz 53b
63: srwi. r0,r5,2
@@ -380,25 +449,59 @@ __copy_tofrom_user:
58: srwi. r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */
clrlwi r5,r5,32-LG_CACHELINE_BYTES
li r11,4
- mtctr r0
beq 63f
-53: dcbz r11,r6
-10: lwz r7,4(r4)
-11: lwz r8,8(r4)
-12: lwz r9,12(r4)
-13: lwzu r10,16(r4)
-14: stw r7,4(r6)
-15: stw r8,8(r6)
-16: stw r9,12(r6)
-17: stwu r10,16(r6)
-20: lwz r7,4(r4)
-21: lwz r8,8(r4)
-22: lwz r9,12(r4)
-23: lwzu r10,16(r4)
-24: stw r7,4(r6)
-25: stw r8,8(r6)
-26: stw r9,12(r6)
-27: stwu r10,16(r6)
+
+#if !defined(CONFIG_8xx)
+ /* Here we decide how far ahead to prefetch the source */
+#if MAX_COPY_PREFETCH > 1
+ /* Heuristically, for large transfers we prefetch
+ MAX_COPY_PREFETCH cachelines ahead. For small transfers
+ we prefetch 1 cacheline ahead. */
+ cmpwi r0,MAX_COPY_PREFETCH
+ li r7,1
+ li r3,4
+ ble 111f
+ li r7,MAX_COPY_PREFETCH
+111: mtctr r7
+112: dcbt r3,r4
+ addi r3,r3,CACHELINE_BYTES
+ bdnz 112b
+#else /* MAX_COPY_PREFETCH == 1 */
+ li r3,CACHELINE_BYTES + 4
+ dcbt r11,r4
+#endif /* MAX_COPY_PREFETCH */
+#endif /* CONFIG_8xx */
+
+ mtctr r0
+53:
+#if !defined(CONFIG_8xx)
+ dcbt r3,r4
+ dcbz r11,r6
+#endif
+/* had to move these to keep extable in order */
+ .section __ex_table,"a"
+ .align 2
+ .long 70b,100f
+ .long 71b,101f
+ .long 72b,102f
+ .long 73b,103f
+ .long 53b,105f
+ .text
+/* the main body of the cacheline loop */
+ COPY_16_BYTES_WITHEX(0)
+#if CACHE_LINE_SIZE >= 32
+ COPY_16_BYTES_WITHEX(1)
+#if CACHE_LINE_SIZE >= 64
+ COPY_16_BYTES_WITHEX(2)
+ COPY_16_BYTES_WITHEX(3)
+#if CACHE_LINE_SIZE >= 128
+ COPY_16_BYTES_WITHEX(4)
+ COPY_16_BYTES_WITHEX(5)
+ COPY_16_BYTES_WITHEX(6)
+ COPY_16_BYTES_WITHEX(7)
+#endif
+#endif
+#endif
bdnz 53b
63: srwi. r0,r5,2
@@ -434,15 +537,31 @@ __copy_tofrom_user:
103: li r4,1
91: li r3,2
b 99f
-/* read fault in 2nd half of cacheline loop */
-106: addi r5,r5,-16
-/* read fault in 1st half of cacheline loop */
+
+/*
+ * this stuff handles faults in the cacheline loop and branches to either
+ * 104f (if in read part) or 105f (if in write part), after updating r5
+ */
+ COPY_16_BYTES_EXCODE(0)
+#if CACHE_LINE_SIZE >= 32
+ COPY_16_BYTES_EXCODE(1)
+#if CACHE_LINE_SIZE >= 64
+ COPY_16_BYTES_EXCODE(2)
+ COPY_16_BYTES_EXCODE(3)
+#if CACHE_LINE_SIZE >= 128
+ COPY_16_BYTES_EXCODE(4)
+ COPY_16_BYTES_EXCODE(5)
+ COPY_16_BYTES_EXCODE(6)
+ COPY_16_BYTES_EXCODE(7)
+#endif
+#endif
+#endif
+
+/* read fault in cacheline loop */
104: li r4,0
b 92f
-/* write fault in 2nd half of cacheline loop */
-107: addi r5,r5,-16
/* fault on dcbz (effectively a write fault) */
-/* or write fault in 1st half of cacheline loop */
+/* or write fault in cacheline loop */
105: li r4,1
92: li r3,LG_CACHELINE_BYTES
b 99f
@@ -485,36 +604,15 @@ __copy_tofrom_user:
bdnz 114b
120: blr
-.section __ex_table,"a"
+ .section __ex_table,"a"
.align 2
- .long 70b,100b
- .long 71b,101b
- .long 72b,102b
- .long 73b,103b
- .long 53b,105b
- .long 10b,104b
- .long 11b,104b
- .long 12b,104b
- .long 13b,104b
- .long 14b,105b
- .long 15b,105b
- .long 16b,105b
- .long 17b,105b
- .long 20b,106b
- .long 21b,106b
- .long 22b,106b
- .long 23b,106b
- .long 24b,107b
- .long 25b,107b
- .long 26b,107b
- .long 27b,107b
.long 30b,108b
.long 31b,109b
.long 40b,110b
.long 41b,111b
.long 112b,120b
.long 114b,120b
-.text
+ .text
.globl __clear_user
__clear_user:
@@ -546,12 +644,13 @@ __clear_user:
blr
99: li r3,-EFAULT
blr
-.section __ex_table,"a"
+
+ .section __ex_table,"a"
.align 2
.long 11b,99b
.long 1b,99b
.long 8b,99b
-.text
+ .text
.globl __strncpy_from_user
__strncpy_from_user:
@@ -570,10 +669,11 @@ __strncpy_from_user:
blr
99: li r3,-EFAULT
blr
-.section __ex_table,"a"
+
+ .section __ex_table,"a"
.align 2
.long 1b,99b
-.text
+ .text
/* r3 = str, r4 = len (> 0), r5 = top (highest addr) */
.globl __strnlen_user
@@ -596,6 +696,7 @@ __strnlen_user:
blr
99: li r3,0 /* bad address, return 0 */
blr
-.section __ex_table,"a"
+
+ .section __ex_table,"a"
.align 2
.long 1b,99b
diff --git a/arch/ppc/mbxboot/misc.c b/arch/ppc/mbxboot/misc.c
index 60563122d..ac400b8c6 100644
--- a/arch/ppc/mbxboot/misc.c
+++ b/arch/ppc/mbxboot/misc.c
@@ -269,6 +269,11 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, b
*/
#ifdef CONFIG_MBX
cmd_line = (char *)(load_addr - 0x10000);
+
+ /* To be like everyone else, we need one too, although this
+ * board information is passed from the boot rom.
+ */
+ bp->bi_baudrate = 9600;
#else
cmd_line = (char *)(0x200000);
#endif
diff --git a/arch/ppc/mm/extable.c b/arch/ppc/mm/extable.c
index dc57bf868..f43bfaff4 100644
--- a/arch/ppc/mm/extable.c
+++ b/arch/ppc/mm/extable.c
@@ -4,11 +4,47 @@
* from linux/arch/i386/mm/extable.c
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <asm/uaccess.h>
-extern const struct exception_table_entry __start___ex_table[];
-extern const struct exception_table_entry __stop___ex_table[];
+extern struct exception_table_entry __start___ex_table[];
+extern struct exception_table_entry __stop___ex_table[];
+
+/*
+ * The exception table needs to be sorted because we use the macros
+ * which put things into the exception table in a variety of segments
+ * such as the prep, pmac, chrp, etc. segments as well as the init
+ * segment and the main kernel text segment.
+ */
+static inline void
+sort_ex_table(struct exception_table_entry *start,
+ struct exception_table_entry *finish)
+{
+ struct exception_table_entry el, *p, *q;
+
+ /* insertion sort */
+ for (p = start + 1; p < finish; ++p) {
+ /* start .. p-1 is sorted */
+ if (p[0].insn < p[-1].insn) {
+ /* move element p down to its right place */
+ el = *p;
+ q = p;
+ do {
+ /* el comes before q[-1], move q[-1] up one */
+ q[0] = q[-1];
+ --q;
+ } while (q > start && el.insn < q[-1].insn);
+ *q = el;
+ }
+ }
+}
+
+void
+sort_exception_table(void)
+{
+ sort_ex_table(__start___ex_table, __stop___ex_table);
+}
static inline unsigned long
search_one_table(const struct exception_table_entry *first,
@@ -36,25 +72,21 @@ search_exception_table(unsigned long addr)
{
unsigned long ret;
-#if 1 /*ndef CONFIG_MODULES*/
+#ifndef CONFIG_MODULES
/* There is only the kernel to search. */
ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
if (ret) return ret;
#else
/* The kernel is the last "module" -- no need to treat it special. */
struct module *mp;
- read_lock(&modlist_lock);
for (mp = module_list; mp != NULL; mp = mp->next) {
if (mp->ex_table_start == NULL)
continue;
ret = search_one_table(mp->ex_table_start,
mp->ex_table_end - 1, addr);
- if (ret) {
- read_unlock(&modlist_lock);
+ if (ret)
return ret;
- }
}
- read_unlock(&modlist_lock);
#endif
return 0;
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
index 0b551c803..b6da2cdfc 100644
--- a/arch/ppc/mm/fault.c
+++ b/arch/ppc/mm/fault.c
@@ -67,7 +67,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
#if defined(CONFIG_4xx)
int is_write = error_code & ESR_DST;
#else
- int is_write = error_code & 0x02000000;
+ int is_write = 0;
/*
* Fortunately the bit assignments in SRR1 for an instruction
@@ -77,6 +77,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
*/
if (regs->trap == 0x400)
error_code &= 0x48200000;
+ else
+ is_write = error_code & 0x02000000;
#endif /* CONFIG_4xx */
#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index 67257c50b..be7d1f063 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -36,6 +36,7 @@
#include <linux/delay.h>
#include <linux/openpic.h>
#include <linux/bootmem.h>
+#include <linux/highmem.h>
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h> /* for initrd_* */
#endif
@@ -69,15 +70,20 @@
#include "4xx_tlb.h"
#endif
+#define MAX_LOW_MEM (640 << 20)
+
#define PGTOKB(pages) (((pages) * PAGE_SIZE) >> 10)
int prom_trashed;
atomic_t next_mmu_context;
unsigned long *end_of_DRAM;
+unsigned long total_memory;
+unsigned long total_lowmem;
int mem_init_done;
int init_bootmem_done;
int boot_mapsize;
unsigned long totalram_pages = 0;
+unsigned long totalhigh_pages = 0;
extern pgd_t swapper_pg_dir[];
extern char _start[], _end[];
extern char etext[], _stext[];
@@ -98,22 +104,26 @@ extern unsigned int rtas_data, rtas_size;
#ifndef CONFIG_SMP
struct pgtable_cache_struct quicklists;
#endif
+#ifdef CONFIG_HIGHMEM
+pte_t *kmap_pte;
+pgprot_t kmap_prot;
+#endif
void MMU_init(void);
static void *MMU_get_page(void);
-unsigned long *prep_find_end_of_memory(void);
-unsigned long *pmac_find_end_of_memory(void);
-unsigned long *apus_find_end_of_memory(void);
-unsigned long *gemini_find_end_of_memory(void);
-extern unsigned long *find_end_of_memory(void);
+unsigned long prep_find_end_of_memory(void);
+unsigned long pmac_find_end_of_memory(void);
+unsigned long apus_find_end_of_memory(void);
+unsigned long gemini_find_end_of_memory(void);
+extern unsigned long find_end_of_memory(void);
#ifdef CONFIG_8xx
-unsigned long *m8xx_find_end_of_memory(void);
+unsigned long m8xx_find_end_of_memory(void);
#endif /* CONFIG_8xx */
#ifdef CONFIG_4xx
-unsigned long *oak_find_end_of_memory(void);
+unsigned long oak_find_end_of_memory(void);
#endif
#ifdef CONFIG_8260
-unsigned long *m8260_find_end_of_memory(void);
+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);
@@ -269,6 +279,7 @@ void show_mem(void)
int i,free = 0,total = 0,reserved = 0;
int shared = 0, cached = 0;
struct task_struct *p;
+ int highmem = 0;
printk("Mem-info:\n");
show_free_areas();
@@ -276,6 +287,8 @@ void show_mem(void)
i = max_mapnr;
while (i-- > 0) {
total++;
+ if (PageHighMem(mem_map+i))
+ highmem++;
if (PageReserved(mem_map+i))
reserved++;
else if (PageSwapCache(mem_map+i))
@@ -286,6 +299,7 @@ void show_mem(void)
shared += atomic_read(&mem_map[i].count) - 1;
}
printk("%d pages of RAM\n",total);
+ printk("%d pages of HIGHMEM\n", highmem);
printk("%d free pages\n",free);
printk("%d reserved pages\n",reserved);
printk("%d pages shared\n",shared);
@@ -354,6 +368,8 @@ void si_meminfo(struct sysinfo *val)
continue;
val->sharedram += atomic_read(&mem_map[i].count) - 1;
}
+ val->totalhigh = totalhigh_pages;
+ val->freehigh = nr_free_highpages();
val->mem_unit = PAGE_SIZE;
}
@@ -443,7 +459,8 @@ out:
void iounmap(void *addr)
{
- /* XXX todo */
+ if (addr > high_memory && (unsigned long) addr < ioremap_bot)
+ vfree((void *) (PAGE_MASK & (unsigned long) addr));
}
unsigned long iopa(unsigned long addr)
@@ -476,7 +493,7 @@ map_page(unsigned long va, unsigned long pa, int flags)
{
pmd_t *pd, oldpd;
pte_t *pg;
-
+
/* Use upper 10 bits of VA to index the first level map */
pd = pmd_offset(pgd_offset_k(va), va);
oldpd = *pd;
@@ -516,6 +533,7 @@ local_flush_tlb_all(void)
flush_hash_segments(0xd, 0xffffff);
#else
__clear_user(Hash, Hash_size);
+ _tlbia();
#ifdef CONFIG_SMP
smp_send_tlb_invalidate(0);
#endif /* CONFIG_SMP */
@@ -610,6 +628,13 @@ mmu_context_overflow(void)
}
#endif /* CONFIG_8xx */
+void flush_page_to_ram(struct page *page)
+{
+ unsigned long vaddr = kmap(page);
+ __flush_page_to_ram(vaddr);
+ kunmap(page);
+}
+
#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
static void get_mem_prop(char *, struct mem_pieces *);
@@ -722,7 +747,7 @@ static void __init mapin_ram(void)
if (align && align < max_size)
max_size = align;
- tot = (unsigned long)end_of_DRAM - KERNELBASE;
+ tot = total_lowmem;
for (bl = 128<<10; bl < max_size; bl <<= 1) {
if (bl * 2 > tot)
break;
@@ -745,6 +770,8 @@ static void __init mapin_ram(void)
for (i = 0; i < phys_mem.n_regions; ++i) {
v = (ulong)__va(phys_mem.regions[i].address);
p = phys_mem.regions[i].address;
+ if (p >= total_lowmem)
+ break;
for (s = 0; s < phys_mem.regions[i].size; s += PAGE_SIZE) {
/* On the MPC8xx, we want the page shared so we
* don't get ASID compares on kernel space.
@@ -766,6 +793,8 @@ static void __init mapin_ram(void)
map_page(v, p, f);
v += PAGE_SIZE;
p += PAGE_SIZE;
+ if (p >= total_lowmem)
+ break;
}
}
}
@@ -788,77 +817,42 @@ static void __init *MMU_get_page(void)
return p;
}
-void __init free_initmem(void)
+static void free_sec(unsigned long start, unsigned long end, const char *name)
{
- unsigned long a;
- unsigned long num_freed_pages = 0, num_prep_pages = 0,
- num_pmac_pages = 0, num_openfirmware_pages = 0,
- num_apus_pages = 0, num_chrp_pages = 0;
-#define FREESEC(START,END,CNT) do { \
- a = (unsigned long)(&START); \
- for (; a < (unsigned long)(&END); a += PAGE_SIZE) { \
- clear_bit(PG_reserved, &virt_to_page(a)->flags); \
- set_page_count(virt_to_page(a), 1); \
- free_page(a); \
- CNT++; \
- } \
-} while (0)
-
- FREESEC(__init_begin,__init_end,num_freed_pages);
- switch (_machine)
- {
- case _MACH_Pmac:
- FREESEC(__apus_begin,__apus_end,num_apus_pages);
- FREESEC(__prep_begin,__prep_end,num_prep_pages);
- FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
- break;
- case _MACH_chrp:
- FREESEC(__apus_begin,__apus_end,num_apus_pages);
- FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
- FREESEC(__prep_begin,__prep_end,num_prep_pages);
- break;
- case _MACH_prep:
- FREESEC(__apus_begin,__apus_end,num_apus_pages);
- FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
- FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
- break;
- case _MACH_mbx:
- FREESEC(__apus_begin,__apus_end,num_apus_pages);
- FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
- FREESEC(__prep_begin,__prep_end,num_prep_pages);
- FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
- break;
- case _MACH_apus:
- FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
- FREESEC(__prep_begin,__prep_end,num_prep_pages);
- FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
- break;
- case _MACH_gemini:
- FREESEC(__apus_begin,__apus_end,num_apus_pages);
- FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
- FREESEC(__prep_begin,__prep_end,num_prep_pages);
- FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
- break;
- }
+ unsigned long cnt = 0;
- if ( !have_of )
- FREESEC( __openfirmware_begin, __openfirmware_end,
- num_openfirmware_pages );
-
- printk ("Freeing unused kernel memory: %ldk init",
- PGTOKB(num_freed_pages));
-
- if ( num_prep_pages )
- printk(" %ldk prep", PGTOKB(num_prep_pages));
- if ( num_chrp_pages )
- printk(" %ldk chrp", PGTOKB(num_chrp_pages));
- if ( num_pmac_pages )
- printk(" %ldk pmac", PGTOKB(num_pmac_pages));
- if ( num_openfirmware_pages )
- printk(" %ldk open firmware", PGTOKB(num_openfirmware_pages));
- if ( num_apus_pages )
- printk(" %ldk apus", PGTOKB(num_apus_pages));
- printk("\n");
+ while (start < end) {
+ clear_bit(PG_reserved, &virt_to_page(start)->flags);
+ set_page_count(virt_to_page(start), 1);
+ free_page(start);
+ cnt++;
+ start += PAGE_SIZE;
+ }
+ if (cnt)
+ printk(" %ldk %s", PGTOKB(cnt), name);
+}
+
+void free_initmem(void)
+{
+#define FREESEC(TYPE) \
+ free_sec((unsigned long)(&__ ## TYPE ## _begin), \
+ (unsigned long)(&__ ## TYPE ## _end), \
+ #TYPE);
+
+ printk ("Freeing unused kernel memory:");
+ FREESEC(init);
+ if (_machine != _MACH_Pmac)
+ FREESEC(pmac);
+ if (_machine != _MACH_chrp)
+ FREESEC(chrp);
+ if (_machine != _MACH_prep)
+ FREESEC(prep);
+ if (_machine != _MACH_apus)
+ FREESEC(apus);
+ if (!have_of)
+ FREESEC(openfirmware);
+ printk("\n");
+#undef FREESEC
}
#ifdef CONFIG_BLK_DEV_INITRD
@@ -909,7 +903,8 @@ MMU_init(void)
* at KERNELBASE.
*/
- end_of_DRAM = oak_find_end_of_memory();
+ total_memory = total_lowmem = oak_find_end_of_memory();
+ end_of_DRAM = __va(total_memory);
mapin_ram();
/*
@@ -939,23 +934,33 @@ void __init MMU_init(void)
if ( ppc_md.progress ) ppc_md.progress("MMU:enter", 0x111);
#ifndef CONFIG_8xx
if (have_of)
- end_of_DRAM = pmac_find_end_of_memory();
+ total_memory = pmac_find_end_of_memory();
#ifdef CONFIG_APUS
else if (_machine == _MACH_apus )
- end_of_DRAM = apus_find_end_of_memory();
+ total_memory = apus_find_end_of_memory();
#endif
#ifdef CONFIG_GEMINI
else if ( _machine == _MACH_gemini )
- end_of_DRAM = gemini_find_end_of_memory();
+ total_memory = gemini_find_end_of_memory();
#endif /* CONFIG_GEMINI */
#if defined(CONFIG_8260)
else
- end_of_DRAM = m8260_find_end_of_memory();
+ total_memory = m8260_find_end_of_memory();
#else
else /* prep */
- end_of_DRAM = prep_find_end_of_memory();
+ total_memory = prep_find_end_of_memory();
#endif
+ total_lowmem = total_memory;
+#ifdef CONFIG_HIGHMEM
+ if (total_lowmem > MAX_LOW_MEM) {
+ total_lowmem = MAX_LOW_MEM;
+ mem_pieces_remove(&phys_avail, total_lowmem,
+ total_memory - total_lowmem, 0);
+ }
+#endif /* CONFIG_HIGHMEM */
+ end_of_DRAM = __va(total_lowmem);
+
if ( ppc_md.progress ) ppc_md.progress("MMU:hash init", 0x300);
hash_init();
#ifndef CONFIG_PPC64BRIDGE
@@ -995,7 +1000,7 @@ void __init MMU_init(void)
#endif
break;
case _MACH_Pmac:
- ioremap_base = 0xf8000000;
+ ioremap_base = 0xfe000000;
break;
case _MACH_apus:
/* Map PPC exception vectors. */
@@ -1022,7 +1027,15 @@ void __init MMU_init(void)
#endif /* CONFIG_POWER4 */
#else /* CONFIG_8xx */
- end_of_DRAM = m8xx_find_end_of_memory();
+ total_memory = total_lowmem = m8xx_find_end_of_memory();
+#ifdef CONFIG_HIGHMEM
+ if (total_lowmem > MAX_LOW_MEM) {
+ total_lowmem = MAX_LOW_MEM;
+ mem_pieces_remove(&phys_avail, total_lowmem,
+ total_memory - total_lowmem, 0);
+ }
+#endif /* CONFIG_HIGHMEM */
+ end_of_DRAM = __va(total_lowmem);
/* Map in all of RAM starting at KERNELBASE */
mapin_ram();
@@ -1055,7 +1068,7 @@ void __init MMU_init(void)
if ( ppc_md.progress ) ppc_md.progress("MMU:exit", 0x211);
#ifdef CONFIG_BOOTX_TEXT
/* Must be done last, or ppc_md.progress will die */
- if (_machine == _MACH_Pmac)
+ if (_machine == _MACH_Pmac || _machine == _MACH_chrp)
map_bootx_text();
#endif
}
@@ -1092,7 +1105,7 @@ void __init do_init_bootmem(void)
start = PAGE_ALIGN(start);
boot_mapsize = init_bootmem(start >> PAGE_SHIFT,
- __pa(end_of_DRAM) >> PAGE_SHIFT);
+ total_lowmem >> PAGE_SHIFT);
/* remove the bootmem bitmap from the available memory */
mem_pieces_remove(&phys_avail, start, boot_mapsize, 1);
@@ -1105,47 +1118,6 @@ void __init do_init_bootmem(void)
init_bootmem_done = 1;
}
-#if 0
-/*
- * Find some memory for setup_arch to return.
- * We use the largest chunk of available memory as the area
- * that setup_arch returns, making sure that there are at
- * least 32 pages unused before this for MMU_get_page to use.
- */
-unsigned long __init find_available_memory(void)
-{
- int i, rn;
- unsigned long a, free;
- unsigned long start, end;
-
- if (_machine == _MACH_mbx) {
- /* Return the first, not the last region, because we
- * may not yet have properly initialized the additonal
- * memory DIMM.
- */
- a = PAGE_ALIGN(phys_avail.regions[0].address);
- avail_start = (unsigned long) __va(a);
- return avail_start;
- }
-
- rn = 0;
- for (i = 1; i < phys_avail.n_regions; ++i)
- if (phys_avail.regions[i].size > phys_avail.regions[rn].size)
- rn = i;
- free = 0;
- for (i = 0; i < rn; ++i) {
- start = phys_avail.regions[i].address;
- end = start + phys_avail.regions[i].size;
- free += (end & PAGE_MASK) - PAGE_ALIGN(start);
- }
- a = PAGE_ALIGN(phys_avail.regions[rn].address);
- if (free < 32 * PAGE_SIZE)
- a += 32 * PAGE_SIZE - free;
- avail_start = (unsigned long) __va(a);
- return avail_start;
-}
-#endif /* 0 */
-
/*
* paging_init() sets up the page tables - in fact we've already done this.
*/
@@ -1153,6 +1125,14 @@ void __init paging_init(void)
{
unsigned long zones_size[MAX_NR_ZONES], i;
+#ifdef CONFIG_HIGHMEM
+ map_page(PKMAP_BASE, 0, 0); /* XXX gross */
+ pkmap_page_table = pte_offset(pmd_offset(pgd_offset_k(PKMAP_BASE), PKMAP_BASE), PKMAP_BASE);
+ map_page(KMAP_FIX_BEGIN, 0, 0); /* XXX gross */
+ kmap_pte = pte_offset(pmd_offset(pgd_offset_k(KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN);
+ kmap_prot = PAGE_KERNEL;
+#endif /* CONFIG_HIGHMEM */
+
/*
* Grab some memory for bad_page and bad_pagetable to use.
*/
@@ -1162,9 +1142,14 @@ void __init paging_init(void)
/*
* All pages are DMA-able so we put them all in the DMA zone.
*/
- zones_size[0] = ((unsigned long)end_of_DRAM - KERNELBASE) >> PAGE_SHIFT;
+ zones_size[ZONE_DMA] = total_lowmem >> PAGE_SHIFT;
for (i = 1; i < MAX_NR_ZONES; i++)
zones_size[i] = 0;
+
+#ifdef CONFIG_HIGHMEM
+ zones_size[ZONE_HIGHMEM] = (total_memory - total_lowmem) >> PAGE_SHIFT;
+#endif /* CONFIG_HIGHMEM */
+
free_area_init(zones_size);
}
@@ -1176,7 +1161,17 @@ void __init mem_init(void)
int codepages = 0;
int datapages = 0;
int initpages = 0;
+#ifdef CONFIG_HIGHMEM
+ unsigned long highmem_mapnr;
+
+ highmem_mapnr = total_lowmem >> PAGE_SHIFT;
+ highmem_start_page = mem_map + highmem_mapnr;
+ max_mapnr = total_memory >> PAGE_SHIFT;
+ totalram_pages += max_mapnr - highmem_mapnr;
+#else
max_mapnr = max_low_pfn;
+#endif /* CONFIG_HIGHMEM */
+
high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
num_physpages = max_mapnr; /* RAM is assumed contiguous */
@@ -1217,11 +1212,28 @@ void __init mem_init(void)
datapages++;
}
- printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08x,%08lx]\n",
+#ifdef CONFIG_HIGHMEM
+ {
+ unsigned long pfn;
+
+ for (pfn = highmem_mapnr; pfn < max_mapnr; ++pfn) {
+ struct page *page = mem_map + pfn;
+
+ ClearPageReserved(page);
+ set_bit(PG_highmem, &page->flags);
+ atomic_set(&page->count, 1);
+ __free_page(page);
+ totalhigh_pages++;
+ }
+ totalram_pages += totalhigh_pages;
+ }
+#endif /* CONFIG_HIGHMEM */
+
+ printk("Memory: %luk available (%dk kernel code, %dk data, %dk init, %ldk highmem)\n",
(unsigned long)nr_free_pages()<< (PAGE_SHIFT-10),
codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10),
initpages<< (PAGE_SHIFT-10),
- PAGE_OFFSET, (unsigned long) end_of_DRAM);
+ (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
mem_init_done = 1;
}
@@ -1234,7 +1246,7 @@ void __init mem_init(void)
* Our text, data, bss use something over 1MB, starting at 0.
* Open Firmware may be using 1MB at the 4MB point.
*/
-unsigned long __init *pmac_find_end_of_memory(void)
+unsigned long __init pmac_find_end_of_memory(void)
{
unsigned long a, total;
unsigned long ram_limit = 0xe0000000 - KERNELBASE;
@@ -1279,7 +1291,7 @@ unsigned long __init *pmac_find_end_of_memory(void)
set_phys_avail(&phys_mem);
- return __va(total);
+ return total;
}
#endif /* CONFIG_ALL_PPC */
@@ -1290,7 +1302,7 @@ unsigned long __init *pmac_find_end_of_memory(void)
* this will likely stay separate from the pmac.
* -- Cort
*/
-unsigned long __init *prep_find_end_of_memory(void)
+unsigned long __init prep_find_end_of_memory(void)
{
unsigned long total;
total = res->TotalMemory;
@@ -1308,15 +1320,15 @@ unsigned long __init *prep_find_end_of_memory(void)
mem_pieces_append(&phys_mem, 0, total);
set_phys_avail(&phys_mem);
- return (__va(total));
+ return (total);
}
#endif /* defined(CONFIG_ALL_PPC) */
#if defined(CONFIG_GEMINI)
-unsigned long __init *gemini_find_end_of_memory(void)
+unsigned long __init gemini_find_end_of_memory(void)
{
- unsigned long total, *ret;
+ unsigned long total;
unsigned char reg;
reg = readb(GEMINI_MEMCFG);
@@ -1327,9 +1339,8 @@ unsigned long __init *gemini_find_end_of_memory(void)
phys_mem.regions[0].size = total;
phys_mem.n_regions = 1;
- ret = __va(phys_mem.regions[0].size);
set_phys_avail(&phys_mem);
- return ret;
+ return phys_mem.regions[0].size;
}
#endif /* defined(CONFIG_GEMINI) */
@@ -1337,10 +1348,9 @@ unsigned long __init *gemini_find_end_of_memory(void)
/*
* Same hack as 8xx.
*/
-unsigned long __init *m8260_find_end_of_memory(void)
+unsigned long __init m8260_find_end_of_memory(void)
{
bd_t *binfo;
- unsigned long *ret;
extern unsigned char __res[];
binfo = (bd_t *)__res;
@@ -1349,15 +1359,14 @@ unsigned long __init *m8260_find_end_of_memory(void)
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;
+ return phys_mem.regions[0].size;
}
#endif /* CONFIG_8260 */
#ifdef CONFIG_APUS
#define HARDWARE_MAPPED_SIZE (512*1024)
-unsigned long __init *apus_find_end_of_memory(void)
+unsigned long __init apus_find_end_of_memory(void)
{
int shadow = 0;
@@ -1421,7 +1430,7 @@ unsigned long __init *apus_find_end_of_memory(void)
the PowerUP board. Other system memory is horrible slow in
comparison. The user can use other memory for swapping
using the z2ram device. */
- return __va(memory[0].addr + memory[0].size);
+ return memory[0].addr + memory[0].size;
}
#endif /* CONFIG_APUS */
@@ -1484,7 +1493,7 @@ static void __init hash_init(void)
/* Find some memory for the hash table. */
if ( Hash_size ) {
Hash = mem_pieces_find(Hash_size, Hash_size);
- /*__clear_user(Hash, Hash_size);*/
+ cacheable_memzero(Hash, Hash_size);
} else
Hash = 0;
#endif /* CONFIG_PPC64BRIDGE */
@@ -1544,10 +1553,9 @@ static void __init hash_init(void)
* functions in the image just to get prom_init, all we really need right
* now is the initialization of the physical memory region.
*/
-unsigned long __init *m8xx_find_end_of_memory(void)
+unsigned long __init m8xx_find_end_of_memory(void)
{
bd_t *binfo;
- unsigned long *ret;
extern unsigned char __res[];
binfo = (bd_t *)__res;
@@ -1555,12 +1563,9 @@ unsigned long __init *m8xx_find_end_of_memory(void)
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].address+
- phys_mem.regions[0].size);
set_phys_avail(&phys_mem);
- return ret;
+ return phys_mem.regions[0].address + phys_mem.regions[0].size;
}
#endif /* !CONFIG_4xx && !CONFIG_8xx */
@@ -1569,7 +1574,7 @@ unsigned long __init *m8xx_find_end_of_memory(void)
* Return the virtual address representing the top of physical RAM
* on the Oak board.
*/
-unsigned long __init *
+unsigned long __init
oak_find_end_of_memory(void)
{
extern unsigned char __res[];
@@ -1580,12 +1585,9 @@ oak_find_end_of_memory(void)
phys_mem.regions[0].address = 0;
phys_mem.regions[0].size = bip->bi_memsize;
phys_mem.n_regions = 1;
-
- ret = __va(phys_mem.regions[0].address +
- phys_mem.regions[0].size);
set_phys_avail(&phys_mem);
- return (ret);
+ return (phys_mem.regions[0].address + phys_mem.regions[0].size);
}
#endif
diff --git a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c
index a816f0b9d..499c5b6c8 100644
--- a/arch/ppc/xmon/start.c
+++ b/arch/ppc/xmon/start.c
@@ -8,6 +8,7 @@
#include <asm/page.h>
#include <linux/adb.h>
#include <linux/pmu.h>
+#include <linux/cuda.h>
#include <linux/kernel.h>
#include <asm/prom.h>
#include <asm/bootx.h>
@@ -67,6 +68,12 @@ xmon_map_scc(void)
use_screen = 1;
}
#endif
+#ifdef CONFIG_ADB_CUDA
+ if (!via_modem && disp_bi ) {
+ prom_drawstring("xmon uses screen and keyboard\n");
+ use_screen = 1;
+ }
+#endif
#endif
#ifdef CHRP_ESCC
@@ -100,6 +107,10 @@ xmon_map_scc(void)
/* should already be mapped by the kernel boot */
sccc = (volatile unsigned char *) (isa_io_base + 0x3fd);
sccd = (volatile unsigned char *) (isa_io_base + 0x3f8);
+ if (xmon_use_sccb) {
+ sccc -= 0x100;
+ sccd -= 0x100;
+ }
TXRDY = 0x20;
RXRDY = 1;
}
@@ -109,6 +120,19 @@ static int scc_initialized = 0;
void xmon_init_scc(void);
extern void pmu_poll(void);
+extern void cuda_poll(void);
+
+static inline void do_poll_adb(void)
+{
+#ifdef CONFIG_ADB_PMU
+ if (sys_ctrler == SYS_CTRLER_PMU)
+ pmu_poll();
+#endif /* CONFIG_ADB_PMU */
+#ifdef CONFIG_ADB_CUDA
+ if (sys_ctrler == SYS_CTRLER_CUDA)
+ cuda_poll();
+#endif /* CONFIG_ADB_CUDA */
+}
int
xmon_write(void *handle, void *ptr, int nb)
@@ -128,12 +152,8 @@ xmon_write(void *handle, void *ptr, int nb)
xmon_init_scc();
ct = 0;
for (i = 0; i < nb; ++i) {
- while ((*sccc & TXRDY) == 0) {
-#ifdef CONFIG_ADB_PMU
- if (sys_ctrler == SYS_CTRLER_PMU)
- pmu_poll();
-#endif /* CONFIG_ADB_PMU */
- }
+ while ((*sccc & TXRDY) == 0)
+ do_poll_adb();
c = p[i];
if (c == '\n' && !ct) {
c = '\r';
@@ -189,9 +209,7 @@ xmon_get_adb_key(void)
prom_drawchar('\b');
t = 200000;
}
-#ifdef CONFIG_ADB_PMU
- pmu_poll();
-#endif /* CONFIG_ADB_PMU */
+ do_poll_adb();
} while (xmon_adb_keycode == -1);
k = xmon_adb_keycode;
if (on)
@@ -230,14 +248,9 @@ xmon_read(void *handle, void *ptr, int nb)
xmon_init_scc();
for (i = 0; i < nb; ++i) {
while ((*sccc & RXRDY) == 0)
-#ifdef CONFIG_ADB_PMU
- if (sys_ctrler == SYS_CTRLER_PMU)
- pmu_poll();
-#else
- ;
-#endif /* CONFIG_ADB_PMU */
+ do_poll_adb();
buf_access();
- *p++ = *sccd;
+ *p++ = *sccd;
}
return i;
}
@@ -246,10 +259,7 @@ int
xmon_read_poll(void)
{
if ((*sccc & RXRDY) == 0) {
-#ifdef CONFIG_ADB_PMU
- if (sys_ctrler == SYS_CTRLER_PMU)
- pmu_poll();
-#endif /* CONFIG_ADB_PMU */
+ do_poll_adb();
return -1;
}
buf_access();
@@ -491,3 +501,19 @@ xmon_fgets(char *str, int nb, void *f)
*p = 0;
return str;
}
+
+void
+xmon_enter(void)
+{
+#ifdef CONFIG_ADB_PMU
+ pmu_suspend();
+#endif
+}
+
+void
+xmon_leave(void)
+{
+#ifdef CONFIG_ADB_PMU
+ pmu_resume();
+#endif
+}
diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c
index 75160d9b8..49c3be834 100644
--- a/arch/ppc/xmon/xmon.c
+++ b/arch/ppc/xmon/xmon.c
@@ -6,15 +6,23 @@
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/sched.h>
+#include <linux/smp.h>
#include <asm/ptrace.h>
#include <asm/string.h>
#include <asm/prom.h>
+#include <asm/bitops.h>
#include "nonstdio.h"
#include "privinst.h"
#define scanhex xmon_scanhex
#define skipbl xmon_skipbl
+#ifdef CONFIG_SMP
+static unsigned long cpus_in_xmon = 0;
+static unsigned long got_xmon = 0;
+static volatile int take_xmon = -1;
+#endif /* CONFIG_SMP */
+
static unsigned adrs;
static int size = 1;
static unsigned ndump = 64;
@@ -84,6 +92,9 @@ static void insert_bpts(void);
static struct bpt *at_breakpoint(unsigned pc);
static void bpt_cmds(void);
static void cacheflush(void);
+#ifdef CONFIG_SMP
+static void cpu_cmd(void);
+#endif /* CONFIG_SMP */
#if 0 /* Makes compile with -Wall */
static char *pretty_print_addr(unsigned long addr);
static char *lookup_name(unsigned long addr);
@@ -96,8 +107,18 @@ extern int putchar(int ch);
extern int setjmp(u_int *);
extern void longjmp(u_int *, int);
+extern void xmon_enter(void);
+extern void xmon_leave(void);
+
#define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
+#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
+ || ('a' <= (c) && (c) <= 'f') \
+ || ('A' <= (c) && (c) <= 'F'))
+#define isalnum(c) (('0' <= (c) && (c) <= '9') \
+ || ('a' <= (c) && (c) <= 'z') \
+ || ('A' <= (c) && (c) <= 'Z'))
+
static char *help_string = "\
Commands:\n\
d dump bytes\n\
@@ -117,10 +138,12 @@ Commands:\n\
x exit monitor\n\
";
-static int xmon_trace;
+static int xmon_trace[NR_CPUS];
#define SSTEP 1 /* stepping because of 's' command */
#define BRSTEP 2 /* stepping over breakpoint */
+static struct pt_regs *xmon_regs[NR_CPUS];
+
void
xmon(struct pt_regs *excp)
{
@@ -143,27 +166,52 @@ xmon(struct pt_regs *excp)
msr = get_msr();
set_msr(msr & ~0x8000); /* disable interrupts */
- remove_bpts();
+ xmon_regs[smp_processor_id()] = excp;
+ xmon_enter();
excprint(excp);
+#ifdef CONFIG_SMP
+ if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon))
+ for (;;)
+ ;
+ while (test_and_set_bit(0, &got_xmon)) {
+ if (take_xmon == smp_processor_id()) {
+ take_xmon = -1;
+ break;
+ }
+ }
+ /*
+ * XXX: breakpoints are removed while any cpu is in xmon
+ */
+#endif /* CONFIG_SMP */
+ remove_bpts();
cmd = cmds(excp);
if (cmd == 's') {
- xmon_trace = SSTEP;
+ xmon_trace[smp_processor_id()] = SSTEP;
excp->msr |= 0x400;
} else if (at_breakpoint(excp->nip)) {
- xmon_trace = BRSTEP;
+ xmon_trace[smp_processor_id()] = BRSTEP;
excp->msr |= 0x400;
} else {
- xmon_trace = 0;
+ xmon_trace[smp_processor_id()] = 0;
insert_bpts();
}
+ xmon_leave();
+ xmon_regs[smp_processor_id()] = 0;
+#ifdef CONFIG_SMP
+ clear_bit(0, &got_xmon);
+ clear_bit(smp_processor_id(), &cpus_in_xmon);
+#endif /* CONFIG_SMP */
set_msr(msr); /* restore interrupt enable */
}
void
xmon_irq(int irq, void *d, struct pt_regs *regs)
{
+ unsigned long flags;
+ save_flags(flags);cli();
printf("Keyboard interrupt\n");
xmon(regs);
+ restore_flags(flags);
}
int
@@ -178,7 +226,7 @@ xmon_bpt(struct pt_regs *regs)
--bp->count;
remove_bpts();
excprint(regs);
- xmon_trace = BRSTEP;
+ xmon_trace[smp_processor_id()] = BRSTEP;
regs->msr |= 0x400;
} else {
xmon(regs);
@@ -189,10 +237,10 @@ xmon_bpt(struct pt_regs *regs)
int
xmon_sstep(struct pt_regs *regs)
{
- if (!xmon_trace)
+ if (!xmon_trace[smp_processor_id()])
return 0;
- if (xmon_trace == BRSTEP) {
- xmon_trace = 0;
+ if (xmon_trace[smp_processor_id()] == BRSTEP) {
+ xmon_trace[smp_processor_id()] = 0;
insert_bpts();
} else {
xmon(regs);
@@ -207,7 +255,7 @@ xmon_dabr_match(struct pt_regs *regs)
--dabr.count;
remove_bpts();
excprint(regs);
- xmon_trace = BRSTEP;
+ xmon_trace[smp_processor_id()] = BRSTEP;
regs->msr |= 0x400;
} else {
dabr.instr = regs->nip;
@@ -223,7 +271,7 @@ xmon_iabr_match(struct pt_regs *regs)
--iabr.count;
remove_bpts();
excprint(regs);
- xmon_trace = BRSTEP;
+ xmon_trace[smp_processor_id()] = BRSTEP;
regs->msr |= 0x400;
} else {
xmon(regs);
@@ -264,6 +312,7 @@ insert_bpts()
bp->address);
bp->enabled = 0;
}
+ store_inst((void *) bp->address);
}
#if !defined(CONFIG_8xx) && !defined(CONFIG_POWER4)
if (dabr.enabled)
@@ -293,6 +342,7 @@ remove_bpts()
&& mwrite(bp->address, &bp->instr, 4) != 4)
printf("Couldn't remove breakpoint at %x\n",
bp->address);
+ store_inst((void *) bp->address);
}
}
@@ -306,6 +356,9 @@ cmds(struct pt_regs *excp)
last_cmd = NULL;
for(;;) {
+#ifdef CONFIG_SMP
+ printf("%d:", smp_processor_id());
+#endif /* CONFIG_SMP */
printf("mon> ");
fflush(stdout);
flush_input();
@@ -383,12 +436,67 @@ cmds(struct pt_regs *excp)
case 'b':
bpt_cmds();
break;
- case 'c':
+ case 'C':
csum();
break;
+#ifdef CONFIG_SMP
+ case 'c':
+ cpu_cmd();
+ break;
+#endif /* CONFIG_SMP */
+ }
+ }
+}
+
+#ifdef CONFIG_SMP
+static void cpu_cmd(void)
+{
+ unsigned cpu;
+ int timeout;
+ int cmd;
+
+ cmd = inchar();
+ if (cmd == 'i') {
+ /* interrupt other cpu(s) */
+ cpu = MSG_ALL_BUT_SELF;
+ scanhex(&cpu);
+ smp_send_xmon_break(cpu);
+ return;
+ }
+ termch = cmd;
+ if (!scanhex(&cpu)) {
+ /* print cpus waiting or in xmon */
+ printf("cpus stopped:");
+ for (cpu = 0; cpu < NR_CPUS; ++cpu) {
+ if (test_bit(cpu, &cpus_in_xmon)) {
+ printf(" %d", cpu);
+ if (cpu == smp_processor_id())
+ printf("*", cpu);
+ }
+ }
+ printf("\n");
+ return;
+ }
+ /* try to switch to cpu specified */
+ take_xmon = cpu;
+ timeout = 10000000;
+ while (take_xmon >= 0) {
+ if (--timeout == 0) {
+ /* yes there's a race here */
+ take_xmon = -1;
+ printf("cpu %u didn't take control\n", cpu);
+ return;
+ }
+ }
+ /* now have to wait to be given control back */
+ while (test_and_set_bit(0, &got_xmon)) {
+ if (take_xmon == smp_processor_id()) {
+ take_xmon = -1;
+ break;
}
}
}
+#endif /* CONFIG_SMP */
static unsigned short fcstab[256] = {
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
@@ -551,6 +659,8 @@ backtrace(struct pt_regs *excp)
extern char lost_irq_ret, do_bottom_half_ret, do_signal_ret;
extern char ret_from_except;
+ printf("backtrace:\n");
+
if (excp != NULL)
sp = excp->gpr[1];
else
@@ -592,6 +702,9 @@ getsp()
void
excprint(struct pt_regs *fp)
{
+#ifdef CONFIG_SMP
+ printf("cpu %d: ", smp_processor_id());
+#endif /* CONFIG_SMP */
printf("vector: %x at pc = %x",
fp->trap, fp->nip);
printf(", lr = %x, msr = %x, sp = %x [%x]\n",
@@ -1163,9 +1276,6 @@ bsesc()
return c;
}
-#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
- || ('a' <= (c) && (c) <= 'f') \
- || ('A' <= (c) && (c) <= 'F'))
void
dump()
{
@@ -1402,6 +1512,16 @@ skipbl()
return c;
}
+#define N_PTREGS 44
+static char *regnames[N_PTREGS] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+ "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
+ "trap", "dar", "dsisr", "res"
+};
+
int
scanhex(vp)
unsigned *vp;
@@ -1410,6 +1530,36 @@ unsigned *vp;
unsigned v;
c = skipbl();
+ if (c == '%') {
+ /* parse register name */
+ char regname[8];
+ int i;
+
+ for (i = 0; i < sizeof(regname) - 1; ++i) {
+ c = inchar();
+ if (!isalnum(c)) {
+ termch = c;
+ break;
+ }
+ regname[i] = c;
+ }
+ regname[i] = 0;
+ for (i = 0; i < N_PTREGS; ++i) {
+ if (strcmp(regnames[i], regname) == 0) {
+ unsigned *rp = (unsigned *)
+ xmon_regs[smp_processor_id()];
+ if (rp == NULL) {
+ printf("regs not available\n");
+ return 0;
+ }
+ *vp = rp[i];
+ return 1;
+ }
+ }
+ printf("invalid register name '%%%s'\n", regname);
+ return 0;
+ }
+
d = hexdigit(c);
if( d == EOF ){
termch = c;