summaryrefslogtreecommitdiffstats
path: root/arch/ppc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc')
-rw-r--r--arch/ppc/8xx_io/Makefile8
-rw-r--r--arch/ppc/8xx_io/commproc.c45
-rw-r--r--arch/ppc/8xx_io/commproc.h87
-rw-r--r--arch/ppc/8xx_io/enet.c2
-rw-r--r--arch/ppc/8xx_io/fec.c985
-rw-r--r--arch/ppc/8xx_io/uart.c290
-rw-r--r--arch/ppc/Makefile7
-rw-r--r--arch/ppc/amiga/amiints.c549
-rw-r--r--arch/ppc/amiga/config.c919
-rw-r--r--arch/ppc/amiga/time.c22
-rw-r--r--arch/ppc/apus_defconfig282
-rw-r--r--arch/ppc/boot/Makefile56
-rw-r--r--arch/ppc/boot/head.S8
-rw-r--r--arch/ppc/boot/mbxtty.c16
-rw-r--r--arch/ppc/boot/misc.c281
-rw-r--r--arch/ppc/boot/mkprep.c20
-rw-r--r--arch/ppc/boot/offset2
-rw-r--r--arch/ppc/boot/size2
-rw-r--r--arch/ppc/chrp_defconfig96
-rw-r--r--arch/ppc/chrpboot/Makefile6
-rw-r--r--arch/ppc/chrpboot/main.c4
-rw-r--r--arch/ppc/chrpboot/nonstdio.h18
-rw-r--r--arch/ppc/chrpboot/zlib.c2143
-rw-r--r--arch/ppc/chrpboot/zlib.h432
-rw-r--r--arch/ppc/coffboot/Makefile13
-rw-r--r--arch/ppc/coffboot/misc.S11
-rw-r--r--arch/ppc/coffboot/zlib.c4
-rw-r--r--arch/ppc/common_defconfig204
-rw-r--r--arch/ppc/config.in52
-rw-r--r--arch/ppc/defconfig71
-rw-r--r--arch/ppc/kernel/Makefile11
-rw-r--r--arch/ppc/kernel/align.c4
-rw-r--r--arch/ppc/kernel/apus_setup.c199
-rw-r--r--arch/ppc/kernel/chrp_setup.c62
-rw-r--r--arch/ppc/kernel/feature.c249
-rw-r--r--arch/ppc/kernel/find_name.c4
-rw-r--r--arch/ppc/kernel/head.S358
-rw-r--r--arch/ppc/kernel/idle.c26
-rw-r--r--arch/ppc/kernel/irq.c561
-rw-r--r--arch/ppc/kernel/misc.S93
-rw-r--r--arch/ppc/kernel/openpic.c77
-rw-r--r--arch/ppc/kernel/pci.c18
-rw-r--r--arch/ppc/kernel/pmac_pci.c10
-rw-r--r--arch/ppc/kernel/pmac_setup.c201
-rw-r--r--arch/ppc/kernel/pmac_support.c3
-rw-r--r--arch/ppc/kernel/ppc_defs.h69
-rw-r--r--arch/ppc/kernel/ppc_htab.c150
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c18
-rw-r--r--arch/ppc/kernel/prep_pci.c66
-rw-r--r--arch/ppc/kernel/prep_setup.c96
-rw-r--r--arch/ppc/kernel/process.c39
-rw-r--r--arch/ppc/kernel/prom.c903
-rw-r--r--arch/ppc/kernel/residual.c85
-rw-r--r--arch/ppc/kernel/setup.c215
-rw-r--r--arch/ppc/kernel/signal.c14
-rw-r--r--arch/ppc/kernel/smp.c114
-rw-r--r--arch/ppc/kernel/syscalls.c2
-rw-r--r--arch/ppc/kernel/time.c9
-rw-r--r--arch/ppc/kernel/totalmp.c109
-rw-r--r--arch/ppc/lib/locks.c18
-rw-r--r--arch/ppc/lib/string.S84
-rw-r--r--arch/ppc/mbx_defconfig1
-rw-r--r--arch/ppc/mm/fault.c2
-rw-r--r--arch/ppc/mm/init.c221
-rw-r--r--arch/ppc/pmac_defconfig153
-rw-r--r--arch/ppc/prep_defconfig106
66 files changed, 6844 insertions, 4141 deletions
diff --git a/arch/ppc/8xx_io/Makefile b/arch/ppc/8xx_io/Makefile
index b33919a5d..0da0a492d 100644
--- a/arch/ppc/8xx_io/Makefile
+++ b/arch/ppc/8xx_io/Makefile
@@ -8,6 +8,12 @@
# Note 2! The CFLAGS definition is now in the main makefile...
O_TARGET := 8xx_io.a
-O_OBJS = commproc.o uart.o enet.o
+O_OBJS = commproc.o uart.o
+ifdef CONFIG_MBX
+O_OBJS += enet.o
+endif
+ifdef CONFIG_FADS
+O_OBJS += fec.o
+endif
include $(TOPDIR)/Rules.make
diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c
index 00bbbe72d..b1ea955ed 100644
--- a/arch/ppc/8xx_io/commproc.c
+++ b/arch/ppc/8xx_io/commproc.c
@@ -21,6 +21,7 @@
* applications that require more DP ram, we can expand the boundaries
* but then we have to be careful of any downloaded microcode.
*/
+#include <linux/config.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -29,7 +30,12 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
+#ifdef CONFIG_MBX
#include <asm/mbx.h>
+#endif
+#ifdef CONFIG_FADS
+#include <asm/fads.h>
+#endif
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/8xx_immap.h>
@@ -52,13 +58,13 @@ static void cpm_interrupt(int irq, void * dev, struct pt_regs * regs);
static void cpm_error_interrupt(void *);
void
-mbx_cpm_reset(uint host_page_addr)
+m8xx_cpm_reset(uint host_page_addr)
{
volatile immap_t *imp;
volatile cpm8xx_t *commproc;
pte_t *pte;
- imp = (immap_t *)MBX_IMAP_ADDR;
+ imp = (immap_t *)IMAP_ADDR;
commproc = (cpm8xx_t *)&imp->im_cpm;
#ifdef notdef
@@ -78,6 +84,10 @@ mbx_cpm_reset(uint host_page_addr)
#endif
/* Set SDMA Bus Request priority 5.
+ * On 860T, this also enables FEC priority 6. I am not sure
+ * this is what we realy want for some applications, but the
+ * manual recommends it.
+ * Bit 25, FAM can also be set to use FEC aggressive mode (860T).
*/
imp->im_siu_conf.sc_sdcr = 1;
@@ -99,10 +109,10 @@ mbx_cpm_reset(uint host_page_addr)
/* Initialize the CPM interrupt controller.
*/
- ((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cicr =
+ ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr =
(CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
((CPM_INTERRUPT/2) << 13) | CICR_HP_MASK;
- ((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cimr = 0;
+ ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr = 0;
/* Set our interrupt handler with the core CPU.
*/
if (request_irq(CPM_INTERRUPT, cpm_interrupt, 0, "cpm", NULL) != 0)
@@ -111,7 +121,7 @@ mbx_cpm_reset(uint host_page_addr)
/* Install our own error handler.
*/
cpm_install_handler(CPMVEC_ERROR, cpm_error_interrupt, NULL);
- ((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN;
+ ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN;
}
/* CPM interrupt controller interrupt.
@@ -124,19 +134,19 @@ cpm_interrupt(int irq, void * dev, struct pt_regs * regs)
/* Get the vector by setting the ACK bit and then reading
* the register.
*/
- ((volatile immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_civr = 1;
- vec = ((volatile immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_civr;
+ ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr = 1;
+ vec = ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr;
vec >>= 11;
if (cpm_vecs[vec].handler != 0)
(*cpm_vecs[vec].handler)(cpm_vecs[vec].dev_id);
else
- ((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec);
+ ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec);
/* After servicing the interrupt, we have to remove the status
* indicator.
*/
- ((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cisr |= (1 << vec);
+ ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr |= (1 << vec);
}
@@ -160,7 +170,7 @@ cpm_install_handler(int vec, void (*handler)(void *), void *dev_id)
(uint)handler, (uint)cpm_vecs[vec].handler);
cpm_vecs[vec].handler = handler;
cpm_vecs[vec].dev_id = dev_id;
- ((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << vec);
+ ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << vec);
}
/* Allocate some memory from the dual ported ram. We may want to
@@ -168,7 +178,7 @@ cpm_install_handler(int vec, void (*handler)(void *), void *dev_id)
* citizen.
*/
uint
-mbx_cpm_dpalloc(uint size)
+m8xx_cpm_dpalloc(uint size)
{
uint retloc;
@@ -185,7 +195,7 @@ mbx_cpm_dpalloc(uint size)
* UART "fifos" and the like.
*/
uint
-mbx_cpm_hostalloc(uint size)
+m8xx_cpm_hostalloc(uint size)
{
uint retloc;
@@ -201,13 +211,13 @@ mbx_cpm_hostalloc(uint size)
/* Set a baud rate generator. This needs lots of work. There are
* four BRGs, any of which can be wired to any channel.
* The internal baud rate clock is the system clock divided by 16.
- * I need to find a way to get this system clock frequency, which is
- * part of the VPD.......
+ * This assumes the baudrate is 16x oversampled by the uart.
*/
-#define BRG_INT_CLK (40000000/16)
+#define BRG_INT_CLK (((bd_t *)res)->bi_intfreq * 1000000)
+#define BRG_UART_CLK (BRG_INT_CLK/16)
void
-mbx_cpm_setbrg(uint brg, uint rate)
+m8xx_cpm_setbrg(uint brg, uint rate)
{
volatile uint *bp;
@@ -215,5 +225,6 @@ mbx_cpm_setbrg(uint brg, uint rate)
*/
bp = (uint *)&cpmp->cp_brgc1;
bp += brg;
- *bp = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN;
+ *bp = ((BRG_UART_CLK / rate) << 1) | CPM_BRG_EN;
}
+
diff --git a/arch/ppc/8xx_io/commproc.h b/arch/ppc/8xx_io/commproc.h
index 38046a31c..50140ab26 100644
--- a/arch/ppc/8xx_io/commproc.h
+++ b/arch/ppc/8xx_io/commproc.h
@@ -62,9 +62,9 @@
* and dual port ram.
*/
extern cpm8xx_t *cpmp; /* Pointer to comm processor */
-uint mbx_cpm_dpalloc(uint size);
-uint mbx_cpm_hostalloc(uint size);
-void mbx_cpm_setbrg(uint brg, uint rate);
+uint m8xx_cpm_dpalloc(uint size);
+uint m8xx_cpm_hostalloc(uint size);
+void m8xx_cpm_setbrg(uint brg, uint rate);
/* Buffer descriptors used by many of the CPM protocols.
*/
@@ -87,8 +87,16 @@ typedef struct cpm_buf_desc {
#define BD_SC_OV ((ushort)0x0002) /* Overrun */
#define BD_SC_CD ((ushort)0x0001) /* ?? */
-/* Define enough so I can at least use the MBX serial port as a UART.
- * The MBX uses SMC1 as the host serial port.
+/* Parameter RAM offsets.
+*/
+#define PROFF_SCC1 ((uint)0x0000)
+#define PROFF_SCC2 ((uint)0x0100)
+#define PROFF_SCC3 ((uint)0x0200)
+#define PROFF_SMC1 ((uint)0x0280)
+#define PROFF_SCC4 ((uint)0x0300)
+#define PROFF_SMC2 ((uint)0x0380)
+
+/* Define enough so I can at least use the serial port as a UART.
*/
typedef struct smc_uart {
ushort smc_rbase; /* Rx Buffer descriptor base address */
@@ -114,9 +122,6 @@ typedef struct smc_uart {
ushort smc_rmask; /* Temporary bit mask */
} smc_uart_t;
-#define PROFF_SMC1 ((uint)0x0280) /* Offset in Parameter RAM */
-#define PROFF_SMC2 ((uint)0x0380)
-
/* Function code bits.
*/
#define SMC_EB ((u_char)0x10) /* Set big endian byte order */
@@ -139,7 +144,7 @@ typedef struct smc_uart {
/* SMC Event and Mask register.
*/
#define SMCM_TXE ((unsigned char)0x10)
-#define SMCM_BSY ((unsigned char)0x14)
+#define SMCM_BSY ((unsigned char)0x04)
#define SMCM_TX ((unsigned char)0x02)
#define SMCM_RX ((unsigned char)0x01)
@@ -238,6 +243,13 @@ typedef struct smc_uart {
#define SCC_TODR_TOD ((ushort)0x8000)
+/* SCC Event and Mask register.
+*/
+#define SCCM_TXE ((unsigned char)0x10)
+#define SCCM_BSY ((unsigned char)0x04)
+#define SCCM_TX ((unsigned char)0x02)
+#define SCCM_RX ((unsigned char)0x01)
+
typedef struct scc_param {
ushort scc_rbase; /* Rx Buffer descriptor base address */
ushort scc_tbase; /* Tx Buffer descriptor base address */
@@ -317,8 +329,6 @@ typedef struct scc_enet {
ushort sen_taddrl; /* temp address (LSB) */
} scc_enet_t;
-#define PROFF_SCC1 ((uint)0x0000) /* Offset in Parameter RAM */
-
/* Bits in parallel I/O port registers that have to be set/cleared
* to configure the pins for SCC1 use. The TCLK and RCLK seem unique
* to the MBX860 board. Any two of the four available clocks could be
@@ -397,6 +407,37 @@ typedef struct scc_enet {
#define BD_ENET_TX_CSL ((ushort)0x0001)
#define BD_ENET_TX_STATS ((ushort)0x03ff) /* All status bits */
+/* SCC as UART
+*/
+typedef struct scc_uart {
+ sccp_t scc_genscc;
+ uint scc_res1; /* Reserved */
+ uint scc_res2; /* Reserved */
+ ushort scc_maxidl; /* Maximum idle chars */
+ ushort scc_idlc; /* temp idle counter */
+ ushort scc_brkcr; /* Break count register */
+ ushort scc_parec; /* receive parity error counter */
+ ushort scc_frmec; /* receive framing error counter */
+ ushort scc_nosec; /* receive noise counter */
+ ushort scc_brkec; /* receive break condition counter */
+ ushort scc_brkln; /* last received break length */
+ ushort scc_uaddr1; /* UART address character 1 */
+ ushort scc_uaddr2; /* UART address character 2 */
+ ushort scc_rtemp; /* Temp storage */
+ ushort scc_toseq; /* Transmit out of sequence char */
+ ushort scc_char1; /* control character 1 */
+ ushort scc_char2; /* control character 2 */
+ ushort scc_char3; /* control character 3 */
+ ushort scc_char4; /* control character 4 */
+ ushort scc_char5; /* control character 5 */
+ ushort scc_char6; /* control character 6 */
+ ushort scc_char7; /* control character 7 */
+ ushort scc_char8; /* control character 8 */
+ ushort scc_rccm; /* receive control character mask */
+ ushort scc_rccr; /* receive control character register */
+ ushort scc_rlbc; /* receive last break character */
+} scc_uart_t;
+
/* SCC Event and Mask registers when it is used as a UART.
*/
#define UART_SCCM_GLR ((ushort)0x1000)
@@ -411,6 +452,30 @@ typedef struct scc_enet {
#define UART_SCCM_TX ((ushort)0x0002)
#define UART_SCCM_RX ((ushort)0x0001)
+/* The SCC PMSR when used as a UART.
+*/
+#define SCU_PMSR_FLC ((ushort)0x8000)
+#define SCU_PMSR_SL ((ushort)0x4000)
+#define SCU_PMSR_CL ((ushort)0x3000)
+#define SCU_PMSR_UM ((ushort)0x0c00)
+#define SCU_PMSR_FRZ ((ushort)0x0200)
+#define SCU_PMSR_RZS ((ushort)0x0100)
+#define SCU_PMSR_SYN ((ushort)0x0080)
+#define SCU_PMSR_DRT ((ushort)0x0040)
+#define SCU_PMSR_PEN ((ushort)0x0010)
+#define SCU_PMSR_RPM ((ushort)0x000c)
+#define SCU_PMSR_REVP ((ushort)0x0008)
+#define SCU_PMSR_TPM ((ushort)0x0003)
+#define SCU_PMSR_TEVP ((ushort)0x0003)
+
+/* CPM Transparent mode SCC.
+ */
+typedef struct scc_trans {
+ sccp_t st_genscc;
+ uint st_cpres; /* Preset CRC */
+ uint st_cmask; /* Constant mask for CRC */
+} scc_trans_t;
+
/* CPM interrupts. There are nearly 32 interrupts generated by CPM
* channels or devices. All of these are presented to the PPC core
* as a single interrupt. The CPM interrupt handler dispatches its
diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c
index 0b5f0452c..8c3401d6f 100644
--- a/arch/ppc/8xx_io/enet.c
+++ b/arch/ppc/8xx_io/enet.c
@@ -96,7 +96,7 @@
*/
/* 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
+ * pool. The code may assume these are power of two, so it is best
* to keep them that size.
* We don't need to allocate pages for the transmitter. We just use
* the skbuffer directly.
diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c
new file mode 100644
index 000000000..2b797a498
--- /dev/null
+++ b/arch/ppc/8xx_io/fec.c
@@ -0,0 +1,985 @@
+/*
+ * Fast Ethernet Controller (FECC) driver for Motorola MPC8xx.
+ * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
+ *
+ * This version of the driver is specific to the FADS implementation,
+ * since the board contains control registers external to the processor
+ * for the control of the LevelOne LXT970 transceiver. The MPC860T manual
+ * describes connections using the internal parallel port I/O, which
+ * is basically all of Port D.
+ *
+ * Right now, I am very watseful with the buffers. I allocate memory
+ * pages and then divide them into 2K frame buffers. This way I know I
+ * have buffers large enough to hold one frame within one buffer descriptor.
+ * Once I get this working, I will use 64 or 128 byte CPM buffers, which
+ * will be much more memory efficient and will easily handle lots of
+ * small packets.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <asm/8xx_immap.h>
+#include <asm/pgtable.h>
+#include <asm/fads.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include "commproc.h"
+
+/* 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.
+ */
+#if 1
+#define FEC_ENET_RX_PAGES 4
+#define FEC_ENET_RX_FRSIZE 2048
+#define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE)
+#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
+#define TX_RING_SIZE 8 /* Must be power of two */
+#define TX_RING_MOD_MASK 7 /* for this to work */
+#else
+#define FEC_ENET_RX_PAGES 16
+#define FEC_ENET_RX_FRSIZE 2048
+#define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE)
+#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
+#define TX_RING_SIZE 16 /* Must be power of two */
+#define TX_RING_MOD_MASK 15 /* for this to work */
+#endif
+
+/* Interrupt events/masks.
+*/
+#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */
+#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */
+#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */
+#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */
+#define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */
+#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */
+#define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */
+#define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */
+#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */
+#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */
+
+/* The FEC stores dest/src/type, data, and checksum for receive packets.
+ */
+#define PKT_MAXBUF_SIZE 1518
+#define PKT_MINBUF_SIZE 64
+#define PKT_MAXBLR_SIZE 1520
+
+/* The FEC 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 fec_enet_private {
+ /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+ struct sk_buff* tx_skbuff[TX_RING_SIZE];
+ ushort skb_cur;
+ ushort skb_dirty;
+
+ /* CPM dual port RAM relative addresses.
+ */
+ cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */
+ cbd_t *tx_bd_base;
+ cbd_t *cur_rx, *cur_tx; /* The next free ring entry */
+ cbd_t *dirty_tx; /* The ring entries to be free()ed. */
+ scc_t *sccp;
+ struct net_device_stats stats;
+ char tx_full;
+ unsigned long lock;
+};
+
+static int fec_enet_open(struct device *dev);
+static int fec_enet_start_xmit(struct sk_buff *skb, struct device *dev);
+static int fec_enet_rx(struct device *dev);
+static void fec_enet_mii(struct device *dev);
+static void fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
+static int fec_enet_close(struct device *dev);
+static struct net_device_stats *fec_enet_get_stats(struct device *dev);
+static void set_multicast_list(struct device *dev);
+
+static ushort my_enet_addr[] = { 0x0800, 0x3e26, 0x1559 };
+
+/* 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 mii_list *mii_next;
+} mii_list_t;
+
+#define NMII 10
+mii_list_t mii_cmds[NMII];
+mii_list_t *mii_free;
+mii_list_t *mii_head;
+mii_list_t *mii_tail;
+
+static int mii_queue(int request, void (*func)(int));
+
+/* Make MII read/write commands for the FEC.
+*/
+#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18))
+#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | \
+ (VAL & 0xffff))
+
+static int
+fec_enet_open(struct device *dev)
+{
+
+ /* I should reset the ring buffers here, but I don't yet know
+ * a simple way to do that.
+ */
+
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+
+ return 0; /* Always succeed */
+}
+
+static int
+fec_enet_start_xmit(struct sk_buff *skb, struct device *dev)
+{
+ struct fec_enet_private *fep = (struct fec_enet_private *)dev->priv;
+ volatile cbd_t *bdp;
+ unsigned long flags;
+
+ /* Transmitter timeout, serious problems. */
+ if (dev->tbusy) {
+ int tickssofar = jiffies - dev->trans_start;
+ if (tickssofar < 20)
+ return 1;
+ printk("%s: transmit timed out.\n", dev->name);
+ fep->stats.tx_errors++;
+#ifndef final_version
+ {
+ int i;
+ cbd_t *bdp;
+ printk(" Ring data dump: cur_tx %x%s cur_rx %x.\n",
+ fep->cur_tx, fep->tx_full ? " (full)" : "",
+ fep->cur_rx);
+ bdp = fep->tx_bd_base;
+ for (i = 0 ; i < TX_RING_SIZE; i++)
+ printk("%04x %04x %08x\n",
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ bdp = fep->rx_bd_base;
+ for (i = 0 ; i < RX_RING_SIZE; i++)
+ printk("%04x %04x %08x\n",
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ }
+#endif
+
+ dev->tbusy=0;
+ dev->trans_start = jiffies;
+
+ return 0;
+ }
+
+ /* Block a timer-based transmit from overlapping. This could better be
+ done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+ if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+ printk("%s: Transmitter access conflict.\n", dev->name);
+ return 1;
+ }
+
+ if (test_and_set_bit(0, (void*)&fep->lock) != 0) {
+ printk("%s: tx queue lock!.\n", dev->name);
+ /* don't clear dev->tbusy flag. */
+ return 1;
+ }
+
+ /* Fill in a Tx ring entry */
+ bdp = fep->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 dev->tbusy should be set.
+ */
+ printk("%s: tx queue full!.\n", dev->name);
+ fep->lock = 0;
+ return 1;
+ }
+#endif
+
+ /* Clear all of the status flags.
+ */
+ bdp->cbd_sc &= ~BD_ENET_TX_STATS;
+
+ /* Set buffer length and buffer pointer.
+ */
+ bdp->cbd_bufaddr = __pa(skb->data);
+ bdp->cbd_datlen = skb->len;
+
+ /* Save skb pointer.
+ */
+ fep->tx_skbuff[fep->skb_cur] = skb;
+
+ fep->stats.tx_bytes += skb->len;
+ fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK;
+
+ /* Push the data cache so the CPM does not get stale memory
+ * data.
+ */
+ /*flush_dcache_range(skb->data, skb->data + skb->len);*/
+
+ /* 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.
+ */
+ save_flags(flags);
+ cli();
+
+ bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+
+ dev->trans_start = jiffies;
+ (&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec))->fec_x_des_active = 0x01000000;
+
+ /* If this was the last BD in the ring, start at the beginning again.
+ */
+ if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+ bdp = fep->tx_bd_base;
+ else
+ bdp++;
+
+ fep->lock = 0;
+ if (bdp->cbd_sc & BD_ENET_TX_READY)
+ fep->tx_full = 1;
+ else
+ dev->tbusy=0;
+ restore_flags(flags);
+
+ fep->cur_tx = (cbd_t *)bdp;
+
+ return 0;
+}
+
+/* The interrupt handler.
+ * This is called from the MPC core interrupt.
+ */
+static void
+fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+ struct device *dev = dev_id;
+ struct fec_enet_private *fep;
+ volatile cbd_t *bdp;
+ volatile fec_t *ep;
+ uint int_events;
+ int c=0;
+
+ fep = (struct fec_enet_private *)dev->priv;
+ ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec);
+ if (dev->interrupt)
+ printk("%s: Re-entering the interrupt handler.\n", dev->name);
+ dev->interrupt = 1;
+
+ /* Get the interrupt events that caused us to be here.
+ */
+ while ((int_events = ep->fec_ievent) != 0) {
+ ep->fec_ievent = int_events;
+ if ((int_events &
+ (FEC_ENET_HBERR | FEC_ENET_BABR |
+ FEC_ENET_BABT | FEC_ENET_EBERR)) != 0)
+ printk("FEC ERROR %x\n", int_events);
+
+ /* Handle receive event in its own function.
+ */
+ if (int_events & (FEC_ENET_RXF | FEC_ENET_RXB))
+ fec_enet_rx(dev_id);
+
+ /* Transmit OK, or non-fatal error. Update the buffer descriptors.
+ * FEC handles all errors, we just discover them as part of the
+ * transmit process.
+ */
+ if (int_events & (FEC_ENET_TXF | FEC_ENET_TXB)) {
+ bdp = fep->dirty_tx;
+ while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
+#if 1
+ if (bdp==fep->cur_tx)
+ break;
+#endif
+ if (++c>1) {/*we go here when an it has been lost*/};
+
+
+ if (bdp->cbd_sc & BD_ENET_TX_HB) /* No heartbeat */
+ fep->stats.tx_heartbeat_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_LC) /* Late collision */
+ fep->stats.tx_window_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_RL) /* Retrans limit */
+ fep->stats.tx_aborted_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_UN) /* Underrun */
+ fep->stats.tx_fifo_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */
+ fep->stats.tx_carrier_errors++;
+
+ fep->stats.tx_errors++;
+
+ fep->stats.tx_packets++;
+
+#ifndef final_version
+ if (bdp->cbd_sc & BD_ENET_TX_READY)
+ printk("HEY! Enet xmit interrupt and TX_READY.\n");
+#endif
+ /* Deferred means some collisions occurred during transmit,
+ * but we eventually sent the packet OK.
+ */
+ if (bdp->cbd_sc & BD_ENET_TX_DEF)
+ fep->stats.collisions++;
+
+ /* Free the sk buffer associated with this last transmit.
+ */
+ dev_kfree_skb(fep->tx_skbuff[fep->skb_dirty]/*, FREE_WRITE*/);
+ fep->skb_dirty = (fep->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 = fep->tx_bd_base;
+ else
+ bdp++;
+
+ /* Since we have freed up a buffer, the ring is no longer
+ * full.
+ */
+ if (fep->tx_full && dev->tbusy) {
+ fep->tx_full = 0;
+ dev->tbusy = 0;
+ mark_bh(NET_BH);
+ }
+
+ fep->dirty_tx = (cbd_t *)bdp;
+#if 0
+ if (bdp==fep->cur_tx)
+ break;
+#endif
+ }/*while (bdp->cbd_sc&BD_ENET_TX_READY)==0*/
+ } /* if tx events */
+
+ if (int_events & FEC_ENET_MII)
+ fec_enet_mii(dev_id);
+
+ } /* while any events */
+
+ dev->interrupt = 0;
+
+ 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
+fec_enet_rx(struct device *dev)
+{
+ struct fec_enet_private *fep;
+ volatile cbd_t *bdp;
+ struct sk_buff *skb;
+ ushort pkt_len;
+ volatile fec_t *ep;
+
+ fep = (struct fec_enet_private *)dev->priv;
+ ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec);
+
+ /* First, grab all of the stats for the incoming packet.
+ * These get messed up if we get called due to a busy condition.
+ */
+ bdp = fep->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,
+ * the last indicator should be set.
+ */
+ if ((bdp->cbd_sc & BD_ENET_RX_LAST) == 0)
+ printk("FEC ENET: rcv is not +last\n");
+#endif
+
+ /* Frame too long or too short.
+ */
+ if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
+ fep->stats.rx_length_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_NO) /* Frame alignment */
+ fep->stats.rx_frame_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_CR) /* CRC Error */
+ fep->stats.rx_crc_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_OV) /* FIFO overrun */
+ fep->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) {
+ fep->stats.rx_frame_errors++;
+ }
+ else {
+
+ /* Process the incoming frame.
+ */
+ fep->stats.rx_packets++;
+ pkt_len = bdp->cbd_datlen;
+ fep->stats.rx_bytes += pkt_len;
+
+ /* This does 16 byte alignment, exactly what we need.
+ */
+ skb = dev_alloc_skb(pkt_len);
+
+ 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 */
+ eth_copy_and_sum(skb,
+ (unsigned char *)__va(bdp->cbd_bufaddr),
+ pkt_len, 0);
+ skb->protocol=eth_type_trans(skb,dev);
+ netif_rx(skb);
+ }
+ }
+
+ /* Clear the status flags for this buffer.
+ */
+ bdp->cbd_sc &= ~BD_ENET_RX_STATS;
+
+ /* Mark the buffer empty.
+ */
+ bdp->cbd_sc |= BD_ENET_RX_EMPTY;
+
+ /* Update BD pointer to next entry.
+ */
+ if (bdp->cbd_sc & BD_ENET_RX_WRAP)
+ bdp = fep->rx_bd_base;
+ else
+ bdp++;
+
+#if 1
+ /* Doing this here will keep the FEC running while we process
+ * incoming frames. On a heavily loaded network, we should be
+ * able to keep up at the expense of system resources.
+ */
+ ep->fec_r_des_active = 0x01000000;
+#endif
+ }
+ fep->cur_rx = (cbd_t *)bdp;
+
+#if 0
+ /* Doing this here will allow us to process all frames in the
+ * ring before the FEC is allowed to put more there. On a heavily
+ * loaded network, some frames may be lost. Unfortunately, this
+ * increases the interrupt overhead since we can potentially work
+ * our way back to the interrupt return only to come right back
+ * here.
+ */
+ ep->fec_r_des_active = 0x01000000;
+#endif
+
+ return 0;
+}
+
+static void
+fec_enet_mii(struct device *dev)
+{
+ struct fec_enet_private *fep;
+ volatile fec_t *ep;
+ mii_list_t *mip;
+ uint mii_reg;
+
+ fep = (struct fec_enet_private *)dev->priv;
+ ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec);
+ mii_reg = ep->fec_mii_data;
+
+ if ((mip = mii_head) == NULL) {
+ printk("MII and no head!\n");
+ return;
+ }
+
+ if (mip->mii_func != NULL)
+ (*(mip->mii_func))(mii_reg);
+
+ mii_head = mip->mii_next;
+ mip->mii_next = mii_free;
+ mii_free = mip;
+
+ if ((mip = mii_head) != NULL)
+ ep->fec_mii_data = mip->mii_regval;
+}
+
+static int
+mii_queue(int regval, void (*func)(int))
+{
+ 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;
+ (&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec))->fec_mii_data = regval;
+ }
+ }
+ else {
+ retval = 1;
+ }
+
+ restore_flags(flags);
+
+ return(retval);
+}
+
+static void
+mii_status(uint mii_reg)
+{
+ 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.
+ */
+ printk("fec: ");
+ if (mii_reg & 0x0800)
+ printk("100 Mbps");
+ else
+ printk("10 Mbps");
+
+ if (mii_reg & 0x1000)
+ printk(", Full-Duplex\n");
+ else
+ printk(", Half-Duplex\n");
+ }
+}
+
+static void
+mii_startup_cmds(void)
+{
+
+ /* 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);
+
+ /* Enable Link status change interrupts.
+ mii_queue(mk_mii_write(0x11, 0x0002), NULL);
+ */
+}
+
+/* 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)
+{
+ 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.
+ */
+ 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");
+ else
+ printk(", Half-Duplex\n");
+ }
+}
+
+/* This interrupt occurs when the LTX970 detects a link change.
+*/
+static void
+mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+ struct device *dev = dev_id;
+ struct fec_enet_private *fep;
+ volatile fec_t *ep;
+
+ fep = (struct fec_enet_private *)dev->priv;
+ ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec);
+
+ /* We need to sequentially read registers 1 and 18 to clear
+ * the interrupt. We don't need to do that here because this
+ * is an edge triggered interrupt that has already been acknowledged
+ * by the top level handler. We also read the extended status
+ * register 20. We just queue the commands and let them happen
+ * as part of the "normal" processing.
+ */
+ mii_queue(mk_mii_read(1), mii_relink);
+ mii_queue(mk_mii_read(18), mii_relink);
+ mii_queue(mk_mii_read(20), mii_relink);
+}
+
+static int
+fec_enet_close(struct device *dev)
+{
+ /* Don't know what to do yet.
+ */
+
+ return 0;
+}
+
+static struct net_device_stats *fec_enet_get_stats(struct device *dev)
+{
+ struct fec_enet_private *fep = (struct fec_enet_private *)dev->priv;
+
+ return &fep->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+ * Skeleton taken from sunlance driver.
+ * The CPM Ethernet implementation allows Multicast as well as individual
+ * MAC address filtering. Some of the drivers check to make sure it is
+ * a group multicast address, and discard those that are not. I guess I
+ * will do the same for now, but just remove the test if you want
+ * individual filtering as well (do the upper net layers want or support
+ * this kind of feature?).
+ */
+
+static void set_multicast_list(struct device *dev)
+{
+ struct fec_enet_private *fep;
+ struct dev_mc_list *dmi;
+ u_char *mcptr, *tdptr;
+ volatile fec_t *ep;
+ int i, j;
+
+ fep = (struct fec_enet_private *)dev->priv;
+ ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec);
+
+ if (dev->flags&IFF_PROMISC) {
+
+ /* Log any net taps. */
+ printk("%s: Promiscuous mode enabled.\n", dev->name);
+ ep->fec_r_cntrl |= 0x0008;
+ } else {
+
+ ep->fec_r_cntrl &= ~0x0008;
+
+ if (dev->flags & IFF_ALLMULTI) {
+ /* Catch all multicast addresses, so set the
+ * filter to all 1's.
+ */
+ ep->fec_hash_table_high = 0xffffffff;
+ ep->fec_hash_table_low = 0xffffffff;
+ }
+#if 0
+ else {
+ /* Clear filter and add the addresses in the list.
+ */
+ ep->sen_gaddr1 = 0;
+ ep->sen_gaddr2 = 0;
+ ep->sen_gaddr3 = 0;
+ ep->sen_gaddr4 = 0;
+
+ dmi = dev->mc_list;
+
+ for (i=0; i<dev->mc_count; i++) {
+
+ /* Only support group multicast for now.
+ */
+ if (!(dmi->dmi_addr[0] & 1))
+ continue;
+
+ /* The address in dmi_addr is LSB first,
+ * and taddr is MSB first. We have to
+ * copy bytes MSB first from dmi_addr.
+ */
+ mcptr = (u_char *)dmi->dmi_addr + 5;
+ tdptr = (u_char *)&ep->sen_taddrh;
+ for (j=0; j<6; j++)
+ *tdptr++ = *mcptr--;
+
+ /* Ask CPM to run CRC and set bit in
+ * filter mask.
+ */
+ cpmp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_SET_GADDR) | CPM_CR_FLG;
+ /* this delay is necessary here -- Cort */
+ udelay(10);
+ while (cpmp->cp_cpcr & CPM_CR_FLG);
+ }
+ }
+#endif
+ }
+}
+
+/* Initialize the FECC Ethernet on 860T.
+ */
+__initfunc(int m8xx_enet_init(void))
+{
+ struct device *dev;
+ struct fec_enet_private *fep;
+ int i, j;
+ unsigned char *eap;
+ unsigned long mem_addr;
+ pte_t *pte;
+ volatile cbd_t *bdp;
+ cbd_t *cbd_base;
+ volatile immap_t *immap;
+ volatile fec_t *fecp;
+ unsigned char rtc_save_cfg, rtc_val;
+
+ immap = (immap_t *)IMAP_ADDR; /* pointer to internal registers */
+
+ /* Allocate some private information.
+ */
+ fep = (struct fec_enet_private *)kmalloc(sizeof(*fep), GFP_KERNEL);
+ __clear_user(fep,sizeof(*fep));
+
+ /* Create an Ethernet device instance.
+ */
+ dev = init_etherdev(0, 0);
+
+ fecp = &(immap->im_cpm.cp_fec);
+
+ /* Whack a reset. We should wait for this.
+ */
+ fecp->fec_ecntrl = 1;
+ udelay(10);
+
+ /* Enable interrupts we wish to service.
+ */
+ fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
+ FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
+
+ /* Clear any outstanding interrupt.
+ */
+ fecp->fec_ievent = 0xffc0;
+
+ fecp->fec_ivec = (FEC_INTERRUPT/2) << 29;
+
+ /* Set station address.
+ */
+ fecp->fec_addr_low = (my_enet_addr[0] << 16) | my_enet_addr[1];
+ fecp->fec_addr_high = my_enet_addr[2];
+
+ eap = (unsigned char *)&my_enet_addr[0];
+ for (i=0; i<6; i++)
+ dev->dev_addr[i] = *eap++;
+
+ /* Reset all multicast.
+ */
+ fecp->fec_hash_table_high = 0;
+ fecp->fec_hash_table_low = 0;
+
+ /* Set maximum receive buffer size.
+ */
+ fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
+ fecp->fec_r_hash = PKT_MAXBUF_SIZE;
+
+ /* Allocate memory for buffer descriptors.
+ */
+ if (((RX_RING_SIZE + TX_RING_SIZE) * sizeof(cbd_t)) > PAGE_SIZE) {
+ printk("FECC init error. Need more space.\n");
+ printk("FECC initialization failed.\n");
+ return 1;
+ }
+ mem_addr = __get_free_page(GFP_KERNEL);
+ cbd_base = (cbd_t *)mem_addr;
+
+ /* Make it uncached.
+ */
+ pte = va_to_pte(&init_task, (int)mem_addr);
+ pte_val(*pte) |= _PAGE_NO_CACHE;
+ flush_tlb_page(current->mm->mmap, mem_addr);
+
+ /* Set receive and transmit descriptor base.
+ */
+ fecp->fec_r_des_start = __pa(mem_addr);
+ fep->rx_bd_base = cbd_base;
+ fecp->fec_x_des_start = __pa((unsigned long)(cbd_base + RX_RING_SIZE));
+ fep->tx_bd_base = cbd_base + RX_RING_SIZE;
+
+ fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
+ fep->cur_rx = fep->rx_bd_base;
+
+ fep->skb_cur = fep->skb_dirty = 0;
+
+ /* Initialize the receive buffer descriptors.
+ */
+ bdp = fep->rx_bd_base;
+ for (i=0; i<FEC_ENET_RX_PAGES; i++) {
+
+ /* Allocate a page.
+ */
+ mem_addr = __get_free_page(GFP_KERNEL);
+
+ /* Make it uncached.
+ */
+ pte = va_to_pte(&init_task, mem_addr);
+ pte_val(*pte) |= _PAGE_NO_CACHE;
+ flush_tlb_page(current->mm->mmap, mem_addr);
+
+ /* Initialize the BD for every fragment in the page.
+ */
+ for (j=0; j<FEC_ENET_RX_FRPPG; j++) {
+ bdp->cbd_sc = BD_ENET_RX_EMPTY;
+ bdp->cbd_bufaddr = __pa(mem_addr);
+ mem_addr += FEC_ENET_RX_FRSIZE;
+ bdp++;
+ }
+ }
+
+ /* Set the last buffer to wrap.
+ */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+
+ /* ...and the same for transmmit.
+ */
+ bdp = fep->tx_bd_base;
+ for (i=0; i<TX_RING_SIZE; i++) {
+
+ /* Initialize the BD for every fragment in the page.
+ */
+ bdp->cbd_sc = 0;
+ bdp->cbd_bufaddr = 0;
+ bdp++;
+ }
+
+ /* Set the last buffer to wrap.
+ */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+
+ /* Enable MII mode, half-duplex until we know better..
+ */
+ fecp->fec_r_cntrl = 0x0c;
+ fecp->fec_x_cntrl = 0x00;
+
+ /* Enable big endian and don't care about SDMA FC.
+ */
+ fecp->fec_fun_code = 0x78000000;
+
+ /* Set MII speed (50 MHz core).
+ */
+ fecp->fec_mii_speed = 0x14;
+
+ /* Configure all of port D for MII.
+ */
+ immap->im_ioport.iop_pdpar = 0x1fff;
+ immap->im_ioport.iop_pddir = 0x1c58;
+
+ /* Install our interrupt handlers. The 860T FADS board uses
+ * IRQ2 for the MII interrupt.
+ */
+ if (request_irq(FEC_INTERRUPT, fec_enet_interrupt, 0, "fec", dev) != 0)
+ panic("Could not allocate FEC IRQ!");
+ if (request_irq(SIU_IRQ2, mii_link_interrupt, 0, "mii", dev) != 0)
+ panic("Could not allocate MII IRQ!");
+
+ dev->base_addr = (unsigned long)fecp;
+ dev->priv = fep;
+ dev->name = "fec";
+
+ /* The FEC Ethernet specific entries in the device structure. */
+ dev->open = fec_enet_open;
+ dev->hard_start_xmit = fec_enet_start_xmit;
+ dev->stop = fec_enet_close;
+ dev->get_stats = fec_enet_get_stats;
+ dev->set_multicast_list = set_multicast_list;
+
+ /* And last, enable the transmit and receive processing.
+ */
+ fecp->fec_ecntrl = 2;
+ fecp->fec_r_des_active = 0x01000000;
+
+ printk("FEC ENET Version 0.1, ");
+ for (i=0; i<5; i++)
+ printk("%02x:", dev->dev_addr[i]);
+ printk("%02x\n", dev->dev_addr[5]);
+
+ for (i=0; i<NMII-1; i++)
+ mii_cmds[i].mii_next = &mii_cmds[i+1];
+ mii_free = mii_cmds;
+
+ mii_startup_cmds();
+
+ return 0;
+}
+
diff --git a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c
index 9d859a46b..fdbd0c796 100644
--- a/arch/ppc/8xx_io/uart.c
+++ b/arch/ppc/8xx_io/uart.c
@@ -37,7 +37,14 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
+#include <asm/8xx_immap.h>
+#ifdef CONFIG_MBX
+#include <asm/mbx.h>
+#endif
+#ifdef CONFIG_FADS
+#include <asm/fads.h>
+#endif
#include "commproc.h"
#ifdef CONFIG_SERIAL_CONSOLE
@@ -53,7 +60,7 @@
#define TX_WAKEUP ASYNC_SHARE_IRQ
static char *serial_name = "CPM UART driver";
-static char *serial_version = "0.01";
+static char *serial_version = "0.02";
static DECLARE_TASK_QUEUE(tq_serial);
@@ -96,10 +103,16 @@ static int serial_console_setup(struct console *co, char *options);
#define smc_scc_num hub6
#define SCC_NUM_BASE 2
+/* The index into the CPM registers for the first SCC in the table.
+*/
+#define SCC_IDX_BASE 1
+
static struct serial_state rs_table[] = {
/* UART CLK PORT IRQ FLAGS NUM */
{ 0, 0, PROFF_SMC1, CPMVEC_SMC1, 0, 0 }, /* SMC1 ttyS0 */
{ 0, 0, PROFF_SMC2, CPMVEC_SMC2, 0, 1 }, /* SMC1 ttyS0 */
+ { 0, 0, PROFF_SCC2, CPMVEC_SCC2, 0, 2 }, /* SCC2 ttyS2 */
+ { 0, 0, PROFF_SCC3, CPMVEC_SCC3, 0, 3 }, /* SCC3 ttyS3 */
};
#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state))
@@ -212,7 +225,7 @@ static void rs_8xx_stop(struct tty_struct *tty)
smcp->smc_smcm &= ~SMCM_TX;
}
else {
- sccp = &cpmp->cp_scc[idx - SCC_NUM_BASE];
+ sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE];
sccp->scc_sccm &= ~UART_SCCM_TX;
}
restore_flags(flags);
@@ -235,7 +248,7 @@ static void rs_8xx_start(struct tty_struct *tty)
smcp->smc_smcm |= SMCM_TX;
}
else {
- sccp = &cpmp->cp_scc[idx - SCC_NUM_BASE];
+ sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE];
sccp->scc_sccm |= UART_SCCM_TX;
}
restore_flags(flags);
@@ -507,26 +520,33 @@ static void rs_8xx_interrupt(void *dev_id)
int idx;
ser_info_t *info;
volatile smc_t *smcp;
+ volatile scc_t *sccp;
info = (ser_info_t *)dev_id;
if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
smcp = &cpmp->cp_smc[idx];
+ events = smcp->smc_smce;
+ if (events & SMCM_RX)
+ receive_chars(info);
+ if (events & SMCM_TX)
+ transmit_chars(info);
+ smcp->smc_smce = events;
}
else {
- panic("SCC UART Interrupt....not ready");
+ sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE];
+ events = sccp->scc_scce;
+ if (events & SCCM_RX)
+ receive_chars(info);
+ if (events & SCCM_TX)
+ transmit_chars(info);
+ sccp->scc_scce = events;
}
- events = smcp->smc_smce;
#ifdef SERIAL_DEBUG_INTR
printk("rs_interrupt_single(%d, %x)...",
info->state->smc_scc_num, events);
#endif
- if (events & SMCM_RX)
- receive_chars(info);
- if (events & SMCM_TX)
- transmit_chars(info);
- smcp->smc_smce = events;
#ifdef modem_control
check_modem_status(info);
#endif
@@ -610,6 +630,7 @@ static int startup(ser_info_t *info)
volatile smc_t *smcp;
volatile scc_t *sccp;
volatile smc_uart_t *up;
+ volatile scc_uart_t *scup;
save_flags(flags); cli();
@@ -662,13 +683,28 @@ static int startup(ser_info_t *info)
* are coming.
*/
up = (smc_uart_t *)&cpmp->cp_dparam[state->port];
+#if 0
up->smc_mrblr = 1; /* receive buffer length */
up->smc_maxidl = 0; /* wait forever for next char */
+#else
+ up->smc_mrblr = RX_BUF_SIZE;
+ up->smc_maxidl = RX_BUF_SIZE;
+#endif
up->smc_brkcr = 1; /* number of break chars */
}
else {
- sccp = &cpmp->cp_scc[idx - SCC_NUM_BASE];
- sccp->scc_sccm |= UART_SCCM_RX;
+ sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE];
+ scup = (scc_uart_t *)&cpmp->cp_dparam[state->port];
+#if 0
+ scup->scc_genscc.scc_mrblr = 1; /* receive buffer length */
+ scup->scc_maxidl = 0; /* wait forever for next char */
+#else
+ scup->scc_genscc.scc_mrblr = RX_BUF_SIZE;
+ scup->scc_maxidl = RX_BUF_SIZE;
+#endif
+
+ sccp->scc_sccm |= (UART_SCCM_TX | UART_SCCM_RX);
+ sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
}
info->flags |= ASYNC_INITIALIZED;
@@ -719,10 +755,10 @@ static void shutdown(ser_info_t * info)
smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
}
else {
- sccp = &cpmp->cp_scc[idx - SCC_NUM_BASE];
- sccp->scc_sccm &= ~UART_SCCM_RX;
+ sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE];
+ sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
+ sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
}
-
if (info->tty)
set_bit(TTY_IO_ERROR, &info->tty->flags);
@@ -738,8 +774,8 @@ static void shutdown(ser_info_t * info)
static void change_speed(ser_info_t *info)
{
int baud_rate;
- unsigned cflag, cval, prev_mode;
- int i, bits, idx;
+ unsigned cflag, cval, scval, prev_mode;
+ int i, bits, sbits, idx;
unsigned long flags;
volatile smc_t *smcp;
volatile scc_t *sccp;
@@ -754,6 +790,7 @@ static void change_speed(ser_info_t *info)
* The value 'bits' counts this for us.
*/
cval = 0;
+ scval = 0;
/* byte size and parity */
switch (cflag & CSIZE) {
@@ -764,16 +801,22 @@ static void change_speed(ser_info_t *info)
/* Never happens, but GCC is too dumb to figure it out */
default: bits = 8; break;
}
+ sbits = bits - 5;
+
if (cflag & CSTOPB) {
cval |= SMCMR_SL; /* Two stops */
+ scval |= SCU_PMSR_SL;
bits++;
}
if (cflag & PARENB) {
cval |= SMCMR_PEN;
+ scval |= SCU_PMSR_PEN;
bits++;
}
- if (!(cflag & PARODD))
+ if (!(cflag & PARODD)) {
cval |= SMCMR_PM_EVEN;
+ scval |= (SCU_PMSR_REVP | SCU_PMSR_TEVP);
+ }
/* Determine divisor based on baud rate */
i = cflag & CBAUD;
@@ -859,11 +902,11 @@ static void change_speed(ser_info_t *info)
smcp->smc_smcmr |= (prev_mode & (SMCMR_REN | SMCMR_TEN));
}
else {
- sccp = &cpmp->cp_scc[idx - SCC_NUM_BASE];
- sccp->scc_sccm &= ~UART_SCCM_RX;
+ sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE];
+ sccp->scc_pmsr = (sbits << 12) | scval;
}
- mbx_cpm_setbrg(info->state->smc_scc_num, baud_rate);
+ m8xx_cpm_setbrg(info->state->smc_scc_num, baud_rate);
restore_flags(flags);
}
@@ -1271,12 +1314,11 @@ static void end_break(ser_info_t *info)
static void send_break(ser_info_t *info, int duration)
{
current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + duration;
#ifdef SERIAL_DEBUG_SEND_BREAK
printk("rs_send_break(%d) jiff=%lu...", duration, jiffies);
#endif
begin_break(info);
- schedule();
+ schedule_timeout(duration);
end_break(info);
#ifdef SERIAL_DEBUG_SEND_BREAK
printk("done jiffies=%lu\n", jiffies);
@@ -1568,8 +1610,9 @@ static void rs_8xx_close(struct tty_struct *tty, struct file * filp)
smcp->smc_smcmr &= ~SMCMR_REN;
}
else {
- sccp = &cpmp->cp_scc[idx - SCC_NUM_BASE];
+ sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE];
sccp->scc_sccm &= ~UART_SCCM_RX;
+ sccp->scc_gsmrl &= ~SCC_GSMRL_ENR;
}
/*
* Before we drop DTR, make sure the UART transmitter
@@ -1589,8 +1632,7 @@ static void rs_8xx_close(struct tty_struct *tty, struct file * filp)
if (info->blocked_open) {
if (info->close_delay) {
current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + info->close_delay;
- schedule();
+ schedule_timeout(info->close_delay);
}
wake_up_interruptible(&info->open_wait);
}
@@ -1647,8 +1689,7 @@ static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout)
#endif
current->state = TASK_INTERRUPTIBLE;
/* current->counter = 0; make us low-priority */
- current->timeout = jiffies + char_time;
- schedule();
+ schedule_timeout(char_time);
if (signal_pending(current))
break;
if (timeout && ((orig_jiffies + timeout) < jiffies))
@@ -2218,12 +2259,15 @@ __initfunc(int rs_8xx_init(void))
struct serial_state * state;
ser_info_t *info;
uint mem_addr, dp_addr;
- int i, j;
+ int i, j, idx;
ushort chan;
volatile cbd_t *bdp;
volatile cpm8xx_t *cp;
volatile smc_t *sp;
volatile smc_uart_t *up;
+ volatile scc_t *scp;
+ volatile scc_uart_t *sup;
+ volatile immap_t *immap;
init_bh(SERIAL_BH, do_serial_bh);
#if 0
@@ -2289,6 +2333,7 @@ __initfunc(int rs_8xx_init(void))
panic("Couldn't register callout driver\n");
cp = cpmp; /* Get pointer to Communication Processor */
+ immap = (immap_t *)IMAP_ADDR; /* and to internal registers */
/* Configure SMCs Tx/Rx instead of port B parallel I/O.
*/
@@ -2296,10 +2341,41 @@ __initfunc(int rs_8xx_init(void))
cp->cp_pbdir &= ~0x00000cc0;
cp->cp_pbodr &= ~0x00000cc0;
+ /* Configure SCC2 and SCC3 instead of port A parallel I/O.
+ */
+#ifndef CONFIG_MBX
+ /* The "standard" configuration through the 860.
+ */
+ immap->im_ioport.iop_papar |= 0x003c;
+ immap->im_ioport.iop_padir &= ~0x003c;
+ immap->im_ioport.iop_paodr &= ~0x003c;
+#else
+ /* On the MBX, SCC3 is through Port D.
+ */
+ immap->im_ioport.iop_papar |= 0x000c; /* SCC2 on port A */
+ immap->im_ioport.iop_padir &= ~0x000c;
+ immap->im_ioport.iop_paodr &= ~0x000c;
+
+ immap->im_ioport.iop_pdpar |= 0x0030; /* SCC3 on port D */
+#endif
+
+ /* Since we don't yet do modem control, connect the port C pins
+ * as general purpose I/O. This will assert CTS and CD for the
+ * SCC ports.
+ */
+ immap->im_ioport.iop_pcdir |= 0x03c6;
+ immap->im_ioport.iop_pcpar &= ~0x03c6;
+
/* Wire BRG1 to SMC1 and BRG2 to SMC2.
*/
cp->cp_simode = 0x10000000;
+ /* Connect SCC2 and SCC3 to NMSI. Connect BRG3 to SCC2 and
+ * BRG4 to SCC3.
+ */
+ cp->cp_sicr &= ~0x00ffff00;
+ cp->cp_sicr |= 0x001b1200;
+
for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
state->magic = SSTATE_MAGIC;
state->line = i;
@@ -2340,28 +2416,21 @@ __initfunc(int rs_8xx_init(void))
info->state = state;
state->info = (struct async_struct *)info;
- /* Right now, assume we are using SMCs.
- */
- sp = &cp->cp_smc[state->smc_scc_num];
-
- up = (smc_uart_t *)&cp->cp_dparam[state->port];
-
/* We need to allocate a transmit and receive buffer
* descriptors from dual port ram, and a character
* buffer area from host mem.
*/
- dp_addr = mbx_cpm_dpalloc(sizeof(cbd_t) * RX_NUM_FIFO);
+ dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * RX_NUM_FIFO);
/* Allocate space for FIFOs in the host memory.
*/
- mem_addr = mbx_cpm_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE);
+ mem_addr = m8xx_cpm_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE);
/* Set the physical address of the host memory
* buffers in the buffer descriptors, and the
* virtual address for us to work with.
*/
bdp = (cbd_t *)&cp->cp_dpmem[dp_addr];
- up->smc_rbase = dp_addr;
info->rx_cur = info->rx_bd_base = (cbd_t *)bdp;
for (j=0; j<(RX_NUM_FIFO-1); j++) {
@@ -2373,18 +2442,28 @@ __initfunc(int rs_8xx_init(void))
bdp->cbd_bufaddr = __pa(mem_addr);
bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
- dp_addr = mbx_cpm_dpalloc(sizeof(cbd_t) * TX_NUM_FIFO);
+ if ((idx = state->smc_scc_num) < SCC_NUM_BASE) {
+ sp = &cp->cp_smc[idx];
+ up = (smc_uart_t *)&cp->cp_dparam[state->port];
+ up->smc_rbase = dp_addr;
+ }
+ else {
+ scp = &cp->cp_scc[idx - SCC_IDX_BASE];
+ sup = (scc_uart_t *)&cp->cp_dparam[state->port];
+ sup->scc_genscc.scc_rbase = dp_addr;
+ }
+
+ dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * TX_NUM_FIFO);
/* Allocate space for FIFOs in the host memory.
*/
- mem_addr = mbx_cpm_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE);
+ mem_addr = m8xx_cpm_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE);
/* Set the physical address of the host memory
* buffers in the buffer descriptors, and the
* virtual address for us to work with.
*/
bdp = (cbd_t *)&cp->cp_dpmem[dp_addr];
- up->smc_tbase = dp_addr;
info->tx_cur = info->tx_bd_base = (cbd_t *)bdp;
for (j=0; j<(TX_NUM_FIFO-1); j++) {
@@ -2396,39 +2475,104 @@ __initfunc(int rs_8xx_init(void))
bdp->cbd_bufaddr = __pa(mem_addr);
bdp->cbd_sc = (BD_SC_WRAP | BD_SC_INTRPT);
- /* Set up the uart parameters in the parameter ram.
- */
- up->smc_rfcr = SMC_EB;
- up->smc_tfcr = SMC_EB;
+ if (idx < SCC_NUM_BASE) {
+ up->smc_tbase = dp_addr;
- /* Set this to 1 for now, so we get single character
- * interrupts. Using idle charater time requires
- * some additional tuning.
- */
- up->smc_mrblr = 1; /* receive buffer length */
- up->smc_maxidl = 0; /* wait forever for next char */
- up->smc_brkcr = 1; /* number of break chars */
+ /* Set up the uart parameters in the
+ * parameter ram.
+ */
+ up->smc_rfcr = SMC_EB;
+ up->smc_tfcr = SMC_EB;
- /* Send the CPM an initialize command.
- */
- if (state->smc_scc_num == 0)
- chan = CPM_CR_CH_SMC1;
- else
- chan = CPM_CR_CH_SMC2;
- cp->cp_cpcr = mk_cr_cmd(chan,
+ /* Set this to 1 for now, so we get single
+ * character interrupts. Using idle charater
+ * time requires some additional tuning.
+ */
+ up->smc_mrblr = 1;
+ up->smc_maxidl = 0;
+ up->smc_brkcr = 1;
+
+ /* Send the CPM an initialize command.
+ */
+ if (state->smc_scc_num == 0)
+ chan = CPM_CR_CH_SMC1;
+ else
+ chan = CPM_CR_CH_SMC2;
+
+ cp->cp_cpcr = mk_cr_cmd(chan,
CPM_CR_INIT_TRX) | CPM_CR_FLG;
- while (cp->cp_cpcr & CPM_CR_FLG);
+ while (cp->cp_cpcr & CPM_CR_FLG);
- /* Set UART mode, 8 bit, no parity, one stop.
- * Enable receive and transmit.
- */
- sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
- /* Disable all interrupts and clear all pending
- * events.
- */
- sp->smc_smcm = 0;
- sp->smc_smce = 0xff;
+ /* Disable all interrupts and clear all pending
+ * events.
+ */
+ sp->smc_smcm = 0;
+ sp->smc_smce = 0xff;
+ }
+ else {
+ sup->scc_genscc.scc_tbase = dp_addr;
+
+ /* Set up the uart parameters in the
+ * parameter ram.
+ */
+ sup->scc_genscc.scc_rfcr = SMC_EB;
+ sup->scc_genscc.scc_tfcr = SMC_EB;
+
+ /* Set this to 1 for now, so we get single
+ * character interrupts. Using idle charater
+ * time requires some additional tuning.
+ */
+ sup->scc_genscc.scc_mrblr = 1;
+ sup->scc_maxidl = 0;
+ sup->scc_brkcr = 1;
+ sup->scc_parec = 0;
+ sup->scc_frmec = 0;
+ sup->scc_nosec = 0;
+ sup->scc_brkec = 0;
+ sup->scc_uaddr1 = 0;
+ sup->scc_uaddr2 = 0;
+ sup->scc_toseq = 0;
+ sup->scc_char1 = 0x8000;
+ sup->scc_char2 = 0x8000;
+ sup->scc_char3 = 0x8000;
+ sup->scc_char4 = 0x8000;
+ sup->scc_char5 = 0x8000;
+ sup->scc_char6 = 0x8000;
+ sup->scc_char7 = 0x8000;
+ sup->scc_char8 = 0x8000;
+ sup->scc_rccm = 0xc0ff;
+
+ /* Send the CPM an initialize command.
+ */
+ if (state->smc_scc_num == 2)
+ chan = CPM_CR_CH_SCC2;
+ else
+ chan = CPM_CR_CH_SCC3;
+
+ cp->cp_cpcr = mk_cr_cmd(chan,
+ CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ scp->scc_gsmrh = 0;
+ scp->scc_gsmrl =
+ (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
+
+ /* Disable all interrupts and clear all pending
+ * events.
+ */
+ scp->scc_sccm = 0;
+ scp->scc_scce = 0xffff;
+ scp->scc_dsr = 0x7e7e;
+ scp->scc_pmsr = 0x3000;
+ }
/* Install interrupt handler.
*/
@@ -2436,7 +2580,7 @@ __initfunc(int rs_8xx_init(void))
/* Set up the baud rate generator.
*/
- mbx_cpm_setbrg(state->smc_scc_num, 9600);
+ m8xx_cpm_setbrg(state->smc_scc_num, 9600);
/* If the port is the console, enable Rx and Tx.
*/
@@ -2479,11 +2623,11 @@ __initfunc(static int serial_console_setup(struct console *co, char *options))
/* Allocate space for two buffer descriptors in the DP ram.
*/
- dp_addr = mbx_cpm_dpalloc(sizeof(cbd_t) * 2);
+ dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * 2);
/* Allocate space for two 2 byte FIFOs in the host memory.
*/
- mem_addr = mbx_cpm_hostalloc(4);
+ mem_addr = m8xx_cpm_hostalloc(4);
/* Set the physical address of the host memory buffers in
* the buffer descriptors.
@@ -2526,7 +2670,7 @@ __initfunc(static int serial_console_setup(struct console *co, char *options))
/* Set up the baud rate generator.
*/
- mbx_cpm_setbrg(ser->smc_scc_num, 9600);
+ m8xx_cpm_setbrg(ser->smc_scc_num, 9600);
/* And finally, enable Rx and Tx.
*/
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index 38c6e01e4..cd98b4513 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -14,11 +14,10 @@
KERNELLOAD =0xc0000000
-# PowerPC (cross) tools
-ifneq ($(shell uname -m),ppc)
-CROSS_COMPILE = ppc-linux-elf-
-else
+ifeq ($(shell uname -m),ppc)
CHECKS = checks
+else
+CROSS_COMPILE = ppc-linux-elf-
endif
ASFLAGS =
diff --git a/arch/ppc/amiga/amiints.c b/arch/ppc/amiga/amiints.c
index a9a6b218d..690173cc9 100644
--- a/arch/ppc/amiga/amiints.c
+++ b/arch/ppc/amiga/amiints.c
@@ -2,4 +2,551 @@
#define amiga_request_irq request_irq
#define amiga_free_irq free_irq
-#include "../../m68k/amiga/amiints.c"
+/*
+ * linux/arch/m68k/amiga/amiints.c -- Amiga Linux interrupt handling code
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ * 11/07/96: rewritten interrupt handling, irq lists are exists now only for
+ * this sources where it makes sense (VERTB/PORTS/EXTER) and you must
+ * be careful that dev_id for this sources is unique since this the
+ * only possibility to distinguish between different handlers for
+ * free_irq. irq lists also have different irq flags:
+ * - IRQ_FLG_FAST: handler is inserted at top of list (after other
+ * fast handlers)
+ * - IRQ_FLG_SLOW: handler is inserted at bottom of list and before
+ * they're executed irq level is set to the previous
+ * one, but handlers don't need to be reentrant, if
+ * reentrance occured, slow handlers will be just
+ * called again.
+ * The whole interrupt handling for CIAs is moved to cia.c
+ * /Roman Zippel
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/traps.h>
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+#include <asm/amipcmcia.h>
+
+#ifdef CONFIG_APUS
+#include <asm/amigappc.h>
+#endif
+
+extern int cia_request_irq(struct ciabase *base,int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id);
+extern void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id);
+extern void cia_init_IRQ(struct ciabase *base);
+extern int cia_get_irq_list(struct ciabase *base, char *buf);
+
+/* irq node variables for amiga interrupt sources */
+static irq_node_t *ami_irq_list[AMI_STD_IRQS];
+
+unsigned short ami_intena_vals[AMI_STD_IRQS] = {
+ IF_VERTB, IF_COPER, IF_AUD0, IF_AUD1, IF_AUD2, IF_AUD3, IF_BLIT,
+ IF_DSKSYN, IF_DSKBLK, IF_RBF, IF_TBE, IF_SOFT, IF_PORTS, IF_EXTER
+};
+static const unsigned char ami_servers[AMI_STD_IRQS] = {
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1
+};
+
+static short ami_ablecount[AMI_IRQS];
+
+static void ami_badint(int irq, void *dev_id, struct pt_regs *fp)
+{
+ num_spurious += 1;
+}
+
+/*
+ * void amiga_init_IRQ(void)
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ * This function should be called during kernel startup to initialize
+ * the amiga IRQ handling routines.
+ */
+
+__initfunc(void amiga_init_IRQ(void))
+{
+ int i;
+
+ /* initialize handlers */
+ for (i = 0; i < AMI_STD_IRQS; i++) {
+ if (ami_servers[i]) {
+ ami_irq_list[i] = NULL;
+ } else {
+ ami_irq_list[i] = new_irq_node();
+ ami_irq_list[i]->handler = ami_badint;
+ ami_irq_list[i]->flags = IRQ_FLG_STD;
+ ami_irq_list[i]->dev_id = NULL;
+ ami_irq_list[i]->devname = NULL;
+ ami_irq_list[i]->next = NULL;
+ }
+ }
+ for (i = 0; i < AMI_IRQS; i++)
+ ami_ablecount[i] = 0;
+
+ /* turn off PCMCIA interrupts */
+ if (AMIGAHW_PRESENT(PCMCIA))
+ pcmcia_disable_irq();
+
+ /* turn off all interrupts... */
+ custom.intena = 0x7fff;
+ custom.intreq = 0x7fff;
+
+#ifdef CONFIG_APUS
+ /* Clear any inter-CPU interupt requests. Circumvents bug in
+ Blizzard IPL emulation HW (or so it appears). */
+ APUS_WRITE(APUS_INT_LVL, INTLVL_SETRESET | INTLVL_MASK);
+
+ /* Init IPL emulation. */
+ APUS_WRITE(APUS_REG_INT, REGINT_INTMASTER | REGINT_ENABLEIPL);
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT);
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_IPLMASK);
+#endif
+ /* ... and enable the master interrupt bit */
+ custom.intena = IF_SETCLR | IF_INTEN;
+
+ cia_init_IRQ(&ciaa_base);
+ cia_init_IRQ(&ciab_base);
+}
+
+static inline void amiga_insert_irq(irq_node_t **list, irq_node_t *node)
+{
+ unsigned long flags;
+ irq_node_t *cur;
+
+ if (!node->dev_id)
+ printk("%s: Warning: dev_id of %s is zero\n",
+ __FUNCTION__, node->devname);
+
+ save_flags(flags);
+ cli();
+
+ cur = *list;
+
+ if (node->flags & IRQ_FLG_FAST) {
+ node->flags &= ~IRQ_FLG_SLOW;
+ while (cur && cur->flags & IRQ_FLG_FAST) {
+ list = &cur->next;
+ cur = cur->next;
+ }
+ } else if (node->flags & IRQ_FLG_SLOW) {
+ while (cur) {
+ list = &cur->next;
+ cur = cur->next;
+ }
+ } else {
+ while (cur && !(cur->flags & IRQ_FLG_SLOW)) {
+ list = &cur->next;
+ cur = cur->next;
+ }
+ }
+
+ node->next = cur;
+ *list = node;
+
+ restore_flags(flags);
+}
+
+static inline void amiga_delete_irq(irq_node_t **list, void *dev_id)
+{
+ unsigned long flags;
+ irq_node_t *node;
+
+ save_flags(flags);
+ cli();
+
+ for (node = *list; node; list = &node->next, node = *list) {
+ if (node->dev_id == dev_id) {
+ *list = node->next;
+ /* Mark it as free. */
+ node->handler = NULL;
+ restore_flags(flags);
+ return;
+ }
+ }
+ restore_flags(flags);
+ printk ("%s: tried to remove invalid irq\n", __FUNCTION__);
+}
+
+/*
+ * amiga_request_irq : add an interrupt service routine for a particular
+ * machine specific interrupt source.
+ * If the addition was successful, it returns 0.
+ */
+
+int amiga_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id)
+{
+ irq_node_t *node;
+
+ if (irq >= AMI_IRQS) {
+ printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__, irq, devname);
+ return -ENXIO;
+ }
+
+ if (irq >= IRQ_AMIGA_AUTO)
+ return sys_request_irq(irq - IRQ_AMIGA_AUTO, handler,
+ flags, devname, dev_id);
+
+ if (irq >= IRQ_AMIGA_CIAB)
+ return cia_request_irq(&ciab_base, irq - IRQ_AMIGA_CIAB,
+ handler, flags, devname, dev_id);
+
+ if (irq >= IRQ_AMIGA_CIAA)
+ return cia_request_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA,
+ handler, flags, devname, dev_id);
+
+ if (ami_servers[irq]) {
+ if (!(node = new_irq_node()))
+ return -ENOMEM;
+ node->handler = handler;
+ node->flags = flags;
+ node->dev_id = dev_id;
+ node->devname = devname;
+ node->next = NULL;
+ amiga_insert_irq(&ami_irq_list[irq], node);
+ } else {
+ if (!(ami_irq_list[irq]->flags & IRQ_FLG_STD)) {
+ if (ami_irq_list[irq]->flags & IRQ_FLG_LOCK) {
+ printk("%s: IRQ %d from %s is not replaceable\n",
+ __FUNCTION__, irq, ami_irq_list[irq]->devname);
+ return -EBUSY;
+ }
+ if (!(flags & IRQ_FLG_REPLACE)) {
+ printk("%s: %s can't replace IRQ %d from %s\n",
+ __FUNCTION__, devname, irq, ami_irq_list[irq]->devname);
+ return -EBUSY;
+ }
+ }
+ ami_irq_list[irq]->handler = handler;
+ ami_irq_list[irq]->flags = flags;
+ ami_irq_list[irq]->dev_id = dev_id;
+ ami_irq_list[irq]->devname = devname;
+ }
+
+ /* enable the interrupt */
+ if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq])
+ custom.intena = IF_SETCLR | ami_intena_vals[irq];
+
+ return 0;
+}
+
+void amiga_free_irq(unsigned int irq, void *dev_id)
+{
+ if (irq >= AMI_IRQS) {
+ printk ("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
+ return;
+ }
+
+ if (irq >= IRQ_AMIGA_AUTO)
+ sys_free_irq(irq - IRQ_AMIGA_AUTO, dev_id);
+
+ if (irq >= IRQ_AMIGA_CIAB) {
+ cia_free_irq(&ciab_base, irq - IRQ_AMIGA_CIAB, dev_id);
+ return;
+ }
+
+ if (irq >= IRQ_AMIGA_CIAA) {
+ cia_free_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA, dev_id);
+ return;
+ }
+
+ if (ami_servers[irq]) {
+ amiga_delete_irq(&ami_irq_list[irq], dev_id);
+ /* if server list empty, disable the interrupt */
+ if (!ami_irq_list[irq] && irq < IRQ_AMIGA_PORTS)
+ custom.intena = ami_intena_vals[irq];
+ } else {
+ if (ami_irq_list[irq]->dev_id != dev_id)
+ printk("%s: removing probably wrong IRQ %d from %s\n",
+ __FUNCTION__, irq, ami_irq_list[irq]->devname);
+ ami_irq_list[irq]->handler = ami_badint;
+ ami_irq_list[irq]->flags = IRQ_FLG_STD;
+ ami_irq_list[irq]->dev_id = NULL;
+ ami_irq_list[irq]->devname = NULL;
+ custom.intena = ami_intena_vals[irq];
+ }
+}
+
+/*
+ * Enable/disable a particular machine specific interrupt source.
+ * Note that this may affect other interrupts in case of a shared interrupt.
+ * This function should only be called for a _very_ short time to change some
+ * internal data, that may not be changed by the interrupt at the same time.
+ * ami_(enable|disable)_irq calls may also be nested.
+ */
+
+void amiga_enable_irq(unsigned int irq)
+{
+ if (irq >= AMI_IRQS) {
+ printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
+ return;
+ }
+
+ if (--ami_ablecount[irq])
+ return;
+
+ /* No action for auto-vector interrupts */
+ if (irq >= IRQ_AMIGA_AUTO){
+ printk("%s: Trying to enable auto-vector IRQ %i\n",
+ __FUNCTION__, irq - IRQ_AMIGA_AUTO);
+ return;
+ }
+
+ if (irq >= IRQ_AMIGA_CIAB) {
+ cia_set_irq(&ciab_base, (1 << (irq - IRQ_AMIGA_CIAB)));
+ cia_able_irq(&ciab_base, CIA_ICR_SETCLR |
+ (1 << (irq - IRQ_AMIGA_CIAB)));
+ return;
+ }
+
+ if (irq >= IRQ_AMIGA_CIAA) {
+ cia_set_irq(&ciaa_base, (1 << (irq - IRQ_AMIGA_CIAA)));
+ cia_able_irq(&ciaa_base, CIA_ICR_SETCLR |
+ (1 << (irq - IRQ_AMIGA_CIAA)));
+ return;
+ }
+
+ /* enable the interrupt */
+ custom.intena = IF_SETCLR | ami_intena_vals[irq];
+}
+
+void amiga_disable_irq(unsigned int irq)
+{
+ if (irq >= AMI_IRQS) {
+ printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
+ return;
+ }
+
+ if (ami_ablecount[irq]++)
+ return;
+
+ /* No action for auto-vector interrupts */
+ if (irq >= IRQ_AMIGA_AUTO) {
+ printk("%s: Trying to disable auto-vector IRQ %i\n",
+ __FUNCTION__, irq - IRQ_AMIGA_AUTO);
+ return;
+ }
+
+ if (irq >= IRQ_AMIGA_CIAB) {
+ cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB));
+ return;
+ }
+
+ if (irq >= IRQ_AMIGA_CIAA) {
+ cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA));
+ return;
+ }
+
+ /* disable the interrupt */
+ custom.intena = ami_intena_vals[irq];
+}
+
+inline void amiga_do_irq(int irq, struct pt_regs *fp)
+{
+ kstat.irqs[0][SYS_IRQS + irq]++;
+ ami_irq_list[irq]->handler(irq, ami_irq_list[irq]->dev_id, fp);
+}
+
+void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server)
+{
+ irq_node_t *node, *slow_nodes;
+ unsigned short flags;
+
+ kstat.irqs[0][SYS_IRQS + irq]++;
+ if (server->count++)
+ server->reentrance = 1;
+ /* serve first fast and normal handlers */
+ for (node = ami_irq_list[irq];
+ node && (!(node->flags & IRQ_FLG_SLOW));
+ node = node->next)
+ node->handler(irq, node->dev_id, fp);
+ custom.intreq = ami_intena_vals[irq];
+ if (!node) {
+ server->count--;
+ return;
+ }
+#ifdef CONFIG_APUS
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_DISABLEINT);
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_IPLMASK);
+ APUS_WRITE(APUS_IPL_EMU, (IPLEMU_SETRESET
+ | (~(fp->mq) & IPLEMU_IPLMASK)));
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT);
+#else
+ save_flags(flags);
+ restore_flags((flags & ~0x0700) | (fp->sr & 0x0700));
+#endif
+ /* if slow handlers exists, serve them now */
+ slow_nodes = node;
+ for (;;) {
+ for (; node; node = node->next)
+ node->handler(irq, node->dev_id, fp);
+ /* if reentrance occured, serve slow handlers again */
+ custom.intena = ami_intena_vals[irq];
+ if (!server->reentrance) {
+ server->count--;
+ custom.intena = IF_SETCLR | ami_intena_vals[irq];
+ return;
+ }
+ server->reentrance = 0;
+ custom.intena = IF_SETCLR | ami_intena_vals[irq];
+ node = slow_nodes;
+ }
+}
+
+/*
+ * The builtin Amiga hardware interrupt handlers.
+ */
+
+static void ami_int1(int irq, void *dev_id, struct pt_regs *fp)
+{
+ unsigned short ints = custom.intreqr & custom.intenar;
+
+ /* if serial transmit buffer empty, interrupt */
+ if (ints & IF_TBE) {
+ custom.intreq = IF_TBE;
+ amiga_do_irq(IRQ_AMIGA_TBE, fp);
+ }
+
+ /* if floppy disk transfer complete, interrupt */
+ if (ints & IF_DSKBLK) {
+ custom.intreq = IF_DSKBLK;
+ amiga_do_irq(IRQ_AMIGA_DSKBLK, fp);
+ }
+
+ /* if software interrupt set, interrupt */
+ if (ints & IF_SOFT) {
+ custom.intreq = IF_SOFT;
+ amiga_do_irq(IRQ_AMIGA_SOFT, fp);
+ }
+}
+
+static void ami_int3(int irq, void *dev_id, struct pt_regs *fp)
+{
+ unsigned short ints = custom.intreqr & custom.intenar;
+ static struct irq_server server = {0, 0};
+
+ /* if a blitter interrupt */
+ if (ints & IF_BLIT) {
+ custom.intreq = IF_BLIT;
+ amiga_do_irq(IRQ_AMIGA_BLIT, fp);
+ }
+
+ /* if a copper interrupt */
+ if (ints & IF_COPER) {
+ custom.intreq = IF_COPER;
+ amiga_do_irq(IRQ_AMIGA_COPPER, fp);
+ }
+
+ /* if a vertical blank interrupt */
+ if (ints & IF_VERTB)
+ amiga_do_irq_list(IRQ_AMIGA_VERTB, fp, &server);
+}
+
+static void ami_int4(int irq, void *dev_id, struct pt_regs *fp)
+{
+ unsigned short ints = custom.intreqr & custom.intenar;
+
+ /* if audio 0 interrupt */
+ if (ints & IF_AUD0) {
+ custom.intreq = IF_AUD0;
+ amiga_do_irq(IRQ_AMIGA_AUD0, fp);
+ }
+
+ /* if audio 1 interrupt */
+ if (ints & IF_AUD1) {
+ custom.intreq = IF_AUD1;
+ amiga_do_irq(IRQ_AMIGA_AUD1, fp);
+ }
+
+ /* if audio 2 interrupt */
+ if (ints & IF_AUD2) {
+ custom.intreq = IF_AUD2;
+ amiga_do_irq(IRQ_AMIGA_AUD2, fp);
+ }
+
+ /* if audio 3 interrupt */
+ if (ints & IF_AUD3) {
+ custom.intreq = IF_AUD3;
+ amiga_do_irq(IRQ_AMIGA_AUD3, fp);
+ }
+}
+
+static void ami_int5(int irq, void *dev_id, struct pt_regs *fp)
+{
+ unsigned short ints = custom.intreqr & custom.intenar;
+
+ /* if serial receive buffer full interrupt */
+ if (ints & IF_RBF) {
+ /* acknowledge of IF_RBF must be done by the serial interrupt */
+ amiga_do_irq(IRQ_AMIGA_RBF, fp);
+ }
+
+ /* if a disk sync interrupt */
+ if (ints & IF_DSKSYN) {
+ custom.intreq = IF_DSKSYN;
+ amiga_do_irq(IRQ_AMIGA_DSKSYN, fp);
+ }
+}
+
+static void ami_int7(int irq, void *dev_id, struct pt_regs *fp)
+{
+ panic ("level 7 interrupt received\n");
+}
+
+void (*amiga_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
+ ami_badint, ami_int1, ami_badint, ami_int3,
+ ami_int4, ami_int5, ami_badint, ami_int7
+};
+
+int amiga_get_irq_list(char *buf)
+{
+ int i, len = 0;
+ irq_node_t *node;
+
+ for (i = 0; i < AMI_STD_IRQS; i++) {
+ if (!(node = ami_irq_list[i]))
+ continue;
+ if (node->flags & IRQ_FLG_STD)
+ continue;
+ len += sprintf(buf+len, "ami %2d: %10u ", i,
+ kstat.irqs[0][SYS_IRQS + i]);
+ do {
+ if (ami_servers[i]) {
+ if (node->flags & IRQ_FLG_FAST)
+ len += sprintf(buf+len, "F ");
+ else if (node->flags & IRQ_FLG_SLOW)
+ len += sprintf(buf+len, "S ");
+ else
+ len += sprintf(buf+len, " ");
+ } else {
+ if (node->flags & IRQ_FLG_LOCK)
+ len += sprintf(buf+len, "L ");
+ else
+ len += sprintf(buf+len, " ");
+ }
+ len += sprintf(buf+len, "%s\n", node->devname);
+ if ((node = node->next))
+ len += sprintf(buf+len, " ");
+ } while (node);
+ }
+
+ len += cia_get_irq_list(&ciaa_base, buf+len);
+ len += cia_get_irq_list(&ciab_base, buf+len);
+ return len;
+}
diff --git a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c
index d24aeb621..f79172390 100644
--- a/arch/ppc/amiga/config.c
+++ b/arch/ppc/amiga/config.c
@@ -2,6 +2,923 @@
#define m68k_num_memory num_memory
#define m68k_memory memory
+#include <linux/init.h>
+
+/* machine dependent "kbd-reset" setup function */
+void (*kbd_reset_setup) (char *, int) __initdata = 0;
+
#include <asm/io.h>
-#include "../../m68k/amiga/config.c"
+/*
+ * linux/arch/m68k/amiga/config.c
+ *
+ * Copyright (C) 1993 Hamish Macdonald
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+/*
+ * Miscellaneous Amiga stuff
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/kd.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/init.h>
+
+#include <asm/bootinfo.h>
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+#include <linux/zorro.h>
+
+unsigned long amiga_model;
+unsigned long amiga_eclock;
+unsigned long amiga_masterclock;
+unsigned long amiga_colorclock;
+unsigned long amiga_chipset;
+unsigned char amiga_vblank;
+unsigned char amiga_psfreq;
+struct amiga_hw_present amiga_hw_present;
+
+static const char *amiga_models[] = {
+ "A500", "A500+", "A600", "A1000", "A1200", "A2000", "A2500", "A3000",
+ "A3000T", "A3000+", "A4000", "A4000T", "CDTV", "CD32", "Draco"
+};
+
+extern char m68k_debug_device[];
+
+static void amiga_sched_init(void (*handler)(int, void *, struct pt_regs *));
+/* amiga specific keyboard functions */
+extern int amiga_keyb_init(void);
+extern int amiga_kbdrate (struct kbd_repeat *);
+extern void amiga_kbd_reset_setup(char*, int);
+/* amiga specific irq functions */
+extern void amiga_init_IRQ (void);
+extern void (*amiga_default_handler[]) (int, void *, struct pt_regs *);
+extern int amiga_request_irq (unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname,
+ void *dev_id);
+extern void amiga_free_irq (unsigned int irq, void *dev_id);
+extern void amiga_enable_irq (unsigned int);
+extern void amiga_disable_irq (unsigned int);
+static void amiga_get_model(char *model);
+static int amiga_get_hardware_list(char *buffer);
+extern int amiga_get_irq_list (char *);
+/* amiga specific timer functions */
+static unsigned long amiga_gettimeoffset (void);
+static void a3000_gettod (int *, int *, int *, int *, int *, int *);
+static void a2000_gettod (int *, int *, int *, int *, int *, int *);
+static int amiga_hwclk (int, struct hwclk_time *);
+static int amiga_set_clock_mmss (unsigned long);
+extern void amiga_mksound( unsigned int count, unsigned int ticks );
+#ifdef CONFIG_AMIGA_FLOPPY
+extern void amiga_floppy_setup(char *, int *);
+#endif
+static void amiga_reset (void);
+static int amiga_wait_key (struct console *co);
+extern void amiga_init_sound(void);
+static void amiga_savekmsg_init(void);
+static void amiga_mem_console_write(struct console *co, const char *b,
+ unsigned int count);
+void amiga_serial_console_write(struct console *co, const char *s,
+ unsigned int count);
+static void amiga_debug_init(void);
+#ifdef CONFIG_HEARTBEAT
+static void amiga_heartbeat(int on);
+#endif
+
+static struct console amiga_console_driver = {
+ "debug",
+ NULL, /* write */
+ NULL, /* read */
+ NULL, /* device */
+ amiga_wait_key, /* wait_key */
+ NULL, /* unblank */
+ NULL, /* setup */
+ CON_PRINTBUFFER,
+ -1,
+ 0,
+ NULL
+};
+
+#ifdef CONFIG_MAGIC_SYSRQ
+static char amiga_sysrq_xlate[128] =
+ "\0001234567890-=\\\000\000" /* 0x00 - 0x0f */
+ "qwertyuiop[]\000123" /* 0x10 - 0x1f */
+ "asdfghjkl;'\000\000456" /* 0x20 - 0x2f */
+ "\000zxcvbnm,./\000+789" /* 0x30 - 0x3f */
+ " \177\t\r\r\000\177\000\000\000-\000\000\000\000\000" /* 0x40 - 0x4f */
+ "\000\201\202\203\204\205\206\207\210\211()/*+\000" /* 0x50 - 0x5f */
+ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" /* 0x60 - 0x6f */
+ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"; /* 0x70 - 0x7f */
+#endif
+
+extern void (*kd_mksound)(unsigned int, unsigned int);
+
+ /*
+ * Parse an Amiga-specific record in the bootinfo
+ */
+
+int amiga_parse_bootinfo(const struct bi_record *record)
+{
+ int unknown = 0;
+ const unsigned long *data = record->data;
+
+ switch (record->tag) {
+ case BI_AMIGA_MODEL:
+ amiga_model = *data;
+ break;
+
+ case BI_AMIGA_ECLOCK:
+ amiga_eclock = *data;
+ break;
+
+ case BI_AMIGA_CHIPSET:
+ amiga_chipset = *data;
+ break;
+
+ case BI_AMIGA_CHIP_SIZE:
+ amiga_chip_size = *(const int *)data;
+ break;
+
+ case BI_AMIGA_VBLANK:
+ amiga_vblank = *(const unsigned char *)data;
+ break;
+
+ case BI_AMIGA_PSFREQ:
+ amiga_psfreq = *(const unsigned char *)data;
+ break;
+
+ case BI_AMIGA_AUTOCON:
+ if (zorro_num_autocon < ZORRO_NUM_AUTO)
+ memcpy(&zorro_autocon[zorro_num_autocon++],
+ (const struct ConfigDev *)data,
+ sizeof(struct ConfigDev));
+ else
+ printk("amiga_parse_bootinfo: too many AutoConfig devices\n");
+ break;
+
+ case BI_AMIGA_SERPER:
+ /* serial port period: ignored here */
+ break;
+
+ default:
+ unknown = 1;
+ }
+ return(unknown);
+}
+
+ /*
+ * Identify builtin hardware
+ */
+
+__initfunc(static void amiga_identify(void))
+{
+ /* Fill in some default values, if necessary */
+ if (amiga_eclock == 0)
+ amiga_eclock = 709379;
+
+ memset(&amiga_hw_present, 0, sizeof(amiga_hw_present));
+
+ printk("Amiga hardware found: ");
+ if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO)
+ printk("[%s] ", amiga_models[amiga_model-AMI_500]);
+
+ switch(amiga_model) {
+ case AMI_UNKNOWN:
+ goto Generic;
+
+ case AMI_600:
+ case AMI_1200:
+ AMIGAHW_SET(A1200_IDE);
+ AMIGAHW_SET(PCMCIA);
+ case AMI_500:
+ case AMI_500PLUS:
+ case AMI_1000:
+ case AMI_2000:
+ case AMI_2500:
+ AMIGAHW_SET(A2000_CLK); /* Is this correct for all models? */
+ goto Generic;
+
+ case AMI_3000:
+ case AMI_3000T:
+ AMIGAHW_SET(AMBER_FF);
+ AMIGAHW_SET(MAGIC_REKICK);
+ /* fall through */
+ case AMI_3000PLUS:
+ AMIGAHW_SET(A3000_SCSI);
+ AMIGAHW_SET(A3000_CLK);
+ AMIGAHW_SET(ZORRO3);
+ goto Generic;
+
+ case AMI_4000T:
+ AMIGAHW_SET(A4000_SCSI);
+ /* fall through */
+ case AMI_4000:
+ AMIGAHW_SET(A4000_IDE);
+ AMIGAHW_SET(A3000_CLK);
+ AMIGAHW_SET(ZORRO3);
+ goto Generic;
+
+ case AMI_CDTV:
+ case AMI_CD32:
+ AMIGAHW_SET(CD_ROM);
+ AMIGAHW_SET(A2000_CLK); /* Is this correct? */
+ goto Generic;
+
+ Generic:
+ AMIGAHW_SET(AMI_VIDEO);
+ AMIGAHW_SET(AMI_BLITTER);
+ AMIGAHW_SET(AMI_AUDIO);
+ AMIGAHW_SET(AMI_FLOPPY);
+ AMIGAHW_SET(AMI_KEYBOARD);
+ AMIGAHW_SET(AMI_MOUSE);
+ AMIGAHW_SET(AMI_SERIAL);
+ AMIGAHW_SET(AMI_PARALLEL);
+ AMIGAHW_SET(CHIP_RAM);
+ AMIGAHW_SET(PAULA);
+
+ switch(amiga_chipset) {
+ case CS_OCS:
+ case CS_ECS:
+ case CS_AGA:
+ switch (custom.deniseid & 0xf) {
+ case 0x0c:
+ AMIGAHW_SET(DENISE_HR);
+ break;
+ case 0x08:
+ AMIGAHW_SET(LISA);
+ break;
+ }
+ break;
+ default:
+ AMIGAHW_SET(DENISE);
+ break;
+ }
+ switch ((custom.vposr>>8) & 0x7f) {
+ case 0x00:
+ AMIGAHW_SET(AGNUS_PAL);
+ break;
+ case 0x10:
+ AMIGAHW_SET(AGNUS_NTSC);
+ break;
+ case 0x20:
+ case 0x21:
+ AMIGAHW_SET(AGNUS_HR_PAL);
+ break;
+ case 0x30:
+ case 0x31:
+ AMIGAHW_SET(AGNUS_HR_NTSC);
+ break;
+ case 0x22:
+ case 0x23:
+ AMIGAHW_SET(ALICE_PAL);
+ break;
+ case 0x32:
+ case 0x33:
+ AMIGAHW_SET(ALICE_NTSC);
+ break;
+ }
+ AMIGAHW_SET(ZORRO);
+ break;
+
+ case AMI_DRACO:
+ panic("No support for Draco yet");
+
+ default:
+ panic("Unknown Amiga Model");
+ }
+
+#define AMIGAHW_ANNOUNCE(name, str) \
+ if (AMIGAHW_PRESENT(name)) \
+ printk(str)
+
+ AMIGAHW_ANNOUNCE(AMI_VIDEO, "VIDEO ");
+ AMIGAHW_ANNOUNCE(AMI_BLITTER, "BLITTER ");
+ AMIGAHW_ANNOUNCE(AMBER_FF, "AMBER_FF ");
+ AMIGAHW_ANNOUNCE(AMI_AUDIO, "AUDIO ");
+ AMIGAHW_ANNOUNCE(AMI_FLOPPY, "FLOPPY ");
+ AMIGAHW_ANNOUNCE(A3000_SCSI, "A3000_SCSI ");
+ AMIGAHW_ANNOUNCE(A4000_SCSI, "A4000_SCSI ");
+ AMIGAHW_ANNOUNCE(A1200_IDE, "A1200_IDE ");
+ AMIGAHW_ANNOUNCE(A4000_IDE, "A4000_IDE ");
+ AMIGAHW_ANNOUNCE(CD_ROM, "CD_ROM ");
+ AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "KEYBOARD ");
+ AMIGAHW_ANNOUNCE(AMI_MOUSE, "MOUSE ");
+ AMIGAHW_ANNOUNCE(AMI_SERIAL, "SERIAL ");
+ AMIGAHW_ANNOUNCE(AMI_PARALLEL, "PARALLEL ");
+ AMIGAHW_ANNOUNCE(A2000_CLK, "A2000_CLK ");
+ AMIGAHW_ANNOUNCE(A3000_CLK, "A3000_CLK ");
+ AMIGAHW_ANNOUNCE(CHIP_RAM, "CHIP_RAM ");
+ AMIGAHW_ANNOUNCE(PAULA, "PAULA ");
+ AMIGAHW_ANNOUNCE(DENISE, "DENISE ");
+ AMIGAHW_ANNOUNCE(DENISE_HR, "DENISE_HR ");
+ AMIGAHW_ANNOUNCE(LISA, "LISA ");
+ AMIGAHW_ANNOUNCE(AGNUS_PAL, "AGNUS_PAL ");
+ AMIGAHW_ANNOUNCE(AGNUS_NTSC, "AGNUS_NTSC ");
+ AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "AGNUS_HR_PAL ");
+ AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "AGNUS_HR_NTSC ");
+ AMIGAHW_ANNOUNCE(ALICE_PAL, "ALICE_PAL ");
+ AMIGAHW_ANNOUNCE(ALICE_NTSC, "ALICE_NTSC ");
+ AMIGAHW_ANNOUNCE(MAGIC_REKICK, "MAGIC_REKICK ");
+ AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA ");
+ if (AMIGAHW_PRESENT(ZORRO))
+ printk("ZORRO%s ", AMIGAHW_PRESENT(ZORRO3) ? "3" : "");
+ printk("\n");
+
+#undef AMIGAHW_ANNOUNCE
+}
+
+ /*
+ * Setup the Amiga configuration info
+ */
+
+__initfunc(void config_amiga(void))
+{
+ amiga_debug_init();
+ amiga_identify();
+
+ mach_sched_init = amiga_sched_init;
+ mach_keyb_init = amiga_keyb_init;
+ mach_kbdrate = amiga_kbdrate;
+ kbd_reset_setup = amiga_kbd_reset_setup;
+ mach_init_IRQ = amiga_init_IRQ;
+ mach_default_handler = &amiga_default_handler;
+#ifndef CONFIG_APUS
+ mach_request_irq = amiga_request_irq;
+ mach_free_irq = amiga_free_irq;
+ enable_irq = amiga_enable_irq;
+ disable_irq = amiga_disable_irq;
+#endif
+ mach_get_model = amiga_get_model;
+ mach_get_hardware_list = amiga_get_hardware_list;
+ mach_get_irq_list = amiga_get_irq_list;
+ mach_gettimeoffset = amiga_gettimeoffset;
+ if (AMIGAHW_PRESENT(A3000_CLK)){
+ mach_gettod = a3000_gettod;
+ }
+ else{ /* if (AMIGAHW_PRESENT(A2000_CLK)) */
+ mach_gettod = a2000_gettod;
+ }
+
+ mach_max_dma_address = 0xffffffff; /*
+ * default MAX_DMA=0xffffffff
+ * on all machines. If we don't
+ * do so, the SCSI code will not
+ * be able to allocate any mem
+ * for transfers, unless we are
+ * dealing with a Z2 mem only
+ * system. /Jes
+ */
+
+ mach_hwclk = amiga_hwclk;
+ mach_set_clock_mmss = amiga_set_clock_mmss;
+#ifdef CONFIG_AMIGA_FLOPPY
+ mach_floppy_setup = amiga_floppy_setup;
+#endif
+ mach_reset = amiga_reset;
+ conswitchp = &dummy_con;
+ kd_mksound = amiga_mksound;
+#ifdef CONFIG_MAGIC_SYSRQ
+ mach_sysrq_key = 0x5f; /* HELP */
+ mach_sysrq_shift_state = 0x03; /* SHIFT+ALTGR */
+ mach_sysrq_shift_mask = 0xff; /* all modifiers except CapsLock */
+ mach_sysrq_xlate = amiga_sysrq_xlate;
+#endif
+#ifdef CONFIG_HEARTBEAT
+ mach_heartbeat = amiga_heartbeat;
+#endif
+
+ /* Fill in the clock values (based on the 700 kHz E-Clock) */
+ amiga_masterclock = 40*amiga_eclock; /* 28 MHz */
+ amiga_colorclock = 5*amiga_eclock; /* 3.5 MHz */
+
+ /* clear all DMA bits */
+ custom.dmacon = DMAF_ALL;
+ /* ensure that the DMA master bit is set */
+ custom.dmacon = DMAF_SETCLR | DMAF_MASTER;
+
+ /* initialize chipram allocator */
+ amiga_chip_init ();
+
+ /* debugging using chipram */
+ if (!strcmp( m68k_debug_device, "mem" )){
+ if (!AMIGAHW_PRESENT(CHIP_RAM))
+ printk("Warning: no chipram present for debugging\n");
+ else {
+ amiga_savekmsg_init();
+ amiga_console_driver.write = amiga_mem_console_write;
+ register_console(&amiga_console_driver);
+ }
+ }
+
+ /* our beloved beeper */
+ if (AMIGAHW_PRESENT(AMI_AUDIO))
+ amiga_init_sound();
+
+ /*
+ * if it is an A3000, set the magic bit that forces
+ * a hard rekick
+ */
+ if (AMIGAHW_PRESENT(MAGIC_REKICK))
+ *(unsigned char *)ZTWO_VADDR(0xde0002) |= 0x80;
+}
+
+static unsigned short jiffy_ticks;
+
+__initfunc(static void amiga_sched_init(void (*timer_routine)(int, void *,
+ struct pt_regs *)))
+{
+ jiffy_ticks = (amiga_eclock+HZ/2)/HZ;
+
+ ciab.cra &= 0xC0; /* turn off timer A, continuous mode, from Eclk */
+ ciab.talo = jiffy_ticks % 256;
+ ciab.tahi = jiffy_ticks / 256;
+
+ /* install interrupt service routine for CIAB Timer A
+ *
+ * Please don't change this to use ciaa, as it interferes with the
+ * SCSI code. We'll have to take a look at this later
+ */
+ request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, IRQ_FLG_LOCK,
+ "timer", NULL);
+ /* start timer */
+ ciab.cra |= 0x11;
+}
+
+#define TICK_SIZE 10000
+
+/* This is always executed with interrupts disabled. */
+static unsigned long amiga_gettimeoffset (void)
+{
+ unsigned short hi, lo, hi2;
+ unsigned long ticks, offset = 0;
+
+ /* read CIA B timer A current value */
+ hi = ciab.tahi;
+ lo = ciab.talo;
+ hi2 = ciab.tahi;
+
+ if (hi != hi2) {
+ lo = ciab.talo;
+ hi = hi2;
+ }
+
+ ticks = hi << 8 | lo;
+
+ if (ticks > jiffy_ticks / 2)
+ /* check for pending interrupt */
+ if (cia_set_irq(&ciab_base, 0) & CIA_ICR_TA)
+ offset = 10000;
+
+ ticks = jiffy_ticks - ticks;
+ ticks = (10000 * ticks) / jiffy_ticks;
+
+ return ticks + offset;
+}
+
+static void a3000_gettod (int *yearp, int *monp, int *dayp,
+ int *hourp, int *minp, int *secp)
+{
+ volatile struct tod3000 *tod = TOD_3000;
+
+ tod->cntrl1 = TOD3000_CNTRL1_HOLD;
+
+ *secp = tod->second1 * 10 + tod->second2;
+ *minp = tod->minute1 * 10 + tod->minute2;
+ *hourp = tod->hour1 * 10 + tod->hour2;
+ *dayp = tod->day1 * 10 + tod->day2;
+ *monp = tod->month1 * 10 + tod->month2;
+ *yearp = tod->year1 * 10 + tod->year2;
+
+ tod->cntrl1 = TOD3000_CNTRL1_FREE;
+}
+
+static void a2000_gettod (int *yearp, int *monp, int *dayp,
+ int *hourp, int *minp, int *secp)
+{
+ volatile struct tod2000 *tod = TOD_2000;
+
+ tod->cntrl1 = TOD2000_CNTRL1_HOLD;
+
+ while (tod->cntrl1 & TOD2000_CNTRL1_BUSY)
+ ;
+
+ *secp = tod->second1 * 10 + tod->second2;
+ *minp = tod->minute1 * 10 + tod->minute2;
+ *hourp = (tod->hour1 & 3) * 10 + tod->hour2;
+ *dayp = tod->day1 * 10 + tod->day2;
+ *monp = tod->month1 * 10 + tod->month2;
+ *yearp = tod->year1 * 10 + tod->year2;
+
+ if (!(tod->cntrl3 & TOD2000_CNTRL3_24HMODE)){
+ if (!(tod->hour1 & TOD2000_HOUR1_PM) && *hourp == 12)
+ *hourp = 0;
+ else if ((tod->hour1 & TOD2000_HOUR1_PM) && *hourp != 12)
+ *hourp += 12;
+ }
+
+ tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD;
+}
+
+static int amiga_hwclk(int op, struct hwclk_time *t)
+{
+ if (AMIGAHW_PRESENT(A3000_CLK)) {
+ volatile struct tod3000 *tod = TOD_3000;
+
+ tod->cntrl1 = TOD3000_CNTRL1_HOLD;
+
+ if (!op) { /* read */
+ t->sec = tod->second1 * 10 + tod->second2;
+ t->min = tod->minute1 * 10 + tod->minute2;
+ t->hour = tod->hour1 * 10 + tod->hour2;
+ t->day = tod->day1 * 10 + tod->day2;
+ t->wday = tod->weekday;
+ t->mon = tod->month1 * 10 + tod->month2 - 1;
+ t->year = tod->year1 * 10 + tod->year2;
+ } else {
+ tod->second1 = t->sec / 10;
+ tod->second2 = t->sec % 10;
+ tod->minute1 = t->min / 10;
+ tod->minute2 = t->min % 10;
+ tod->hour1 = t->hour / 10;
+ tod->hour2 = t->hour % 10;
+ tod->day1 = t->day / 10;
+ tod->day2 = t->day % 10;
+ if (t->wday != -1)
+ tod->weekday = t->wday;
+ tod->month1 = (t->mon + 1) / 10;
+ tod->month2 = (t->mon + 1) % 10;
+ tod->year1 = t->year / 10;
+ tod->year2 = t->year % 10;
+ }
+
+ tod->cntrl1 = TOD3000_CNTRL1_FREE;
+ } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ {
+ volatile struct tod2000 *tod = TOD_2000;
+
+ tod->cntrl1 = TOD2000_CNTRL1_HOLD;
+
+ while (tod->cntrl1 & TOD2000_CNTRL1_BUSY)
+ ;
+
+ if (!op) { /* read */
+ t->sec = tod->second1 * 10 + tod->second2;
+ t->min = tod->minute1 * 10 + tod->minute2;
+ t->hour = (tod->hour1 & 3) * 10 + tod->hour2;
+ t->day = tod->day1 * 10 + tod->day2;
+ t->wday = tod->weekday;
+ t->mon = tod->month1 * 10 + tod->month2 - 1;
+ t->year = tod->year1 * 10 + tod->year2;
+
+ if (!(tod->cntrl3 & TOD2000_CNTRL3_24HMODE)){
+ if (!(tod->hour1 & TOD2000_HOUR1_PM) && t->hour == 12)
+ t->hour = 0;
+ else if ((tod->hour1 & TOD2000_HOUR1_PM) && t->hour != 12)
+ t->hour += 12;
+ }
+ } else {
+ tod->second1 = t->sec / 10;
+ tod->second2 = t->sec % 10;
+ tod->minute1 = t->min / 10;
+ tod->minute2 = t->min % 10;
+ if (tod->cntrl3 & TOD2000_CNTRL3_24HMODE)
+ tod->hour1 = t->hour / 10;
+ else if (t->hour >= 12)
+ tod->hour1 = TOD2000_HOUR1_PM +
+ (t->hour - 12) / 10;
+ else
+ tod->hour1 = t->hour / 10;
+ tod->hour2 = t->hour % 10;
+ tod->day1 = t->day / 10;
+ tod->day2 = t->day % 10;
+ if (t->wday != -1)
+ tod->weekday = t->wday;
+ tod->month1 = (t->mon + 1) / 10;
+ tod->month2 = (t->mon + 1) % 10;
+ tod->year1 = t->year / 10;
+ tod->year2 = t->year % 10;
+ }
+
+ tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD;
+ }
+
+ return 0;
+}
+
+static int amiga_set_clock_mmss (unsigned long nowtime)
+{
+ short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
+
+ if (AMIGAHW_PRESENT(A3000_CLK)) {
+ volatile struct tod3000 *tod = TOD_3000;
+
+ tod->cntrl1 = TOD3000_CNTRL1_HOLD;
+
+ tod->second1 = real_seconds / 10;
+ tod->second2 = real_seconds % 10;
+ tod->minute1 = real_minutes / 10;
+ tod->minute2 = real_minutes % 10;
+
+ tod->cntrl1 = TOD3000_CNTRL1_FREE;
+ } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ {
+ volatile struct tod2000 *tod = TOD_2000;
+
+ tod->cntrl1 = TOD2000_CNTRL1_HOLD;
+
+ while (tod->cntrl1 & TOD2000_CNTRL1_BUSY)
+ ;
+
+ tod->second1 = real_seconds / 10;
+ tod->second2 = real_seconds % 10;
+ tod->minute1 = real_minutes / 10;
+ tod->minute2 = real_minutes % 10;
+
+ tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD;
+ }
+
+ return 0;
+}
+
+static int amiga_wait_key (struct console *co)
+{
+ int i;
+
+ while (1) {
+ while (ciaa.pra & 0x40);
+
+ /* debounce */
+ for (i = 0; i < 1000; i++);
+
+ if (!(ciaa.pra & 0x40))
+ break;
+ }
+
+ /* wait for button up */
+ while (1) {
+ while (!(ciaa.pra & 0x40));
+
+ /* debounce */
+ for (i = 0; i < 1000; i++);
+
+ if (ciaa.pra & 0x40)
+ break;
+ }
+ return 0;
+}
+
+void dbprintf(const char *fmt , ...)
+{
+ static char buf[1024];
+ va_list args;
+ extern void console_print (const char *str);
+ extern int vsprintf(char * buf, const char * fmt, va_list args);
+
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ va_end(args);
+
+ console_print (buf);
+}
+
+static NORET_TYPE void amiga_reset( void )
+ ATTRIB_NORET;
+
+static void amiga_reset (void)
+{
+ for (;;);
+}
+
+
+ /*
+ * Debugging
+ */
+
+#define SAVEKMSG_MAXMEM 128*1024
+
+#define SAVEKMSG_MAGIC1 0x53415645 /* 'SAVE' */
+#define SAVEKMSG_MAGIC2 0x4B4D5347 /* 'KMSG' */
+
+struct savekmsg {
+ unsigned long magic1; /* SAVEKMSG_MAGIC1 */
+ unsigned long magic2; /* SAVEKMSG_MAGIC2 */
+ unsigned long magicptr; /* address of magic1 */
+ unsigned long size;
+ char data[0];
+};
+
+static struct savekmsg *savekmsg = NULL;
+
+static void amiga_mem_console_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ if (savekmsg->size+count <= SAVEKMSG_MAXMEM-sizeof(struct savekmsg)) {
+ memcpy(savekmsg->data+savekmsg->size, s, count);
+ savekmsg->size += count;
+ }
+}
+
+static void amiga_savekmsg_init(void)
+{
+ savekmsg = (struct savekmsg *)amiga_chip_alloc(SAVEKMSG_MAXMEM);
+ savekmsg->magic1 = SAVEKMSG_MAGIC1;
+ savekmsg->magic2 = SAVEKMSG_MAGIC2;
+ savekmsg->magicptr = virt_to_phys(savekmsg);
+ savekmsg->size = 0;
+}
+
+static void amiga_serial_putc(char c)
+{
+ custom.serdat = (unsigned char)c | 0x100;
+ iobarrier ();
+ while (!(custom.serdatr & 0x2000))
+ ;
+}
+
+void amiga_serial_console_write(struct console *co, const char *s,
+ unsigned int count)
+{
+#if 0 /* def CONFIG_KGDB */
+ /* FIXME:APUS GDB doesn't seem to like O-packages before it is
+ properly connected with the target. */
+ __gdb_output_string (s, count);
+#else
+ while (count--) {
+ if (*s == '\n')
+ amiga_serial_putc('\r');
+ amiga_serial_putc(*s++);
+ }
+#endif
+}
+
+#ifdef CONFIG_SERIAL_CONSOLE
+void amiga_serial_puts(const char *s)
+{
+ amiga_serial_console_write(NULL, s, strlen(s));
+}
+
+int amiga_serial_console_wait_key(struct console *co)
+{
+ int ch;
+
+ while (!(custom.intreqr & IF_RBF))
+ barrier();
+ ch = custom.serdatr & 0xff;
+ /* clear the interrupt, so that another character can be read */
+ custom.intreq = IF_RBF;
+ return ch;
+}
+
+void amiga_serial_gets(struct console *co, char *s, int len)
+{
+ int ch, cnt = 0;
+
+ while (1) {
+ ch = amiga_serial_console_wait_key(co);
+
+ /* Check for backspace. */
+ if (ch == 8 || ch == 127) {
+ if (cnt == 0) {
+ amiga_serial_putc('\007');
+ continue;
+ }
+ cnt--;
+ amiga_serial_puts("\010 \010");
+ continue;
+ }
+
+ /* Check for enter. */
+ if (ch == 10 || ch == 13)
+ break;
+
+ /* See if line is too long. */
+ if (cnt >= len + 1) {
+ amiga_serial_putc(7);
+ cnt--;
+ continue;
+ }
+
+ /* Store and echo character. */
+ s[cnt++] = ch;
+ amiga_serial_putc(ch);
+ }
+ /* Print enter. */
+ amiga_serial_puts("\r\n");
+ s[cnt] = 0;
+}
+#endif
+
+__initfunc(static void amiga_debug_init(void))
+{
+ if (!strcmp( m68k_debug_device, "ser" )) {
+ /* no initialization required (?) */
+ amiga_console_driver.write = amiga_serial_console_write;
+ register_console(&amiga_console_driver);
+ }
+}
+
+#ifdef CONFIG_HEARTBEAT
+static void amiga_heartbeat(int on)
+{
+ if (on)
+ ciaa.pra &= ~2;
+ else
+ ciaa.pra |= 2;
+}
+#endif
+
+ /*
+ * Amiga specific parts of /proc
+ */
+
+static void amiga_get_model(char *model)
+{
+ strcpy(model, "Amiga ");
+ if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO)
+ strcat(model, amiga_models[amiga_model-AMI_500]);
+}
+
+
+static int amiga_get_hardware_list(char *buffer)
+{
+ int len = 0;
+
+ if (AMIGAHW_PRESENT(CHIP_RAM))
+ len += sprintf(buffer+len, "Chip RAM:\t%ldK\n", amiga_chip_size>>10);
+ len += sprintf(buffer+len, "PS Freq:\t%dHz\nEClock Freq:\t%ldHz\n",
+ amiga_psfreq, amiga_eclock);
+ if (AMIGAHW_PRESENT(AMI_VIDEO)) {
+ char *type;
+ switch(amiga_chipset) {
+ case CS_OCS:
+ type = "OCS";
+ break;
+ case CS_ECS:
+ type = "ECS";
+ break;
+ case CS_AGA:
+ type = "AGA";
+ break;
+ default:
+ type = "Old or Unknown";
+ break;
+ }
+ len += sprintf(buffer+len, "Graphics:\t%s\n", type);
+ }
+
+#define AMIGAHW_ANNOUNCE(name, str) \
+ if (AMIGAHW_PRESENT(name)) \
+ len += sprintf (buffer+len, "\t%s\n", str)
+
+ len += sprintf (buffer + len, "Detected hardware:\n");
+
+ AMIGAHW_ANNOUNCE(AMI_VIDEO, "Amiga Video");
+ AMIGAHW_ANNOUNCE(AMI_BLITTER, "Blitter");
+ AMIGAHW_ANNOUNCE(AMBER_FF, "Amber Flicker Fixer");
+ AMIGAHW_ANNOUNCE(AMI_AUDIO, "Amiga Audio");
+ AMIGAHW_ANNOUNCE(AMI_FLOPPY, "Floppy Controller");
+ AMIGAHW_ANNOUNCE(A3000_SCSI, "SCSI Controller WD33C93 (A3000 style)");
+ AMIGAHW_ANNOUNCE(A4000_SCSI, "SCSI Controller NCR53C710 (A4000T style)");
+ AMIGAHW_ANNOUNCE(A1200_IDE, "IDE Interface (A1200 style)");
+ AMIGAHW_ANNOUNCE(A4000_IDE, "IDE Interface (A4000 style)");
+ AMIGAHW_ANNOUNCE(CD_ROM, "Internal CD ROM drive");
+ AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "Keyboard");
+ AMIGAHW_ANNOUNCE(AMI_MOUSE, "Mouse Port");
+ AMIGAHW_ANNOUNCE(AMI_SERIAL, "Serial Port");
+ AMIGAHW_ANNOUNCE(AMI_PARALLEL, "Parallel Port");
+ AMIGAHW_ANNOUNCE(A2000_CLK, "Hardware Clock (A2000 style)");
+ AMIGAHW_ANNOUNCE(A3000_CLK, "Hardware Clock (A3000 style)");
+ AMIGAHW_ANNOUNCE(CHIP_RAM, "Chip RAM");
+ AMIGAHW_ANNOUNCE(PAULA, "Paula 8364");
+ AMIGAHW_ANNOUNCE(DENISE, "Denise 8362");
+ AMIGAHW_ANNOUNCE(DENISE_HR, "Denise 8373");
+ AMIGAHW_ANNOUNCE(LISA, "Lisa 8375");
+ AMIGAHW_ANNOUNCE(AGNUS_PAL, "Normal/Fat PAL Agnus 8367/8371");
+ AMIGAHW_ANNOUNCE(AGNUS_NTSC, "Normal/Fat NTSC Agnus 8361/8370");
+ AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "Fat Hires PAL Agnus 8372");
+ AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "Fat Hires NTSC Agnus 8372");
+ AMIGAHW_ANNOUNCE(ALICE_PAL, "PAL Alice 8374");
+ AMIGAHW_ANNOUNCE(ALICE_NTSC, "NTSC Alice 8374");
+ AMIGAHW_ANNOUNCE(MAGIC_REKICK, "Magic Hard Rekick");
+ AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA Slot");
+ if (AMIGAHW_PRESENT(ZORRO))
+ len += sprintf(buffer+len, "\tZorro%s AutoConfig: %d Expansion Device%s\n",
+ AMIGAHW_PRESENT(ZORRO3) ? " III" : "",
+ zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s");
+
+#undef AMIGAHW_ANNOUNCE
+
+ return(len);
+}
diff --git a/arch/ppc/amiga/time.c b/arch/ppc/amiga/time.c
index b14a59b53..65f94d778 100644
--- a/arch/ppc/amiga/time.c
+++ b/arch/ppc/amiga/time.c
@@ -1,3 +1,4 @@
+#include <linux/config.h> /* CONFIG_HEARTBEAT */
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -68,3 +69,24 @@ static inline unsigned long mktime(unsigned int year, unsigned int mon,
}
+void apus_heartbeat (void)
+{
+#ifdef CONFIG_HEARTBEAT
+ static unsigned cnt = 0, period = 0, dist = 0;
+
+ if (cnt == 0 || cnt == dist)
+ mach_heartbeat( 1 );
+ else if (cnt == 7 || cnt == dist+7)
+ mach_heartbeat( 0 );
+
+ if (++cnt > period) {
+ cnt = 0;
+ /* The hyperbolic function below modifies the heartbeat period
+ * length in dependency of the current (5min) load. It goes
+ * through the points f(0)=126, f(1)=86, f(5)=51,
+ * f(inf)->30. */
+ period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
+ dist = period / 4;
+ }
+#endif
+}
diff --git a/arch/ppc/apus_defconfig b/arch/ppc/apus_defconfig
index a5f0d2e3c..1e9499a9c 100644
--- a/arch/ppc/apus_defconfig
+++ b/arch/ppc/apus_defconfig
@@ -8,11 +8,11 @@
CONFIG_PPC=y
CONFIG_6xx=y
# CONFIG_8xx is not set
-# CONFIG_PMAC is not set
+CONFIG_PMAC=y
# CONFIG_PREP is not set
# CONFIG_CHRP is not set
# CONFIG_ALL_PPC is not set
-CONFIG_APUS=y
+# CONFIG_APUS is not set
# CONFIG_MBX is not set
CONFIG_MACH_SPECIFIC=y
@@ -20,42 +20,33 @@ CONFIG_MACH_SPECIFIC=y
# General setup
#
CONFIG_EXPERIMENTAL=y
-# CONFIG_MODULES is not set
-# CONFIG_PCI is not set
-# CONFIG_PCI_OLD_PROC is not set
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+CONFIG_PCI=y
+# CONFIG_PCI_QUIRKS is not set
+CONFIG_PCI_OLD_PROC=y
CONFIG_NET=y
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_BINFMT_ELF=y
CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
+CONFIG_BINFMT_MISC=m
# CONFIG_BINFMT_JAVA is not set
# CONFIG_PARPORT is not set
-CONFIG_ABSTRACT_CONSOLE=y
-CONFIG_FB=y
# CONFIG_VGA_CONSOLE is not set
-# CONFIG_FB_COMPAT_XPMAC is not set
-# CONFIG_MAC_KEYBOARD is not set
-# CONFIG_MAC_FLOPPY is not set
-# CONFIG_MACMOUSE is not set
-# CONFIG_PROC_DEVICETREE is not set
+CONFIG_FB=y
+CONFIG_FB_COMPAT_XPMAC=y
+CONFIG_PMAC_PBOOK=y
+CONFIG_MAC_KEYBOARD=y
+CONFIG_MAC_FLOPPY=y
+CONFIG_MAC_SERIAL=y
+CONFIG_ADBMOUSE=y
+CONFIG_PROC_DEVICETREE=y
# CONFIG_KGDB is not set
# CONFIG_XMON is not set
-CONFIG_FB_CONSOLE=y
-CONFIG_AMIGA=y
-CONFIG_ZORRO=y
-CONFIG_AMIGAMOUSE=y
-CONFIG_ABSTRACT_CONSOLE=y
-CONFIG_FB=y
-CONFIG_AMIGA_FLOPPY=y
-CONFIG_AMIGA_BUILTIN_SERIAL=y
-CONFIG_GVPIOEXT=y
-# CONFIG_GVPIOEXT_LP is not set
-# CONFIG_GVPIOEXT_PLIP is not set
-CONFIG_MULTIFACE_III_TTY=y
-# CONFIG_SERIAL_CONSOLE is not set
-# CONFIG_PROC_HARDWARE is not set
+# CONFIG_TOTALMP is not set
#
# Plug and Play support
@@ -63,7 +54,7 @@ CONFIG_MULTIFACE_III_TTY=y
# CONFIG_PNP is not set
#
-# Floppy, IDE, and other block devices
+# Block devices
#
# CONFIG_BLK_DEV_FD is not set
CONFIG_BLK_DEV_IDE=y
@@ -71,20 +62,27 @@ CONFIG_BLK_DEV_IDE=y
#
# Please see Documentation/ide.txt for help/info on IDE drives
#
-CONFIG_BLK_DEV_GAYLE=y
# CONFIG_BLK_DEV_HD_IDE is not set
CONFIG_BLK_DEV_IDEDISK=y
CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDE_PMAC=y
+CONFIG_BLK_DEV_IDEDMA_PMAC=y
+CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_PMAC_IDEDMA_AUTO=y
# CONFIG_IDE_CHIPSETS is not set
#
# Additional Block Devices
#
# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_MD is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_INITRD=y
@@ -96,30 +94,30 @@ CONFIG_PARIDE_PARPORT=y
#
# Networking options
#
-# CONFIG_PACKET is not set
-# CONFIG_NETLINK is not set
+CONFIG_PACKET=y
+CONFIG_NETLINK=y
+# CONFIG_RTNETLINK is not set
+# CONFIG_NETLINK_DEV is not set
# CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
+CONFIG_NET_ALIAS=y
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_IP_ACCT is not set
+# CONFIG_IP_PNP is not set
# CONFIG_IP_ROUTER is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
+# CONFIG_IP_MROUTE is not set
+CONFIG_IP_ALIAS=y
# CONFIG_SYN_COOKIES is not set
#
# (it is safe to leave these untouched)
#
CONFIG_INET_RARP=y
-# CONFIG_IP_NOSR is not set
+CONFIG_IP_NOSR=y
CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
@@ -127,7 +125,7 @@ CONFIG_SKB_LARGE=y
#
#
# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
+CONFIG_ATALK=m
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_BRIDGE is not set
@@ -138,7 +136,6 @@ CONFIG_SKB_LARGE=y
# CONFIG_NET_HW_FLOWCONTROL is not set
# CONFIG_CPU_IS_SLOW is not set
# CONFIG_NET_SCHED is not set
-# CONFIG_NET_PROFILE is not set
#
# SCSI support
@@ -149,7 +146,7 @@ CONFIG_SCSI=y
# SCSI support type (disk, tape, CD-ROM)
#
CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
+CONFIG_CHR_DEV_ST=y
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
# CONFIG_CHR_DEV_SG is not set
@@ -158,7 +155,7 @@ CONFIG_BLK_DEV_SR_VENDOR=y
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_CONSTANTS is not set
+CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
#
@@ -168,7 +165,10 @@ CONFIG_BLK_DEV_SR_VENDOR=y
# CONFIG_SCSI_AHA152X is not set
# CONFIG_SCSI_AHA1542 is not set
# CONFIG_SCSI_AHA1740 is not set
-# CONFIG_SCSI_AIC7XXX is not set
+CONFIG_SCSI_AIC7XXX=y
+# CONFIG_OVERRIDE_CMDS is not set
+CONFIG_AIC7XXX_PROC_STATS=y
+CONFIG_AIC7XXX_RESET_DELAY=15
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
# CONFIG_SCSI_AM53C974 is not set
@@ -181,24 +181,23 @@ CONFIG_BLK_DEV_SR_VENDOR=y
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_GENERIC_NCR5380 is not set
# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_NCR53C7xx is not set
+# CONFIG_SCSI_NCR53C8XX is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_PCI2000 is not set
# CONFIG_SCSI_PCI2220I is not set
# CONFIG_SCSI_PSI240I is not set
# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_SEAGATE is not set
+# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_T128 is not set
# CONFIG_SCSI_U14_34F is not set
# CONFIG_SCSI_ULTRASTOR is not set
# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_MESH is not set
-CONFIG_A3000_SCSI=y
-CONFIG_A2091_SCSI=y
-CONFIG_GVP11_SCSI=y
-CONFIG_FASTLANE_SCSI=y
-# CONFIG_A4000T_SCSI is not set
-# CONFIG_A4091_SCSI is not set
-# CONFIG_SCSI_MAC53C94 is not set
+CONFIG_SCSI_MESH=y
+CONFIG_SCSI_MESH_SYNC_RATE=5
+CONFIG_SCSI_MAC53C94=y
#
# Network device support
@@ -207,31 +206,51 @@ CONFIG_NETDEVICES=y
# CONFIG_ARCNET is not set
# CONFIG_DUMMY is not set
# CONFIG_EQUALIZER is not set
+# CONFIG_ETHERTAP is not set
CONFIG_NET_ETHERNET=y
-CONFIG_ARIADNE=y
-CONFIG_A2065=y
-CONFIG_HYDRA=y
+CONFIG_MACE=y
+CONFIG_BMAC=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_RTL8139 is not set
+# CONFIG_YELLOWFIN is not set
# CONFIG_NET_ISA is not set
-# CONFIG_NET_EISA is not set
+CONFIG_NET_EISA=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+CONFIG_DE4X5=y
+CONFIG_DEC_ELCP=m
+# CONFIG_DGRS is not set
+# CONFIG_EEXPRESS_PRO100 is not set
+# CONFIG_LNE390 is not set
+# CONFIG_NE3210 is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_ES3210 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_ZNET is not set
# CONFIG_NET_POCKET is not set
# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
# CONFIG_DLCI is not set
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+# CONFIG_IPDDP is not set
CONFIG_PPP=y
#
# CCP compressors for PPP are only built as modules.
#
-CONFIG_SLIP=y
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-# CONFIG_SLIP_MODE_SLIP6 is not set
+# CONFIG_SLIP is not set
# CONFIG_NET_RADIO is not set
# CONFIG_TR is not set
# CONFIG_SHAPER is not set
+# CONFIG_HOSTESS_SV11 is not set
#
# Amateur Radio support
@@ -249,21 +268,71 @@ CONFIG_SLIP_SMART=y
# CONFIG_CD_NO_IDESCSI is not set
#
+# Console drivers
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FB_OF=y
+CONFIG_FB_CONTROL=y
+CONFIG_FB_PLATINUM=y
+CONFIG_FB_VALKYRIE=y
+CONFIG_FB_ATY=y
+CONFIG_FB_IMSTT=y
+CONFIG_FB_CT65550=y
+# CONFIG_FB_S3TRIO is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+CONFIG_FBCON_CFB32=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+CONFIG_FONT_SUN8x16=y
+CONFIG_FONT_SUN12x22=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=m
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+# CONFIG_MOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_VIDEO_DEV is not set
+CONFIG_NVRAM=y
+# CONFIG_JOYSTICK is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+
+#
# Filesystems
#
# CONFIG_QUOTA is not set
-CONFIG_MINIX_FS=y
+# CONFIG_MINIX_FS is not set
CONFIG_EXT2_FS=y
CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
# CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=y
+CONFIG_VFAT_FS=m
CONFIG_PROC_FS=y
CONFIG_NFS_FS=y
-# CONFIG_ROOT_NFS is not set
-# CONFIG_NFSD is not set
+CONFIG_NFSD=y
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
# CONFIG_CODA_FS is not set
@@ -271,27 +340,24 @@ CONFIG_LOCKD=y
# CONFIG_HPFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_SYSV_FS is not set
-CONFIG_AFFS_FS=y
-# CONFIG_HFS_FS is not set
+# CONFIG_AFFS_FS is not set
+CONFIG_HFS_FS=y
# CONFIG_ROMFS_FS is not set
-# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS_FS=y
# CONFIG_UFS_FS is not set
-
-#
-# Partition Tables
-#
-CONFIG_AMIGA_PARTITION=y
-# CONFIG_FOREIGN_PARTITIONS is not set
# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_SMD_DISKLABEL is not set
# CONFIG_SOLARIS_X86_PARTITION is not set
+CONFIG_DEVPTS_FS=y
# CONFIG_ADFS_FS is not set
-# CONFIG_DEVPTS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_MAC_PARTITION=y
CONFIG_NLS=y
#
# Native Language Support
#
-# CONFIG_NLS_CODEPAGE_437 is not set
+CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
# CONFIG_NLS_CODEPAGE_850 is not set
@@ -319,55 +385,13 @@ CONFIG_NLS=y
# CONFIG_NLS_KOI8_R is not set
#
-# Frame buffer devices
-#
-CONFIG_FB_AMIGA=y
-CONFIG_FB_AMIGA_OCS=y
-CONFIG_FB_AMIGA_ECS=y
-CONFIG_FB_AMIGA_AGA=y
-CONFIG_FB_CYBER=y
-CONFIG_FB_VIRGE=y
-CONFIG_FB_RETINAZ3=y
-# CONFIG_FB_OF is not set
-# CONFIG_FB_S3TRIO is not set
-CONFIG_FB_VIRTUAL=y
-# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_MFB=y
-CONFIG_FBCON_ILBM=y
-CONFIG_FBCON_AFB=y
-CONFIG_FBCON_MAC=y
-CONFIG_FBCON_CFB2=y
-CONFIG_FBCON_CFB4=y
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_CFB24=y
-CONFIG_FBCON_CFB32=y
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_MOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-# CONFIG_APM is not set
-# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_NVRAM is not set
-# CONFIG_JOYSTICK is not set
-# CONFIG_MISC_RADIO is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-
-#
# Sound
#
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+CONFIG_DMASOUND=y
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_OSS is not set
diff --git a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile
index f0843e17c..fde1ad4c6 100644
--- a/arch/ppc/boot/Makefile
+++ b/arch/ppc/boot/Makefile
@@ -20,20 +20,25 @@
.S.o:
$(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $<
-
ZOFF = 0
ZSZ = 0
IOFF = 0
ISZ = 0
+
+ifeq ($(CONFIG_ALL_PPC),y)
+# yes, we want to build prep stuff
+CONFIG_PREP = y
+endif
+
ifeq ($(CONFIG_MBX),y)
ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00100000
else
-#ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00800000
ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00600000
endif
+
GZIP_FLAGS = -v9
-OBJECTS := head.o misc.o ../coffboot/zlib.o # inflate.o unzip.o
+OBJECTS := head.o misc.o ../coffboot/zlib.o
CFLAGS = -O2 -DSTDC_HEADERS -fno-builtin -I$(TOPDIR)/include
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJCOPY_ARGS = -O elf32-powerpc
@@ -47,10 +52,6 @@ endif
all: zImage
-ifeq ($(CONFIG_ALL_PPC),y)
-CONFIG_PREP = y
-endif
-
ifeq ($(CONFIG_PREP),y)
zvmlinux.initrd: zvmlinux
$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
@@ -58,10 +59,10 @@ zvmlinux.initrd: zvmlinux
--add-section=initrd=ramdisk.image.gz \
--add-section=image=../coffboot/vmlinux.gz \
zvmlinux.initrd.tmp zvmlinux.initrd
- $(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset zvmlinux.initrd initrd` \
- -DINITRD_SIZE=`sh size zvmlinux.initrd initrd` \
- -DZIMAGE_OFFSET=`sh offset zvmlinux.initrd image` \
- -DZIMAGE_SIZE=`sh size zvmlinux.initrd image` \
+ $(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd initrd` \
+ -DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd initrd` \
+ -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd image` \
+ -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd image` \
-DKERNELBASE=$(KERNELBASE) -c -o misc.o misc.c
$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
@@ -77,10 +78,10 @@ zvmlinux.initrd: zvmlinux
--add-section=initrd=ramdisk.image.gz \
--add-section=image=../coffboot/vmlinux.gz \
zvmlinux.initrd.tmp zvmlinux.initrd
- $(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset zvmlinux.initrd initrd` \
- -DINITRD_SIZE=`sh size zvmlinux.initrd initrd` \
- -DZIMAGE_OFFSET=`sh offset zvmlinux.initrd image` \
- -DZIMAGE_SIZE=`sh size zvmlinux.initrd image` \
+ $(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd initrd` \
+ -DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd initrd` \
+ -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd image` \
+ -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd image` \
-DKERNELBASE=$(KERNELBASE) -c -o misc.o misc.c
$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
@@ -90,19 +91,24 @@ zvmlinux.initrd: zvmlinux
rm zvmlinux.initrd.tmp
endif
-zImage: zvmlinux mkprep
ifeq ($(CONFIG_PREP),y)
+zImage: zvmlinux mkprep
./mkprep -pbp zvmlinux zImage
-endif
+else
ifeq ($(CONFIG_MBX),y)
+zImage: zvmlinux
ln -sf zvmlinux zImage
+else
+zImage:
+endif
endif
-zImage.initrd: zvmlinux.initrd mkprep
ifeq ($(CONFIG_PREP),y)
+zImage.initrd: zvmlinux.initrd mkprep
./mkprep -pbp zvmlinux.initrd zImage.initrd
endif
ifeq ($(CONFIG_MBX),y)
+zImage.initrd: zvmlinux.initrd
ln -sf zvmlinux.initrd zImage.initrd
endif
@@ -118,8 +124,8 @@ zvmlinux: $(OBJECTS) ../coffboot/vmlinux.gz
# then with the offset rebuild the bootloader so we know where the kernel is
#
$(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \
- -DZIMAGE_OFFSET=`sh offset zvmlinux image` \
- -DZIMAGE_SIZE=`sh size zvmlinux image` -DKERNELBASE=$(KERNELBASE) \
+ -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux image` \
+ -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux image` -DKERNELBASE=$(KERNELBASE) \
-c -o misc.o misc.c
$(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS)
$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \
@@ -131,17 +137,21 @@ ifeq ($(CONFIG_PREP),y)
dd if=zImage of=/dev/fd0H1440 bs=64b
endif
-mkprep : mkprep.c
ifeq ($(CONFIG_PREP),y)
+mkprep : mkprep.c
$(HOSTCC) -DKERNELBASE=$(KERNELBASE) -o mkprep mkprep.c
endif
-znetboot : zImage
ifeq ($(CONFIG_PREP),y)
+znetboot : zImage
cp zImage /tftpboot/zImage.prep
-endif
+else
ifeq ($(CONFIG_MBX),y)
+znetboot : zImage
cp zImage /tftpboot/zImage.mbx
+else
+znetboot :
+endif
endif
znetboot.initrd : zImage.initrd
diff --git a/arch/ppc/boot/head.S b/arch/ppc/boot/head.S
index fe03a46f7..43facf7e2 100644
--- a/arch/ppc/boot/head.S
+++ b/arch/ppc/boot/head.S
@@ -7,7 +7,7 @@
.text
/*
- * $Id: head.S,v 1.24 1998/07/21 02:43:50 cort Exp $
+ * $Id: head.S,v 1.26 1998/09/19 01:21:20 cort Exp $
*
* This code is loaded by the ROM loader at some arbitrary location.
* Move it to high memory so that it can load the kernel at 0x0000.
@@ -144,6 +144,11 @@ start_ldr:
mr r3, r11
mr r21, r11
bl serial_init /* Init MBX serial port */
+
+ lis r8, 0xfa200000@h /* Disable Ethernet SCC */
+ li r0, 0
+ stw r0, 0x0a00(r8)
+
mr r11, r21
lis r8,start@h
ori r8,r8,start@l
@@ -166,6 +171,7 @@ start_ldr:
as ptr to residual -- Cort*/
lis r6,cmd_line@h
ori r6,r6,cmd_line@l
+ lwz r6, 0(r6)
subi r7,r6,1
00: lbzu r2,1(r7)
cmpi 0,r2,0
diff --git a/arch/ppc/boot/mbxtty.c b/arch/ppc/boot/mbxtty.c
index 3d4105034..e5566dc32 100644
--- a/arch/ppc/boot/mbxtty.c
+++ b/arch/ppc/boot/mbxtty.c
@@ -12,14 +12,22 @@
* I f**ked around for a day trying to figure out how to make EPPC-Bug
* use SMC1, but gave up and decided to fix it here.
*/
+#include <linux/config.h>
#include <linux/types.h>
+#ifdef CONFIG_MBX
#include <asm/mbx.h>
+#endif
+#ifdef CONFIG_FADS
+#include <asm/fads.h>
+#endif
#include "../8xx_io/commproc.h"
+#ifdef CONFIG_MBX
#define MBX_CSR1 ((volatile u_char *)0xfa100000)
#define CSR1_COMEN (u_char)0x02
+#endif
-static cpm8xx_t *cpmp = (cpm8xx_t *)&(((immap_t *)MBX_IMAP_ADDR)->im_cpm);
+static cpm8xx_t *cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
void
serial_init(bd_t *bd)
@@ -38,6 +46,7 @@ serial_init(bd_t *bd)
*/
sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+#ifdef CONFIG_MBX
if (*MBX_CSR1 & CSR1_COMEN) {
/* COM1 is enabled. Initialize SMC1 and use it for
* the console port.
@@ -45,7 +54,7 @@ serial_init(bd_t *bd)
/* Enable SDMA.
*/
- ((immap_t *)MBX_IMAP_ADDR)->im_siu_conf.sc_sdcr = 1;
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1;
/* Use Port B for SMCs instead of other functions.
*/
@@ -103,6 +112,7 @@ serial_init(bd_t *bd)
*MBX_CSR1 &= ~CSR1_COMEN;
}
else {
+#endif
/* SMC1 is used as console port.
*/
tbdf = (cbd_t *)&cp->cp_dpmem[up->smc_tbase];
@@ -113,7 +123,9 @@ serial_init(bd_t *bd)
cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC1,
CPM_CR_STOP_TX) | CPM_CR_FLG;
while (cp->cp_cpcr & CPM_CR_FLG);
+#ifdef CONFIG_MBX
}
+#endif
/* Make the first buffer the only buffer.
*/
diff --git a/arch/ppc/boot/misc.c b/arch/ppc/boot/misc.c
index 869fb9f1d..42cb533da 100644
--- a/arch/ppc/boot/misc.c
+++ b/arch/ppc/boot/misc.c
@@ -1,7 +1,7 @@
/*
* misc.c
*
- * $Id: misc.c,v 1.49 1998/07/26 21:29:15 geert Exp $
+ * $Id: misc.c,v 1.52 1998/09/19 01:21:24 cort Exp $
*
* Adapted for PowerPC by Gary Thomas
*
@@ -9,6 +9,7 @@
* One day to be replaced by a single bootloader for chrp/prep/pmac. -- Cort
*/
+#include <linux/types.h>
#include "../coffboot/zlib.h"
#include "asm/residual.h"
#include <elf.h>
@@ -18,7 +19,9 @@
#include <asm/mmu.h>
#ifdef CONFIG_MBX
#include <asm/mbx.h>
-bd_t hold_board_info;
+#endif
+#ifdef CONFIG_FADS
+#include <asm/fads.h>
#endif
/*
@@ -31,8 +34,30 @@ bd_t hold_board_info;
char *avail_ram;
char *end_avail;
-char cmd_line[256];
-RESIDUAL hold_residual;
+/* Because of the limited amount of memory on the MBX, it presents
+ * loading problems. The biggest is that we load this boot program
+ * into a relatively low memory address, and the Linux kernel Bss often
+ * extends into this space when it get loaded. When the kernel starts
+ * and zeros the BSS space, it also writes over the information we
+ * save here and pass to the kernel (command line and board info).
+ * On the MBX we grab some known memory holes to hold this information.
+ */
+char cmd_buf[256];
+char *cmd_line = cmd_buf;
+
+#if defined(CONFIG_MBX) || defined(CONFIG_FADS)
+char *root_string = "root=/dev/nfs";
+char *nfsaddrs_string = "nfsaddrs=";
+char *nfsroot_string = "nfsroot=";
+char *defroot_string = "/sys/mbxroot";
+int do_ipaddrs(char **cmd_cp, int echo);
+void do_nfsroot(char **cmd_cp, char *dp);
+int strncmp(const char * cs,const char * ct,size_t count);
+char *strrchr(const char * s, int c);
+#endif
+
+RESIDUAL hold_resid_buf;
+RESIDUAL *hold_residual = &hold_resid_buf;
unsigned long initrd_start = 0, initrd_end = 0;
char *zimage_start;
int zimage_size;
@@ -60,7 +85,7 @@ void exit()
while(1);
}
-#ifndef CONFIG_MBX
+#if !defined(CONFIG_MBX) && !defined(CONFIG_FADS)
static void clear_screen()
{
int i, j;
@@ -311,6 +336,9 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
unsigned long i;
BATU *u;
BATL *l;
+#if defined(CONFIG_MBX) || defined(CONFIG_KB)
+ char *dp;
+#endif
lines = 25;
cols = 80;
@@ -318,7 +346,7 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
orig_y = 24;
-#ifndef CONFIG_MBX
+#if !defined(CONFIG_MBX) && !defined(CONFIG_FADS)
/*
* IBM's have the MMU on, so we have to disable it or
* things get really unhappy in the kernel when
@@ -331,18 +359,30 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
vga_init(0xC0000000);
if (residual)
- memcpy(&hold_residual,residual,sizeof(RESIDUAL));
+ memcpy(hold_residual,residual,sizeof(RESIDUAL));
#else /* CONFIG_MBX */
+
+ /* Grab some space for the command line and board info. Since
+ * we no longer use the ELF header, but it was loaded, grab
+ * that space.
+ */
+ cmd_line = (char *)(load_addr - 0x10000);
+ hold_residual = (RESIDUAL *)(cmd_line + sizeof(cmd_buf));
/* copy board data */
if (residual)
- _bcopy((char *)residual, (char *)&hold_board_info,
- sizeof(hold_board_info));
+ memcpy(hold_residual,residual,sizeof(bd_t));
#endif /* CONFIG_MBX */
/* MBX/prep sometimes put the residual/board info at the end of mem
* assume 16M for now -- Cort
+ * To boot on standard MBX boards with 4M, we can't use initrd,
+ * and we have to assume less memory. -- Dan
*/
- end_avail = (char *)0x01000000;
+ if ( INITRD_OFFSET )
+ end_avail = (char *)0x01000000;
+ else
+ end_avail = (char *)0x00400000;
+
/* let residual data tell us it's higher */
if ( (unsigned long)residual > 0x00800000 )
end_avail = (char *)PAGE_ALIGN((unsigned long)residual);
@@ -361,23 +401,19 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
{
puts("board data at: "); puthex((unsigned long)residual);
puts(" ");
-#ifdef CONFIG_MBX
+#if defined(CONFIG_MBX) || defined(CONFIG_FADS)
puthex((unsigned long)((unsigned long)residual + sizeof(bd_t)));
#else
puthex((unsigned long)((unsigned long)residual + sizeof(RESIDUAL)));
#endif
puts("\n");
puts("relocated to: ");
-#ifdef CONFIG_MBX
- puthex((unsigned long)&hold_board_info);
-#else
- puthex((unsigned long)&hold_residual);
-#endif
+ puthex((unsigned long)hold_residual);
puts(" ");
-#ifdef CONFIG_MBX
- puthex((unsigned long)((unsigned long)&hold_board_info + sizeof(bd_t)));
+#if defined(CONFIG_MBX) || defined(CONFIG_FADS)
+ puthex((unsigned long)((unsigned long)hold_residual + sizeof(bd_t)));
#else
- puthex((unsigned long)((unsigned long)&hold_residual + sizeof(RESIDUAL)));
+ puthex((unsigned long)((unsigned long)hold_residual + sizeof(RESIDUAL)));
#endif
puts("\n");
}
@@ -411,8 +447,11 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
/*
* don't relocate the zimage if it was loaded above 16M since
* things get weird if we try to relocate -- Cort
+ * We don't relocate zimage on a base MBX board because of
+ * insufficient memory. In this case we don't have initrd either,
+ * so use that as an indicator. -- Dan
*/
- if ( (unsigned long)zimage_start <= 0x01000000 )
+ if (( (unsigned long)zimage_start <= 0x01000000 ) && initrd_start)
{
memcpy ((void *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-zimage_size),
(void *)zimage_start, zimage_size );
@@ -439,6 +478,7 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
* max ram is.
* -- Cort
*/
+#if 0
memcpy ((void *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-INITRD_SIZE),
(void *)initrd_start,
INITRD_SIZE );
@@ -447,20 +487,26 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
end_avail = (char *)initrd_start;
puts("relocated to: "); puthex(initrd_start);
puts(" "); puthex(initrd_end); puts("\n");
+#endif
}
+#ifndef CONFIG_MBX
/* this is safe, just use it */
+ /* I don't know why it didn't work for me on the MBX with 20 MB
+ * memory. I guess something was saved up there, but I can't
+ * figure it out......we are running on luck. -- Dan.
+ */
avail_ram = (char *)0x00400000;
end_avail = (char *)0x00600000;
+#endif
puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" ");
puthex((unsigned long)end_avail); puts("\n");
-#ifndef CONFIG_MBX
+#if !defined(CONFIG_MBX) && !defined(CONFIG_FADS)
CRT_tstc(); /* Forces keyboard to be initialized */
#endif
-#ifdef CONFIG_PREP
-/* I need to fix this for mbx -- Cort */
+
puts("\nLinux/PPC load: ");
timer = 0;
cp = cmd_line;
@@ -472,6 +518,13 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
cp--;
puts("\b \b");
}
+#ifdef CONFIG_MBX
+ } else if (ch == '?') {
+ if (!do_ipaddrs(&cp, 1)) {
+ *cp++ = ch;
+ putc(ch);
+ }
+#endif
} else {
*cp++ = ch;
putc(ch);
@@ -482,12 +535,38 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
udelay(1000); /* 1 msec */
}
*cp = 0;
+#ifdef CONFIG_MBX
+ /* The MBX does not currently have any default boot strategy.
+ * If the command line is not filled in, we will automatically
+ * create the default network boot.
+ */
+ if (cmd_line[0] == 0) {
+ dp = root_string;
+ while (*dp != 0)
+ *cp++ = *dp++;
+ *cp++ = ' ';
+
+ dp = nfsaddrs_string;
+ while (*dp != 0)
+ *cp++ = *dp++;
+ dp = cp;
+ do_ipaddrs(&cp, 0);
+ *cp++ = ' ';
+
+ /* Add the server address to the root file system path.
+ */
+ dp = strrchr(dp, ':');
+ dp++;
+ do_nfsroot(&cp, dp);
+ *cp = 0;
+ }
+#endif
puts("\n");
-#endif /* CONFIG_PREP */
+
/* mappings on early boot can only handle 16M */
- if ( (int)(&cmd_line[0]) > (16<<20))
+ if ( (int)(cmd_line[0]) > (16<<20))
puts("cmd_line located > 16M\n");
- if ( (int)&hold_residual > (16<<20))
+ if ( (int)hold_residual > (16<<20))
puts("hold_residual located > 16M\n");
if ( initrd_start > (16<<20))
puts("initrd_start located > 16M\n");
@@ -497,13 +576,153 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
gunzip(0, 0x400000, zimage_start, &zimage_size);
puts("done.\n");
puts("Now booting the kernel\n");
-#ifndef CONFIG_MBX
- return (unsigned long)&hold_residual;
-#else
- return (unsigned long)&hold_board_info;
-#endif
+ return (unsigned long)hold_residual;
+}
+
+#ifdef CONFIG_MBX
+int
+do_ipaddrs(char **cmd_cp, int echo)
+{
+ char *cp, *ip, ch;
+ unsigned char ipd;
+ int i, j, retval;
+
+ /* We need to create the string:
+ * <my_ip>:<serv_ip>
+ */
+ cp = *cmd_cp;
+ retval = 0;
+
+ if ((cp - 9) >= cmd_line) {
+ if (strncmp(cp - 9, "nfsaddrs=", 9) == 0) {
+ ip = (char *)0xfa000060;
+ retval = 1;
+ for (j=0; j<2; j++) {
+ for (i=0; i<4; i++) {
+ ipd = *ip++;
+
+ ch = ipd/100;
+ if (ch) {
+ ch += '0';
+ if (echo)
+ putc(ch);
+ *cp++ = ch;
+ ipd -= 100 * (ch - '0');
+ }
+
+ ch = ipd/10;
+ if (ch) {
+ ch += '0';
+ if (echo)
+ putc(ch);
+ *cp++ = ch;
+ ipd -= 10 * (ch - '0');
+ }
+
+ ch = ipd + '0';
+ if (echo)
+ putc(ch);
+ *cp++ = ch;
+
+ ch = '.';
+ if (echo)
+ putc(ch);
+ *cp++ = ch;
+ }
+
+ /* At the end of the string, remove the
+ * '.' and replace it with a ':'.
+ */
+ *(cp - 1) = ':';
+ if (echo) {
+ putc('\b'); putc(':');
+ }
+ }
+
+ /* At the end of the second string, remove the
+ * '.' from both the command line and the
+ * screen.
+ */
+ --cp;
+ putc('\b'); putc(' '); putc('\b');
+ }
+ }
+ *cmd_cp = cp;
+ return(retval);
}
+void
+do_nfsroot(char **cmd_cp, char *dp)
+{
+ char *cp, *rp, *ep;
+
+ /* The boot argument (i.e /sys/mbxroot/zImage) is stored
+ * at offset 0x0078 in NVRAM. We use this path name to
+ * construct the root file system path.
+ */
+ cp = *cmd_cp;
+
+ /* build command string.
+ */
+ rp = nfsroot_string;
+ while (*rp != 0)
+ *cp++ = *rp++;
+
+ /* Add the server address to the path.
+ */
+ while (*dp != ' ')
+ *cp++ = *dp++;
+ *cp++ = ':';
+
+ rp = (char *)0xfa000078;
+ ep = strrchr(rp, '/');
+
+ if (ep != 0) {
+ while (rp < ep)
+ *cp++ = *rp++;
+ }
+ else {
+ rp = defroot_string;
+ while (*rp != 0)
+ *cp++ = *rp++;
+ }
+
+ *cmd_cp = cp;
+}
+
+size_t strlen(const char * s)
+{
+ const char *sc;
+
+ for (sc = s; *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+
+int strncmp(const char * cs,const char * ct,size_t count)
+{
+ register signed char __res = 0;
+
+ while (count) {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ count--;
+ }
+
+ return __res;
+}
+
+char * strrchr(const char * s, int c)
+{
+ const char *p = s + strlen(s);
+ do {
+ if (*p == (char)c)
+ return (char *)p;
+ } while (--p >= s);
+ return NULL;
+}
+#endif
+
void puthex(unsigned long val)
{
unsigned char buf[10];
diff --git a/arch/ppc/boot/mkprep.c b/arch/ppc/boot/mkprep.c
index a65953f4e..7799c9acc 100644
--- a/arch/ppc/boot/mkprep.c
+++ b/arch/ppc/boot/mkprep.c
@@ -10,16 +10,18 @@
* 3) -asm - strips elf header and writes out as asm data
* useful for generating data for a compressed image
* -- Cort
+ *
+ * Modified for x86 hosted builds by Matt Porter <porter@neta.com>
*/
#ifdef linux
#include <linux/types.h>
-#include <asm/stat.h>
+/*#include <asm/stat.h>*/
/*#include <asm/byteorder.h>*/ /* the byte swap funcs don't work here -- Cort */
#else
#include <unistd.h>
-#include <sys/stat.h>
#endif
+#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
@@ -164,8 +166,13 @@ void write_prep_partition(int in, int out)
bzero( block, sizeof block );
/* set entry point and boot image size skipping over elf header */
+#ifdef __i386__
+ *entry = 0x400/*+65536*/;
+ *length = info.st_size+0x400;
+#else
*entry = cpu_to_le32(0x400/*+65536*/);
*length = cpu_to_le32(info.st_size+0x400);
+#endif /* __i386__ */
/* sets magic number for msdos partition (used by linux) */
block[510] = 0x55;
@@ -202,9 +209,18 @@ void write_prep_partition(int in, int out)
pe->beginning_sector = cpu_to_le32(1);
#else
/* This has to be 0 on the PowerStack? */
+#ifdef __i386__
+ pe->beginning_sector = 0;
+#else
pe->beginning_sector = cpu_to_le32(0);
+#endif /* __i386__ */
#endif
+
+#ifdef __i386__
+ pe->number_of_sectors = 2*18*80-1;
+#else
pe->number_of_sectors = cpu_to_le32(2*18*80-1);
+#endif /* __i386__ */
write( out, block, sizeof(block) );
write( out, entry, sizeof(*entry) );
diff --git a/arch/ppc/boot/offset b/arch/ppc/boot/offset
index c9f39ed3f..52a1b5546 100644
--- a/arch/ppc/boot/offset
+++ b/arch/ppc/boot/offset
@@ -1,4 +1,4 @@
#!/bin/bash
-OFFSET=`objdump -h $1 | grep $2 | grep -v zvmlinux| awk '{print $6}'`
+OFFSET=`$1 -h $2 | grep $3 | grep -v zvmlinux| awk '{print $6}'`
echo "0x"$OFFSET
diff --git a/arch/ppc/boot/size b/arch/ppc/boot/size
index c4b12cf94..6c48f8d14 100644
--- a/arch/ppc/boot/size
+++ b/arch/ppc/boot/size
@@ -1,4 +1,4 @@
#!/bin/bash
-OFFSET=`objdump -h $1 | grep $2 | grep -v zvmlinux | awk '{print $3}'`
+OFFSET=`$1 -h $2 | grep $3 | grep -v zvmlinux | awk '{print $3}'`
echo "0x"$OFFSET
diff --git a/arch/ppc/chrp_defconfig b/arch/ppc/chrp_defconfig
index fea81c513..dcaf4b2d5 100644
--- a/arch/ppc/chrp_defconfig
+++ b/arch/ppc/chrp_defconfig
@@ -41,10 +41,11 @@ CONFIG_FB_COMPAT_XPMAC=y
CONFIG_MAC_KEYBOARD=y
# CONFIG_MAC_FLOPPY is not set
# CONFIG_MAC_SERIAL is not set
-CONFIG_MACMOUSE=y
+# CONFIG_ADBMOUSE is not set
CONFIG_PROC_DEVICETREE=y
# CONFIG_KGDB is not set
# CONFIG_XMON is not set
+# CONFIG_TOTALMP is not set
#
# Plug and Play support
@@ -148,12 +149,11 @@ CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_NCR53C406A is not set
# CONFIG_SCSI_NCR53C7xx is not set
CONFIG_SCSI_NCR53C8XX=y
-# CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT is not set
-# CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE is not set
-# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4
CONFIG_SCSI_NCR53C8XX_SYNC=5
-# CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT is not set
+# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
+# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_PCI2000 is not set
@@ -199,9 +199,9 @@ CONFIG_DEC_ELCP=y
# CONFIG_EEXPRESS_PRO100 is not set
# CONFIG_LNE390 is not set
# CONFIG_NE2K_PCI is not set
+# CONFIG_TLAN is not set
# CONFIG_ES3210 is not set
# CONFIG_EPIC100 is not set
-# CONFIG_TLAN is not set
# CONFIG_ZNET is not set
# CONFIG_NET_POCKET is not set
# CONFIG_FDDI is not set
@@ -228,50 +228,29 @@ CONFIG_DEC_ELCP=y
# CONFIG_CD_NO_IDESCSI is not set
#
-# Filesystems
-#
-# CONFIG_QUOTA is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_EXT2_FS=y
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_NFS_FS=y
-# CONFIG_NFSD is not set
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-# CONFIG_CODA_FS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_AFFS_FS is not set
-CONFIG_HFS_FS=y
-# CONFIG_ROMFS_FS is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_ADFS_FS is not set
-# CONFIG_DEVPTS_FS is not set
-CONFIG_MAC_PARTITION=y
-# CONFIG_NLS is not set
-
-#
# Console drivers
#
+CONFIG_DUMMY_CONSOLE=y
CONFIG_FB_OF=y
-CONFIG_FB_S3TRIO=y
+# CONFIG_FB_CONTROL is not set
+# CONFIG_FB_PLATINUM is not set
+# CONFIG_FB_VALKYRIE is not set
CONFIG_FB_ATY=y
+CONFIG_FB_IMSTT=y
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_S3TRIO is not set
CONFIG_FB_VGA=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FBCON_ADVANCED is not set
CONFIG_FBCON_CFB8=y
CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
CONFIG_FBCON_CFB32=y
CONFIG_FBCON_VGA=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+# CONFIG_FBCON_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
#
# Character devices
@@ -282,16 +261,15 @@ CONFIG_SERIAL=y
# CONFIG_SERIAL_CONSOLE is not set
# CONFIG_SERIAL_EXTENDED is not set
# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
# CONFIG_MOUSE is not set
# CONFIG_UMISC is not set
# CONFIG_QIC02_TAPE is not set
-# CONFIG_APM is not set
# CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set
# CONFIG_VIDEO_DEV is not set
CONFIG_NVRAM=y
# CONFIG_JOYSTICK is not set
-# CONFIG_MISC_RADIO is not set
#
# Ftape, the floppy tape device driver
@@ -299,7 +277,43 @@ CONFIG_NVRAM=y
# CONFIG_FTAPE is not set
#
+# Filesystems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_EXT2_FS=y
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+CONFIG_PROC_FS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFSD is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_CODA_FS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_AFFS_FS is not set
+CONFIG_HFS_FS=y
+# CONFIG_ROMFS_FS is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_ADFS_FS is not set
+CONFIG_MAC_PARTITION=y
+# CONFIG_NLS is not set
+
+#
# Sound
#
CONFIG_SOUND=y
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
# CONFIG_SOUND_OSS is not set
diff --git a/arch/ppc/chrpboot/Makefile b/arch/ppc/chrpboot/Makefile
index 4a194a5be..946845a5d 100644
--- a/arch/ppc/chrpboot/Makefile
+++ b/arch/ppc/chrpboot/Makefile
@@ -20,9 +20,13 @@ CFLAGS = -O -fno-builtin -DSTDC_HEADERS -I$(TOPDIR)/include
LD_ARGS = -T ../vmlinux.lds -Ttext 0x00800000
OBJCOPY = $(CROSS_COMPILE)objcopy
-OBJS = crt0.o start.o main.o misc.o string.o zlib.o image.o # initrd.o
+OBJS = crt0.o start.o main.o misc.o ../coffboot/string.o ../coffboot/zlib.o image.o # initrd.o
LIBS = $(TOPDIR)/lib/lib.a
+ifeq ($(CONFIG_ALL_PPC),y)
+# yes, we want to build chrp stuff
+CONFIG_CHRP = y
+endif
all: $(TOPDIR)/zImage
diff --git a/arch/ppc/chrpboot/main.c b/arch/ppc/chrpboot/main.c
index 05a2f85d3..e89ae2720 100644
--- a/arch/ppc/chrpboot/main.c
+++ b/arch/ppc/chrpboot/main.c
@@ -6,8 +6,8 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-#include "nonstdio.h"
-#include "zlib.h"
+#include "../coffboot/nonstdio.h"
+#include "../coffboot/zlib.h"
extern void *finddevice(const char *);
extern int getprop(void *, const char *, void *, int);
diff --git a/arch/ppc/chrpboot/nonstdio.h b/arch/ppc/chrpboot/nonstdio.h
deleted file mode 100644
index 664b8384a..000000000
--- a/arch/ppc/chrpboot/nonstdio.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-typedef int FILE;
-extern FILE *stdin, *stdout;
-#define NULL ((void *)0)
-#define EOF (-1)
-#define fopen(n, m) NULL
-#define fflush(f) 0
-#define fclose(f) 0
-extern char *fgets();
-
-#define perror(s) printf("%s: no files!\n", (s))
diff --git a/arch/ppc/chrpboot/zlib.c b/arch/ppc/chrpboot/zlib.c
deleted file mode 100644
index 4f69fb3d8..000000000
--- a/arch/ppc/chrpboot/zlib.c
+++ /dev/null
@@ -1,2143 +0,0 @@
-/*
- * This file is derived from various .h and .c files from the zlib-0.95
- * distribution by Jean-loup Gailly and Mark Adler, with some additions
- * by Paul Mackerras to aid in implementing Deflate compression and
- * decompression for PPP packets. See zlib.h for conditions of
- * distribution and use.
- *
- * Changes that have been made include:
- * - changed functions not used outside this file to "local"
- * - added minCompression parameter to deflateInit2
- * - added Z_PACKET_FLUSH (see zlib.h for details)
- * - added inflateIncomp
- *
- * $Id: zlib.c,v 1.1 1997/09/19 07:03:44 paulus Exp $
- */
-
-/*+++++*/
-/* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
- part of the implementation of the compression library and is
- subject to change. Applications should only use zlib.h.
- */
-
-/* From: zutil.h,v 1.9 1995/05/03 17:27:12 jloup Exp */
-
-#define _Z_UTIL_H
-
-#include "zlib.h"
-
-#ifndef local
-# define local static
-#endif
-/* compile with -Dlocal if your debugger can't find static symbols */
-
-#define FAR
-
-typedef unsigned char uch;
-typedef uch FAR uchf;
-typedef unsigned short ush;
-typedef ush FAR ushf;
-typedef unsigned long ulg;
-
-extern char *z_errmsg[]; /* indexed by 1-zlib_error */
-
-#define ERR_RETURN(strm,err) return (strm->msg=z_errmsg[1-err], err)
-/* To be used only when the state is known to be valid */
-
-#ifndef NULL
-#define NULL ((void *) 0)
-#endif
-
- /* common constants */
-
-#define DEFLATED 8
-
-#ifndef DEF_WBITS
-# define DEF_WBITS MAX_WBITS
-#endif
-/* default windowBits for decompression. MAX_WBITS is for compression only */
-
-#if MAX_MEM_LEVEL >= 8
-# define DEF_MEM_LEVEL 8
-#else
-# define DEF_MEM_LEVEL MAX_MEM_LEVEL
-#endif
-/* default memLevel */
-
-#define STORED_BLOCK 0
-#define STATIC_TREES 1
-#define DYN_TREES 2
-/* The three kinds of block type */
-
-#define MIN_MATCH 3
-#define MAX_MATCH 258
-/* The minimum and maximum match lengths */
-
- /* functions */
-
-#include <string.h>
-#define zmemcpy memcpy
-#define zmemzero(dest, len) memset(dest, 0, len)
-
-/* Diagnostic functions */
-#ifdef DEBUG_ZLIB
-# include <stdio.h>
-# ifndef verbose
-# define verbose 0
-# endif
-# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
-# define Trace(x) fprintf x
-# define Tracev(x) {if (verbose) fprintf x ;}
-# define Tracevv(x) {if (verbose>1) fprintf x ;}
-# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
-#else
-# define Assert(cond,msg)
-# define Trace(x)
-# define Tracev(x)
-# define Tracevv(x)
-# define Tracec(c,x)
-# define Tracecv(c,x)
-#endif
-
-
-typedef uLong (*check_func) OF((uLong check, Bytef *buf, uInt len));
-
-/* voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); */
-/* void zcfree OF((voidpf opaque, voidpf ptr)); */
-
-#define ZALLOC(strm, items, size) \
- (*((strm)->zalloc))((strm)->opaque, (items), (size))
-#define ZFREE(strm, addr, size) \
- (*((strm)->zfree))((strm)->opaque, (voidpf)(addr), (size))
-#define TRY_FREE(s, p, n) {if (p) ZFREE(s, p, n);}
-
-/* deflate.h -- internal compression state
- * Copyright (C) 1995 Jean-loup Gailly
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
- part of the implementation of the compression library and is
- subject to change. Applications should only use zlib.h.
- */
-
-/*+++++*/
-/* infblock.h -- header to use infblock.c
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
- part of the implementation of the compression library and is
- subject to change. Applications should only use zlib.h.
- */
-
-struct inflate_blocks_state;
-typedef struct inflate_blocks_state FAR inflate_blocks_statef;
-
-local inflate_blocks_statef * inflate_blocks_new OF((
- z_stream *z,
- check_func c, /* check function */
- uInt w)); /* window size */
-
-local int inflate_blocks OF((
- inflate_blocks_statef *,
- z_stream *,
- int)); /* initial return code */
-
-local void inflate_blocks_reset OF((
- inflate_blocks_statef *,
- z_stream *,
- uLongf *)); /* check value on output */
-
-local int inflate_blocks_free OF((
- inflate_blocks_statef *,
- z_stream *,
- uLongf *)); /* check value on output */
-
-local int inflate_addhistory OF((
- inflate_blocks_statef *,
- z_stream *));
-
-local int inflate_packet_flush OF((
- inflate_blocks_statef *));
-
-/*+++++*/
-/* inftrees.h -- header to use inftrees.c
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
- part of the implementation of the compression library and is
- subject to change. Applications should only use zlib.h.
- */
-
-/* Huffman code lookup table entry--this entry is four bytes for machines
- that have 16-bit pointers (e.g. PC's in the small or medium model). */
-
-typedef struct inflate_huft_s FAR inflate_huft;
-
-struct inflate_huft_s {
- union {
- struct {
- Byte Exop; /* number of extra bits or operation */
- Byte Bits; /* number of bits in this code or subcode */
- } what;
- uInt Nalloc; /* number of these allocated here */
- Bytef *pad; /* pad structure to a power of 2 (4 bytes for */
- } word; /* 16-bit, 8 bytes for 32-bit machines) */
- union {
- uInt Base; /* literal, length base, or distance base */
- inflate_huft *Next; /* pointer to next level of table */
- } more;
-};
-
-#ifdef DEBUG_ZLIB
- local uInt inflate_hufts;
-#endif
-
-local int inflate_trees_bits OF((
- uIntf *, /* 19 code lengths */
- uIntf *, /* bits tree desired/actual depth */
- inflate_huft * FAR *, /* bits tree result */
- z_stream *)); /* for zalloc, zfree functions */
-
-local int inflate_trees_dynamic OF((
- uInt, /* number of literal/length codes */
- uInt, /* number of distance codes */
- uIntf *, /* that many (total) code lengths */
- uIntf *, /* literal desired/actual bit depth */
- uIntf *, /* distance desired/actual bit depth */
- inflate_huft * FAR *, /* literal/length tree result */
- inflate_huft * FAR *, /* distance tree result */
- z_stream *)); /* for zalloc, zfree functions */
-
-local int inflate_trees_fixed OF((
- uIntf *, /* literal desired/actual bit depth */
- uIntf *, /* distance desired/actual bit depth */
- inflate_huft * FAR *, /* literal/length tree result */
- inflate_huft * FAR *)); /* distance tree result */
-
-local int inflate_trees_free OF((
- inflate_huft *, /* tables to free */
- z_stream *)); /* for zfree function */
-
-
-/*+++++*/
-/* infcodes.h -- header to use infcodes.c
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
- part of the implementation of the compression library and is
- subject to change. Applications should only use zlib.h.
- */
-
-struct inflate_codes_state;
-typedef struct inflate_codes_state FAR inflate_codes_statef;
-
-local inflate_codes_statef *inflate_codes_new OF((
- uInt, uInt,
- inflate_huft *, inflate_huft *,
- z_stream *));
-
-local int inflate_codes OF((
- inflate_blocks_statef *,
- z_stream *,
- int));
-
-local void inflate_codes_free OF((
- inflate_codes_statef *,
- z_stream *));
-
-
-/*+++++*/
-/* inflate.c -- zlib interface to inflate modules
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* inflate private state */
-struct internal_state {
-
- /* mode */
- enum {
- METHOD, /* waiting for method byte */
- FLAG, /* waiting for flag byte */
- BLOCKS, /* decompressing blocks */
- CHECK4, /* four check bytes to go */
- CHECK3, /* three check bytes to go */
- CHECK2, /* two check bytes to go */
- CHECK1, /* one check byte to go */
- DONE, /* finished check, done */
- BAD} /* got an error--stay here */
- mode; /* current inflate mode */
-
- /* mode dependent information */
- union {
- uInt method; /* if FLAGS, method byte */
- struct {
- uLong was; /* computed check value */
- uLong need; /* stream check value */
- } check; /* if CHECK, check values to compare */
- uInt marker; /* if BAD, inflateSync's marker bytes count */
- } sub; /* submode */
-
- /* mode independent information */
- int nowrap; /* flag for no wrapper */
- uInt wbits; /* log2(window size) (8..15, defaults to 15) */
- inflate_blocks_statef
- *blocks; /* current inflate_blocks state */
-
-};
-
-
-int inflateReset(z)
-z_stream *z;
-{
- uLong c;
-
- if (z == Z_NULL || z->state == Z_NULL)
- return Z_STREAM_ERROR;
- z->total_in = z->total_out = 0;
- z->msg = Z_NULL;
- z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
- inflate_blocks_reset(z->state->blocks, z, &c);
- Trace((stderr, "inflate: reset\n"));
- return Z_OK;
-}
-
-
-int inflateEnd(z)
-z_stream *z;
-{
- uLong c;
-
- if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
- return Z_STREAM_ERROR;
- if (z->state->blocks != Z_NULL)
- inflate_blocks_free(z->state->blocks, z, &c);
- ZFREE(z, z->state, sizeof(struct internal_state));
- z->state = Z_NULL;
- Trace((stderr, "inflate: end\n"));
- return Z_OK;
-}
-
-
-int inflateInit2(z, w)
-z_stream *z;
-int w;
-{
- /* initialize state */
- if (z == Z_NULL)
- return Z_STREAM_ERROR;
-/* if (z->zalloc == Z_NULL) z->zalloc = zcalloc; */
-/* if (z->zfree == Z_NULL) z->zfree = zcfree; */
- if ((z->state = (struct internal_state FAR *)
- ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
- return Z_MEM_ERROR;
- z->state->blocks = Z_NULL;
-
- /* handle undocumented nowrap option (no zlib header or check) */
- z->state->nowrap = 0;
- if (w < 0)
- {
- w = - w;
- z->state->nowrap = 1;
- }
-
- /* set window size */
- if (w < 8 || w > 15)
- {
- inflateEnd(z);
- return Z_STREAM_ERROR;
- }
- z->state->wbits = (uInt)w;
-
- /* create inflate_blocks state */
- if ((z->state->blocks =
- inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w))
- == Z_NULL)
- {
- inflateEnd(z);
- return Z_MEM_ERROR;
- }
- Trace((stderr, "inflate: allocated\n"));
-
- /* reset state */
- inflateReset(z);
- return Z_OK;
-}
-
-
-int inflateInit(z)
-z_stream *z;
-{
- return inflateInit2(z, DEF_WBITS);
-}
-
-
-#define NEEDBYTE {if(z->avail_in==0)goto empty;r=Z_OK;}
-#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
-
-int inflate(z, f)
-z_stream *z;
-int f;
-{
- int r;
- uInt b;
-
- if (z == Z_NULL || z->next_in == Z_NULL)
- return Z_STREAM_ERROR;
- r = Z_BUF_ERROR;
- while (1) switch (z->state->mode)
- {
- case METHOD:
- NEEDBYTE
- if (((z->state->sub.method = NEXTBYTE) & 0xf) != DEFLATED)
- {
- z->state->mode = BAD;
- z->msg = "unknown compression method";
- z->state->sub.marker = 5; /* can't try inflateSync */
- break;
- }
- if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
- {
- z->state->mode = BAD;
- z->msg = "invalid window size";
- z->state->sub.marker = 5; /* can't try inflateSync */
- break;
- }
- z->state->mode = FLAG;
- case FLAG:
- NEEDBYTE
- if ((b = NEXTBYTE) & 0x20)
- {
- z->state->mode = BAD;
- z->msg = "invalid reserved bit";
- z->state->sub.marker = 5; /* can't try inflateSync */
- break;
- }
- if (((z->state->sub.method << 8) + b) % 31)
- {
- z->state->mode = BAD;
- z->msg = "incorrect header check";
- z->state->sub.marker = 5; /* can't try inflateSync */
- break;
- }
- Trace((stderr, "inflate: zlib header ok\n"));
- z->state->mode = BLOCKS;
- case BLOCKS:
- r = inflate_blocks(z->state->blocks, z, r);
- if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0)
- r = inflate_packet_flush(z->state->blocks);
- if (r == Z_DATA_ERROR)
- {
- z->state->mode = BAD;
- z->state->sub.marker = 0; /* can try inflateSync */
- break;
- }
- if (r != Z_STREAM_END)
- return r;
- r = Z_OK;
- inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
- if (z->state->nowrap)
- {
- z->state->mode = DONE;
- break;
- }
- z->state->mode = CHECK4;
- case CHECK4:
- NEEDBYTE
- z->state->sub.check.need = (uLong)NEXTBYTE << 24;
- z->state->mode = CHECK3;
- case CHECK3:
- NEEDBYTE
- z->state->sub.check.need += (uLong)NEXTBYTE << 16;
- z->state->mode = CHECK2;
- case CHECK2:
- NEEDBYTE
- z->state->sub.check.need += (uLong)NEXTBYTE << 8;
- z->state->mode = CHECK1;
- case CHECK1:
- NEEDBYTE
- z->state->sub.check.need += (uLong)NEXTBYTE;
-
- if (z->state->sub.check.was != z->state->sub.check.need)
- {
- z->state->mode = BAD;
- z->msg = "incorrect data check";
- z->state->sub.marker = 5; /* can't try inflateSync */
- break;
- }
- Trace((stderr, "inflate: zlib check ok\n"));
- z->state->mode = DONE;
- case DONE:
- return Z_STREAM_END;
- case BAD:
- return Z_DATA_ERROR;
- default:
- return Z_STREAM_ERROR;
- }
-
- empty:
- if (f != Z_PACKET_FLUSH)
- return r;
- z->state->mode = BAD;
- z->state->sub.marker = 0; /* can try inflateSync */
- return Z_DATA_ERROR;
-}
-
-/*
- * This subroutine adds the data at next_in/avail_in to the output history
- * without performing any output. The output buffer must be "caught up";
- * i.e. no pending output (hence s->read equals s->write), and the state must
- * be BLOCKS (i.e. we should be willing to see the start of a series of
- * BLOCKS). On exit, the output will also be caught up, and the checksum
- * will have been updated if need be.
- */
-
-int inflateIncomp(z)
-z_stream *z;
-{
- if (z->state->mode != BLOCKS)
- return Z_DATA_ERROR;
- return inflate_addhistory(z->state->blocks, z);
-}
-
-
-int inflateSync(z)
-z_stream *z;
-{
- uInt n; /* number of bytes to look at */
- Bytef *p; /* pointer to bytes */
- uInt m; /* number of marker bytes found in a row */
- uLong r, w; /* temporaries to save total_in and total_out */
-
- /* set up */
- if (z == Z_NULL || z->state == Z_NULL)
- return Z_STREAM_ERROR;
- if (z->state->mode != BAD)
- {
- z->state->mode = BAD;
- z->state->sub.marker = 0;
- }
- if ((n = z->avail_in) == 0)
- return Z_BUF_ERROR;
- p = z->next_in;
- m = z->state->sub.marker;
-
- /* search */
- while (n && m < 4)
- {
- if (*p == (Byte)(m < 2 ? 0 : 0xff))
- m++;
- else if (*p)
- m = 0;
- else
- m = 4 - m;
- p++, n--;
- }
-
- /* restore */
- z->total_in += p - z->next_in;
- z->next_in = p;
- z->avail_in = n;
- z->state->sub.marker = m;
-
- /* return no joy or set up to restart on a new block */
- if (m != 4)
- return Z_DATA_ERROR;
- r = z->total_in; w = z->total_out;
- inflateReset(z);
- z->total_in = r; z->total_out = w;
- z->state->mode = BLOCKS;
- return Z_OK;
-}
-
-#undef NEEDBYTE
-#undef NEXTBYTE
-
-/*+++++*/
-/* infutil.h -- types and macros common to blocks and codes
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
- part of the implementation of the compression library and is
- subject to change. Applications should only use zlib.h.
- */
-
-/* inflate blocks semi-private state */
-struct inflate_blocks_state {
-
- /* mode */
- enum {
- TYPE, /* get type bits (3, including end bit) */
- LENS, /* get lengths for stored */
- STORED, /* processing stored block */
- TABLE, /* get table lengths */
- BTREE, /* get bit lengths tree for a dynamic block */
- DTREE, /* get length, distance trees for a dynamic block */
- CODES, /* processing fixed or dynamic block */
- DRY, /* output remaining window bytes */
- DONEB, /* finished last block, done */
- BADB} /* got a data error--stuck here */
- mode; /* current inflate_block mode */
-
- /* mode dependent information */
- union {
- uInt left; /* if STORED, bytes left to copy */
- struct {
- uInt table; /* table lengths (14 bits) */
- uInt index; /* index into blens (or border) */
- uIntf *blens; /* bit lengths of codes */
- uInt bb; /* bit length tree depth */
- inflate_huft *tb; /* bit length decoding tree */
- int nblens; /* # elements allocated at blens */
- } trees; /* if DTREE, decoding info for trees */
- struct {
- inflate_huft *tl, *td; /* trees to free */
- inflate_codes_statef
- *codes;
- } decode; /* if CODES, current state */
- } sub; /* submode */
- uInt last; /* true if this block is the last block */
-
- /* mode independent information */
- uInt bitk; /* bits in bit buffer */
- uLong bitb; /* bit buffer */
- Bytef *window; /* sliding window */
- Bytef *end; /* one byte after sliding window */
- Bytef *read; /* window read pointer */
- Bytef *write; /* window write pointer */
- check_func checkfn; /* check function */
- uLong check; /* check on output */
-
-};
-
-
-/* defines for inflate input/output */
-/* update pointers and return */
-#define UPDBITS {s->bitb=b;s->bitk=k;}
-#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
-#define UPDOUT {s->write=q;}
-#define UPDATE {UPDBITS UPDIN UPDOUT}
-#define LEAVE {UPDATE return inflate_flush(s,z,r);}
-/* get bytes and bits */
-#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
-#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
-#define NEXTBYTE (n--,*p++)
-#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
-#define DUMPBITS(j) {b>>=(j);k-=(j);}
-/* output bytes */
-#define WAVAIL (q<s->read?s->read-q-1:s->end-q)
-#define LOADOUT {q=s->write;m=WAVAIL;}
-#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=WAVAIL;}}
-#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
-#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
-#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
-/* load local pointers */
-#define LOAD {LOADIN LOADOUT}
-
-/* And'ing with mask[n] masks the lower n bits */
-local uInt inflate_mask[] = {
- 0x0000,
- 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
- 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
-};
-
-/* copy as much as possible from the sliding window to the output area */
-local int inflate_flush OF((
- inflate_blocks_statef *,
- z_stream *,
- int));
-
-/*+++++*/
-/* inffast.h -- header to use inffast.c
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
- part of the implementation of the compression library and is
- subject to change. Applications should only use zlib.h.
- */
-
-local int inflate_fast OF((
- uInt,
- uInt,
- inflate_huft *,
- inflate_huft *,
- inflate_blocks_statef *,
- z_stream *));
-
-
-/*+++++*/
-/* infblock.c -- interpret and process block types to last block
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* Table for deflate from PKZIP's appnote.txt. */
-local uInt border[] = { /* Order of the bit length code lengths */
- 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
-
-/*
- Notes beyond the 1.93a appnote.txt:
-
- 1. Distance pointers never point before the beginning of the output
- stream.
- 2. Distance pointers can point back across blocks, up to 32k away.
- 3. There is an implied maximum of 7 bits for the bit length table and
- 15 bits for the actual data.
- 4. If only one code exists, then it is encoded using one bit. (Zero
- would be more efficient, but perhaps a little confusing.) If two
- codes exist, they are coded using one bit each (0 and 1).
- 5. There is no way of sending zero distance codes--a dummy must be
- sent if there are none. (History: a pre 2.0 version of PKZIP would
- store blocks with no distance codes, but this was discovered to be
- too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
- zero distance codes, which is sent as one code of zero bits in
- length.
- 6. There are up to 286 literal/length codes. Code 256 represents the
- end-of-block. Note however that the static length tree defines
- 288 codes just to fill out the Huffman codes. Codes 286 and 287
- cannot be used though, since there is no length base or extra bits
- defined for them. Similarily, there are up to 30 distance codes.
- However, static trees define 32 codes (all 5 bits) to fill out the
- Huffman codes, but the last two had better not show up in the data.
- 7. Unzip can check dynamic Huffman blocks for complete code sets.
- The exception is that a single code would not be complete (see #4).
- 8. The five bits following the block type is really the number of
- literal codes sent minus 257.
- 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
- (1+6+6). Therefore, to output three times the length, you output
- three codes (1+1+1), whereas to output four times the same length,
- you only need two codes (1+3). Hmm.
- 10. In the tree reconstruction algorithm, Code = Code + Increment
- only if BitLength(i) is not zero. (Pretty obvious.)
- 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
- 12. Note: length code 284 can represent 227-258, but length code 285
- really is 258. The last length deserves its own, short code
- since it gets used a lot in very redundant files. The length
- 258 is special since 258 - 3 (the min match length) is 255.
- 13. The literal/length and distance code bit lengths are read as a
- single stream of lengths. It is possible (and advantageous) for
- a repeat code (16, 17, or 18) to go across the boundary between
- the two sets of lengths.
- */
-
-
-local void inflate_blocks_reset(s, z, c)
-inflate_blocks_statef *s;
-z_stream *z;
-uLongf *c;
-{
- if (s->checkfn != Z_NULL)
- *c = s->check;
- if (s->mode == BTREE || s->mode == DTREE)
- ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
- if (s->mode == CODES)
- {
- inflate_codes_free(s->sub.decode.codes, z);
- inflate_trees_free(s->sub.decode.td, z);
- inflate_trees_free(s->sub.decode.tl, z);
- }
- s->mode = TYPE;
- s->bitk = 0;
- s->bitb = 0;
- s->read = s->write = s->window;
- if (s->checkfn != Z_NULL)
- s->check = (*s->checkfn)(0L, Z_NULL, 0);
- Trace((stderr, "inflate: blocks reset\n"));
-}
-
-
-local inflate_blocks_statef *inflate_blocks_new(z, c, w)
-z_stream *z;
-check_func c;
-uInt w;
-{
- inflate_blocks_statef *s;
-
- if ((s = (inflate_blocks_statef *)ZALLOC
- (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
- return s;
- if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
- {
- ZFREE(z, s, sizeof(struct inflate_blocks_state));
- return Z_NULL;
- }
- s->end = s->window + w;
- s->checkfn = c;
- s->mode = TYPE;
- Trace((stderr, "inflate: blocks allocated\n"));
- inflate_blocks_reset(s, z, &s->check);
- return s;
-}
-
-
-local int inflate_blocks(s, z, r)
-inflate_blocks_statef *s;
-z_stream *z;
-int r;
-{
- uInt t; /* temporary storage */
- uLong b; /* bit buffer */
- uInt k; /* bits in bit buffer */
- Bytef *p; /* input data pointer */
- uInt n; /* bytes available there */
- Bytef *q; /* output window write pointer */
- uInt m; /* bytes to end of window or read pointer */
-
- /* copy input/output information to locals (UPDATE macro restores) */
- LOAD
-
- /* process input based on current state */
- while (1) switch (s->mode)
- {
- case TYPE:
- NEEDBITS(3)
- t = (uInt)b & 7;
- s->last = t & 1;
- switch (t >> 1)
- {
- case 0: /* stored */
- Trace((stderr, "inflate: stored block%s\n",
- s->last ? " (last)" : ""));
- DUMPBITS(3)
- t = k & 7; /* go to byte boundary */
- DUMPBITS(t)
- s->mode = LENS; /* get length of stored block */
- break;
- case 1: /* fixed */
- Trace((stderr, "inflate: fixed codes block%s\n",
- s->last ? " (last)" : ""));
- {
- uInt bl, bd;
- inflate_huft *tl, *td;
-
- inflate_trees_fixed(&bl, &bd, &tl, &td);
- s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
- if (s->sub.decode.codes == Z_NULL)
- {
- r = Z_MEM_ERROR;
- LEAVE
- }
- s->sub.decode.tl = Z_NULL; /* don't try to free these */
- s->sub.decode.td = Z_NULL;
- }
- DUMPBITS(3)
- s->mode = CODES;
- break;
- case 2: /* dynamic */
- Trace((stderr, "inflate: dynamic codes block%s\n",
- s->last ? " (last)" : ""));
- DUMPBITS(3)
- s->mode = TABLE;
- break;
- case 3: /* illegal */
- DUMPBITS(3)
- s->mode = BADB;
- z->msg = "invalid block type";
- r = Z_DATA_ERROR;
- LEAVE
- }
- break;
- case LENS:
- NEEDBITS(32)
- if (((~b) >> 16) != (b & 0xffff))
- {
- s->mode = BADB;
- z->msg = "invalid stored block lengths";
- r = Z_DATA_ERROR;
- LEAVE
- }
- s->sub.left = (uInt)b & 0xffff;
- b = k = 0; /* dump bits */
- Tracev((stderr, "inflate: stored length %u\n", s->sub.left));
- s->mode = s->sub.left ? STORED : TYPE;
- break;
- case STORED:
- if (n == 0)
- LEAVE
- NEEDOUT
- t = s->sub.left;
- if (t > n) t = n;
- if (t > m) t = m;
- zmemcpy(q, p, t);
- p += t; n -= t;
- q += t; m -= t;
- if ((s->sub.left -= t) != 0)
- break;
- Tracev((stderr, "inflate: stored end, %lu total out\n",
- z->total_out + (q >= s->read ? q - s->read :
- (s->end - s->read) + (q - s->window))));
- s->mode = s->last ? DRY : TYPE;
- break;
- case TABLE:
- NEEDBITS(14)
- s->sub.trees.table = t = (uInt)b & 0x3fff;
-#ifndef PKZIP_BUG_WORKAROUND
- if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
- {
- s->mode = BADB;
- z->msg = "too many length or distance symbols";
- r = Z_DATA_ERROR;
- LEAVE
- }
-#endif
- t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
- if (t < 19)
- t = 19;
- if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
- {
- r = Z_MEM_ERROR;
- LEAVE
- }
- s->sub.trees.nblens = t;
- DUMPBITS(14)
- s->sub.trees.index = 0;
- Tracev((stderr, "inflate: table sizes ok\n"));
- s->mode = BTREE;
- case BTREE:
- while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
- {
- NEEDBITS(3)
- s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
- DUMPBITS(3)
- }
- while (s->sub.trees.index < 19)
- s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
- s->sub.trees.bb = 7;
- t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
- &s->sub.trees.tb, z);
- if (t != Z_OK)
- {
- r = t;
- if (r == Z_DATA_ERROR)
- s->mode = BADB;
- LEAVE
- }
- s->sub.trees.index = 0;
- Tracev((stderr, "inflate: bits tree ok\n"));
- s->mode = DTREE;
- case DTREE:
- while (t = s->sub.trees.table,
- s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
- {
- inflate_huft *h;
- uInt i, j, c;
-
- t = s->sub.trees.bb;
- NEEDBITS(t)
- h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
- t = h->word.what.Bits;
- c = h->more.Base;
- if (c < 16)
- {
- DUMPBITS(t)
- s->sub.trees.blens[s->sub.trees.index++] = c;
- }
- else /* c == 16..18 */
- {
- i = c == 18 ? 7 : c - 14;
- j = c == 18 ? 11 : 3;
- NEEDBITS(t + i)
- DUMPBITS(t)
- j += (uInt)b & inflate_mask[i];
- DUMPBITS(i)
- i = s->sub.trees.index;
- t = s->sub.trees.table;
- if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
- (c == 16 && i < 1))
- {
- s->mode = BADB;
- z->msg = "invalid bit length repeat";
- r = Z_DATA_ERROR;
- LEAVE
- }
- c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
- do {
- s->sub.trees.blens[i++] = c;
- } while (--j);
- s->sub.trees.index = i;
- }
- }
- inflate_trees_free(s->sub.trees.tb, z);
- s->sub.trees.tb = Z_NULL;
- {
- uInt bl, bd;
- inflate_huft *tl, *td;
- inflate_codes_statef *c;
-
- bl = 9; /* must be <= 9 for lookahead assumptions */
- bd = 6; /* must be <= 9 for lookahead assumptions */
- t = s->sub.trees.table;
- t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
- s->sub.trees.blens, &bl, &bd, &tl, &td, z);
- if (t != Z_OK)
- {
- if (t == (uInt)Z_DATA_ERROR)
- s->mode = BADB;
- r = t;
- LEAVE
- }
- Tracev((stderr, "inflate: trees ok\n"));
- if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
- {
- inflate_trees_free(td, z);
- inflate_trees_free(tl, z);
- r = Z_MEM_ERROR;
- LEAVE
- }
- ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
- s->sub.decode.codes = c;
- s->sub.decode.tl = tl;
- s->sub.decode.td = td;
- }
- s->mode = CODES;
- case CODES:
- UPDATE
- if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
- return inflate_flush(s, z, r);
- r = Z_OK;
- inflate_codes_free(s->sub.decode.codes, z);
- inflate_trees_free(s->sub.decode.td, z);
- inflate_trees_free(s->sub.decode.tl, z);
- LOAD
- Tracev((stderr, "inflate: codes end, %lu total out\n",
- z->total_out + (q >= s->read ? q - s->read :
- (s->end - s->read) + (q - s->window))));
- if (!s->last)
- {
- s->mode = TYPE;
- break;
- }
- if (k > 7) /* return unused byte, if any */
- {
- Assert(k < 16, "inflate_codes grabbed too many bytes")
- k -= 8;
- n++;
- p--; /* can always return one */
- }
- s->mode = DRY;
- case DRY:
- FLUSH
- if (s->read != s->write)
- LEAVE
- s->mode = DONEB;
- case DONEB:
- r = Z_STREAM_END;
- LEAVE
- case BADB:
- r = Z_DATA_ERROR;
- LEAVE
- default:
- r = Z_STREAM_ERROR;
- LEAVE
- }
-}
-
-
-local int inflate_blocks_free(s, z, c)
-inflate_blocks_statef *s;
-z_stream *z;
-uLongf *c;
-{
- inflate_blocks_reset(s, z, c);
- ZFREE(z, s->window, s->end - s->window);
- ZFREE(z, s, sizeof(struct inflate_blocks_state));
- Trace((stderr, "inflate: blocks freed\n"));
- return Z_OK;
-}
-
-/*
- * This subroutine adds the data at next_in/avail_in to the output history
- * without performing any output. The output buffer must be "caught up";
- * i.e. no pending output (hence s->read equals s->write), and the state must
- * be BLOCKS (i.e. we should be willing to see the start of a series of
- * BLOCKS). On exit, the output will also be caught up, and the checksum
- * will have been updated if need be.
- */
-local int inflate_addhistory(s, z)
-inflate_blocks_statef *s;
-z_stream *z;
-{
- uLong b; /* bit buffer */ /* NOT USED HERE */
- uInt k; /* bits in bit buffer */ /* NOT USED HERE */
- uInt t; /* temporary storage */
- Bytef *p; /* input data pointer */
- uInt n; /* bytes available there */
- Bytef *q; /* output window write pointer */
- uInt m; /* bytes to end of window or read pointer */
-
- if (s->read != s->write)
- return Z_STREAM_ERROR;
- if (s->mode != TYPE)
- return Z_DATA_ERROR;
-
- /* we're ready to rock */
- LOAD
- /* while there is input ready, copy to output buffer, moving
- * pointers as needed.
- */
- while (n) {
- t = n; /* how many to do */
- /* is there room until end of buffer? */
- if (t > m) t = m;
- /* update check information */
- if (s->checkfn != Z_NULL)
- s->check = (*s->checkfn)(s->check, q, t);
- zmemcpy(q, p, t);
- q += t;
- p += t;
- n -= t;
- z->total_out += t;
- s->read = q; /* drag read pointer forward */
-/* WRAP */ /* expand WRAP macro by hand to handle s->read */
- if (q == s->end) {
- s->read = q = s->window;
- m = WAVAIL;
- }
- }
- UPDATE
- return Z_OK;
-}
-
-
-/*
- * At the end of a Deflate-compressed PPP packet, we expect to have seen
- * a `stored' block type value but not the (zero) length bytes.
- */
-local int inflate_packet_flush(s)
- inflate_blocks_statef *s;
-{
- if (s->mode != LENS)
- return Z_DATA_ERROR;
- s->mode = TYPE;
- return Z_OK;
-}
-
-
-/*+++++*/
-/* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* simplify the use of the inflate_huft type with some defines */
-#define base more.Base
-#define next more.Next
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-
-local int huft_build OF((
- uIntf *, /* code lengths in bits */
- uInt, /* number of codes */
- uInt, /* number of "simple" codes */
- uIntf *, /* list of base values for non-simple codes */
- uIntf *, /* list of extra bits for non-simple codes */
- inflate_huft * FAR*,/* result: starting table */
- uIntf *, /* maximum lookup bits (returns actual) */
- z_stream *)); /* for zalloc function */
-
-local voidpf falloc OF((
- voidpf, /* opaque pointer (not used) */
- uInt, /* number of items */
- uInt)); /* size of item */
-
-local void ffree OF((
- voidpf q, /* opaque pointer (not used) */
- voidpf p, /* what to free (not used) */
- uInt n)); /* number of bytes (not used) */
-
-/* Tables for deflate from PKZIP's appnote.txt. */
-local uInt cplens[] = { /* Copy lengths for literal codes 257..285 */
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
- 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
- /* actually lengths - 2; also see note #13 above about 258 */
-local uInt cplext[] = { /* Extra bits for literal codes 257..285 */
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
- 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 192, 192}; /* 192==invalid */
-local uInt cpdist[] = { /* Copy offsets for distance codes 0..29 */
- 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
- 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
- 8193, 12289, 16385, 24577};
-local uInt cpdext[] = { /* Extra bits for distance codes */
- 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
- 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
- 12, 12, 13, 13};
-
-/*
- Huffman code decoding is performed using a multi-level table lookup.
- The fastest way to decode is to simply build a lookup table whose
- size is determined by the longest code. However, the time it takes
- to build this table can also be a factor if the data being decoded
- is not very long. The most common codes are necessarily the
- shortest codes, so those codes dominate the decoding time, and hence
- the speed. The idea is you can have a shorter table that decodes the
- shorter, more probable codes, and then point to subsidiary tables for
- the longer codes. The time it costs to decode the longer codes is
- then traded against the time it takes to make longer tables.
-
- This results of this trade are in the variables lbits and dbits
- below. lbits is the number of bits the first level table for literal/
- length codes can decode in one step, and dbits is the same thing for
- the distance codes. Subsequent tables are also less than or equal to
- those sizes. These values may be adjusted either when all of the
- codes are shorter than that, in which case the longest code length in
- bits is used, or when the shortest code is *longer* than the requested
- table size, in which case the length of the shortest code in bits is
- used.
-
- There are two different values for the two tables, since they code a
- different number of possibilities each. The literal/length table
- codes 286 possible values, or in a flat code, a little over eight
- bits. The distance table codes 30 possible values, or a little less
- than five bits, flat. The optimum values for speed end up being
- about one bit more than those, so lbits is 8+1 and dbits is 5+1.
- The optimum values may differ though from machine to machine, and
- possibly even between compilers. Your mileage may vary.
- */
-
-
-/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
-#define BMAX 15 /* maximum bit length of any code */
-#define N_MAX 288 /* maximum number of codes in any set */
-
-#ifdef DEBUG_ZLIB
- uInt inflate_hufts;
-#endif
-
-local int huft_build(b, n, s, d, e, t, m, zs)
-uIntf *b; /* code lengths in bits (all assumed <= BMAX) */
-uInt n; /* number of codes (assumed <= N_MAX) */
-uInt s; /* number of simple-valued codes (0..s-1) */
-uIntf *d; /* list of base values for non-simple codes */
-uIntf *e; /* list of extra bits for non-simple codes */
-inflate_huft * FAR *t; /* result: starting table */
-uIntf *m; /* maximum lookup bits, returns actual */
-z_stream *zs; /* for zalloc function */
-/* Given a list of code lengths and a maximum table size, make a set of
- tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
- if the given code set is incomplete (the tables are still built in this
- case), Z_DATA_ERROR if the input is invalid (all zero length codes or an
- over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. */
-{
-
- uInt a; /* counter for codes of length k */
- uInt c[BMAX+1]; /* bit length count table */
- uInt f; /* i repeats in table every f entries */
- int g; /* maximum code length */
- int h; /* table level */
- register uInt i; /* counter, current code */
- register uInt j; /* counter */
- register int k; /* number of bits in current code */
- int l; /* bits per table (returned in m) */
- register uIntf *p; /* pointer into c[], b[], or v[] */
- inflate_huft *q; /* points to current table */
- struct inflate_huft_s r; /* table entry for structure assignment */
- inflate_huft *u[BMAX]; /* table stack */
- uInt v[N_MAX]; /* values in order of bit length */
- register int w; /* bits before this table == (l * h) */
- uInt x[BMAX+1]; /* bit offsets, then code stack */
- uIntf *xp; /* pointer into x */
- int y; /* number of dummy codes added */
- uInt z; /* number of entries in current table */
-
-
- /* Generate counts for each bit length */
- p = c;
-#define C0 *p++ = 0;
-#define C2 C0 C0 C0 C0
-#define C4 C2 C2 C2 C2
- C4 /* clear c[]--assume BMAX+1 is 16 */
- p = b; i = n;
- do {
- c[*p++]++; /* assume all entries <= BMAX */
- } while (--i);
- if (c[0] == n) /* null input--all zero length codes */
- {
- *t = (inflate_huft *)Z_NULL;
- *m = 0;
- return Z_OK;
- }
-
-
- /* Find minimum and maximum length, bound *m by those */
- l = *m;
- for (j = 1; j <= BMAX; j++)
- if (c[j])
- break;
- k = j; /* minimum code length */
- if ((uInt)l < j)
- l = j;
- for (i = BMAX; i; i--)
- if (c[i])
- break;
- g = i; /* maximum code length */
- if ((uInt)l > i)
- l = i;
- *m = l;
-
-
- /* Adjust last length count to fill out codes, if needed */
- for (y = 1 << j; j < i; j++, y <<= 1)
- if ((y -= c[j]) < 0)
- return Z_DATA_ERROR;
- if ((y -= c[i]) < 0)
- return Z_DATA_ERROR;
- c[i] += y;
-
-
- /* Generate starting offsets into the value table for each length */
- x[1] = j = 0;
- p = c + 1; xp = x + 2;
- while (--i) { /* note that i == g from above */
- *xp++ = (j += *p++);
- }
-
-
- /* Make a table of values in order of bit lengths */
- p = b; i = 0;
- do {
- if ((j = *p++) != 0)
- v[x[j]++] = i;
- } while (++i < n);
-
-
- /* Generate the Huffman codes and for each, make the table entries */
- x[0] = i = 0; /* first Huffman code is zero */
- p = v; /* grab values in bit order */
- h = -1; /* no tables yet--level -1 */
- w = -l; /* bits decoded == (l * h) */
- u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */
- q = (inflate_huft *)Z_NULL; /* ditto */
- z = 0; /* ditto */
-
- /* go through the bit lengths (k already is bits in shortest code) */
- for (; k <= g; k++)
- {
- a = c[k];
- while (a--)
- {
- /* here i is the Huffman code of length k bits for value *p */
- /* make tables up to required level */
- while (k > w + l)
- {
- h++;
- w += l; /* previous table always l bits */
-
- /* compute minimum size table less than or equal to l bits */
- z = (z = g - w) > (uInt)l ? l : z; /* table size upper limit */
- if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
- { /* too few codes for k-w bit table */
- f -= a + 1; /* deduct codes from patterns left */
- xp = c + k;
- if (j < z)
- while (++j < z) /* try smaller tables up to z bits */
- {
- if ((f <<= 1) <= *++xp)
- break; /* enough codes to use up j bits */
- f -= *xp; /* else deduct codes from patterns */
- }
- }
- z = 1 << j; /* table entries for j-bit table */
-
- /* allocate and link in new table */
- if ((q = (inflate_huft *)ZALLOC
- (zs,z + 1,sizeof(inflate_huft))) == Z_NULL)
- {
- if (h)
- inflate_trees_free(u[0], zs);
- return Z_MEM_ERROR; /* not enough memory */
- }
- q->word.Nalloc = z + 1;
-#ifdef DEBUG_ZLIB
- inflate_hufts += z + 1;
-#endif
- *t = q + 1; /* link to list for huft_free() */
- *(t = &(q->next)) = Z_NULL;
- u[h] = ++q; /* table starts after link */
-
- /* connect to last table, if there is one */
- if (h)
- {
- x[h] = i; /* save pattern for backing up */
- r.bits = (Byte)l; /* bits to dump before this table */
- r.exop = (Byte)j; /* bits in this table */
- r.next = q; /* pointer to this table */
- j = i >> (w - l); /* (get around Turbo C bug) */
- u[h-1][j] = r; /* connect to last table */
- }
- }
-
- /* set up table entry in r */
- r.bits = (Byte)(k - w);
- if (p >= v + n)
- r.exop = 128 + 64; /* out of values--invalid code */
- else if (*p < s)
- {
- r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */
- r.base = *p++; /* simple code is just the value */
- }
- else
- {
- r.exop = (Byte)e[*p - s] + 16 + 64; /* non-simple--look up in lists */
- r.base = d[*p++ - s];
- }
-
- /* fill code-like entries with r */
- f = 1 << (k - w);
- for (j = i >> w; j < z; j += f)
- q[j] = r;
-
- /* backwards increment the k-bit code i */
- for (j = 1 << (k - 1); i & j; j >>= 1)
- i ^= j;
- i ^= j;
-
- /* backup over finished tables */
- while ((i & ((1 << w) - 1)) != x[h])
- {
- h--; /* don't need to update q */
- w -= l;
- }
- }
- }
-
-
- /* Return Z_BUF_ERROR if we were given an incomplete table */
- return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
-}
-
-
-local int inflate_trees_bits(c, bb, tb, z)
-uIntf *c; /* 19 code lengths */
-uIntf *bb; /* bits tree desired/actual depth */
-inflate_huft * FAR *tb; /* bits tree result */
-z_stream *z; /* for zfree function */
-{
- int r;
-
- r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z);
- if (r == Z_DATA_ERROR)
- z->msg = "oversubscribed dynamic bit lengths tree";
- else if (r == Z_BUF_ERROR)
- {
- inflate_trees_free(*tb, z);
- z->msg = "incomplete dynamic bit lengths tree";
- r = Z_DATA_ERROR;
- }
- return r;
-}
-
-
-local int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, z)
-uInt nl; /* number of literal/length codes */
-uInt nd; /* number of distance codes */
-uIntf *c; /* that many (total) code lengths */
-uIntf *bl; /* literal desired/actual bit depth */
-uIntf *bd; /* distance desired/actual bit depth */
-inflate_huft * FAR *tl; /* literal/length tree result */
-inflate_huft * FAR *td; /* distance tree result */
-z_stream *z; /* for zfree function */
-{
- int r;
-
- /* build literal/length tree */
- if ((r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z)) != Z_OK)
- {
- if (r == Z_DATA_ERROR)
- z->msg = "oversubscribed literal/length tree";
- else if (r == Z_BUF_ERROR)
- {
- inflate_trees_free(*tl, z);
- z->msg = "incomplete literal/length tree";
- r = Z_DATA_ERROR;
- }
- return r;
- }
-
- /* build distance tree */
- if ((r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z)) != Z_OK)
- {
- if (r == Z_DATA_ERROR)
- z->msg = "oversubscribed literal/length tree";
- else if (r == Z_BUF_ERROR) {
-#ifdef PKZIP_BUG_WORKAROUND
- r = Z_OK;
- }
-#else
- inflate_trees_free(*td, z);
- z->msg = "incomplete literal/length tree";
- r = Z_DATA_ERROR;
- }
- inflate_trees_free(*tl, z);
- return r;
-#endif
- }
-
- /* done */
- return Z_OK;
-}
-
-
-/* build fixed tables only once--keep them here */
-local int fixed_lock = 0;
-local int fixed_built = 0;
-#define FIXEDH 530 /* number of hufts used by fixed tables */
-local uInt fixed_left = FIXEDH;
-local inflate_huft fixed_mem[FIXEDH];
-local uInt fixed_bl;
-local uInt fixed_bd;
-local inflate_huft *fixed_tl;
-local inflate_huft *fixed_td;
-
-
-local voidpf falloc(q, n, s)
-voidpf q; /* opaque pointer (not used) */
-uInt n; /* number of items */
-uInt s; /* size of item */
-{
- Assert(s == sizeof(inflate_huft) && n <= fixed_left,
- "inflate_trees falloc overflow");
- if (q) s++; /* to make some compilers happy */
- fixed_left -= n;
- return (voidpf)(fixed_mem + fixed_left);
-}
-
-
-local void ffree(q, p, n)
-voidpf q;
-voidpf p;
-uInt n;
-{
- Assert(0, "inflate_trees ffree called!");
- if (q) q = p; /* to make some compilers happy */
-}
-
-
-local int inflate_trees_fixed(bl, bd, tl, td)
-uIntf *bl; /* literal desired/actual bit depth */
-uIntf *bd; /* distance desired/actual bit depth */
-inflate_huft * FAR *tl; /* literal/length tree result */
-inflate_huft * FAR *td; /* distance tree result */
-{
- /* build fixed tables if not built already--lock out other instances */
- while (++fixed_lock > 1)
- fixed_lock--;
- if (!fixed_built)
- {
- int k; /* temporary variable */
- unsigned c[288]; /* length list for huft_build */
- z_stream z; /* for falloc function */
-
- /* set up fake z_stream for memory routines */
- z.zalloc = falloc;
- z.zfree = ffree;
- z.opaque = Z_NULL;
-
- /* literal table */
- for (k = 0; k < 144; k++)
- c[k] = 8;
- for (; k < 256; k++)
- c[k] = 9;
- for (; k < 280; k++)
- c[k] = 7;
- for (; k < 288; k++)
- c[k] = 8;
- fixed_bl = 7;
- huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z);
-
- /* distance table */
- for (k = 0; k < 30; k++)
- c[k] = 5;
- fixed_bd = 5;
- huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z);
-
- /* done */
- fixed_built = 1;
- }
- fixed_lock--;
- *bl = fixed_bl;
- *bd = fixed_bd;
- *tl = fixed_tl;
- *td = fixed_td;
- return Z_OK;
-}
-
-
-local int inflate_trees_free(t, z)
-inflate_huft *t; /* table to free */
-z_stream *z; /* for zfree function */
-/* Free the malloc'ed tables built by huft_build(), which makes a linked
- list of the tables it made, with the links in a dummy first entry of
- each table. */
-{
- register inflate_huft *p, *q;
-
- /* Go through linked list, freeing from the malloced (t[-1]) address. */
- p = t;
- while (p != Z_NULL)
- {
- q = (--p)->next;
- ZFREE(z, p, p->word.Nalloc * sizeof(inflate_huft));
- p = q;
- }
- return Z_OK;
-}
-
-/*+++++*/
-/* infcodes.c -- process literals and length/distance pairs
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* simplify the use of the inflate_huft type with some defines */
-#define base more.Base
-#define next more.Next
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-/* inflate codes private state */
-struct inflate_codes_state {
-
- /* mode */
- enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
- START, /* x: set up for LEN */
- LEN, /* i: get length/literal/eob next */
- LENEXT, /* i: getting length extra (have base) */
- DIST, /* i: get distance next */
- DISTEXT, /* i: getting distance extra */
- COPY, /* o: copying bytes in window, waiting for space */
- LIT, /* o: got literal, waiting for output space */
- WASH, /* o: got eob, possibly still output waiting */
- END, /* x: got eob and all data flushed */
- BADCODE} /* x: got error */
- mode; /* current inflate_codes mode */
-
- /* mode dependent information */
- uInt len;
- union {
- struct {
- inflate_huft *tree; /* pointer into tree */
- uInt need; /* bits needed */
- } code; /* if LEN or DIST, where in tree */
- uInt lit; /* if LIT, literal */
- struct {
- uInt get; /* bits to get for extra */
- uInt dist; /* distance back to copy from */
- } copy; /* if EXT or COPY, where and how much */
- } sub; /* submode */
-
- /* mode independent information */
- Byte lbits; /* ltree bits decoded per branch */
- Byte dbits; /* dtree bits decoder per branch */
- inflate_huft *ltree; /* literal/length/eob tree */
- inflate_huft *dtree; /* distance tree */
-
-};
-
-
-local inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
-uInt bl, bd;
-inflate_huft *tl, *td;
-z_stream *z;
-{
- inflate_codes_statef *c;
-
- if ((c = (inflate_codes_statef *)
- ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
- {
- c->mode = START;
- c->lbits = (Byte)bl;
- c->dbits = (Byte)bd;
- c->ltree = tl;
- c->dtree = td;
- Tracev((stderr, "inflate: codes new\n"));
- }
- return c;
-}
-
-
-local int inflate_codes(s, z, r)
-inflate_blocks_statef *s;
-z_stream *z;
-int r;
-{
- uInt j; /* temporary storage */
- inflate_huft *t; /* temporary pointer */
- uInt e; /* extra bits or operation */
- uLong b; /* bit buffer */
- uInt k; /* bits in bit buffer */
- Bytef *p; /* input data pointer */
- uInt n; /* bytes available there */
- Bytef *q; /* output window write pointer */
- uInt m; /* bytes to end of window or read pointer */
- Bytef *f; /* pointer to copy strings from */
- inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
-
- /* copy input/output information to locals (UPDATE macro restores) */
- LOAD
-
- /* process input and output based on current state */
- while (1) switch (c->mode)
- { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
- case START: /* x: set up for LEN */
-#ifndef SLOW
- if (m >= 258 && n >= 10)
- {
- UPDATE
- r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
- LOAD
- if (r != Z_OK)
- {
- c->mode = r == Z_STREAM_END ? WASH : BADCODE;
- break;
- }
- }
-#endif /* !SLOW */
- c->sub.code.need = c->lbits;
- c->sub.code.tree = c->ltree;
- c->mode = LEN;
- case LEN: /* i: get length/literal/eob next */
- j = c->sub.code.need;
- NEEDBITS(j)
- t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
- DUMPBITS(t->bits)
- e = (uInt)(t->exop);
- if (e == 0) /* literal */
- {
- c->sub.lit = t->base;
- Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
- "inflate: literal '%c'\n" :
- "inflate: literal 0x%02x\n", t->base));
- c->mode = LIT;
- break;
- }
- if (e & 16) /* length */
- {
- c->sub.copy.get = e & 15;
- c->len = t->base;
- c->mode = LENEXT;
- break;
- }
- if ((e & 64) == 0) /* next table */
- {
- c->sub.code.need = e;
- c->sub.code.tree = t->next;
- break;
- }
- if (e & 32) /* end of block */
- {
- Tracevv((stderr, "inflate: end of block\n"));
- c->mode = WASH;
- break;
- }
- c->mode = BADCODE; /* invalid code */
- z->msg = "invalid literal/length code";
- r = Z_DATA_ERROR;
- LEAVE
- case LENEXT: /* i: getting length extra (have base) */
- j = c->sub.copy.get;
- NEEDBITS(j)
- c->len += (uInt)b & inflate_mask[j];
- DUMPBITS(j)
- c->sub.code.need = c->dbits;
- c->sub.code.tree = c->dtree;
- Tracevv((stderr, "inflate: length %u\n", c->len));
- c->mode = DIST;
- case DIST: /* i: get distance next */
- j = c->sub.code.need;
- NEEDBITS(j)
- t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
- DUMPBITS(t->bits)
- e = (uInt)(t->exop);
- if (e & 16) /* distance */
- {
- c->sub.copy.get = e & 15;
- c->sub.copy.dist = t->base;
- c->mode = DISTEXT;
- break;
- }
- if ((e & 64) == 0) /* next table */
- {
- c->sub.code.need = e;
- c->sub.code.tree = t->next;
- break;
- }
- c->mode = BADCODE; /* invalid code */
- z->msg = "invalid distance code";
- r = Z_DATA_ERROR;
- LEAVE
- case DISTEXT: /* i: getting distance extra */
- j = c->sub.copy.get;
- NEEDBITS(j)
- c->sub.copy.dist += (uInt)b & inflate_mask[j];
- DUMPBITS(j)
- Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
- c->mode = COPY;
- case COPY: /* o: copying bytes in window, waiting for space */
-#ifndef __TURBOC__ /* Turbo C bug for following expression */
- f = (uInt)(q - s->window) < c->sub.copy.dist ?
- s->end - (c->sub.copy.dist - (q - s->window)) :
- q - c->sub.copy.dist;
-#else
- f = q - c->sub.copy.dist;
- if ((uInt)(q - s->window) < c->sub.copy.dist)
- f = s->end - (c->sub.copy.dist - (q - s->window));
-#endif
- while (c->len)
- {
- NEEDOUT
- OUTBYTE(*f++)
- if (f == s->end)
- f = s->window;
- c->len--;
- }
- c->mode = START;
- break;
- case LIT: /* o: got literal, waiting for output space */
- NEEDOUT
- OUTBYTE(c->sub.lit)
- c->mode = START;
- break;
- case WASH: /* o: got eob, possibly more output */
- FLUSH
- if (s->read != s->write)
- LEAVE
- c->mode = END;
- case END:
- r = Z_STREAM_END;
- LEAVE
- case BADCODE: /* x: got error */
- r = Z_DATA_ERROR;
- LEAVE
- default:
- r = Z_STREAM_ERROR;
- LEAVE
- }
-}
-
-
-local void inflate_codes_free(c, z)
-inflate_codes_statef *c;
-z_stream *z;
-{
- ZFREE(z, c, sizeof(struct inflate_codes_state));
- Tracev((stderr, "inflate: codes free\n"));
-}
-
-/*+++++*/
-/* inflate_util.c -- data and routines common to blocks and codes
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* copy as much as possible from the sliding window to the output area */
-local int inflate_flush(s, z, r)
-inflate_blocks_statef *s;
-z_stream *z;
-int r;
-{
- uInt n;
- Bytef *p, *q;
-
- /* local copies of source and destination pointers */
- p = z->next_out;
- q = s->read;
-
- /* compute number of bytes to copy as far as end of window */
- n = (uInt)((q <= s->write ? s->write : s->end) - q);
- if (n > z->avail_out) n = z->avail_out;
- if (n && r == Z_BUF_ERROR) r = Z_OK;
-
- /* update counters */
- z->avail_out -= n;
- z->total_out += n;
-
- /* update check information */
- if (s->checkfn != Z_NULL)
- s->check = (*s->checkfn)(s->check, q, n);
-
- /* copy as far as end of window */
- zmemcpy(p, q, n);
- p += n;
- q += n;
-
- /* see if more to copy at beginning of window */
- if (q == s->end)
- {
- /* wrap pointers */
- q = s->window;
- if (s->write == s->end)
- s->write = s->window;
-
- /* compute bytes to copy */
- n = (uInt)(s->write - q);
- if (n > z->avail_out) n = z->avail_out;
- if (n && r == Z_BUF_ERROR) r = Z_OK;
-
- /* update counters */
- z->avail_out -= n;
- z->total_out += n;
-
- /* update check information */
- if (s->checkfn != Z_NULL)
- s->check = (*s->checkfn)(s->check, q, n);
-
- /* copy */
- zmemcpy(p, q, n);
- p += n;
- q += n;
- }
-
- /* update pointers */
- z->next_out = p;
- s->read = q;
-
- /* done */
- return r;
-}
-
-
-/*+++++*/
-/* inffast.c -- process literals and length/distance pairs fast
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* simplify the use of the inflate_huft type with some defines */
-#define base more.Base
-#define next more.Next
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-/* macros for bit input with no checking and for returning unused bytes */
-#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
-#define UNGRAB {n+=(c=k>>3);p-=c;k&=7;}
-
-/* Called with number of bytes left to write in window at least 258
- (the maximum string length) and number of input bytes available
- at least ten. The ten bytes are six bytes for the longest length/
- distance pair plus four bytes for overloading the bit buffer. */
-
-local int inflate_fast(bl, bd, tl, td, s, z)
-uInt bl, bd;
-inflate_huft *tl, *td;
-inflate_blocks_statef *s;
-z_stream *z;
-{
- inflate_huft *t; /* temporary pointer */
- uInt e; /* extra bits or operation */
- uLong b; /* bit buffer */
- uInt k; /* bits in bit buffer */
- Bytef *p; /* input data pointer */
- uInt n; /* bytes available there */
- Bytef *q; /* output window write pointer */
- uInt m; /* bytes to end of window or read pointer */
- uInt ml; /* mask for literal/length tree */
- uInt md; /* mask for distance tree */
- uInt c; /* bytes to copy */
- uInt d; /* distance back to copy from */
- Bytef *r; /* copy source pointer */
-
- /* load input, output, bit values */
- LOAD
-
- /* initialize masks */
- ml = inflate_mask[bl];
- md = inflate_mask[bd];
-
- /* do until not enough input or output space for fast loop */
- do { /* assume called with m >= 258 && n >= 10 */
- /* get literal/length code */
- GRABBITS(20) /* max bits for literal/length code */
- if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
- {
- DUMPBITS(t->bits)
- Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
- "inflate: * literal '%c'\n" :
- "inflate: * literal 0x%02x\n", t->base));
- *q++ = (Byte)t->base;
- m--;
- continue;
- }
- do {
- DUMPBITS(t->bits)
- if (e & 16)
- {
- /* get extra bits for length */
- e &= 15;
- c = t->base + ((uInt)b & inflate_mask[e]);
- DUMPBITS(e)
- Tracevv((stderr, "inflate: * length %u\n", c));
-
- /* decode distance base of block to copy */
- GRABBITS(15); /* max bits for distance code */
- e = (t = td + ((uInt)b & md))->exop;
- do {
- DUMPBITS(t->bits)
- if (e & 16)
- {
- /* get extra bits to add to distance base */
- e &= 15;
- GRABBITS(e) /* get extra bits (up to 13) */
- d = t->base + ((uInt)b & inflate_mask[e]);
- DUMPBITS(e)
- Tracevv((stderr, "inflate: * distance %u\n", d));
-
- /* do the copy */
- m -= c;
- if ((uInt)(q - s->window) >= d) /* offset before dest */
- { /* just copy */
- r = q - d;
- *q++ = *r++; c--; /* minimum count is three, */
- *q++ = *r++; c--; /* so unroll loop a little */
- }
- else /* else offset after destination */
- {
- e = d - (q - s->window); /* bytes from offset to end */
- r = s->end - e; /* pointer to offset */
- if (c > e) /* if source crosses, */
- {
- c -= e; /* copy to end of window */
- do {
- *q++ = *r++;
- } while (--e);
- r = s->window; /* copy rest from start of window */
- }
- }
- do { /* copy all or what's left */
- *q++ = *r++;
- } while (--c);
- break;
- }
- else if ((e & 64) == 0)
- e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop;
- else
- {
- z->msg = "invalid distance code";
- UNGRAB
- UPDATE
- return Z_DATA_ERROR;
- }
- } while (1);
- break;
- }
- if ((e & 64) == 0)
- {
- if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0)
- {
- DUMPBITS(t->bits)
- Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
- "inflate: * literal '%c'\n" :
- "inflate: * literal 0x%02x\n", t->base));
- *q++ = (Byte)t->base;
- m--;
- break;
- }
- }
- else if (e & 32)
- {
- Tracevv((stderr, "inflate: * end of block\n"));
- UNGRAB
- UPDATE
- return Z_STREAM_END;
- }
- else
- {
- z->msg = "invalid literal/length code";
- UNGRAB
- UPDATE
- return Z_DATA_ERROR;
- }
- } while (1);
- } while (m >= 258 && n >= 10);
-
- /* not enough input or output--restore pointers and return */
- UNGRAB
- UPDATE
- return Z_OK;
-}
-
-
-/*+++++*/
-/* zutil.c -- target dependent utility functions for the compression library
- * Copyright (C) 1995 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* From: zutil.c,v 1.8 1995/05/03 17:27:12 jloup Exp */
-
-char *zlib_version = ZLIB_VERSION;
-
-char *z_errmsg[] = {
-"stream end", /* Z_STREAM_END 1 */
-"", /* Z_OK 0 */
-"file error", /* Z_ERRNO (-1) */
-"stream error", /* Z_STREAM_ERROR (-2) */
-"data error", /* Z_DATA_ERROR (-3) */
-"insufficient memory", /* Z_MEM_ERROR (-4) */
-"buffer error", /* Z_BUF_ERROR (-5) */
-""};
-
-
-/*+++++*/
-/* adler32.c -- compute the Adler-32 checksum of a data stream
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* From: adler32.c,v 1.6 1995/05/03 17:27:08 jloup Exp */
-
-#define BASE 65521L /* largest prime smaller than 65536 */
-#define NMAX 5552
-/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
-
-#define DO1(buf) {s1 += *buf++; s2 += s1;}
-#define DO2(buf) DO1(buf); DO1(buf);
-#define DO4(buf) DO2(buf); DO2(buf);
-#define DO8(buf) DO4(buf); DO4(buf);
-#define DO16(buf) DO8(buf); DO8(buf);
-
-/* ========================================================================= */
-uLong adler32(adler, buf, len)
- uLong adler;
- Bytef *buf;
- uInt len;
-{
- unsigned long s1 = adler & 0xffff;
- unsigned long s2 = (adler >> 16) & 0xffff;
- int k;
-
- if (buf == Z_NULL) return 1L;
-
- while (len > 0) {
- k = len < NMAX ? len : NMAX;
- len -= k;
- while (k >= 16) {
- DO16(buf);
- k -= 16;
- }
- if (k != 0) do {
- DO1(buf);
- } while (--k);
- s1 %= BASE;
- s2 %= BASE;
- }
- return (s2 << 16) | s1;
-}
diff --git a/arch/ppc/chrpboot/zlib.h b/arch/ppc/chrpboot/zlib.h
deleted file mode 100644
index fe45c2c64..000000000
--- a/arch/ppc/chrpboot/zlib.h
+++ /dev/null
@@ -1,432 +0,0 @@
-/* $Id: zlib.h,v 1.1 1997/09/19 07:03:47 paulus Exp $ */
-
-/*
- * This file is derived from zlib.h and zconf.h from the zlib-0.95
- * distribution by Jean-loup Gailly and Mark Adler, with some additions
- * by Paul Mackerras to aid in implementing Deflate compression and
- * decompression for PPP packets.
- */
-
-/*
- * ==FILEVERSION 960122==
- *
- * This marker is used by the Linux installation script to determine
- * whether an up-to-date version of this file is already installed.
- */
-
-/* zlib.h -- interface of the 'zlib' general purpose compression library
- version 0.95, Aug 16th, 1995.
-
- Copyright (C) 1995 Jean-loup Gailly and Mark Adler
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-
- Jean-loup Gailly Mark Adler
- gzip@prep.ai.mit.edu madler@alumni.caltech.edu
- */
-
-#ifndef _ZLIB_H
-#define _ZLIB_H
-
-/* #include "zconf.h" */ /* included directly here */
-
-/* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */
-
-/*
- The library does not install any signal handler. It is recommended to
- add at least a handler for SIGSEGV when decompressing; the library checks
- the consistency of the input data whenever possible but may go nuts
- for some forms of corrupted input.
- */
-
-/*
- * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
- * than 64k bytes at a time (needed on systems with 16-bit int).
- * Compile with -DUNALIGNED_OK if it is OK to access shorts or ints
- * at addresses which are not a multiple of their size.
- * Under DOS, -DFAR=far or -DFAR=__far may be needed.
- */
-
-#ifndef STDC
-# if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus)
-# define STDC
-# endif
-#endif
-
-#ifdef __MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */
-# include <unix.h>
-#endif
-
-/* Maximum value for memLevel in deflateInit2 */
-#ifndef MAX_MEM_LEVEL
-# ifdef MAXSEG_64K
-# define MAX_MEM_LEVEL 8
-# else
-# define MAX_MEM_LEVEL 9
-# endif
-#endif
-
-#ifndef FAR
-# define FAR
-#endif
-
-/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
-#ifndef MAX_WBITS
-# define MAX_WBITS 15 /* 32K LZ77 window */
-#endif
-
-/* The memory requirements for deflate are (in bytes):
- 1 << (windowBits+2) + 1 << (memLevel+9)
- that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
- plus a few kilobytes for small objects. For example, if you want to reduce
- the default memory requirements from 256K to 128K, compile with
- make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
- Of course this will generally degrade compression (there's no free lunch).
-
- The memory requirements for inflate are (in bytes) 1 << windowBits
- that is, 32K for windowBits=15 (default value) plus a few kilobytes
- for small objects.
-*/
-
- /* Type declarations */
-
-#ifndef OF /* function prototypes */
-# ifdef STDC
-# define OF(args) args
-# else
-# define OF(args) ()
-# endif
-#endif
-
-typedef unsigned char Byte; /* 8 bits */
-typedef unsigned int uInt; /* 16 bits or more */
-typedef unsigned long uLong; /* 32 bits or more */
-
-typedef Byte FAR Bytef;
-typedef char FAR charf;
-typedef int FAR intf;
-typedef uInt FAR uIntf;
-typedef uLong FAR uLongf;
-
-#ifdef STDC
- typedef void FAR *voidpf;
- typedef void *voidp;
-#else
- typedef Byte FAR *voidpf;
- typedef Byte *voidp;
-#endif
-
-/* end of original zconf.h */
-
-#define ZLIB_VERSION "0.95P"
-
-/*
- The 'zlib' compression library provides in-memory compression and
- decompression functions, including integrity checks of the uncompressed
- data. This version of the library supports only one compression method
- (deflation) but other algorithms may be added later and will have the same
- stream interface.
-
- For compression the application must provide the output buffer and
- may optionally provide the input buffer for optimization. For decompression,
- the application must provide the input buffer and may optionally provide
- the output buffer for optimization.
-
- Compression can be done in a single step if the buffers are large
- enough (for example if an input file is mmap'ed), or can be done by
- repeated calls of the compression function. In the latter case, the
- application must provide more input and/or consume the output
- (providing more output space) before each call.
-*/
-
-typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
-typedef void (*free_func) OF((voidpf opaque, voidpf address, uInt nbytes));
-
-struct internal_state;
-
-typedef struct z_stream_s {
- Bytef *next_in; /* next input byte */
- uInt avail_in; /* number of bytes available at next_in */
- uLong total_in; /* total nb of input bytes read so far */
-
- Bytef *next_out; /* next output byte should be put there */
- uInt avail_out; /* remaining free space at next_out */
- uLong total_out; /* total nb of bytes output so far */
-
- char *msg; /* last error message, NULL if no error */
- struct internal_state FAR *state; /* not visible by applications */
-
- alloc_func zalloc; /* used to allocate the internal state */
- free_func zfree; /* used to free the internal state */
- voidp opaque; /* private data object passed to zalloc and zfree */
-
- Byte data_type; /* best guess about the data type: ascii or binary */
-
-} z_stream;
-
-/*
- The application must update next_in and avail_in when avail_in has
- dropped to zero. It must update next_out and avail_out when avail_out
- has dropped to zero. The application must initialize zalloc, zfree and
- opaque before calling the init function. All other fields are set by the
- compression library and must not be updated by the application.
-
- The opaque value provided by the application will be passed as the first
- parameter for calls of zalloc and zfree. This can be useful for custom
- memory management. The compression library attaches no meaning to the
- opaque value.
-
- zalloc must return Z_NULL if there is not enough memory for the object.
- On 16-bit systems, the functions zalloc and zfree must be able to allocate
- exactly 65536 bytes, but will not be required to allocate more than this
- if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
- pointers returned by zalloc for objects of exactly 65536 bytes *must*
- have their offset normalized to zero. The default allocation function
- provided by this library ensures this (see zutil.c). To reduce memory
- requirements and avoid any allocation of 64K objects, at the expense of
- compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
-
- The fields total_in and total_out can be used for statistics or
- progress reports. After compression, total_in holds the total size of
- the uncompressed data and may be saved for use in the decompressor
- (particularly if the decompressor wants to decompress everything in
- a single step).
-*/
-
- /* constants */
-
-#define Z_NO_FLUSH 0
-#define Z_PARTIAL_FLUSH 1
-#define Z_FULL_FLUSH 2
-#define Z_SYNC_FLUSH 3 /* experimental: partial_flush + byte align */
-#define Z_FINISH 4
-#define Z_PACKET_FLUSH 5
-/* See deflate() below for the usage of these constants */
-
-#define Z_OK 0
-#define Z_STREAM_END 1
-#define Z_ERRNO (-1)
-#define Z_STREAM_ERROR (-2)
-#define Z_DATA_ERROR (-3)
-#define Z_MEM_ERROR (-4)
-#define Z_BUF_ERROR (-5)
-/* error codes for the compression/decompression functions */
-
-#define Z_BEST_SPEED 1
-#define Z_BEST_COMPRESSION 9
-#define Z_DEFAULT_COMPRESSION (-1)
-/* compression levels */
-
-#define Z_FILTERED 1
-#define Z_HUFFMAN_ONLY 2
-#define Z_DEFAULT_STRATEGY 0
-
-#define Z_BINARY 0
-#define Z_ASCII 1
-#define Z_UNKNOWN 2
-/* Used to set the data_type field */
-
-#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
-
-extern char *zlib_version;
-/* The application can compare zlib_version and ZLIB_VERSION for consistency.
- If the first character differs, the library code actually used is
- not compatible with the zlib.h header file used by the application.
- */
-
- /* basic functions */
-
-extern int inflateInit OF((z_stream *strm));
-/*
- Initializes the internal stream state for decompression. The fields
- zalloc and zfree must be initialized before by the caller. If zalloc and
- zfree are set to Z_NULL, inflateInit updates them to use default allocation
- functions.
-
- inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
- enough memory. msg is set to null if there is no error message.
- inflateInit does not perform any decompression: this will be done by
- inflate().
-*/
-
-
-extern int inflate OF((z_stream *strm, int flush));
-/*
- Performs one or both of the following actions:
-
- - Decompress more input starting at next_in and update next_in and avail_in
- accordingly. If not all input can be processed (because there is not
- enough room in the output buffer), next_in is updated and processing
- will resume at this point for the next call of inflate().
-
- - Provide more output starting at next_out and update next_out and avail_out
- accordingly. inflate() always provides as much output as possible
- (until there is no more input data or no more space in the output buffer).
-
- Before the call of inflate(), the application should ensure that at least
- one of the actions is possible, by providing more input and/or consuming
- more output, and updating the next_* and avail_* values accordingly.
- The application can consume the uncompressed output when it wants, for
- example when the output buffer is full (avail_out == 0), or after each
- call of inflate().
-
- If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH,
- inflate flushes as much output as possible to the output buffer. The
- flushing behavior of inflate is not specified for values of the flush
- parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the
- current implementation actually flushes as much output as possible
- anyway. For Z_PACKET_FLUSH, inflate checks that once all the input data
- has been consumed, it is expecting to see the length field of a stored
- block; if not, it returns Z_DATA_ERROR.
-
- inflate() should normally be called until it returns Z_STREAM_END or an
- error. However if all decompression is to be performed in a single step
- (a single call of inflate), the parameter flush should be set to
- Z_FINISH. In this case all pending input is processed and all pending
- output is flushed; avail_out must be large enough to hold all the
- uncompressed data. (The size of the uncompressed data may have been saved
- by the compressor for this purpose.) The next operation on this stream must
- be inflateEnd to deallocate the decompression state. The use of Z_FINISH
- is never required, but can be used to inform inflate that a faster routine
- may be used for the single inflate() call.
-
- inflate() returns Z_OK if some progress has been made (more input
- processed or more output produced), Z_STREAM_END if the end of the
- compressed data has been reached and all uncompressed output has been
- produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if
- the stream structure was inconsistent (for example if next_in or next_out
- was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no
- progress is possible or if there was not enough room in the output buffer
- when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then
- call inflateSync to look for a good compression block. */
-
-
-extern int inflateEnd OF((z_stream *strm));
-/*
- All dynamically allocated data structures for this stream are freed.
- This function discards any unprocessed input and does not flush any
- pending output.
-
- inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
- was inconsistent. In the error case, msg may be set but then points to a
- static string (which must not be deallocated).
-*/
-
- /* advanced functions */
-
-extern int inflateInit2 OF((z_stream *strm,
- int windowBits));
-/*
- This is another version of inflateInit with more compression options. The
- fields next_out, zalloc and zfree must be initialized before by the caller.
-
- The windowBits parameter is the base two logarithm of the maximum window
- size (the size of the history buffer). It should be in the range 8..15 for
- this version of the library (the value 16 will be allowed soon). The
- default value is 15 if inflateInit is used instead. If a compressed stream
- with a larger window size is given as input, inflate() will return with
- the error code Z_DATA_ERROR instead of trying to allocate a larger window.
-
- If next_out is not null, the library will use this buffer for the history
- buffer; the buffer must either be large enough to hold the entire output
- data, or have at least 1<<windowBits bytes. If next_out is null, the
- library will allocate its own buffer (and leave next_out null). next_in
- need not be provided here but must be provided by the application for the
- next call of inflate().
-
- If the history buffer is provided by the application, next_out must
- never be changed by the application since the decompressor maintains
- history information inside this buffer from call to call; the application
- can only reset next_out to the beginning of the history buffer when
- avail_out is zero and all output has been consumed.
-
- inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
- not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
- windowBits < 8). msg is set to null if there is no error message.
- inflateInit2 does not perform any decompression: this will be done by
- inflate().
-*/
-
-extern int inflateSync OF((z_stream *strm));
-/*
- Skips invalid compressed data until the special marker (see deflate()
- above) can be found, or until all available input is skipped. No output
- is provided.
-
- inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
- if no more input was provided, Z_DATA_ERROR if no marker has been found,
- or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
- case, the application may save the current current value of total_in which
- indicates where valid compressed data was found. In the error case, the
- application may repeatedly call inflateSync, providing more input each time,
- until success or end of the input data.
-*/
-
-extern int inflateReset OF((z_stream *strm));
-/*
- This function is equivalent to inflateEnd followed by inflateInit,
- but does not free and reallocate all the internal decompression state.
- The stream will keep attributes that may have been set by inflateInit2.
-
- inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
- stream state was inconsistent (such as zalloc or state being NULL).
-*/
-
-extern int inflateIncomp OF((z_stream *strm));
-/*
- This function adds the data at next_in (avail_in bytes) to the output
- history without performing any output. There must be no pending output,
- and the decompressor must be expecting to see the start of a block.
- Calling this function is equivalent to decompressing a stored block
- containing the data at next_in (except that the data is not output).
-*/
-
- /* checksum functions */
-
-/*
- This function is not related to compression but is exported
- anyway because it might be useful in applications using the
- compression library.
-*/
-
-extern uLong adler32 OF((uLong adler, Bytef *buf, uInt len));
-
-/*
- Update a running Adler-32 checksum with the bytes buf[0..len-1] and
- return the updated checksum. If buf is NULL, this function returns
- the required initial value for the checksum.
- An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
- much faster. Usage example:
-
- uLong adler = adler32(0L, Z_NULL, 0);
-
- while (read_buffer(buffer, length) != EOF) {
- adler = adler32(adler, buffer, length);
- }
- if (adler != original_adler) error();
-*/
-
-#ifndef _Z_UTIL_H
- struct internal_state {int dummy;}; /* hack for buggy compilers */
-#endif
-
-#endif /* _ZLIB_H */
diff --git a/arch/ppc/coffboot/Makefile b/arch/ppc/coffboot/Makefile
index 3f5ef4a09..72a6df455 100644
--- a/arch/ppc/coffboot/Makefile
+++ b/arch/ppc/coffboot/Makefile
@@ -9,6 +9,12 @@ CROSS_COMPILE =powerpc-eabi-
endif
+# PowerPC (cross) tools
+ifneq ($(shell uname -m),ppc)
+#CROSS_COMPILE =powerpc-eabi-
+CROSS_COMPILE =ppc-linux-elf-
+endif
+
HOSTCC = gcc
HOSTCFLAGS = -O -I$(TOPDIR)/include
@@ -24,6 +30,11 @@ GZ = gzip -9
OBJS = crt0.o start.o main.o misc.o string.o zlib.o
LIBS = $(TOPDIR)/lib/lib.a
+ifeq ($(CONFIG_ALL_PPC),y)
+# yes, we want to build pmac stuff
+CONFIG_PMAC = y
+endif
+
ifeq ($(CONFIG_PMAC),y)
hack-coff: hack-coff.c
$(HOSTCC) $(HOSTCFLAGS) -o hack-coff hack-coff.c
@@ -73,8 +84,6 @@ vmlinux.coff.initrd: vmlinux.gz
floppy: vmlinux.gz
-
-
endif
vmlinux.gz: $(TOPDIR)/vmlinux
diff --git a/arch/ppc/coffboot/misc.S b/arch/ppc/coffboot/misc.S
index 1a9f07129..df542a522 100644
--- a/arch/ppc/coffboot/misc.S
+++ b/arch/ppc/coffboot/misc.S
@@ -21,13 +21,16 @@ setup_bats:
bne 4f
ori 4,4,4 /* set up BAT registers for 601 */
li 5,0x7f
- b 5f
-4: ori 4,4,0xff /* set up BAT registers for 604 */
+ mtibatu 3,4
+ mtibatl 3,5
+ isync
+ blr
+4: ori 4,4,0xfe /* set up BAT registers for 604 */
li 5,2
- mtdbatu 3,4
mtdbatl 3,5
-5: mtibatu 3,4
+ mtdbatu 3,4
mtibatl 3,5
+ mtibatu 3,4
isync
blr
diff --git a/arch/ppc/coffboot/zlib.c b/arch/ppc/coffboot/zlib.c
index 12d07df41..1a839043c 100644
--- a/arch/ppc/coffboot/zlib.c
+++ b/arch/ppc/coffboot/zlib.c
@@ -11,7 +11,7 @@
* - added Z_PACKET_FLUSH (see zlib.h for details)
* - added inflateIncomp
*
- * $Id: zlib.c,v 1.1 1997/08/30 04:51:48 ralf Exp $
+ * $Id: zlib.c,v 1.2 1998/09/03 17:40:53 cort Exp $
*/
/*+++++*/
@@ -80,7 +80,7 @@ extern char *z_errmsg[]; /* indexed by 1-zlib_error */
/* functions */
-#include <string.h>
+#include <linux/string.h>
#define zmemcpy memcpy
#define zmemzero(dest, len) memset(dest, 0, len)
diff --git a/arch/ppc/common_defconfig b/arch/ppc/common_defconfig
index 4fe557754..916af99f1 100644
--- a/arch/ppc/common_defconfig
+++ b/arch/ppc/common_defconfig
@@ -21,7 +21,7 @@ CONFIG_ALL_PPC=y
CONFIG_EXPERIMENTAL=y
CONFIG_MODULES=y
CONFIG_MODVERSIONS=y
-# CONFIG_KMOD is not set
+CONFIG_KMOD=y
CONFIG_PCI=y
# CONFIG_PCI_QUIRKS is not set
CONFIG_PCI_OLD_PROC=y
@@ -34,16 +34,20 @@ CONFIG_KERNEL_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_BINFMT_JAVA is not set
# CONFIG_PARPORT is not set
+# CONFIG_VGA_CONSOLE is not set
CONFIG_FB=y
CONFIG_FB_COMPAT_XPMAC=y
-# CONFIG_PMAC_PBOOK is not set
+CONFIG_PMAC_PBOOK=y
CONFIG_MAC_KEYBOARD=y
-# CONFIG_MAC_FLOPPY is not set
-# CONFIG_MAC_SERIAL is not set
-# CONFIG_MACMOUSE is not set
+CONFIG_MAC_FLOPPY=y
+CONFIG_MAC_SERIAL=y
+CONFIG_ADBMOUSE=y
+CONFIG_BLK_DEV_IDE_PMAC=y
CONFIG_PROC_DEVICETREE=y
# CONFIG_KGDB is not set
-# CONFIG_XMON is not set
+CONFIG_XMON=y
+# CONFIG_TOTALMP is not set
+# CONFIG_BOOTX_TEXT is not set
#
# Plug and Play support
@@ -53,7 +57,7 @@ CONFIG_PROC_DEVICETREE=y
#
# Block devices
#
-CONFIG_BLK_DEV_FD=y
+# CONFIG_BLK_DEV_FD is not set
CONFIG_BLK_DEV_IDE=y
# CONFIG_BLK_DEV_HD_IDE is not set
CONFIG_BLK_DEV_IDEDISK=y
@@ -66,7 +70,7 @@ CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDEPCI is not set
CONFIG_BLK_DEV_SL82C105=y
# CONFIG_IDE_CHIPSETS is not set
-CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP=m
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_MD is not set
CONFIG_BLK_DEV_RAM=y
@@ -94,7 +98,7 @@ CONFIG_INET=y
# CONFIG_NET_IPGRE is not set
# CONFIG_IP_ALIAS is not set
CONFIG_SYN_COOKIES=y
-CONFIG_INET_RARP=y
+# CONFIG_INET_RARP is not set
# CONFIG_IP_NOSR is not set
CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
@@ -116,7 +120,7 @@ CONFIG_SKB_LARGE=y
#
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
+CONFIG_CHR_DEV_ST=m
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
# CONFIG_CHR_DEV_SG is not set
@@ -146,11 +150,11 @@ CONFIG_BLK_DEV_SR_VENDOR=y
# CONFIG_SCSI_NCR53C406A is not set
# CONFIG_SCSI_NCR53C7xx is not set
CONFIG_SCSI_NCR53C8XX=y
-# CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT is not set
-CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE=y
-CONFIG_SCSI_NCR53C8XX_IOMAPPED=y
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4
CONFIG_SCSI_NCR53C8XX_SYNC=5
+# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
+CONFIG_SCSI_NCR53C8XX_IOMAPPED=y
# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_PCI2000 is not set
@@ -166,7 +170,7 @@ CONFIG_SCSI_NCR53C8XX_SYNC=5
# CONFIG_SCSI_DEBUG is not set
CONFIG_SCSI_MESH=y
CONFIG_SCSI_MESH_SYNC_RATE=5
-CONFIG_SCSI_MAC53C94=y
+CONFIG_SCSI_MAC53C94=m
#
# Network device support
@@ -176,17 +180,17 @@ CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_EQUALIZER is not set
CONFIG_NET_ETHERNET=y
-# CONFIG_MACE is not set
-# CONFIG_BMAC is not set
+CONFIG_MACE=y
+CONFIG_BMAC=y
# CONFIG_NET_VENDOR_3COM is not set
-CONFIG_LANCE=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_YELLOWFIN is not set
# CONFIG_NET_ISA is not set
CONFIG_NET_EISA=y
-CONFIG_PCNET32=y
+CONFIG_PCNET32=m
# CONFIG_AC3200 is not set
# CONFIG_APRICOT is not set
# CONFIG_CS89x0 is not set
@@ -195,19 +199,26 @@ CONFIG_DE4X5=y
# CONFIG_DGRS is not set
# CONFIG_EEXPRESS_PRO100 is not set
# CONFIG_LNE390 is not set
+# CONFIG_NE3210 is not set
# CONFIG_NE2K_PCI is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
# CONFIG_ES3210 is not set
# CONFIG_EPIC100 is not set
-# CONFIG_TLAN is not set
# CONFIG_ZNET is not set
# CONFIG_NET_POCKET is not set
# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
# CONFIG_DLCI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
+CONFIG_PPP=y
+CONFIG_SLIP=m
+# CONFIG_SLIP_COMPRESSED is not set
+# CONFIG_SLIP_SMART is not set
+# CONFIG_SLIP_MODE_SLIP6 is not set
# CONFIG_NET_RADIO is not set
# CONFIG_TR is not set
# CONFIG_SHAPER is not set
+# CONFIG_HOSTESS_SV11 is not set
#
# Amateur Radio support
@@ -225,59 +236,27 @@ CONFIG_DE4X5=y
# CONFIG_CD_NO_IDESCSI is not set
#
-# Filesystems
-#
-# CONFIG_QUOTA is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_EXT2_FS=y
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_NFS_FS=y
-# CONFIG_NFSD is not set
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-# CONFIG_CODA_FS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_AFFS_FS is not set
-CONFIG_HFS_FS=y
-# CONFIG_ROMFS_FS is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_ADFS_FS is not set
-# CONFIG_DEVPTS_FS is not set
-CONFIG_MAC_PARTITION=y
-# CONFIG_NLS is not set
-
-#
# Console drivers
#
CONFIG_DUMMY_CONSOLE=y
-CONFIG_FB_OF=y
-# CONFIG_FB_S3TRIO is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_CT65550 is not set
-CONFIG_FB_VGA=y
+# CONFIG_FB_OF is not set
+# CONFIG_FB_MATROX is not set
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_VGA=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+# CONFIG_FBCON_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
#
# Character devices
#
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
-# CONFIG_SERIAL is not set
+CONFIG_SERIAL=m
# CONFIG_SERIAL_EXTENDED is not set
# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
CONFIG_MOUSE=y
# CONFIG_ATIXL_BUSMOUSE is not set
# CONFIG_BUSMOUSE is not set
@@ -285,15 +264,12 @@ CONFIG_MOUSE=y
CONFIG_PSMOUSE=y
# CONFIG_82C710_MOUSE is not set
# CONFIG_PC110_PAD is not set
-# CONFIG_UMISC is not set
# CONFIG_QIC02_TAPE is not set
-# CONFIG_APM is not set
# CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set
# CONFIG_VIDEO_DEV is not set
# CONFIG_NVRAM is not set
# CONFIG_JOYSTICK is not set
-# CONFIG_MISC_RADIO is not set
#
# Ftape, the floppy tape device driver
@@ -301,6 +277,104 @@ CONFIG_PSMOUSE=y
# CONFIG_FTAPE is not set
#
+# Filesystems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_EXT2_FS=y
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+CONFIG_PROC_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFSD=y
+# CONFIG_NFSD_SUN is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_CODA_FS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_AFFS_FS is not set
+CONFIG_HFS_FS=y
+# CONFIG_ROMFS_FS is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_SMD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_KOI8_R is not set
+
+#
# Sound
#
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+CONFIG_DMASOUND=y
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+CONFIG_SOUND_OSS=y
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_ADLIB is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+# CONFIG_SOUND_CS4232 is not set
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_SOFTOSS is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_UART6850 is not set
+
+#
+# Additional low level sound drivers
+#
+# CONFIG_LOWLEVEL_SOUND is not set
diff --git a/arch/ppc/config.in b/arch/ppc/config.in
index 31c3ed423..59223a45c 100644
--- a/arch/ppc/config.in
+++ b/arch/ppc/config.in
@@ -1,41 +1,33 @@
-# $Id: config.in,v 1.65 1998/07/20 18:42:27 geert Exp $
+# $Id: config.in,v 1.80 1998/11/11 03:54:56 paulus Exp $
# For a description of the syntax of this configuration file,
# see the Configure script.
#
mainmenu_name "Linux/PowerPC Kernel Configuration"
-
-
mainmenu_option next_comment
comment 'Platform support'
define_bool CONFIG_PPC y
-#if [ "`uname`" != "Linux" -o "`uname -m`" != "ppc" ]; then
-# define_bool CONFIG_CROSSCOMPILE y
-#else
-# define_bool CONFIG_NATIVE y
-#fi
-
choice 'Processor type' \
"6xx/7xx CONFIG_6xx \
860/821 CONFIG_8xx" 6xx/7xx
choice 'Machine Type' \
"PowerMac CONFIG_PMAC \
- PReP CONFIG_PREP \
+ PReP/MTX CONFIG_PREP \
CHRP CONFIG_CHRP \
PowerMac/PReP/CHRP CONFIG_ALL_PPC \
APUS CONFIG_APUS \
- MBX CONFIG_MBX" PReP
+ MBX CONFIG_MBX" PowerMac
+
+if [ "$CONFIG_ALL_PPC" != "y" ];then
+ define_bool CONFIG_MACH_SPECIFIC y
+fi
endmenu
if [ "$CONFIG_MBX" = "y" ];then
define_bool CONFIG_SERIAL_CONSOLE y
fi
-if [ "$CONFIG_ALL_PPC" != "y" ]; then
- define_bool CONFIG_MACH_SPECIFIC y
-fi
-
mainmenu_option next_comment
comment 'General setup'
@@ -77,24 +69,23 @@ if [ "$CONFIG_PARPORT" != "n" ]; then
fi
fi
+bool 'Support for VGA Console' CONFIG_VGA_CONSOLE
bool 'Support for frame buffer devices' CONFIG_FB
if [ "$CONFIG_FB" = "y" ]; then
bool 'Backward compatibility mode for Xpmac' CONFIG_FB_COMPAT_XPMAC
fi
-if [ "$CONFIG_FB" != "y" ]; then
- bool 'Support for VGA Console' CONFIG_VGA_CONSOLE
-fi
bool 'Power management support for PowerBook 3400/2400' CONFIG_PMAC_PBOOK
bool 'Support for PowerMac keyboard' CONFIG_MAC_KEYBOARD
bool 'Support for PowerMac floppy' CONFIG_MAC_FLOPPY
bool 'Support for PowerMac serial ports' CONFIG_MAC_SERIAL
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool 'Support for PowerMac mouse (EXPERIMENTAL)' CONFIG_MACMOUSE
-fi
+bool 'Support for PowerMac ADB mouse' CONFIG_ADBMOUSE
+bool 'Support for PowerMac IDE devices (must also enable IDE)' CONFIG_BLK_DEV_IDE_PMAC
bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE
bool 'Include kgdb kernel debugger' CONFIG_KGDB
bool 'Include xmon kernel debugger' CONFIG_XMON
+bool 'Support for TotalImpact TotalMP' CONFIG_TOTALMP
+bool 'Support for early boot text console (BootX only)' CONFIG_BOOTX_TEXT
if [ "$CONFIG_APUS" = "y" ]; then
define_bool CONFIG_FB_CONSOLE y
@@ -103,9 +94,8 @@ if [ "$CONFIG_APUS" = "y" ]; then
define_bool CONFIG_AMIGAMOUSE y
define_bool CONFIG_ABSTRACT_CONSOLE y
define_bool CONFIG_FB y
- tristate 'Amiga floppy support' CONFIG_AMIGA_FLOPPY
- bool 'Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE
tristate 'Amiga builtin serial support' CONFIG_AMIGA_BUILTIN_SERIAL
+ tristate 'Parallel printer support' CONFIG_M68K_PRINTER
tristate 'GVP IO-Extender support' CONFIG_GVPIOEXT
dep_tristate 'GVP IO-Extender parallel printer support' CONFIG_GVPIOEXT_LP $CONFIG_GVPIOEXT
dep_tristate 'GVP IO-Extender PLIP support' CONFIG_GVPIOEXT_PLIP $CONFIG_GVPIOEXT
@@ -114,7 +104,8 @@ if [ "$CONFIG_APUS" = "y" ]; then
"$CONFIG_MULTIFACE_III_TTY" = "y" ]; then
bool 'Support for serial port console' CONFIG_SERIAL_CONSOLE
fi
-bool '/proc/hardware support' CONFIG_PROC_HARDWARE
+ bool 'Use power LED as a heartbeat' CONFIG_HEARTBEAT
+ bool '/proc/hardware support' CONFIG_PROC_HARDWARE
fi
endmenu
@@ -129,9 +120,7 @@ fi
mainmenu_option next_comment
comment 'SCSI support'
-
tristate 'SCSI support' CONFIG_SCSI
-
if [ "$CONFIG_SCSI" != "n" ]; then
source drivers/scsi/Config.in
fi
@@ -174,22 +163,15 @@ source drivers/video/Config.in
endmenu
source drivers/char/Config.in
-
source fs/Config.in
-
source fs/nls/Config.in
mainmenu_option next_comment
comment 'Sound'
-
tristate 'Sound card support' CONFIG_SOUND
if [ "$CONFIG_SOUND" != "n" ]; then
- if [ "$CONFIG_APUS" = "y" -o "$CONFIG_PMAC" = "y" ]; then
- tristate 'Amiga or PowerMac DMA sound support' CONFIG_DMASOUND
- fi
- if [ "$CONFIG_PREP" = "y" -o "$CONFIG_CHRP" = "y" ]; then
- source drivers/sound/Config.in
- fi
+ tristate 'Amiga or PowerMac DMA sound support' CONFIG_DMASOUND
+ source drivers/sound/Config.in
fi
endmenu
diff --git a/arch/ppc/defconfig b/arch/ppc/defconfig
index 495b786b3..ae1303bb4 100644
--- a/arch/ppc/defconfig
+++ b/arch/ppc/defconfig
@@ -35,16 +35,20 @@ CONFIG_KERNEL_ELF=y
CONFIG_BINFMT_MISC=m
# CONFIG_BINFMT_JAVA is not set
# CONFIG_PARPORT is not set
-# CONFIG_FB is not set
# CONFIG_VGA_CONSOLE is not set
-# CONFIG_PMAC_PBOOK is not set
+CONFIG_FB=y
+CONFIG_FB_COMPAT_XPMAC=y
+CONFIG_PMAC_PBOOK=y
CONFIG_MAC_KEYBOARD=y
CONFIG_MAC_FLOPPY=y
CONFIG_MAC_SERIAL=y
-CONFIG_MACMOUSE=y
+CONFIG_ADBMOUSE=y
+CONFIG_BLK_DEV_IDE_PMAC=y
CONFIG_PROC_DEVICETREE=y
# CONFIG_KGDB is not set
# CONFIG_XMON is not set
+# CONFIG_TOTALMP is not set
+CONFIG_BOOTX_TEXT=y
#
# Plug and Play support
@@ -64,12 +68,16 @@ CONFIG_BLK_DEV_IDE=y
CONFIG_BLK_DEV_IDEDISK=y
CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_BLK_DEV_CMD640 is not set
# CONFIG_BLK_DEV_RZ1000 is not set
# CONFIG_BLK_DEV_IDEPCI is not set
# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDE_PMAC=y
+CONFIG_BLK_DEV_IDEDMA_PMAC=y
+CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_PMAC_IDEDMA_AUTO=y
# CONFIG_IDE_CHIPSETS is not set
#
@@ -159,7 +167,7 @@ CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_AHA152X is not set
# CONFIG_SCSI_AHA1542 is not set
# CONFIG_SCSI_AHA1740 is not set
-CONFIG_SCSI_AIC7XXX=m
+CONFIG_SCSI_AIC7XXX=y
# CONFIG_OVERRIDE_CMDS is not set
CONFIG_AIC7XXX_PROC_STATS=y
CONFIG_AIC7XXX_RESET_DELAY=15
@@ -216,23 +224,26 @@ CONFIG_NET_EISA=y
# CONFIG_AC3200 is not set
# CONFIG_APRICOT is not set
# CONFIG_CS89x0 is not set
-CONFIG_DE4X5=m
+CONFIG_DE4X5=y
CONFIG_DEC_ELCP=m
# CONFIG_DGRS is not set
# CONFIG_EEXPRESS_PRO100 is not set
# CONFIG_LNE390 is not set
+# CONFIG_NE3210 is not set
# CONFIG_NE2K_PCI is not set
# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
# CONFIG_ES3210 is not set
# CONFIG_EPIC100 is not set
# CONFIG_ZNET is not set
# CONFIG_NET_POCKET is not set
# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
# CONFIG_DLCI is not set
# CONFIG_LTPC is not set
# CONFIG_COPS is not set
# CONFIG_IPDDP is not set
-CONFIG_PPP=m
+CONFIG_PPP=y
#
# CCP compressors for PPP are only built as modules.
@@ -241,6 +252,7 @@ CONFIG_PPP=m
# CONFIG_NET_RADIO is not set
# CONFIG_TR is not set
# CONFIG_SHAPER is not set
+# CONFIG_HOSTESS_SV11 is not set
#
# Amateur Radio support
@@ -260,21 +272,44 @@ CONFIG_PPP=m
#
# Console drivers
#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FB_OF=y
+CONFIG_FB_CONTROL=y
+CONFIG_FB_PLATINUM=y
+CONFIG_FB_VALKYRIE=y
+CONFIG_FB_ATY=y
+CONFIG_FB_IMSTT=y
+CONFIG_FB_CT65550=y
+# CONFIG_FB_S3TRIO is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+CONFIG_FBCON_CFB32=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+CONFIG_FONT_SUN8x16=y
+CONFIG_FONT_SUN12x22=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
#
# Character devices
#
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
-# CONFIG_SERIAL is not set
+CONFIG_SERIAL=m
# CONFIG_SERIAL_EXTENDED is not set
# CONFIG_SERIAL_NONSTANDARD is not set
CONFIG_UNIX98_PTYS=y
CONFIG_UNIX98_PTY_COUNT=256
# CONFIG_MOUSE is not set
-# CONFIG_UMISC is not set
# CONFIG_QIC02_TAPE is not set
-# CONFIG_APM is not set
# CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set
# CONFIG_VIDEO_DEV is not set
@@ -301,6 +336,7 @@ CONFIG_VFAT_FS=m
CONFIG_PROC_FS=y
CONFIG_NFS_FS=y
CONFIG_NFSD=y
+# CONFIG_NFSD_SUN is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
# CONFIG_CODA_FS is not set
@@ -309,12 +345,16 @@ CONFIG_LOCKD=y
# CONFIG_NTFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_AFFS_FS is not set
-CONFIG_HFS_FS=m
+CONFIG_HFS_FS=y
# CONFIG_ROMFS_FS is not set
CONFIG_AUTOFS_FS=y
# CONFIG_UFS_FS is not set
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_SMD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
CONFIG_DEVPTS_FS=y
# CONFIG_ADFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
CONFIG_MAC_PARTITION=y
CONFIG_NLS=y
@@ -351,4 +391,11 @@ CONFIG_NLS_CODEPAGE_437=y
#
# Sound
#
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+CONFIG_DMASOUND=y
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_OSS is not set
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index 6f1060560..4846d5ebb 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -11,11 +11,11 @@
$(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $*.o
O_TARGET := kernel.o
-OX_OBJS := ppc_ksyms.o
+OX_OBJS := ppc_ksyms.o setup.o
O_OBJS := traps.o irq.o idle.o time.o process.o signal.o syscalls.o misc.o \
- bitops.o setup.o ptrace.o align.o ppc_htab.o
+ bitops.o ptrace.o align.o ppc_htab.o feature.o
ifdef CONFIG_PCI
O_OBJS += pci.o
@@ -23,6 +23,9 @@ endif
ifdef CONFIG_KGDB
O_OBJS += ppc-stub.o
endif
+ifdef CONFIG_TOTALMP
+O_OBJS += totalmp.o
+endif
ifeq ($(CONFIG_MBX),y)
O_OBJS += mbx_setup.o mbx_pci.o softemu8xx.o
@@ -31,10 +34,10 @@ ifeq ($(CONFIG_APUS),y)
O_OBJS += apus_setup.o prom.o openpic.o
else
O_OBJS += prep_time.o pmac_time.o chrp_time.o \
- pmac_setup.o pmac_support.o chrp_setup.o \
+ pmac_setup.o pmac_support.o \
prep_pci.o pmac_pci.o chrp_pci.o \
residual.o prom.o openpic.o
-OX_OBJS += prep_setup.o
+OX_OBJS += chrp_setup.o prep_setup.o
endif
endif
diff --git a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c
index 70284674b..83ee7756d 100644
--- a/arch/ppc/kernel/align.c
+++ b/arch/ppc/kernel/align.c
@@ -265,7 +265,7 @@ fix_alignment(struct pt_regs *regs)
#else
giveup_fpu();
#endif
- cvt_fd(&data.f, &current->tss.fpr[reg]);
+ cvt_fd(&data.f, &current->tss.fpr[reg], &current->tss.fpscr);
/* current->tss.fpr[reg] = data.f; */
break;
case ST+F+S:
@@ -275,7 +275,7 @@ fix_alignment(struct pt_regs *regs)
#else
giveup_fpu();
#endif
- cvt_df(&current->tss.fpr[reg], &data.f);
+ cvt_df(&current->tss.fpr[reg], &data.f, &current->tss.fpscr);
/* data.f = current->tss.fpr[reg]; */
break;
default:
diff --git a/arch/ppc/kernel/apus_setup.c b/arch/ppc/kernel/apus_setup.c
index ea2bc5690..93c2fe2d1 100644
--- a/arch/ppc/kernel/apus_setup.c
+++ b/arch/ppc/kernel/apus_setup.c
@@ -19,6 +19,7 @@
#include <asm/amigahw.h>
#include <asm/amigappc.h>
#include <asm/pgtable.h>
+#include <asm/io.h>
unsigned long m68k_machtype;
char debug_device[6] = "";
@@ -60,6 +61,8 @@ extern struct mem_info memory[NUM_MEMINFO];/* memory description */
extern void amiga_floppy_setup(char *, int *);
extern void config_amiga(void);
+static int __60nsram = 0;
+
/*********************************************************** SETUP */
/* From arch/m68k/kernel/setup.c. */
__initfunc(void apus_setup_arch(unsigned long * memory_start_p,
@@ -75,10 +78,17 @@ __initfunc(void apus_setup_arch(unsigned long * memory_start_p,
for( p = cmd_line; p && *p; ) {
i = 0;
if (!strncmp( p, "debug=", 6 )) {
- strncpy( debug_device, p+6, sizeof(debug_device)-1 );
- debug_device[sizeof(debug_device)-1] = 0;
- if ((q = strchr( debug_device, ' ' ))) *q = 0;
- i = 1;
+ strncpy( debug_device, p+6, sizeof(debug_device)-1 );
+ debug_device[sizeof(debug_device)-1] = 0;
+ if ((q = strchr( debug_device, ' ' ))) *q = 0;
+ i = 1;
+ } else if (!strncmp( p, "60nsram", 7 )) {
+ APUS_WRITE (APUS_REG_WAITSTATE,
+ REGWAITSTATE_SETRESET
+ |REGWAITSTATE_PPCR
+ |REGWAITSTATE_PPCW);
+ __60nsram = 1;
+ i = 1;
}
if (i) {
@@ -95,63 +105,85 @@ __initfunc(void apus_setup_arch(unsigned long * memory_start_p,
config_amiga();
}
+
+void get_current_tb(unsigned long long *time)
+{
+ __asm __volatile ("1:mftbu 4 \n\t"
+ " mftb 5 \n\t"
+ " mftbu 6 \n\t"
+ " cmpw 4,6 \n\t"
+ " bne 1b \n\t"
+ " stw 4,0(%0)\n\t"
+ " stw 5,4(%0)\n\t"
+ :
+ : "r" (time)
+ : "r4", "r5", "r6");
+}
+
+
void apus_calibrate_decr(void)
{
int freq, divisor;
- unsigned char c = *(unsigned char*)ZTWO_VADDR(0xf00011);
- switch (c)
+ /* This algorithm for determining the bus speed was
+ contributed by Ralph Schmidt. */
+ unsigned long long start, stop;
+ int bus_speed;
+
{
- case 'A':
- case 'B':
- if (amiga_model == AMI_1200 || amiga_model == AMI_2000){
- freq = 1;
- } else {
- freq = 0;
- }
- break;
- case 'C':
- if (amiga_model == AMI_1200 || amiga_model == AMI_2000){
- freq = 0;
- } else {
- freq = 1;
+ unsigned long loop = amiga_eclock / 10;
+
+ get_current_tb (&start);
+ while (loop--) {
+ unsigned char tmp;
+
+ tmp = ciaa.pra;
}
- break;
- case 'D':
- freq = 1;
- break;
- default:
- freq = 0;
- printk (" *Unknown CPU speed ID ('%c')* ", c);
- break;
+ get_current_tb (&stop);
+ }
+
+ bus_speed = (((unsigned long)(stop-start))*10*4) / 1000000;
+ if (AMI_1200 == amiga_model)
+ bus_speed /= 2;
+
+ if ((bus_speed >= 47) && (bus_speed < 53)) {
+ bus_speed = 50;
+ freq = 12500000;
+ } else if ((bus_speed >= 57) && (bus_speed < 63)) {
+ bus_speed = 60;
+ freq = 15000000;
+ } else if ((bus_speed >= 63) && (bus_speed < 69)) {
+ bus_speed = 66;
+ freq = 16500000;
+ } else {
+ printk ("APUS: Unable to determine bus speed (%d). "
+ "Defaulting to 50MHz", bus_speed);
+ bus_speed = 50;
+ freq = 12500000;
}
+ /* Ease diagnostics... */
{
- int speed;
- switch (freq)
- {
- case 0:
- freq = 15000000;
- speed = 60;
-
- /* Use status of left mouse button to select
- RAM speed. */
- if (!(ciaa.pra & 0x40))
- {
- APUS_WRITE (APUS_REG_WAITSTATE,
- REGWAITSTATE_SETRESET
- |REGWAITSTATE_PPCR
- |REGWAITSTATE_PPCW);
- printk (" [RAM R/W waitstate removed. "
- "(expecting 60ns RAM).] ");
+ extern int __map_without_bats;
+
+ printk ("APUS: BATs=%d, BUS=%dMHz, RAM=%dns\n",
+ (__map_without_bats) ? 0 : 1,
+ bus_speed,
+ (__60nsram) ? 60 : 70);
+
+ /* print a bit more if asked politely... */
+ if (!(ciaa.pra & 0x40)){
+ extern unsigned int bat_addrs[4][3];
+ int b;
+ for (b = 0; b < 4; ++b) {
+ printk ("APUS: BAT%d ", b);
+ printk ("%08x-%08x -> %08x\n",
+ bat_addrs[b][0],
+ bat_addrs[b][1],
+ bat_addrs[b][2]);
}
- break;
- case 1:
- freq = 16500000;
- speed = 66;
- break;
}
- printk ("PowerUp Bus Speed: %dMHz\n", speed);
+
}
freq *= 60; /* try to make freq/1e6 an integer */
@@ -222,7 +254,72 @@ unsigned long kernel_map (unsigned long phys_addr, unsigned long size,
}
return v_ret;
}
-
+
+/* From pgtable.h */
+extern __inline__ pte_t *my_find_pte(struct mm_struct *mm,unsigned long va)
+{
+ pgd_t *dir = 0;
+ pmd_t *pmd = 0;
+ pte_t *pte = 0;
+
+ va &= PAGE_MASK;
+
+ dir = pgd_offset( mm, va );
+ if (dir)
+ {
+ pmd = pmd_offset(dir, va & PAGE_MASK);
+ if (pmd && pmd_present(*pmd))
+ {
+ pte = pte_offset(pmd, va);
+ }
+ }
+ return pte;
+}
+
+
+/* Again simulating an m68k/mm/kmap.c function. */
+void kernel_set_cachemode( unsigned long address, unsigned long size,
+ unsigned int cmode )
+{
+ int mask, flags;
+
+ switch (cmode)
+ {
+ case KERNELMAP_FULL_CACHING:
+ mask = ~(_PAGE_NO_CACHE | _PAGE_GUARDED);
+ flags = 0;
+ break;
+ case KERNELMAP_NOCACHE_SER:
+ mask = ~0;
+ flags = (_PAGE_NO_CACHE | _PAGE_GUARDED);
+ break;
+ default:
+ panic ("kernel_set_cachemode() doesn't support mode %d\n",
+ cmode);
+ break;
+ }
+
+ size /= PAGE_SIZE;
+ address &= PAGE_MASK;
+ while (size--)
+ {
+ pte_t *pte;
+
+ pte = my_find_pte(init_task.mm, address);
+ if ( !pte )
+ {
+ printk("pte NULL in kernel_set_cachemode()\n");
+ return;
+ }
+
+ pte_val (*pte) &= mask;
+ pte_val (*pte) |= flags;
+ flush_tlb_page(find_vma(init_task.mm,address),address);
+
+ address += PAGE_SIZE;
+ }
+}
+
unsigned long mm_ptov (unsigned long paddr)
{
unsigned long ret;
diff --git a/arch/ppc/kernel/chrp_setup.c b/arch/ppc/kernel/chrp_setup.c
index 748a78e00..5b373c876 100644
--- a/arch/ppc/kernel/chrp_setup.c
+++ b/arch/ppc/kernel/chrp_setup.c
@@ -11,6 +11,7 @@
*/
#include <linux/config.h>
+#include <linux/module.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -29,6 +30,7 @@
#include <linux/blk.h>
#include <linux/ioport.h>
#include <linux/console.h>
+#include <linux/pci.h>
#include <asm/mmu.h>
#include <asm/processor.h>
@@ -37,6 +39,7 @@
#include <asm/ide.h>
#include <asm/prom.h>
#include <asm/gg2.h>
+#include <asm/pci-bridge.h>
extern void hydra_init(void);
extern void w83c553f_init(void);
@@ -189,7 +192,15 @@ chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
aux_device_present = 0xaa;
- ROOT_DEV = to_kdev_t(0x0802); /* sda2 (sda1 is for the kernel) */
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* this is fine for chrp */
+ initrd_below_start_ok = 1;
+
+ if (initrd_start)
+ ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+ else
+#endif
+ ROOT_DEV = to_kdev_t(0x0802); /* sda2 (sda1 is for the kernel) */
printk("Boot arguments: %s\n", cmd_line);
@@ -203,7 +214,6 @@ chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
/* PCI bridge config space access area -
* appears to be not in devtree on longtrail. */
ioremap(GG2_PCI_CONFIG_BASE, 0x80000);
-
/*
* Temporary fixes for PCI devices.
* -- Geert
@@ -215,8 +225,54 @@ chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
* Fix the Super I/O configuration
*/
sio_init();
-
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
#endif
+ /* my starmax 6000 needs this but the longtrail shouldn't do it -- Cort */
+ if ( !strncmp("MOT", get_property(find_path_device("/"),
+ "model", NULL),3) )
+ *memory_start_p = pmac_find_bridges(*memory_start_p, *memory_end_p);
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+
+unsigned int chrp_ide_irq = 0;
+int chrp_ide_ports_known = 0;
+ide_ioreg_t chrp_ide_regbase[MAX_HWIFS];
+ide_ioreg_t chrp_idedma_regbase;
+
+void chrp_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+{
+ ide_ioreg_t port = base;
+ int i = 8;
+
+ while (i--)
+ *p++ = port++;
+ *p++ = port;
+ if (irq != NULL)
+ *irq = chrp_ide_irq;
}
+
+void chrp_ide_probe(void) {
+
+ struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL);
+
+ chrp_ide_ports_known = 1;
+
+ if(pdev) {
+ chrp_ide_regbase[0]=pdev->base_address[0] &
+ PCI_BASE_ADDRESS_IO_MASK;
+ chrp_ide_regbase[1]=pdev->base_address[2] &
+ PCI_BASE_ADDRESS_IO_MASK;
+ chrp_idedma_regbase=pdev->base_address[4] &
+ PCI_BASE_ADDRESS_IO_MASK;
+ chrp_ide_irq=pdev->irq;
+ }
+}
+
+EXPORT_SYMBOL(chrp_ide_irq);
+EXPORT_SYMBOL(chrp_ide_ports_known);
+EXPORT_SYMBOL(chrp_ide_regbase);
+EXPORT_SYMBOL(chrp_ide_probe);
+
+#endif
diff --git a/arch/ppc/kernel/feature.c b/arch/ppc/kernel/feature.c
new file mode 100644
index 000000000..48d8bcb39
--- /dev/null
+++ b/arch/ppc/kernel/feature.c
@@ -0,0 +1,249 @@
+/*
+ * arch/ppc/kernel/feature.c
+ *
+ * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/errno.h>
+#include <asm/ohare.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/feature.h>
+
+#define MAX_FEATURE_REGS 2
+#undef DEBUG_FEATURE
+
+static u32 feature_bits_pbook[] = {
+ 0, /* FEATURE_null */
+ OH_SCC_RESET, /* FEATURE_Serial_reset */
+ OH_SCC_ENABLE, /* FEATURE_Serial_enable */
+ OH_SCCA_IO, /* FEATURE_Serial_IO_A */
+ OH_SCCB_IO, /* FEATURE_Serial_IO_B */
+ OH_FLOPPY_ENABLE, /* FEATURE_SWIM3_enable */
+ OH_MESH_ENABLE, /* FEATURE_MESH_enable */
+ OH_IDE_ENABLE, /* FEATURE_IDE_enable */
+ OH_VIA_ENABLE, /* FEATURE_VIA_enable */
+ OH_IDECD_POWER, /* FEATURE_CD_power */
+ OH_BAY_RESET, /* FEATURE_Mediabay_reset */
+ OH_BAY_ENABLE, /* FEATURE_Mediabay_enable */
+ OH_BAY_PCI_ENABLE, /* FEATURE_Mediabay_PCI_enable */
+ OH_BAY_IDE_ENABLE, /* FEATURE_Mediabay_IDE_enable */
+ OH_BAY_FLOPPY_ENABLE, /* FEATURE_Mediabay_floppy_enable */
+ 0, /* FEATURE_BMac_reset */
+ 0, /* FEATURE_BMac_IO_enable */
+ 0, /* FEATURE_Modem_PowerOn -> guess...*/
+ 0 /* FEATURE_Modem_Reset -> guess...*/
+};
+
+/* assume these are the same as the ohare until proven otherwise */
+static u32 feature_bits_heathrow[] = {
+ 0, /* FEATURE_null */
+ OH_SCC_RESET, /* FEATURE_Serial_reset */
+ OH_SCC_ENABLE, /* FEATURE_Serial_enable */
+ OH_SCCA_IO, /* FEATURE_Serial_IO_A */
+ OH_SCCB_IO, /* FEATURE_Serial_IO_B */
+ OH_FLOPPY_ENABLE, /* FEATURE_SWIM3_enable */
+ OH_MESH_ENABLE, /* FEATURE_MESH_enable */
+ OH_IDE_ENABLE, /* FEATURE_IDE_enable */
+ OH_VIA_ENABLE, /* FEATURE_VIA_enable */
+ OH_IDECD_POWER, /* FEATURE_CD_power */
+ OH_BAY_RESET, /* FEATURE_Mediabay_reset */
+ OH_BAY_ENABLE, /* FEATURE_Mediabay_enable */
+ OH_BAY_PCI_ENABLE, /* FEATURE_Mediabay_PCI_enable */
+ OH_BAY_IDE_ENABLE, /* FEATURE_Mediabay_IDE_enable */
+ OH_BAY_FLOPPY_ENABLE, /* FEATURE_Mediabay_floppy_enable */
+ 0x80000000, /* FEATURE_BMac_reset */
+ 0x60000000, /* FEATURE_BMac_IO_enable */
+ 0x02000000, /* FEATURE_Modem_PowerOn -> guess...*/
+ 0x07000000 /* FEATURE_Modem_Reset -> guess...*/
+};
+
+/* definition of a feature controller object */
+struct feature_controller
+{
+ u32* bits;
+ volatile u32* reg;
+ struct device_node* device;
+};
+
+/* static functions */
+static void
+feature_add_controller(struct device_node *controller_device, u32* bits);
+
+static int
+feature_lookup_controller(struct device_node *device);
+
+/* static varialbles */
+static struct feature_controller controllers[MAX_FEATURE_REGS];
+static int controller_count = 0;
+
+
+void
+feature_init(void)
+{
+ struct device_node *np;
+
+ np = find_devices("mac-io");
+ while (np != NULL)
+ {
+ feature_add_controller(np, feature_bits_heathrow);
+ np = np->next;
+ }
+ if (controller_count == 0)
+ {
+ np = find_devices("ohare");
+ if (np)
+ {
+ if (find_devices("via-pmu") != NULL)
+ feature_add_controller(np, feature_bits_pbook);
+ else
+ /* else not sure; maybe this is a Starmax? */
+ feature_add_controller(np, NULL);
+ }
+ }
+
+ if (controller_count)
+ printk(KERN_INFO "Registered %d feature controller(s)\n", controller_count);
+}
+
+static void
+feature_add_controller(struct device_node *controller_device, u32* bits)
+{
+ struct feature_controller* controller;
+
+ if (controller_count >= MAX_FEATURE_REGS)
+ {
+ printk(KERN_INFO "Feature controller %s skipped(MAX:%d)\n",
+ controller_device->full_name, MAX_FEATURE_REGS);
+ return;
+ }
+ controller = &controllers[controller_count];
+
+ controller->bits = bits;
+ controller->device = controller_device;
+ if (controller_device->n_addrs == 0) {
+ printk(KERN_ERR "No addresses for %s\n",
+ controller_device->full_name);
+ return;
+ }
+
+ controller->reg = (volatile u32 *)ioremap(
+ controller_device->addrs[0].address + OHARE_FEATURE_REG, 4);
+
+ if (bits == NULL) {
+ printk(KERN_INFO "Twiddling the magic ohare bits\n");
+ out_le32(controller->reg, STARMAX_FEATURES);
+ return;
+ }
+
+ controller_count++;
+}
+
+static int
+feature_lookup_controller(struct device_node *device)
+{
+ int i;
+
+ if (device == NULL)
+ return -EINVAL;
+
+ while(device)
+ {
+ for (i=0; i<controller_count; i++)
+ if (device == controllers[i].device)
+ return i;
+ device = device->parent;
+ }
+
+#ifdef DEBUG_FEATURE
+ printk("feature: <%s> not found on any controller\n",
+ device->name);
+#endif
+
+ return -ENODEV;
+}
+
+int
+feature_set(struct device_node* device, enum system_feature f)
+{
+ int controller;
+ unsigned long flags;
+
+ if (f >= FEATURE_last)
+ return -EINVAL;
+
+ controller = feature_lookup_controller(device);
+ if (controller < 0)
+ return controller;
+
+#ifdef DEBUG_FEATURE
+ printk("feature: <%s> setting feature %d in controller @0x%x\n",
+ device->name, (int)f, (unsigned int)controllers[controller].reg);
+#endif
+
+ save_flags(flags);
+ cli();
+ st_le32( controllers[controller].reg,
+ ld_le32(controllers[controller].reg) |
+ controllers[controller].bits[f]);
+ restore_flags(flags);
+ udelay(10);
+
+ return 0;
+}
+
+int
+feature_clear(struct device_node* device, enum system_feature f)
+{
+ int controller;
+ unsigned long flags;
+
+ if (f >= FEATURE_last)
+ return -EINVAL;
+
+ controller = feature_lookup_controller(device);
+ if (controller < 0)
+ return controller;
+
+#ifdef DEBUG_FEATURE
+ printk("feature: <%s> clearing feature %d in controller @0x%x\n",
+ device->name, (int)f, (unsigned int)controllers[controller].reg);
+#endif
+
+ save_flags(flags);
+ cli();
+ st_le32( controllers[controller].reg,
+ ld_le32(controllers[controller].reg) &
+ ~(controllers[controller].bits[f]));
+ restore_flags(flags);
+ udelay(10);
+
+ return 0;
+}
+
+int
+feature_test(struct device_node* device, enum system_feature f)
+{
+ int controller;
+
+ if (f >= FEATURE_last)
+ return -EINVAL;
+
+ controller = feature_lookup_controller(device);
+ if (controller < 0)
+ return controller;
+
+ return (ld_le32(controllers[controller].reg) &
+ controllers[controller].bits[f]) != 0;
+}
+
diff --git a/arch/ppc/kernel/find_name.c b/arch/ppc/kernel/find_name.c
index d5d88bff7..3c0fa8e0c 100644
--- a/arch/ppc/kernel/find_name.c
+++ b/arch/ppc/kernel/find_name.c
@@ -16,7 +16,7 @@ int main(int argc, char **argv)
if ( argc < 2 )
{
fprintf(stderr, "Usage: %s <address>\n", argv[0]);
- exit(-1);
+ return -1;
}
for ( i = 1 ; argv[i] ; i++ )
@@ -41,7 +41,7 @@ int main(int argc, char **argv)
strcpy( last, s);
}
- printf( "%s", last);
+ printf( "%s%s", last, s );
}
fclose(f);
return 0;
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index a257e7762..4c528beb8 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -1,7 +1,7 @@
/*
* arch/ppc/kernel/head.S
*
- * $Id: head.S,v 1.98 1998/07/26 21:28:48 geert Exp $
+ * $Id: head.S,v 1.111 1998/11/10 01:10:32 paulus Exp $
*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
@@ -93,15 +93,18 @@ LG_CACHE_LINE_SIZE = 5
bdnz 0b
#endif
+/* 601 only have IBAT cr0.eq is set on 601 when using this macro */
#define LOAD_BAT(n, offset, reg, RA, RB) \
lwz RA,offset+0(reg); \
lwz RB,offset+4(reg); \
mtspr IBAT##n##U,RA; \
mtspr IBAT##n##L,RB; \
+ beq 1f; \
lwz RA,offset+8(reg); \
lwz RB,offset+12(reg); \
mtspr DBAT##n##U,RA; \
- mtspr DBAT##n##L,RB
+ mtspr DBAT##n##L,RB; \
+1:
#ifndef CONFIG_APUS
#define tophys(rd,rs,rt) addis rd,rs,-KERNELBASE@h
@@ -139,6 +142,12 @@ _start:
* pointer (r1) points to just below the end of the half-meg region
* from 0x380000 - 0x400000, which is mapped in already.
*
+ * If we are booted from MacOS via BootX, we enter with the kernel
+ * image loaded somewhere, and the following values in registers:
+ * r3: 'BooX' (0x426f6f58)
+ * r4: virtual address of boot_infos_t
+ * r5: 0
+ *
* PREP
* This is jumped to on prep systems right after the kernel is relocated
* to its proper place in memory by the boot loader. The expected layout
@@ -201,7 +210,8 @@ __start:
mr r27,r7
#ifndef CONFIG_8xx
bl prom_init
-
+ .globl __secondary_start
+__secondary_start:
/*
* Use the first pair of BAT registers to map the 1st 16MB
* of RAM to KERNELBASE. From this point on we can't safely
@@ -213,33 +223,45 @@ __start:
lis r11,KERNELBASE@h
bne 4f
ori r11,r11,4 /* set up BAT registers for 601 */
- li r8,0x7f
+ li r8,0x7f /* valid, block length = 8MB */
oris r9,r11,0x800000@h /* set up BAT reg for 2nd 8M */
oris r10,r8,0x800000@h /* set up BAT reg for 2nd 8M */
+ mtspr IBAT0U,r11 /* N.B. 601 has valid bit in */
+ mtspr IBAT0L,r8 /* lower BAT register */
mtspr IBAT1U,r9
mtspr IBAT1L,r10
b 5f
4:
#ifndef CONFIG_APUS
- ori r11,r11,0x1ff /* set up BAT registers for 604 */
- li r8,2
+ ori r11,r11,0x1fe /* set up BAT registers for 604 */
+ li r8,2 /* R/W access */
#else
- ori r11,r11,0xff /* set up an 8MB mapping */
+ ori r11,r11,0xfe /* set up an 8MB mapping */
lis r8,CYBERBASEp@h
lwz r8,0(r8)
addis r8,r8,KERNELBASE@h
addi r8,r8,2
#endif
-5: mtspr DBAT0U,r11
- mtspr DBAT0L,r8
- mtspr IBAT0U,r11
+ mtspr DBAT0L,r8 /* N.B. 6xx (not 601) have valid */
+ mtspr DBAT0U,r11 /* bit in upper BAT register */
mtspr IBAT0L,r8
- isync
+ mtspr IBAT0U,r11
+5: isync
#ifdef CONFIG_APUS
/* Unfortunately the APUS specific instructions bloat the
* code so it cannot fit in the 0x100 bytes available. We have
* to do it the crude way. */
+
+ /* Map 0xfff00000 so we can access VTOP/PTOV constant when
+ MMU is enabled. */
+ lis r8,0xfff0
+ ori r11,r8,0x2 /* r/w */
+ ori r8,r8,0x2 /* 128KB, supervisor */
+ mtspr DBAT3U,r8
+ mtspr DBAT3L,r11
+
+ /* Copy exception code to exception vector base. */
lis r3,KERNELBASE@h
tophys(r4,r3,r5)
lis r3,0xfff0 /* Copy to 0xfff00000 on APUS */
@@ -263,23 +285,10 @@ __start:
li r3,0
mfmsr r0
andi. r0,r0,MSR_DR /* MMU enabled? */
- beq 7f
+ beq relocate_kernel
lis r3,KERNELBASE@h /* if so, are we */
cmpw 0,r4,r3 /* already running at KERNELBASE? */
- beq 2f
- rlwinm r4,r4,0,8,31 /* translate source address */
- add r4,r4,r3 /* to region mapped with BATs */
-7: addis r9,r26,klimit@ha /* fetch klimit */
- lwz r25,klimit@l(r9)
- addis r25,r25,-KERNELBASE@h
- li r6,0 /* Destination */
- li r5,0x4000 /* # bytes of memory to copy */
- bl copy_and_flush /* copy the first 0x4000 bytes */
- addi r0,r3,4f@l /* jump to the address of 4f */
- mtctr r0 /* in copy and do the rest. */
- bctr /* jump to the copy */
-4: mr r5,r25
- bl copy_and_flush /* copy the rest */
+ bne relocate_kernel
2:
#endif /* CONFIG_APUS */
/*
@@ -356,6 +365,7 @@ __start:
*/
#endif /* CONFIG_8xx */
+turn_on_mmu:
mfmsr r0
ori r0,r0,MSR_DR|MSR_IR
mtspr SRR1,r0
@@ -364,7 +374,7 @@ __start:
mtspr SRR0,r0
SYNC
rfi /* enables MMU */
-
+
/*
* GCC sometimes accesses words at negative offsets from the stack
* pointer, although the SysV ABI says it shouldn't. To cope with
@@ -506,7 +516,7 @@ HardwareInterrupt:
li r20,(IPLEMU_SETRESET|IPLEMU_DISABLEINT)
stb r20,APUS_IPL_EMU@l(r3)
- sync
+ eieio
lbz r3,APUS_IPL_EMU@l(r3)
@@ -1386,15 +1396,13 @@ hash_page_out:
next_slot:
.long 0
-/*
- * FPU stuff for the 6xx/7xx follows
- * -- Cort
- */
load_up_fpu:
/*
* Disable FP for the task which had the FPU previously,
* and save its floating-point registers in its thread_struct.
* Enables the FPU for use in the kernel on return.
+ * On SMP we know the fpu is free, since we give it up every
+ * switch. -- Cort
*/
#ifndef CONFIG_APUS
lis r6,-KERNELBASE@h
@@ -1402,28 +1410,23 @@ load_up_fpu:
lis r6,CYBERBASEp@h
lwz r6,0(r6)
#endif
+
addis r3,r6,last_task_used_math@ha
lwz r4,last_task_used_math@l(r3)
mfmsr r5
ori r5,r5,MSR_FP
SYNC
mtmsr r5 /* enable use of fpu now */
-#ifndef __SMP__
- SYNC
- cmpi 0,r4,0
- beq 1f
-#else
/*
* All the saving of last_task_used_math is handled
* by a switch_to() call to smp_giveup_fpu() in SMP so
* last_task_used_math is not used.
- *
- * We should never be herre on SMP anyway, sinc ethe fpu should
- * always be on.
* -- Cort
*/
- b 1f
-#endif
+#ifndef __SMP__
+ SYNC
+ cmpi 0,r4,0
+ beq 1f
add r4,r4,r6
addi r4,r4,TSS /* want TSS of last_task_used_math */
SAVE_32FPRS(0, r4)
@@ -1432,22 +1435,20 @@ load_up_fpu:
lwz r5,PT_REGS(r4)
add r5,r5,r6
lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
- li r20,MSR_FP
+ li r20,MSR_FP|MSR_FE0|MSR_FE1
andc r4,r4,r20 /* disable FP for previous task */
stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-
-1: ori r23,r23,MSR_FP /* enable use of FP after return */
+#endif /* __SMP__ */
+1: ori r23,r23,MSR_FP|MSR_FE0|MSR_FE1 /* enable use of FP after return */
mfspr r5,SPRG3 /* current task's TSS (phys) */
lfd fr0,TSS_FPSCR-4(r5)
mtfsf 0xff,fr0
REST_32FPRS(0, r5)
-/*
- * on SMP we don't really use last_task_used_math but set it
- * here anyway to avoid the ifdef's -- Cort
- */
subi r4,r5,TSS
sub r4,r4,r6
+#ifndef __SMP__
stw r4,last_task_used_math@l(r3)
+#endif /* __SMP__ */
/* restore registers and return */
lwz r3,_CCR(r21)
lwz r4,_LINK(r21)
@@ -1507,14 +1508,16 @@ giveup_fpu:
cmpi 0,r4,0
beqlr- /* if no previous owner, done */
addi r4,r4,TSS /* want TSS of last_task_used_math */
+#ifndef __SMP__
li r5,0
stw r5,last_task_used_math@l(r3)
+#endif /* __SMP__ */
SAVE_32FPRS(0, r4)
mffs fr0
stfd fr0,TSS_FPSCR-4(r4)
lwz r5,PT_REGS(r4)
lwz r3,_MSR-STACK_FRAME_OVERHEAD(r5)
- li r4,MSR_FP
+ li r4,MSR_FP|MSR_FE0|MSR_FE1
andc r3,r3,r4 /* disable FP for previous task */
stw r3,_MSR-STACK_FRAME_OVERHEAD(r5)
#else /* CONFIG_8xx */
@@ -1522,7 +1525,31 @@ giveup_fpu:
giveup_fpu:
#endif /* CONFIG_8xx */
blr
-
+
+/*
+ * This code is jumped to from the startup code to copy
+ * the kernel image to physical address 0.
+ */
+relocate_kernel:
+ 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 */
+7: addis r9,r26,klimit@ha /* fetch klimit */
+ lwz r25,klimit@l(r9)
+ addis r25,r25,-KERNELBASE@h
+ li r6,0 /* Destination offset */
+ li r5,0x4000 /* # bytes of memory to copy */
+ bl copy_and_flush /* copy the first 0x4000 bytes */
+ addi r0,r3,4f@l /* jump to the address of 4f */
+ mtctr r0 /* in copy and do the rest. */
+ bctr /* jump to the copy */
+4: mr r5,r25
+ bl copy_and_flush /* copy the rest */
+ b turn_on_mmu
+
/*
* Copy routine used to copy the kernel to start at physical address 0
* and flush and invalidate the caches as needed.
@@ -1577,11 +1604,6 @@ start_here:
bne 3f /* don't invalidate the D-cache */
ori r8,r8,HID0_DCI /* unless it wasn't enabled */
3:
- /* turn on dpm for 603 */
- cmpi 0,r9,3
- bne 10f
- oris r11,r11,HID0_DPM@h
-10:
sync
mtspr HID0,r8 /* enable and invalidate caches */
sync
@@ -1600,14 +1622,27 @@ start_here:
5: mtspr HID0,r11 /* superscalar exec & br history tbl */
4:
#endif /* CONFIG_8xx */
+#ifdef __SMP__
+ /* if we're the second cpu stack and r2 are different
+ * and we want to not clear the bss -- Cort */
+ lis r5,first_cpu_booted@h
+ ori r5,r5,first_cpu_booted@l
+ lwz r5,0(r5)
+ cmpi 0,r5,0
+ beq 99f
+
+ /* get current */
+ lis r2,current_set@h
+ ori r2,r2,current_set@l
+ addi r2,r2,4
+ lwz r2,0(r2)
+
+ b 10f
+99:
+#endif /* __SMP__ */
/* ptr to current */
lis r2,init_task_union@h
ori r2,r2,init_task_union@l
- /* stack */
- addi r1,r2,TASK_UNION_SIZE
- li r0,0
- stwu r0,-STACK_FRAME_OVERHEAD(r1)
-
/* Clear out the BSS */
lis r11,_end@ha
addi r11,r11,_end@l
@@ -1623,6 +1658,15 @@ start_here:
3: stwu r0,4(r8)
bdnz 3b
2:
+#ifdef __SMP__
+10:
+#endif /* __SMP__ */
+
+ /* stack */
+ addi r1,r2,TASK_UNION_SIZE
+ li r0,0
+ stwu r0,-STACK_FRAME_OVERHEAD(r1)
+
/*
* Decide what sort of machine this is and initialize the MMU.
*/
@@ -1633,6 +1677,7 @@ start_here:
mr r7,r27
bl identify_machine
bl MMU_init
+
/*
* Go back to running unmapped so we can load up new values
* for SDR1 (hash table pointer) and the segment registers
@@ -1674,9 +1719,11 @@ start_here:
addi r3,r3,1 /* increment VSID */
addis r4,r4,0x1000 /* address of next segment */
bdnz 3b
-
/* Load the BAT registers with the values set up by MMU_init.
MMU_init takes care of whether we're on a 601 or not. */
+ mfpvr r3
+ srwi r3,r3,16
+ cmpwi r3,1
lis r3,BATS@ha
addi r3,r3,BATS@l
tophys(r3,r3,r4)
@@ -1696,6 +1743,20 @@ start_here:
li r4,MSR_KERNEL
lis r3,start_kernel@h
ori r3,r3,start_kernel@l
+#ifdef __SMP__
+ /* the second time through here we go to
+ * start_secondary(). -- Cort
+ */
+ lis r5,first_cpu_booted@h
+ ori r5,r5,first_cpu_booted@l
+ tophys(r5,r5,r3)
+ lwz r5,0(r5)
+ cmpi 0,r5,0
+ beq 10f
+ lis r3,start_secondary@h
+ ori r3,r3,start_secondary@l
+10:
+#endif /* __SMP__ */
mtspr SRR0,r3
mtspr SRR1,r4
rfi /* enable MMU and jump to start_kernel */
@@ -1954,6 +2015,8 @@ int_return:
beq+ 1f
addi r3,r1,STACK_FRAME_OVERHEAD
bl do_IRQ
+ .globl lost_irq_ret
+lost_irq_ret:
b 3b
1: lis r4,bh_mask@ha
lwz r4,bh_mask@l(r4)
@@ -1962,6 +2025,8 @@ int_return:
and. r4,r4,r5
beq+ 2f
bl do_bottom_half
+ .globl do_bottom_half_ret
+do_bottom_half_ret:
SYNC
mtmsr r30 /* disable interrupts again */
SYNC
@@ -1979,6 +2044,8 @@ int_return:
li r3,0
addi r4,r1,STACK_FRAME_OVERHEAD
bl do_signal
+ .globl do_signal_ret
+do_signal_ret:
b 0b
8: addi r4,r1,INT_FRAME_SIZE+STACK_UNDERHEAD /* size of frame */
stw r4,TSS+KSP(r2) /* save kernel stack pointer */
@@ -2221,173 +2288,6 @@ _GLOBAL(flush_hash_page)
_GLOBAL(__main)
blr
-#ifdef __SMP__
-/*
- * Secondary processor begins executing here.
- */
- .globl secondary_entry
-secondary_entry:
- /* just like __start() with a few changes -- Cort */
- mfspr r9,PVR
- rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
- cmpi 0,r9,1
- lis r11,KERNELBASE@h
- bne 4f
- ori r11,r11,4 /* set up BAT registers for 601 */
- li r8,0x7f
- oris r9,r11,0x800000@h /* set up BAT reg for 2nd 8M */
- oris r10,r8,0x800000@h /* set up BAT reg for 2nd 8M */
- mtspr IBAT1U,r9
- mtspr IBAT1L,r10
- b 5f
-4: ori r11,r11,0x1ff /* set up BAT registers for 604 */
- li r8,2
- mtspr DBAT0U,r11
- mtspr DBAT0L,r8
-5: mtspr IBAT0U,r11
- mtspr IBAT0L,r8
- isync
-/*
- * we now have the 1st 16M of ram mapped with the bats.
- * prep needs the mmu to be turned on here, but pmac already has it on.
- * this shouldn't bother the pmac since it just gets turned on again
- * as we jump to our code at KERNELBASE. -- Cort
- */
- mfmsr r0
- ori r0,r0,MSR_DR|MSR_IR
- mtspr SRR1,r0
- lis r0,100f@h
- ori r0,r0,100f@l
- mtspr SRR0,r0
- SYNC
- rfi /* enables MMU */
-100:
- /*
- * Enable caches and 604-specific features if necessary.
- */
- mfspr r9,PVR
- rlwinm r9,r9,16,16,31
- cmpi 0,r9,1
- beq 4f /* not needed for 601 */
- mfspr r11,HID0
- andi. r0,r11,HID0_DCE
- ori r11,r11,HID0_ICE|HID0_DCE
- ori r8,r11,HID0_ICFI
- bne 3f /* don't invalidate the D-cache */
- ori r8,r8,HID0_DCI /* unless it wasn't enabled */
-3:
- /* turn on dpm for 603 */
- cmpi 0,r9,3
- bne 10f
- oris r11,r11,HID0_DPM@h
-10:
- sync
- mtspr HID0,r8 /* enable and invalidate caches */
- sync
- mtspr HID0,r11 /* enable caches */
- sync
- isync
- cmpi 0,r9,4 /* check for 604 */
- cmpi 1,r9,9 /* or 604e */
- cmpi 2,r9,10 /* or mach5 */
- cror 2,2,6
- cror 2,2,10
- bne 4f
- ori r11,r11,HID0_SIED|HID0_BHTE /* for 604[e], enable */
- bne 2,5f
- ori r11,r11,HID0_BTCD
-5: mtspr HID0,r11 /* superscalar exec & br history tbl */
-4:
-/*
- * init_MMU on the first processor has setup the variables
- * for us - all we need to do is load them -- Cort
- */
-
-/*
- * Go back to running unmapped so we can load up new values
- * for SDR1 (hash table pointer) and the segment registers
- * and change to using our exception vectors.
- */
- lis r6,_SDR1@ha
- lwz r6,_SDR1@l(r6)
- lis r4,2f@h
- ori r4,r4,2f@l
- tophys(r4,r4,r3)
- li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
- mtspr SRR0,r4
- mtspr SRR1,r3
- rfi
-/* Load up the kernel context */
-2:
- /* get ptr to current */
- lis r2,current_set@h
- ori r2,r2,current_set@l
- /* assume we're second processor for now */
- tophys(r2,r2,r10)
- lwz r2,4(r2)
- /* stack */
- addi r1,r2,TASK_UNION_SIZE
- li r0,0
- tophys(r3,r1,r10)
- stwu r0,-STACK_FRAME_OVERHEAD(r3)
-
- SYNC /* Force all PTE updates to finish */
- tlbia /* Clear all TLB entries */
- mtspr SDR1,r6
- li r0,16 /* load up segment register values */
- mtctr r0 /* for context 0 */
- lis r3,0x2000 /* Ku = 1, VSID = 0 */
- li r4,0
-3: mtsrin r3,r4
- addi r3,r3,1 /* increment VSID */
- addis r4,r4,0x1000 /* address of next segment */
- bdnz 3b
-
-/* Load the BAT registers with the values set up by MMU_init.
- MMU_init takes care of whether we're on a 601 or not. */
- lis r3,BATS@ha
- addi r3,r3,BATS@l
- tophys(r3,r3,r4)
- LOAD_BAT(0,0,r3,r4,r5)
- LOAD_BAT(1,16,r3,r4,r5)
- LOAD_BAT(2,32,r3,r4,r5)
- LOAD_BAT(3,48,r3,r4,r5)
-
-/* Set up for using our exception vectors */
- /* ptr to phys current tss */
- tophys(r4,r2,r4)
- addi r4,r4,TSS /* init task's TSS */
- mtspr SPRG3,r4
- li r3,0
- mtspr SPRG2,r3 /* 0 => r1 has kernel sp */
-
- /* need to flush/invalidate caches too */
- li r3,0x4000/CACHE_LINE_SIZE
- li r4,0
- mtctr r3
-73: dcbst 0,r4
- addi r4,r4,CACHE_LINE_SIZE
- bdnz 73b
- sync
- li r4,0
- mtctr r3
-72: icbi 0,r4
- addi r4,r4,CACHE_LINE_SIZE
- bdnz 72b
- sync
- isync
-77:
-/* Now turn on the MMU for real! */
- li r4,MSR_KERNEL
- lis r3,start_secondary@h
- ori r3,r3,start_secondary@l
- mtspr SRR0,r3
- mtspr SRR1,r4
- rfi /* enable MMU and jump to start_kernel */
-/* should never return */
- .long 0
-#endif /* __SMP__ */
-
/*
* PROM code for specific machines follows. Put it
* here so it's easy to add arch-specific sections later.
diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
index bd7980678..b6c338946 100644
--- a/arch/ppc/kernel/idle.c
+++ b/arch/ppc/kernel/idle.c
@@ -1,5 +1,5 @@
/*
- * $Id: idle.c,v 1.48 1998/07/30 11:29:22 davem Exp $
+ * $Id: idle.c,v 1.56 1998/10/13 19:14:36 paulus Exp $
*
* Idle daemon for PowerPC. Idle daemon will handle any action
* that needs to be taken when the system becomes idle.
@@ -11,8 +11,6 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-#define __KERNEL_SYSCALLS__
-
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/sched.h>
@@ -32,9 +30,6 @@
#include <asm/processor.h>
#include <asm/mmu.h>
#include <asm/cache.h>
-#ifdef CONFIG_PMAC
-#include <asm/mediabay.h>
-#endif
void zero_paged(void);
void power_save(void);
@@ -53,22 +48,15 @@ int idled(void *unused)
__sti();
/* endless loop with no priority at all */
- current->priority = -100;
- current->counter = -100;
+ current->priority = 0;
+ current->counter = 0;
check_pgt_cache();
if ( !current->need_resched && zero_paged_on ) zero_paged();
if ( !current->need_resched && htab_reclaim_on ) htab_reclaim();
-
- /*
- * Only processor 1 may sleep now since processor 2 would
- * never wake up. Need to add timer code for processor 2
- * then it can sleep. -- Cort
- */
-#ifndef __SMP__
if ( !current->need_resched ) power_save();
-#endif /* __SMP__ */
+ run_task_queue(&tq_scheduler);
schedule();
}
ret = 0;
@@ -92,15 +80,9 @@ int cpu_idle(void *unused)
*/
asmlinkage int sys_idle(void)
{
- extern int media_bay_task(void *);
if(current->pid != 0)
return -EPERM;
-#ifdef CONFIG_PMAC
- if (media_bay_present)
- kernel_thread(media_bay_task, NULL, 0);
-#endif
-
idled(NULL);
return 0; /* should never execute this but it makes gcc happy -- Cort */
}
diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
index cb4d0872e..a180e5f0a 100644
--- a/arch/ppc/kernel/irq.c
+++ b/arch/ppc/kernel/irq.c
@@ -9,7 +9,7 @@
* Adapted for Power Macintosh by Paul Mackerras
* Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
* Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
- *
+ *
* This file contains the code used by various IRQ handling routines:
* asking for different IRQ's should be done through these routines
* instead of just grabbing them. Thus setups with different IRQ numbers
@@ -50,55 +50,29 @@
#include <asm/gg2.h>
#include <asm/cache.h>
#include <asm/prom.h>
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+#include <asm/amigappc.h>
#ifdef CONFIG_8xx
#include <asm/8xx_immap.h>
#include <asm/mbx.h>
#endif
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-#include <asm/amigappc.h>
-#define VEC_SPUR (24)
extern void process_int(unsigned long vec, struct pt_regs *fp);
extern void apus_init_IRQ(void);
extern void amiga_disable_irq(unsigned int irq);
extern void amiga_enable_irq(unsigned int irq);
+static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
+static volatile unsigned char *chrp_int_ack_special;
+extern volatile unsigned long ipi_count;
+static void pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base);
+
#ifdef CONFIG_APUS
/* Rename a few functions. Requires the CONFIG_APUS protection. */
#define request_irq nop_ppc_request_irq
#define free_irq nop_ppc_free_irq
#define get_irq_list nop_get_irq_list
#endif
-
-#undef SHOW_IRQ
-
-#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
-
-int max_irqs;
-unsigned int local_irq_count[NR_CPUS];
-static struct irqaction *irq_action[NR_IRQS];
-static int spurious_interrupts = 0;
-static unsigned int cached_irq_mask[NR_MASK_WORDS];
-unsigned int lost_interrupts[NR_MASK_WORDS];
-atomic_t n_lost_interrupts;
-
-static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
-
-/*spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED;*/
-#ifdef __SMP__
-atomic_t __ppc_bh_counter = ATOMIC_INIT(0);
-#else
-int __ppc_bh_counter = 0;
-#endif
-static volatile unsigned char *gg2_int_ack_special;
-extern volatile unsigned long ipi_count;
-
-#define cached_21 (((char *)(cached_irq_mask))[3])
-#define cached_A1 (((char *)(cached_irq_mask))[2])
-
-/*
- * These are set to the appropriate functions by init_IRQ()
- */
#ifndef CONFIG_8xx
void (*mask_and_ack_irq)(int irq_nr);
void (*mask_irq)(unsigned int irq_nr);
@@ -113,10 +87,24 @@ void (*unmask_irq)(unsigned int irq_nr);
#define unmask_irq(irq) mbx_unmask_irq(irq)
#endif /* CONFIG_8xx */
-
-/* prep */
+#define VEC_SPUR (24)
+#undef SHOW_IRQ
+#undef SHOW_GATWICK_IRQS
+#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
+#define cached_21 (((char *)(cached_irq_mask))[3])
+#define cached_A1 (((char *)(cached_irq_mask))[2])
#define PREP_IRQ_MASK (((unsigned int)cached_A1)<<8) | (unsigned int)cached_21
+unsigned int local_bh_count[NR_CPUS];
+unsigned int local_irq_count[NR_CPUS];
+int max_irqs;
+int max_real_irqs;
+static struct irqaction *irq_action[NR_IRQS];
+static int spurious_interrupts = 0;
+static unsigned int cached_irq_mask[NR_MASK_WORDS];
+unsigned int lost_interrupts[NR_MASK_WORDS];
+atomic_t n_lost_interrupts;
+
/* pmac */
struct pmac_irq_hw {
unsigned int flag;
@@ -126,13 +114,32 @@ struct pmac_irq_hw {
};
/* XXX these addresses should be obtained from the device tree */
-volatile struct pmac_irq_hw *pmac_irq_hw[2] = {
+volatile struct pmac_irq_hw *pmac_irq_hw[4] = {
(struct pmac_irq_hw *) 0xf3000020,
(struct pmac_irq_hw *) 0xf3000010,
+ (struct pmac_irq_hw *) 0xf4000020,
+ (struct pmac_irq_hw *) 0xf4000010,
};
-#define KEYBOARD_IRQ 20 /* irq number for command-power interrupt */
+/* This is the interrupt used on the main controller for the secondary
+ controller. Happens on PowerBooks G3 Series (a second mac-io)
+ -- BenH
+ */
+static int second_irq = -999;
+
+/* Returns the number of 0's to the left of the most significant 1 bit */
+static inline int cntlzw(int bits)
+{
+ int lz;
+
+ asm ("cntlzw %0,%1" : "=r" (lz) : "r" (bits));
+ return lz;
+}
+static inline void sync(void)
+{
+ asm volatile ("sync");
+}
/* nasty hack for shared irq's since we need to do kmalloc calls but
* can't very very early in the boot when we need to do a request irq.
@@ -190,12 +197,12 @@ void i8259_mask_and_ack_irq(int irq_nr)
/* spin_unlock(&irq_controller_lock);*/
}
-void pmac_mask_and_ack_irq(int irq_nr)
+void __pmac pmac_mask_and_ack_irq(int irq_nr)
{
unsigned long bit = 1UL << (irq_nr & 0x1f);
int i = irq_nr >> 5;
- if (irq_nr >= max_irqs)
+ if ((unsigned)irq_nr >= max_irqs)
return;
/*spin_lock(&irq_controller_lock);*/
@@ -205,13 +212,15 @@ void pmac_mask_and_ack_irq(int irq_nr)
out_le32(&pmac_irq_hw[i]->ack, bit);
out_le32(&pmac_irq_hw[i]->enable, cached_irq_mask[i]);
out_le32(&pmac_irq_hw[i]->ack, bit);
+ /* make sure ack gets to controller before we enable interrupts */
+ sync();
/*spin_unlock(&irq_controller_lock);*/
/*if ( irq_controller_lock.lock )
panic("irq controller lock still held in mask and ack\n");*/
}
-void chrp_mask_and_ack_irq(int irq_nr)
+void __openfirmware chrp_mask_and_ack_irq(int irq_nr)
{
/* spinlocks are done by i8259_mask_and_ack() - Cort */
if (is_8259_irq(irq_nr))
@@ -228,12 +237,12 @@ static void i8259_set_irq_mask(int irq_nr)
}
}
-static void pmac_set_irq_mask(int irq_nr)
+static void __pmac pmac_set_irq_mask(int irq_nr)
{
unsigned long bit = 1UL << (irq_nr & 0x1f);
int i = irq_nr >> 5;
- if (irq_nr >= max_irqs)
+ if ((unsigned)irq_nr >= max_irqs)
return;
/* enable unmasked interrupts */
@@ -268,19 +277,20 @@ static void i8259_unmask_irq(unsigned int irq_nr)
i8259_set_irq_mask(irq_nr);
}
-static void pmac_mask_irq(unsigned int irq_nr)
+static void __pmac pmac_mask_irq(unsigned int irq_nr)
{
clear_bit(irq_nr, cached_irq_mask);
pmac_set_irq_mask(irq_nr);
+ sync();
}
-static void pmac_unmask_irq(unsigned int irq_nr)
+static void __pmac pmac_unmask_irq(unsigned int irq_nr)
{
set_bit(irq_nr, cached_irq_mask);
pmac_set_irq_mask(irq_nr);
}
-static void chrp_mask_irq(unsigned int irq_nr)
+static void __openfirmware chrp_mask_irq(unsigned int irq_nr)
{
if (is_8259_irq(irq_nr))
i8259_mask_irq(irq_nr);
@@ -288,7 +298,7 @@ static void chrp_mask_irq(unsigned int irq_nr)
openpic_disable_irq(irq_to_openpic(irq_nr));
}
-static void chrp_unmask_irq(unsigned int irq_nr)
+static void __openfirmware chrp_unmask_irq(unsigned int irq_nr)
{
if (is_8259_irq(irq_nr))
i8259_unmask_irq(irq_nr);
@@ -342,7 +352,7 @@ int get_irq_list(char *buf)
for (i = 0 ; i < NR_IRQS ; i++) {
action = irq_action[i];
- if (!action || !action->handler)
+ if ((!action || !action->handler) && (i != second_irq))
continue;
len += sprintf(buf+len, "%3d: ", i);
#ifdef __SMP__
@@ -358,7 +368,10 @@ int get_irq_list(char *buf)
len += sprintf(buf+len, " 82c59 ");
break;
case _MACH_Pmac:
- len += sprintf(buf+len, " PMAC-PIC ");
+ if (i < 64)
+ len += sprintf(buf+len, " PMAC-PIC ");
+ else
+ len += sprintf(buf+len, " GATWICK ");
break;
case _MACH_chrp:
if ( is_8259_irq(i) )
@@ -371,83 +384,132 @@ int get_irq_list(char *buf)
break;
}
- len += sprintf(buf+len, " %s",action->name);
- for (action=action->next; action; action = action->next) {
- len += sprintf(buf+len, ", %s", action->name);
- }
- len += sprintf(buf+len, "\n");
+ if (i != second_irq) {
+ len += sprintf(buf+len, " %s",action->name);
+ for (action=action->next; action; action = action->next) {
+ len += sprintf(buf+len, ", %s", action->name);
+ }
+ len += sprintf(buf+len, "\n");
+ } else
+ len += sprintf(buf+len, " Gatwick secondary IRQ controller\n");
}
#ifdef __SMP__
/* should this be per processor send/receive? */
- len += sprintf(buf+len, "IPI: %10lu\n", ipi_count);
+ len += sprintf(buf+len, "IPI: %10lu", ipi_count);
for ( i = 0 ; i <= smp_num_cpus-1; i++ )
len += sprintf(buf+len," ");
- len += sprintf(buf+len, " interprocessor messages received\n");
+ len += sprintf(buf+len, " interprocessor messages received\n");
#endif
len += sprintf(buf+len, "BAD: %10u",spurious_interrupts);
for ( i = 0 ; i <= smp_num_cpus-1; i++ )
len += sprintf(buf+len," ");
- len += sprintf(buf+len, " spurious or short\n");
+ len += sprintf(buf+len, " spurious or short\n");
return len;
}
+/*
+ * Global interrupt locks for SMP. Allow interrupts to come in on any
+ * CPU, yet make cli/sti act globally to protect critical regions..
+ */
#ifdef __SMP__
-/* Who has global_irq_lock. */
unsigned char global_irq_holder = NO_PROC_ID;
+unsigned volatile int global_irq_lock;
+atomic_t global_irq_count;
-/* This protects IRQ's. */
-spinlock_t global_irq_lock = SPIN_LOCK_UNLOCKED;
-unsigned long previous_irqholder;
+atomic_t global_bh_count;
+atomic_t global_bh_lock;
-/* This protects BH software state (masks, things like that). */
-spinlock_t global_bh_lock = SPIN_LOCK_UNLOCKED;
+static void show(char * str)
+{
+ int i;
+ unsigned long *stack;
+ int cpu = smp_processor_id();
-/* Global IRQ locking depth. */
-atomic_t global_irq_count = ATOMIC_INIT(0);
+ printk("\n%s, CPU %d:\n", str, cpu);
+ printk("irq: %d [%d %d]\n",
+ atomic_read(&global_irq_count), local_irq_count[0], local_irq_count[1]);
+ printk("bh: %d [%d %d]\n",
+ atomic_read(&global_bh_count), local_bh_count[0], local_bh_count[1]);
+ stack = (unsigned long *) &str;
+ for (i = 40; i ; i--) {
+ unsigned long x = *++stack;
+ if (x > (unsigned long) &init_task_union && x < (unsigned long) &vsprintf) {
+ printk("<[%08lx]> ", x);
+ }
+ }
+}
-#undef INIT_STUCK
-#define INIT_STUCK 100000000
+#define MAXCOUNT 100000000
+static inline void wait_on_bh(void)
+{
+ int count = MAXCOUNT;
+ do {
+ if (!--count) {
+ show("wait_on_bh");
+ count = ~0;
+ }
+ /* nothing .. wait for the other bh's to go away */
+ } while (atomic_read(&global_bh_count) != 0);
+}
-#undef STUCK
-#define STUCK \
-if (!--stuck) {printk("wait_on_irq CPU#%d stuck at %08lx, waiting for %08lx (local=%d, global=%d)\n", cpu, where, previous_irqholder, local_count, atomic_read(&global_irq_count)); stuck = INIT_STUCK; }
-void wait_on_irq(int cpu, unsigned long where)
+#define MAXCOUNT 100000000
+static inline void wait_on_irq(int cpu)
{
- int stuck = INIT_STUCK;
- int local_count = local_irq_count[cpu];
+ int count = MAXCOUNT;
- /* Are we the only one in an interrupt context? */
- while (local_count != atomic_read(&global_irq_count)) {
- /*
- * No such luck. Now we need to release the lock,
- * _and_ release our interrupt context, because
- * otherwise we'd have dead-locks and live-locks
- * and other fun things.
- */
- atomic_sub(local_count, &global_irq_count);
- spin_unlock(&global_irq_lock);
+ for (;;) {
/*
- * Wait for everybody else to go away and release
- * their things before trying to get the lock again.
+ * Wait until all interrupts are gone. Wait
+ * for bottom half handlers unless we're
+ * already executing in one..
*/
+ if (!atomic_read(&global_irq_count)) {
+ if (local_bh_count[cpu] || !atomic_read(&global_bh_count))
+ break;
+ }
+
+ /* Duh, we have to loop. Release the lock to avoid deadlocks */
+ clear_bit(0,&global_irq_lock);
+
for (;;) {
- STUCK;
+ if (!--count) {
+ show("wait_on_irq");
+ count = ~0;
+ }
+ __sti();
+ /* don't worry about the lock race Linus found
+ * on intel here. -- Cort
+ */
+ __cli();
if (atomic_read(&global_irq_count))
continue;
- if (*((unsigned char *)&global_irq_lock))
+ if (global_irq_lock)
continue;
- if (spin_trylock(&global_irq_lock))
+ if (!local_bh_count[cpu] && atomic_read(&global_bh_count))
+ continue;
+ if (!test_and_set_bit(0,&global_irq_lock))
break;
}
- atomic_add(local_count, &global_irq_count);
}
}
-#define irq_active(cpu) \
- (global_irq_count != local_irq_count[cpu])
+/*
+ * This is called when we want to synchronize with
+ * bottom half handlers. We need to wait until
+ * no other CPU is executing any bottom half handler.
+ *
+ * Don't wait if we're already running in an interrupt
+ * context or are inside a bh handler.
+ */
+void synchronize_bh(void)
+{
+ if (atomic_read(&global_bh_count) && !in_interrupt())
+ wait_on_bh();
+}
+
/*
* This is called when we want to synchronize with
@@ -455,97 +517,125 @@ void wait_on_irq(int cpu, unsigned long where)
* stop sending interrupts: but to make sure there
* are no interrupts that are executing on another
* CPU we need to call this function.
- *
- * On UP this is a no-op.
*/
void synchronize_irq(void)
{
- int cpu = smp_processor_id();
- int local_count = local_irq_count[cpu];
-
- /* Do we need to wait? */
- if (local_count != atomic_read(&global_irq_count)) {
- /* The stupid way to do this */
+ if (atomic_read(&global_irq_count)) {
+ /* Stupid approach */
cli();
sti();
}
}
-#undef INIT_STUCK
-#define INIT_STUCK 10000000
-
-#undef STUCK
-#define STUCK \
-if (!--stuck) {\
-ll_printk("get_irqlock stuck at %08lx, waiting for %08lx\n", where, previous_irqholder); stuck = INIT_STUCK;}
-
-void get_irqlock(int cpu, unsigned long where)
+static inline void get_irqlock(int cpu)
{
- int stuck = INIT_STUCK;
- if (!spin_trylock(&global_irq_lock)) {
+ if (test_and_set_bit(0,&global_irq_lock)) {
/* do we already hold the lock? */
if ((unsigned char) cpu == global_irq_holder)
return;
/* Uhhuh.. Somebody else got it. Wait.. */
do {
do {
- STUCK;
- barrier();
- } while (*((unsigned char *)&global_irq_lock));
- } while (!spin_trylock(&global_irq_lock));
+
+ } while (test_bit(0,&global_irq_lock));
+ } while (test_and_set_bit(0,&global_irq_lock));
}
-
- /*
- * Ok, we got the lock bit.
- * But that's actually just the easy part.. Now
- * we need to make sure that nobody else is running
+ /*
+ * We also to make sure that nobody else is running
* in an interrupt context.
*/
- wait_on_irq(cpu, where);
+ wait_on_irq(cpu);
+
/*
- * Finally.
+ * Ok, finally..
*/
global_irq_holder = cpu;
- previous_irqholder = where;
}
+/*
+ * A global "cli()" while in an interrupt context
+ * turns into just a local cli(). Interrupts
+ * should use spinlocks for the (very unlikely)
+ * case that they ever want to protect against
+ * each other.
+ *
+ * If we already have local interrupts disabled,
+ * this will not turn a local disable into a
+ * global one (problems with spinlocks: this makes
+ * save_flags+cli+sti usable inside a spinlock).
+ */
void __global_cli(void)
{
- int cpu = smp_processor_id();
- unsigned long where;
- __asm__("mr %0,31" : "=r" (where)); /* get lr */
- __cli();
- get_irqlock(cpu, where);
+ unsigned int flags;
+
+ __save_flags(flags);
+ if (flags & (1 << 15)) {
+ int cpu = smp_processor_id();
+ __cli();
+ if (!local_irq_count[cpu])
+ get_irqlock(cpu);
+ }
}
void __global_sti(void)
{
- release_irqlock(smp_processor_id());
+ int cpu = smp_processor_id();
+
+ if (!local_irq_count[cpu])
+ release_irqlock(cpu);
__sti();
}
+/*
+ * SMP flags value to restore to:
+ * 0 - global cli
+ * 1 - global sti
+ * 2 - local cli
+ * 3 - local sti
+ */
unsigned long __global_save_flags(void)
{
- return global_irq_holder == (unsigned char) smp_processor_id();
+ int retval;
+ int local_enabled;
+ unsigned long flags;
+
+ __save_flags(flags);
+ local_enabled = (flags >> 15) & 1;
+ /* default to local */
+ retval = 2 + local_enabled;
+
+ /* check for global flags if we're not in an interrupt */
+ if (!local_irq_count[smp_processor_id()]) {
+ if (local_enabled)
+ retval = 1;
+ if (global_irq_holder == (unsigned char) smp_processor_id())
+ retval = 0;
+ }
+ return retval;
}
void __global_restore_flags(unsigned long flags)
{
switch (flags) {
case 0:
- release_irqlock(smp_processor_id());
- __sti();
+ __global_cli();
break;
case 1:
- __global_cli();
+ __global_sti();
+ break;
+ case 2:
+ __cli();
+ break;
+ case 3:
+ __sti();
break;
default:
printk("global_restore_flags: %08lx (%08lx)\n",
flags, (&flags)[-1]);
}
}
-#endif /* __SMP__ */
+#endif /* __SMP__ */
asmlinkage void do_IRQ(struct pt_regs *regs)
{
@@ -569,9 +659,6 @@ asmlinkage void do_IRQ(struct pt_regs *regs)
if (!atomic_read(&n_lost_interrupts))
{
extern void smp_message_recv(void);
- goto out;
-
- ipi_count++;
smp_message_recv();
goto out;
}
@@ -584,20 +671,48 @@ asmlinkage void do_IRQ(struct pt_regs *regs)
switch ( _machine )
{
case _MACH_Pmac:
- for (irq = max_irqs - 1; irq > 0; irq -= 32) {
- int i = irq >> 5, lz;
+ for (irq = max_real_irqs - 1; irq > 0; irq -= 32) {
+ int i = irq >> 5;
bits = ld_le32(&pmac_irq_hw[i]->flag)
| lost_interrupts[i];
if (bits == 0)
continue;
- /* lz = number of 0 bits to left of most sig. 1 */
- asm ("cntlzw %0,%1" : "=r" (lz) : "r" (bits));
- irq -= lz;
+ irq -= cntlzw(bits);
break;
}
+
+ /* Here, we handle interrupts coming from Gatwick,
+ * normal interrupt code will take care of acking and
+ * masking the irq on Gatwick itself but we ack&mask
+ * the Gatwick main interrupt on Heathrow now. It's
+ * unmasked later, after interrupt handling. -- BenH
+ */
+ if (irq == second_irq) {
+ mask_and_ack_irq(second_irq);
+ for (irq = max_irqs - 1; irq > max_real_irqs; irq -= 32) {
+ int i = irq >> 5;
+ bits = ld_le32(&pmac_irq_hw[i]->flag)
+ | lost_interrupts[i];
+ if (bits == 0)
+ continue;
+ irq -= cntlzw(bits);
+ break;
+ }
+ /* If not found, on exit, irq is 63 (128-1-32-32).
+ * We set it to -1 and revalidate second controller
+ */
+ if (irq < max_real_irqs) {
+ irq = -1;
+ unmask_irq(second_irq);
+ }
+#ifdef SHOW_GATWICK_IRQS
+ printk("Gatwick irq %d (i:%d, bits:0x%08lx\n", irq, i, bits);
+#endif
+ }
+
break;
case _MACH_chrp:
- irq = openpic_irq(0);
+ irq = openpic_irq(0);
if (irq == IRQ_8259_CASCADE)
{
/*
@@ -605,7 +720,7 @@ asmlinkage void do_IRQ(struct pt_regs *regs)
*
* This should go in the above mask/ack code soon. -- Cort
*/
- irq = *gg2_int_ack_special;
+ irq = *chrp_int_ack_special;
/*
* Acknowledge as soon as possible to allow i8259
* interrupt nesting
@@ -682,11 +797,13 @@ apus_out:
}
#endif
}
-
+
if (irq < 0) {
- printk(KERN_DEBUG "Bogus interrupt from PC = %lx\n", regs->nip);
+ printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
+ irq, regs->nip);
+ spurious_interrupts++;
goto out;
- }
+ }
#else /* CONFIG_8xx */
/* For MPC8xx, read the SIVEC register and shift the bits down
@@ -695,9 +812,7 @@ apus_out:
bits = ((immap_t *)MBX_IMAP_ADDR)->im_siu_conf.sc_sivec;
irq = bits >> 26;
#endif /* CONFIG_8xx */
-
mask_and_ack_irq(irq);
-
status = 0;
action = irq_action[irq];
kstat.irqs[cpu][irq]++;
@@ -707,14 +822,10 @@ apus_out:
do {
status |= action->flags;
action->handler(irq, action->dev_id, regs);
- /*if (status & SA_SAMPLE_RANDOM)
- add_interrupt_randomness(irq);*/
action = action->next;
} while ( action );
__cli();
- /* spin_lock(&irq_controller_lock);*/
unmask_irq(irq);
- /* spin_unlock(&irq_controller_lock);*/
} else {
#ifndef CONFIG_8xx
if ( irq == 7 ) /* i8259 gives us irq 7 on 'short' intrs */
@@ -723,8 +834,13 @@ apus_out:
disable_irq( irq );
}
+ /* This was a gatwick sub-interrupt, we re-enable them on Heathrow
+ now */
+ if (_machine == _MACH_Pmac && irq >= max_real_irqs)
+ unmask_irq(second_irq);
+
/* make sure we don't miss any cascade intrs due to eoi-ing irq 2 */
-#ifndef CONFIG_8xx
+#ifndef CONFIG_8xx
if ( is_prep && (irq > 7) )
goto retry_cascade;
/* do_bottom_half is called if necessary from int_return in head.S */
@@ -750,12 +866,16 @@ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *)
#ifdef SHOW_IRQ
printk("request_irq(): irq %d handler %08x name %s dev_id %04x\n",
- irq,handler,devname,dev_id);
+ irq,(int)handler,devname,(int)dev_id);
#endif /* SHOW_IRQ */
if (irq >= NR_IRQS)
return -EINVAL;
+ /* Cannot allocate second controller IRQ */
+ if (irq == second_irq)
+ return -EBUSY;
+
if (!handler)
{
/* Free */
@@ -780,7 +900,7 @@ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *)
cli();
action->handler = handler;
- action->flags = irqflags;
+ action->flags = irqflags;
action->mask = 0;
action->name = devname;
action->dev_id = dev_id;
@@ -851,6 +971,9 @@ __initfunc(void init_IRQ(void))
{
extern void xmon_irq(int, void *, struct pt_regs *);
int i;
+ struct device_node *irqctrler;
+ unsigned long addr;
+ struct device_node *np;
#ifndef CONFIG_8xx
switch (_machine)
@@ -860,23 +983,77 @@ __initfunc(void init_IRQ(void))
mask_irq = pmac_mask_irq;
unmask_irq = pmac_unmask_irq;
- /* G3 powermacs have 64 interrupts, others have 32 */
- max_irqs = (find_devices("mac-io") ? 64 : 32);
- printk("System has %d possible interrupts\n", max_irqs);
+ /* G3 powermacs have 64 interrupts, G3 Series PowerBook have 128,
+ others have 32 */
+ max_irqs = max_real_irqs = 32;
+ irqctrler = find_devices("mac-io");
+ if (irqctrler)
+ {
+ max_real_irqs = 64;
+ if (irqctrler->next)
+ max_irqs = 128;
+ else
+ max_irqs = 64;
+ }
+
+ /* get addresses of first controller */
+ if (irqctrler) {
+ if (irqctrler->n_addrs > 0) {
+ addr = (unsigned long)
+ ioremap(irqctrler->addrs[0].address, 0x40);
+ for (i = 0; i < 2; ++i)
+ pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
+ (addr + (2 - i) * 0x10);
+ }
+
+ /* get addresses of second controller */
+ irqctrler = (irqctrler->next) ? irqctrler->next : NULL;
+ if (irqctrler && irqctrler->n_addrs > 0) {
+ addr = (unsigned long)
+ ioremap(irqctrler->addrs[0].address, 0x40);
+ for (i = 2; i < 4; ++i)
+ pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
+ (addr + (4 - i) * 0x10);
+ }
+ }
+ /* disable all interrupts in all controllers */
for (i = 0; i * 32 < max_irqs; ++i)
out_le32(&pmac_irq_hw[i]->enable, 0);
+
+
+ /* get interrupt line of secondary interrupt controller */
+ if (irqctrler) {
+ second_irq = irqctrler->intrs[0].line;
+ printk(KERN_INFO "irq: secondary controller on irq %d\n",
+ (int)second_irq);
+ if (device_is_compatible(irqctrler, "gatwick"))
+ pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs);
+ enable_irq(second_irq);
+ }
+ printk("System has %d possible interrupts\n", max_irqs);
+ if (max_irqs != max_real_irqs)
+ printk(KERN_DEBUG "%d interrupts on main controller\n",
+ max_real_irqs);
+
#ifdef CONFIG_XMON
- request_irq(KEYBOARD_IRQ, xmon_irq, 0, "NMI", 0);
+ request_irq(20, xmon_irq, 0, "NMI", 0);
#endif /* CONFIG_XMON */
break;
case _MACH_chrp:
mask_and_ack_irq = chrp_mask_and_ack_irq;
mask_irq = chrp_mask_irq;
unmask_irq = chrp_unmask_irq;
- gg2_int_ack_special = (volatile unsigned char *)
- ioremap(GG2_INT_ACK_SPECIAL, 1);
- openpic_init();
+
+ if ( !(np = find_devices("pci") ) )
+ printk("Cannot find pci to get ack address\n");
+ else
+ {
+ chrp_int_ack_special = (volatile unsigned char *)
+ (*(unsigned long *)get_property(np,
+ "8259-interrupt-acknowledge", NULL));
+ }
+ openpic_init(1);
i8259_init();
cached_irq_mask[0] = cached_irq_mask[1] = ~0UL;
#ifdef CONFIG_XMON
@@ -935,3 +1112,61 @@ __initfunc(void init_IRQ(void))
}
#endif /* CONFIG_8xx */
}
+
+/* This routine will fix some missing interrupt values in the device tree
+ * on the gatwick mac-io controller used by some PowerBooks
+ */
+__pmac
+static void pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
+{
+ struct device_node *node;
+ static struct interrupt_info int_pool[4];
+
+ memset(int_pool, 0, sizeof(int_pool));
+ node = gw->child;
+ while(node)
+ {
+ /* Fix SCC */
+ if (strcasecmp(node->name, "escc") == 0)
+ if (node->child && node->child->n_intrs == 0)
+ {
+ node->child->n_intrs = 1;
+ node->child->intrs = &int_pool[0];
+ int_pool[0].line = 15+irq_base;
+ printk(KERN_INFO "irq: fixed SCC on second controller (%d)\n",
+ int_pool[0].line);
+ }
+ /* Fix media-bay & left SWIM */
+ if (strcasecmp(node->name, "media-bay") == 0)
+ {
+ struct device_node* ya_node;
+
+ if (node->n_intrs == 0)
+ {
+ node->n_intrs = 1;
+ node->intrs = &int_pool[1];
+ int_pool[1].line = 29+irq_base;
+ printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n",
+ int_pool[1].line);
+ }
+ ya_node = node->child;
+ while(ya_node)
+ {
+ if ((strcasecmp(ya_node->name, "floppy") == 0) &&
+ ya_node->n_intrs == 0)
+ {
+ ya_node->n_intrs = 2;
+ ya_node->intrs = &int_pool[2];
+ int_pool[2].line = 19+irq_base;
+ int_pool[3].line = 1+irq_base;
+ printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n",
+ int_pool[2].line, int_pool[3].line);
+ }
+ ya_node = ya_node->sibling;
+ }
+ }
+ node = node->sibling;
+ }
+
+}
+
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index de55ceaa3..f13508d96 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -363,22 +363,62 @@ _GLOBAL(_get_THRM1)
mfspr r3,THRM1
blr
+_GLOBAL(_get_THRM2)
+ mfspr r3,THRM2
+ blr
+
+_GLOBAL(_get_THRM3)
+ mfspr r3,THRM3
+ blr
+
_GLOBAL(_set_THRM1)
mtspr THRM1,r3
blr
+
+_GLOBAL(_set_THRM2)
+ mtspr THRM2,r3
+ blr
+
+_GLOBAL(_set_THRM3)
+ mtspr THRM3,r3
+ blr
_GLOBAL(_get_L2CR)
mfspr r3,L2CR
blr
-
+
+_GLOBAL(_set_L2CR)
+ mtspr L2CR,r3
+ blr
+
_GLOBAL(_get_PVR)
mfspr r3,PVR
blr
+/*
+ * These are used in the alignment trap handler when emulating
+ * single-precision loads and stores.
+ * We restore and save the fpscr so the task gets the same result
+ * and exceptions as if the cpu had performed the load or store.
+ */
_GLOBAL(cvt_fd)
cvt_fd:
+ lfd 0,-4(r5) /* load up fpscr value */
+ mtfsf 0xff,0
lfs 0,0(r3)
stfd 0,0(r4)
+ mffs 0 /* save new fpscr value */
+ stfd 0,-4(r5)
+ blr
+
+_GLOBAL(cvt_df)
+cvt_df:
+ lfd 0,-4(r5) /* load up fpscr value */
+ mtfsf 0xff,0
+ lfd 0,0(r3)
+ stfs 0,0(r4)
+ mffs 0 /* save new fpscr value */
+ stfd 0,-4(r5)
blr
/*
@@ -390,12 +430,6 @@ _GLOBAL(get_SR)
mr r3,r4
blr
-_GLOBAL(cvt_df)
-cvt_df:
- lfd 0,0(r3)
- stfs 0,0(r4)
- blr
-
/*
* Create a kernel thread
* __kernel_thread(flags, fn, arg)
@@ -435,7 +469,6 @@ _GLOBAL(name) \
#define __NR__exit __NR_exit
SYSCALL(idle)
-SYSCALL(setup)
SYSCALL(sync)
SYSCALL(setsid)
SYSCALL(write)
@@ -455,7 +488,7 @@ SYSCALL(read)
.align 4
.globl sys_call_table
sys_call_table:
- .long sys_setup /* 0 */
+ .long sys_ni_syscall /* 0 - old "setup()" system call */
.long sys_exit
.long sys_fork
.long sys_read
@@ -472,12 +505,12 @@ sys_call_table:
.long sys_mknod
.long sys_chmod /* 15 */
.long sys_lchown
- .long sys_ni_syscall
+ .long sys_ni_syscall /* old break syscall holder */
.long sys_stat
.long sys_lseek
.long sys_getpid /* 20 */
.long sys_mount
- .long sys_umount
+ .long sys_oldumount
.long sys_setuid
.long sys_getuid
.long sys_stime /* 25 */
@@ -486,11 +519,11 @@ sys_call_table:
.long sys_fstat
.long sys_pause
.long sys_utime /* 30 */
- .long /*sys_stty*/ sys_ni_syscall
- .long /*sys_gtty*/ sys_ni_syscall
+ .long sys_ni_syscall /* old stty syscall holder */
+ .long sys_ni_syscall /* old gtty syscall holder */
.long sys_access
.long sys_nice
- .long /*sys_ftime*/ sys_ni_syscall /* 35 */
+ .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
.long sys_sync
.long sys_kill
.long sys_rename
@@ -499,7 +532,7 @@ sys_call_table:
.long sys_dup
.long sys_pipe
.long sys_times
- .long /*sys_prof*/ sys_ni_syscall
+ .long sys_ni_syscall /* old prof syscall holder */
.long sys_brk /* 45 */
.long sys_setgid
.long sys_getgid
@@ -507,13 +540,13 @@ sys_call_table:
.long sys_geteuid
.long sys_getegid /* 50 */
.long sys_acct
- .long /*sys_phys*/ sys_ni_syscall
- .long /*sys_lock*/ sys_ni_syscall
+ .long sys_umount /* recycled never used phys() */
+ .long sys_ni_syscall /* old lock syscall holder */
.long sys_ioctl
.long sys_fcntl /* 55 */
- .long /*sys_mpx*/ sys_ni_syscall
+ .long sys_ni_syscall /* old mpx syscall holder */
.long sys_setpgid
- .long /*sys_ulimit*/ sys_ni_syscall
+ .long sys_ni_syscall /* old ulimit syscall holder */
.long sys_olduname
.long sys_umask /* 60 */
.long sys_chroot
@@ -544,7 +577,7 @@ sys_call_table:
.long sys_uselib
.long sys_swapon
.long sys_reboot
- .long old_readdir /* was sys_readdir */
+ .long old_readdir
.long sys_mmap /* 90 */
.long sys_munmap
.long sys_truncate
@@ -553,7 +586,7 @@ sys_call_table:
.long sys_fchown /* 95 */
.long sys_getpriority
.long sys_setpriority
- .long /*sys_profil*/ sys_ni_syscall
+ .long sys_ni_syscall /* old profil syscall holder */
.long sys_statfs
.long sys_fstatfs /* 100 */
.long sys_ioperm
@@ -592,7 +625,7 @@ sys_call_table:
.long sys_bdflush
.long sys_sysfs /* 135 */
.long sys_personality
- .long 0 /* for afs_syscall */
+ .long sys_ni_syscall /* for afs_syscall */
.long sys_setfsuid
.long sys_setfsgid
.long sys_llseek /* 140 */
@@ -620,22 +653,28 @@ sys_call_table:
.long sys_nanosleep
.long sys_mremap
.long sys_setresuid
- .long sys_getresuid /* 165 */
+ .long sys_getresuid /* 165 */
.long sys_query_module
.long sys_poll
.long sys_nfsservctl
- .long sys_setresgid
- .long sys_getresgid /* 170 */
+ .long sys_setresgid
+ .long sys_getresgid /* 170 */
.long sys_prctl
.long sys_rt_sigreturn
.long sys_rt_sigaction
.long sys_rt_sigprocmask
- .long sys_rt_sigpending /* 175 */
+ .long sys_rt_sigpending /* 175 */
.long sys_rt_sigtimedwait
.long sys_rt_sigqueueinfo
.long sys_rt_sigsuspend
.long sys_pread
- .long sys_pwrite /* 180 */
+ .long sys_pwrite /* 180 */
.long sys_chown
.long sys_getcwd
+ .long sys_capget
+ .long sys_capset
+ .long sys_sigaltstack /* 185 */
+ .long sys_sendfile
+ .long sys_ni_syscall /* streams1 */
+ .long sys_ni_syscall /* streams2 */
.space (NR_syscalls-183)*4
diff --git a/arch/ppc/kernel/openpic.c b/arch/ppc/kernel/openpic.c
index fd104ae9f..ec60ca5a6 100644
--- a/arch/ppc/kernel/openpic.c
+++ b/arch/ppc/kernel/openpic.c
@@ -133,7 +133,7 @@ static inline u_int openpic_readfield(volatile u_int *addr, u_int mask)
return val & mask;
}
-static inline void openpic_writefield(volatile u_int *addr, u_int mask,
+inline void openpic_writefield(volatile u_int *addr, u_int mask,
u_int field)
{
u_int val = openpic_read(addr);
@@ -173,7 +173,7 @@ static void openpic_safe_writefield(volatile u_int *addr, u_int mask,
* Initialize the OpenPIC
*/
-__initfunc(void openpic_init(void))
+__initfunc(void openpic_init(int main_pic))
{
u_int t, i;
u_int vendorid, devid, stepping, timerfreq;
@@ -233,41 +233,44 @@ __initfunc(void openpic_init(void))
else
printk("not set\n");
- /* Initialize timer interrupts */
- for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
- /* Disabled, Priority 0 */
- openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i);
- /* No processor */
- openpic_maptimer(i, 0);
+ if ( main_pic )
+ {
+ /* Initialize timer interrupts */
+ for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
+ /* Disabled, Priority 0 */
+ openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i);
+ /* No processor */
+ openpic_maptimer(i, 0);
+ }
+
+ /* Initialize IPI interrupts */
+ for (i = 0; i < OPENPIC_NUM_IPI; i++) {
+ /* Disabled, Priority 0 */
+ openpic_initipi(i, 0, OPENPIC_VEC_IPI+i);
+ }
+
+ /* Initialize external interrupts */
+ /* SIOint (8259 cascade) is special */
+ openpic_initirq(0, 8, OPENPIC_VEC_SOURCE, 1, 1);
+ /* Processor 0 */
+ openpic_mapirq(0, 1<<0);
+ for (i = 1; i < NumSources; i++) {
+ /* Enabled, Priority 8 */
+ openpic_initirq(i, 8, OPENPIC_VEC_SOURCE+i, 0,
+ i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1);
+ /* Processor 0 */
+ openpic_mapirq(i, 1<<0);
+ }
+
+ /* Initialize the spurious interrupt */
+ openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
+
+ if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
+ "82c59 cascade", NULL))
+ printk("Unable to get OpenPIC IRQ 0 for cascade\n");
+ openpic_set_priority(0, 0);
+ openpic_disable_8259_pass_through();
}
-
- /* Initialize IPI interrupts */
- for (i = 0; i < OPENPIC_NUM_IPI; i++) {
- /* Disabled, Priority 0 */
- openpic_initipi(i, 0, OPENPIC_VEC_IPI+i);
- }
-
- /* Initialize external interrupts */
- /* SIOint (8259 cascade) is special */
- openpic_initirq(0, 8, OPENPIC_VEC_SOURCE, 1, 1);
- /* Processor 0 */
- openpic_mapirq(0, 1<<0);
- for (i = 1; i < NumSources; i++) {
- /* Enabled, Priority 8 */
- openpic_initirq(i, 8, OPENPIC_VEC_SOURCE+i, 0,
- i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1);
- /* Processor 0 */
- openpic_mapirq(i, 1<<0);
- }
-
- /* Initialize the spurious interrupt */
- openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
-
- if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
- "82c59 cascade", NULL))
- printk("Unable to get OpenPIC IRQ 0 for cascade\n");
- openpic_set_priority(0, 0);
- openpic_disable_8259_pass_through();
}
@@ -529,5 +532,3 @@ void openpic_set_sense(u_int irq, int sense)
OPENPIC_SENSE_LEVEL,
(sense ? OPENPIC_SENSE_LEVEL : 0));
}
-
-
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 235365f5e..359446f4f 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -1,5 +1,5 @@
/*
- * $Id: pci.c,v 1.36 1998/08/02 23:22:11 paulus Exp $
+ * $Id: pci.c,v 1.39 1998/10/13 20:59:04 cort Exp $
* Common pmac/prep/chrp pci routines. -- Cort
*/
@@ -164,7 +164,7 @@ __initfunc(void
get_property(find_path_device("/"), "model", NULL),3) )
{
isa_io_base = 0xfe000000;
- set_config_access_method(raven);
+ set_config_access_method(grackle);
}
else
{
@@ -201,8 +201,22 @@ __initfunc(void pcibios_fixup(void))
route_pci_interrupts();
for(dev=pci_devices; dev; dev=dev->next)
{
+ /*
+ * Use our old hard-coded kludge to figure out what
+ * irq this device uses. This is necessary on things
+ * without residual data. -- Cort
+ */
unsigned char d = PCI_SLOT(dev->devfn);
dev->irq = Motherboard_routes[Motherboard_map[d]];
+#if 0
+ /*
+ * If we have residual data and if it knows about this
+ * device ask it what the irq is.
+ * -- Cort
+ */
+ ppcd = residual_find_device_id( ~0L, dev->device,
+ -1,-1,-1, 0);
+#endif
}
break;
case _MACH_chrp:
diff --git a/arch/ppc/kernel/pmac_pci.c b/arch/ppc/kernel/pmac_pci.c
index 481f69e2c..7763059f7 100644
--- a/arch/ppc/kernel/pmac_pci.c
+++ b/arch/ppc/kernel/pmac_pci.c
@@ -40,7 +40,6 @@ static void add_bridges(struct device_node *dev, unsigned long *mem_ptr);
#define BANDIT_COHERENT 0x40
__pmac
-
void *pci_io_base(unsigned int bus)
{
struct bridge_data *bp;
@@ -50,6 +49,7 @@ void *pci_io_base(unsigned int bus)
return bp->io_base;
}
+__pmac
int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr,
unsigned char *devfn_ptr)
{
@@ -68,6 +68,7 @@ int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr,
return 0;
}
+__pmac
int pmac_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned char *val)
{
@@ -90,6 +91,7 @@ int pmac_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
return PCIBIOS_SUCCESSFUL;
}
+__pmac
int pmac_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned short *val)
{
@@ -114,6 +116,7 @@ int pmac_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
return PCIBIOS_SUCCESSFUL;
}
+__pmac
int pmac_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned int *val)
{
@@ -138,6 +141,7 @@ int pmac_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
return PCIBIOS_SUCCESSFUL;
}
+__pmac
int pmac_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned char val)
{
@@ -159,6 +163,7 @@ int pmac_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
return PCIBIOS_SUCCESSFUL;
}
+__pmac
int pmac_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned short val)
{
@@ -182,6 +187,7 @@ int pmac_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
return PCIBIOS_SUCCESSFUL;
}
+__pmac
int pmac_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned int val)
{
@@ -406,7 +412,7 @@ __initfunc(static void add_bridges(struct device_node *dev, unsigned long *mem_p
ioremap(0xfec00000, 0x1000);
bp->cfg_data = (volatile unsigned char *)
ioremap(0xfee00000, 0x1000);
- bp->io_base = (void *) ioremap(0xfe000000, 0x10000);
+ bp->io_base = (void *) ioremap(0xfe000000, 0x20000);
}
if (isa_io_base == 0)
isa_io_base = (unsigned long) bp->io_base;
diff --git a/arch/ppc/kernel/pmac_setup.c b/arch/ppc/kernel/pmac_setup.c
index 7e44b404c..499e8b6a5 100644
--- a/arch/ppc/kernel/pmac_setup.c
+++ b/arch/ppc/kernel/pmac_setup.c
@@ -38,6 +38,7 @@
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/major.h>
+#include <linux/blk.h>
#include <linux/vt_kern.h>
#include <linux/console.h>
#include <asm/prom.h>
@@ -48,28 +49,89 @@
#include <asm/adb.h>
#include <asm/cuda.h>
#include <asm/pmu.h>
-#include <asm/mediabay.h>
#include <asm/ohare.h>
#include <asm/mediabay.h>
+#include <asm/feature.h>
#include "time.h"
-extern int root_mountflags;
-
unsigned char drive_info;
+extern char saved_command_line[];
+
#define DEFAULT_ROOT_DEVICE 0x0801 /* sda1 - slightly silly choice */
extern void zs_kgdb_hook(int tty_num);
static void ohare_init(void);
__pmac
-
int
pmac_get_cpuinfo(char *buffer)
{
int len;
- /* should find motherboard type here as well */
- len = sprintf(buffer,"machine\t\t: PowerMac\n");
+ struct device_node *np;
+ char *pp;
+ int plen;
+
+ /* find motherboard type */
+ len = sprintf(buffer, "machine\t\t: ");
+ np = find_devices("device-tree");
+ if (np != NULL) {
+ pp = (char *) get_property(np, "model", NULL);
+ if (pp != NULL)
+ len += sprintf(buffer+len, "%s\n", pp);
+ else
+ len += sprintf(buffer+len, "PowerMac\n");
+ pp = (char *) get_property(np, "compatible", &plen);
+ if (pp != NULL) {
+ len += sprintf(buffer+len, "motherboard\t:");
+ while (plen > 0) {
+ int l = strlen(pp) + 1;
+ len += sprintf(buffer+len, " %s", pp);
+ plen -= l;
+ pp += l;
+ }
+ buffer[len++] = '\n';
+ }
+ } else
+ len += sprintf(buffer+len, "PowerMac\n");
+
+ /* find l2 cache info */
+ np = find_devices("l2-cache");
+ if (np == 0)
+ np = find_type_devices("cache");
+ if (np != 0) {
+ unsigned int *ic = (unsigned int *)
+ get_property(np, "i-cache-size", NULL);
+ unsigned int *dc = (unsigned int *)
+ get_property(np, "d-cache-size", NULL);
+ len += sprintf(buffer+len, "L2 cache\t:");
+ if (get_property(np, "cache-unified", NULL) != 0 && dc) {
+ len += sprintf(buffer+len, " %dK unified", *dc / 1024);
+ } else {
+ if (ic)
+ len += sprintf(buffer+len, " %dK instruction",
+ *ic / 1024);
+ if (dc)
+ len += sprintf(buffer+len, "%s %dK data",
+ (ic? " +": ""), *dc / 1024);
+ }
+ pp = get_property(np, "ram-type", NULL);
+ if (pp)
+ len += sprintf(buffer+len, " %s", pp);
+ buffer[len++] = '\n';
+ }
+
+ /* find ram info */
+ np = find_devices("memory");
+ if (np != 0) {
+ struct reg_property *reg = (struct reg_property *)
+ get_property(np, "reg", NULL);
+ if (reg != 0) {
+ len += sprintf(buffer+len, "memory\t\t: %dMB\n",
+ reg->size >> 20);
+ }
+ }
+
return len;
}
@@ -82,6 +144,13 @@ pmac_get_cpuinfo(char *buffer)
#include "../../../drivers/scsi/sd.h"
#include "../../../drivers/scsi/hosts.h"
+#define SD_MAJOR(i) (!(i) ? SCSI_DISK0_MAJOR : SCSI_DISK1_MAJOR-1+(i))
+#define SD_MAJOR_NUMBER(i) SD_MAJOR((i) >> 8)
+#define SD_MINOR_NUMBER(i) ((i) & 255)
+#define MKDEV_SD_PARTITION(i) MKDEV(SD_MAJOR_NUMBER(i), SD_MINOR_NUMBER(i))
+#define MKDEV_SD(index) MKDEV_SD_PARTITION((index) << 4)
+
+__init
kdev_t sd_find_target(void *host, int tgt)
{
Scsi_Disk *dp;
@@ -90,7 +159,7 @@ kdev_t sd_find_target(void *host, int tgt)
for (dp = rscsi_disks, i = 0; i < sd_template.dev_max; ++i, ++dp)
if (dp->device != NULL && dp->device->host == host
&& dp->device->id == tgt)
- return MKDEV(SCSI_DISK_MAJOR, i << 4);
+ return MKDEV_SD(i);
return 0;
}
#endif
@@ -99,13 +168,13 @@ kdev_t sd_find_target(void *host, int tgt)
* Dummy mksound function that does nothing.
* The real one is in the dmasound driver.
*/
+__pmac
static void
pmac_mksound(unsigned int hz, unsigned int ticks)
{
}
static volatile u32 *sysctrl_regs;
-static volatile u32 *feature_addr;
__initfunc(void
pmac_setup_arch(unsigned long *memory_start_p, unsigned long *memory_end_p))
@@ -137,10 +206,11 @@ pmac_setup_arch(unsigned long *memory_start_p, unsigned long *memory_end_p))
and some registers used by smp boards */
sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000);
__ioremap(0xffc00000, 0x400000, pgprot_val(PAGE_READONLY));
+ ohare_init();
*memory_start_p = pmac_find_bridges(*memory_start_p, *memory_end_p);
- ohare_init();
+ feature_init();
#ifdef CONFIG_KGDB
zs_kgdb_hook(0);
@@ -154,43 +224,30 @@ pmac_setup_arch(unsigned long *memory_start_p, unsigned long *memory_end_p))
#endif
kd_mksound = pmac_mksound;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+ else
+#endif
+ ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE);
}
__initfunc(static void ohare_init(void))
{
- struct device_node *np;
-
- np = find_devices("ohare");
- if (np == 0)
- return;
- if (np->next != 0)
- printk(KERN_WARNING "only using the first ohare\n");
- if (np->n_addrs == 0) {
- printk(KERN_ERR "No addresses for %s\n", np->full_name);
- return;
- }
- feature_addr = (volatile u32 *)
- ioremap(np->addrs[0].address + OHARE_FEATURE_REG, 4);
-
- if (find_devices("via-pmu") == 0) {
- printk(KERN_INFO "Twiddling the magic ohare bits\n");
- out_le32(feature_addr, STARMAX_FEATURES);
- } else {
- out_le32(feature_addr, in_le32(feature_addr) | PBOOK_FEATURES);
- printk(KERN_DEBUG "feature reg = %x\n", in_le32(feature_addr));
- }
-
/*
* Turn on the L2 cache.
* We assume that we have a PSX memory controller iff
* we have an ohare I/O controller.
*/
- if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) {
- if (sysctrl_regs[4] & 0x10)
- sysctrl_regs[4] |= 0x04000020;
- else
- sysctrl_regs[4] |= 0x04000000;
- printk(KERN_INFO "Level 2 cache enabled\n");
+ if (find_devices("ohare") != NULL) {
+ if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) {
+ if (sysctrl_regs[4] & 0x10)
+ sysctrl_regs[4] |= 0x04000020;
+ else
+ sysctrl_regs[4] |= 0x04000000;
+ printk(KERN_INFO "Level 2 cache enabled\n");
+ }
}
}
@@ -201,8 +258,10 @@ int boot_target;
int boot_part;
kdev_t boot_dev;
-__initfunc(void powermac_init(void))
+void __init powermac_init(void)
{
+ if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )
+ return;
adb_init();
pmac_nvram_init();
if (_machine == _MACH_Pmac) {
@@ -210,6 +269,7 @@ __initfunc(void powermac_init(void))
}
}
+#ifdef CONFIG_SCSI
__initfunc(void
note_scsi_host(struct device_node *node, void *host))
{
@@ -238,28 +298,67 @@ note_scsi_host(struct device_node *node, void *host))
}
}
}
+#endif
-__initfunc(void find_boot_device(void))
+#ifdef CONFIG_BLK_DEV_IDE_PMAC
+extern int pmac_ide_count;
+extern struct device_node *pmac_ide_node[];
+static int ide_majors[] = { 3, 22, 33, 34, 56, 57 };
+
+__initfunc(kdev_t find_ide_boot(void))
{
- kdev_t dev;
+ char *p;
+ int i, n;
- if (kdev_t_to_nr(ROOT_DEV) != 0)
- return;
- ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE);
- if (boot_host == NULL)
- return;
+ if (bootdevice == NULL)
+ return 0;
+ p = strrchr(bootdevice, '/');
+ if (p == NULL)
+ return 0;
+ n = p - bootdevice;
+
+ /*
+ * Look through the list of IDE interfaces for this one.
+ */
+ for (i = 0; i < pmac_ide_count; ++i) {
+ char *name = pmac_ide_node[i]->full_name;
+ if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) {
+ /* XXX should cope with the 2nd drive as well... */
+ return MKDEV(ide_majors[i], 0);
+ }
+ }
+
+ return 0;
+}
+#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+
+__initfunc(void find_boot_device(void))
+{
#ifdef CONFIG_SCSI
- dev = sd_find_target(boot_host, boot_target);
- if (dev == 0)
- return;
- boot_dev = MKDEV(MAJOR(dev), MINOR(dev) + boot_part);
+ if (boot_host != NULL) {
+ boot_dev = sd_find_target(boot_host, boot_target);
+ if (boot_dev != 0)
+ return;
+ }
+#endif
+#ifdef CONFIG_BLK_DEV_IDE_PMAC
+ boot_dev = find_ide_boot();
#endif
- /* XXX should cope with booting from IDE also */
}
-__initfunc(void note_bootable_part(kdev_t dev, int part))
+/* can't be initfunc - can be called whenever a disk is first accessed */
+__pmac
+void note_bootable_part(kdev_t dev, int part)
{
static int found_boot = 0;
+ char *p;
+
+ /* Do nothing if the root has been set already. */
+ if (ROOT_DEV != to_kdev_t(DEFAULT_ROOT_DEVICE))
+ return;
+ p = strstr(saved_command_line, "root=");
+ if (p != NULL && (p == saved_command_line || p[-1] == ' '))
+ return;
if (!found_boot) {
find_boot_device();
diff --git a/arch/ppc/kernel/pmac_support.c b/arch/ppc/kernel/pmac_support.c
index c88c8bae9..0196c5eb6 100644
--- a/arch/ppc/kernel/pmac_support.c
+++ b/arch/ppc/kernel/pmac_support.c
@@ -25,8 +25,7 @@ static int nvram_mult;
#define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */
-__pmac
-
+__init
void pmac_nvram_init(void)
{
struct device_node *dp;
diff --git a/arch/ppc/kernel/ppc_defs.h b/arch/ppc/kernel/ppc_defs.h
new file mode 100644
index 000000000..83315a2ae
--- /dev/null
+++ b/arch/ppc/kernel/ppc_defs.h
@@ -0,0 +1,69 @@
+/*
+ * WARNING! This file is automatically generated - DO NOT EDIT!
+ */
+#define KERNELBASE -1073741824
+#define STATE 0
+#define NEXT_TASK 48
+#define COUNTER 24
+#define PROCESSOR 36
+#define SIGPENDING 8
+#define TSS 568
+#define MM 872
+#define TASK_STRUCT_SIZE 912
+#define KSP 0
+#define PG_TABLES 4
+#define PGD 8
+#define LAST_SYSCALL 20
+#define PT_REGS 12
+#define PF_TRACESYS 32
+#define TASK_FLAGS 4
+#define NEED_RESCHED 20
+#define TSS_FPR0 24
+#define TSS_FPSCR 284
+#define TSS_SMP_FORK_RET 288
+#define TASK_UNION_SIZE 8192
+#define STACK_FRAME_OVERHEAD 16
+#define INT_FRAME_SIZE 192
+#define GPR0 16
+#define GPR1 20
+#define GPR2 24
+#define GPR3 28
+#define GPR4 32
+#define GPR5 36
+#define GPR6 40
+#define GPR7 44
+#define GPR8 48
+#define GPR9 52
+#define GPR10 56
+#define GPR11 60
+#define GPR12 64
+#define GPR13 68
+#define GPR14 72
+#define GPR15 76
+#define GPR16 80
+#define GPR17 84
+#define GPR18 88
+#define GPR19 92
+#define GPR20 96
+#define GPR21 100
+#define GPR22 104
+#define GPR23 108
+#define GPR24 112
+#define GPR25 116
+#define GPR26 120
+#define GPR27 124
+#define GPR28 128
+#define GPR29 132
+#define GPR30 136
+#define GPR31 140
+#define _NIP 144
+#define _MSR 148
+#define _CTR 156
+#define _LINK 160
+#define _CCR 168
+#define _XER 164
+#define _DAR 180
+#define _DSISR 184
+#define ORIG_GPR3 152
+#define RESULT 188
+#define TRAP 176
diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
index c1445d393..3aa0534ea 100644
--- a/arch/ppc/kernel/ppc_htab.c
+++ b/arch/ppc/kernel/ppc_htab.c
@@ -1,5 +1,5 @@
/*
- * $Id: ppc_htab.c,v 1.21 1998/05/13 22:34:55 cort Exp $
+ * $Id: ppc_htab.c,v 1.25 1998/08/26 10:28:26 davem Exp $
*
* PowerPC hash table management proc entry. Will show information
* about the current hash table and will allow changes to it.
@@ -17,6 +17,8 @@
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
+#include <linux/sysctl.h>
+#include <linux/ctype.h>
#include <asm/uaccess.h>
#include <asm/bitops.h>
@@ -31,6 +33,8 @@ static ssize_t ppc_htab_read(struct file * file, char * buf,
static ssize_t ppc_htab_write(struct file * file, const char * buffer,
size_t count, loff_t *ppos);
static long long ppc_htab_lseek(struct file * file, loff_t offset, int orig);
+int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
+ void *buffer, size_t *lenp);
extern PTE *Hash, *Hash_end;
extern unsigned long Hash_size, Hash_mask;
@@ -519,3 +523,147 @@ ppc_htab_lseek(struct file * file, loff_t offset, int orig)
return(-EINVAL);
}
}
+
+int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
+ void *buffer, size_t *lenp)
+{
+ int vleft, first=1, len, left, val;
+ #define TMPBUFLEN 256
+ char buf[TMPBUFLEN], *p;
+
+ if ( (_get_PVR() >> 16) != 8) return -EFAULT;
+
+ if ( /*!table->maxlen ||*/ (filp->f_pos && !write)) {
+ *lenp = 0;
+ return 0;
+ }
+
+ vleft = table->maxlen / sizeof(int);
+ left = *lenp;
+
+ for (; left /*&& vleft--*/; first=0) {
+ if (write) {
+ while (left) {
+ char c;
+ if(get_user(c,(char *) buffer))
+ return -EFAULT;
+ if (!isspace(c))
+ break;
+ left--;
+ ((char *) buffer)++;
+ }
+ if (!left)
+ break;
+ len = left;
+ if (len > TMPBUFLEN-1)
+ len = TMPBUFLEN-1;
+ if(copy_from_user(buf, buffer, len))
+ return -EFAULT;
+ buf[len] = 0;
+ p = buf;
+ if (*p < '0' || *p > '9')
+ break;
+ val = simple_strtoul(p, &p, 0);
+ len = p-buf;
+ if ((len < left) && *p && !isspace(*p))
+ break;
+ buffer += len;
+ left -= len;
+ _set_L2CR(val);
+ while ( _get_L2CR() & 0x1 )
+ /* wait for invalidate to finish */;
+
+ } else {
+ p = buf;
+ if (!first)
+ *p++ = '\t';
+ val = _get_L2CR();
+ p += sprintf(p, "%08x: ", val);
+ p += sprintf(p, " %s",
+ (val&0x80000000)?"enabled":"disabled");
+ p += sprintf(p,",%sparity",(val&0x40000000)?"":"no ");
+
+ switch( (val >> 28) & 0x3 )
+ {
+ case 1: p += sprintf(p,",256Kb");
+ break;
+ case 2: p += sprintf(p,",512Kb");
+ break;
+ case 3: p += sprintf(p,",1M");
+ break;
+ default: p += sprintf(p,",unknown size");
+ break;
+ }
+
+
+ switch( (val >> 25) & 0x7 )
+ {
+ case 0: p += sprintf(p,",clock disabled");
+ break;
+ case 1: p += sprintf(p,",+1 clock");
+ break;
+ case 2: p += sprintf(p,",+1.5 clock");
+ break;
+ case 7:
+ case 3: p += sprintf(p,",reserved clock");
+ break;
+ case 4: p += sprintf(p,",+2 clock");
+ break;
+ case 5: p += sprintf(p,",+2.5 clock");
+ break;
+ case 6: p += sprintf(p,",+3 clock");
+ break;
+ }
+
+ switch( (val >> 23) & 0x2 )
+ {
+ case 0: p += sprintf(p,",flow-through burst SRAM");
+ break;
+ case 1: p += sprintf(p,",reserved SRAM");
+ break;
+ case 2: p += sprintf(p,",pipelined burst SRAM");
+ break;
+ case 3: p += sprintf(p,",pipelined late-write SRAM");
+ break;
+ }
+
+ p += sprintf(p,"%s",(val>>22)?"":",data only");
+ p += sprintf(p,"%s",(val>>20)?",ZZ enabled":"");
+ p += sprintf(p,",%s",(val>>19)?"write-through":"copy-back");
+ p += sprintf(p,",%sns hold",(val>>16)?"1.0":"0.5");
+
+ p += sprintf(p,"\n");
+
+ len = strlen(buf);
+ if (len > left)
+ len = left;
+ if(copy_to_user(buffer, buf, len))
+ return -EFAULT;
+ left -= len;
+ buffer += len;
+ break;
+ }
+ }
+
+ if (!write && !first && left) {
+ if(put_user('\n', (char *) buffer))
+ return -EFAULT;
+ left--, buffer++;
+ }
+ if (write) {
+ p = (char *) buffer;
+ while (left) {
+ char c;
+ if(get_user(c, p++))
+ return -EFAULT;
+ if (!isspace(c))
+ break;
+ left--;
+ }
+ }
+ if (write && first)
+ return -EINVAL;
+ *lenp -= left;
+ filp->f_pos += *lenp;
+ return 0;
+}
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index e869a31dd..ea5f6db0d 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -11,6 +11,7 @@
#include <asm/semaphore.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
+#include <asm/ide.h>
#include <asm/io.h>
#include <asm/atomic.h>
#include <asm/bitops.h>
@@ -23,6 +24,7 @@
#include <asm/system.h>
#include <asm/pci-bridge.h>
#include <asm/irq.h>
+#include <asm/feature.h>
#define __KERNEL_SYSCALLS__
#include <linux/unistd.h>
@@ -56,10 +58,10 @@ EXPORT_SYMBOL(SingleStepException);
EXPORT_SYMBOL(sys_sigreturn);
EXPORT_SYMBOL(n_lost_interrupts);
EXPORT_SYMBOL(do_lost_interrupts);
-EXPORT_SYMBOL(__ppc_bh_counter);
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(local_irq_count);
+EXPORT_SYMBOL(local_bh_count);
EXPORT_SYMBOL(isa_io_base);
EXPORT_SYMBOL(isa_mem_base);
@@ -138,11 +140,12 @@ EXPORT_SYMBOL(ioremap);
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(ide_insw);
+EXPORT_SYMBOL(ide_outsw);
+
EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(__kernel_thread);
-EXPORT_SYMBOL(__down_interruptible);
-
EXPORT_SYMBOL(__cli);
EXPORT_SYMBOL(__sti);
/*EXPORT_SYMBOL(__restore_flags);*/
@@ -154,6 +157,10 @@ EXPORT_SYMBOL(giveup_fpu);
EXPORT_SYMBOL(flush_icache_range);
EXPORT_SYMBOL(xchg_u32);
+#ifndef CONFIG_MACH_SPECIFIC
+EXPORT_SYMBOL(_machine);
+#endif
+
EXPORT_SYMBOL(adb_request);
EXPORT_SYMBOL(adb_autopoll);
EXPORT_SYMBOL(adb_register);
@@ -169,10 +176,15 @@ EXPORT_SYMBOL(sleep_notifier_list);
EXPORT_SYMBOL(abort);
EXPORT_SYMBOL(find_devices);
EXPORT_SYMBOL(find_type_devices);
+EXPORT_SYMBOL(find_compatible_devices);
EXPORT_SYMBOL(find_path_device);
+EXPORT_SYMBOL(find_phandle);
EXPORT_SYMBOL(get_property);
EXPORT_SYMBOL(pci_io_base);
EXPORT_SYMBOL(pci_device_loc);
+EXPORT_SYMBOL(feature_set);
+EXPORT_SYMBOL(feature_clear);
+EXPORT_SYMBOL(feature_test);
EXPORT_SYMBOL(note_scsi_host);
EXPORT_SYMBOL(kd_mksound);
#ifdef CONFIG_PMAC
diff --git a/arch/ppc/kernel/prep_pci.c b/arch/ppc/kernel/prep_pci.c
index 7f45756cb..b7d94d208 100644
--- a/arch/ppc/kernel/prep_pci.c
+++ b/arch/ppc/kernel/prep_pci.c
@@ -1,5 +1,5 @@
/*
- * $Id: prep_pci.c,v 1.20 1998/06/19 16:48:45 cort Exp $
+ * $Id: prep_pci.c,v 1.23 1998/10/21 10:52:24 cort Exp $
* PReP pci functions.
* Originally by Gary Thomas
* rewritten and updated by Cort Dougan (cort@cs.nmt.edu)
@@ -234,6 +234,44 @@ static char ibm8xx_pci_IRQ_routes[] __prepdata = {
15, /* Line 4 */
};
+/*
+ * a 6015 ibm board
+ * -- Cort
+ */
+static char ibm6015_pci_IRQ_map[23] __prepdata = {
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 0, /* Slot 6 - unused */
+ 0, /* Slot 7 - unused */
+ 0, /* Slot 8 - unused */
+ 0, /* Slot 9 - unused */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - */
+ 1, /* Slot 12 - SCSI */
+ 2, /* Slot 13 - */
+ 2, /* Slot 14 - */
+ 1, /* Slot 15 - */
+ 1, /* Slot 16 - */
+ 0, /* Slot 17 - */
+ 2, /* Slot 18 - */
+ 0, /* Slot 19 - */
+ 0, /* Slot 20 - */
+ 0, /* Slot 21 - */
+ 2, /* Slot 22 - */
+};
+static char ibm6015_pci_IRQ_routes[] __prepdata = {
+ 0, /* Line 0 - unused */
+ 13, /* Line 1 */
+ 10, /* Line 2 */
+ 15, /* Line 3 */
+ 15, /* Line 4 */
+};
+
+
/* IBM Nobis and 850 */
static char Nobis_pci_IRQ_map[23] __prepdata ={
0, /* Slot 0 - unused */
@@ -424,6 +462,11 @@ __initfunc(unsigned long route_pci_interrupts(void))
Motherboard_map = Utah_pci_IRQ_map;
Motherboard_routes = Utah_pci_IRQ_routes;
break;
+ case 0xE0: /* MTX -- close enough?? to Genesis, so reuse it */
+ Motherboard_map_name = "Motorola MTX";
+ Motherboard_map = Genesis_pci_IRQ_map;
+ Motherboard_routes = Genesis_pci_IRQ_routes;
+ break;
case 0x40: /* PowerStack */
default: /* Can't hurt, can it? */
Motherboard_map_name = "Blackhawk (Powerstack)";
@@ -434,16 +477,31 @@ __initfunc(unsigned long route_pci_interrupts(void))
} else if ( _prep_type == _PREP_IBM )
{
unsigned char pl_id;
-
- if (inb(0x0852) == 0xFF) {
+ /*
+ * my carolina is 0xf0
+ * 6015 has 0xfc
+ * -- Cort
+ */
+ printk("IBM ID: %08x\n", inb(0x0852));
+ switch(inb(0x0852))
+ {
+ case 0xff:
Motherboard_map_name = "IBM 850/860 Portable\n";
Motherboard_map = Nobis_pci_IRQ_map;
Motherboard_routes = Nobis_pci_IRQ_routes;
- } else {
+ break;
+ case 0xfc:
+ Motherboard_map_name = "IBM 6015";
+ Motherboard_map = ibm6015_pci_IRQ_map;
+ Motherboard_routes = ibm6015_pci_IRQ_routes;
+ break;
+ default:
Motherboard_map_name = "IBM 8xx (Carolina)";
Motherboard_map = ibm8xx_pci_IRQ_map;
Motherboard_routes = ibm8xx_pci_IRQ_routes;
+ break;
}
+
/*printk("Changing IRQ mode\n");*/
pl_id=inb(0x04d0);
/*printk("Low mask is %#0x\n", pl_id);*/
diff --git a/arch/ppc/kernel/prep_setup.c b/arch/ppc/kernel/prep_setup.c
index 406c18281..e596f9ea5 100644
--- a/arch/ppc/kernel/prep_setup.c
+++ b/arch/ppc/kernel/prep_setup.c
@@ -76,26 +76,70 @@ prep_get_cpuinfo(char *buffer)
#endif
len = sprintf(buffer,"machine\t\t: PReP %s\n",Motherboard_map_name);
+
- len += sprintf(buffer+len,"L2\t\t: ");
- switch(*((unsigned char *)CACHECRBA) & L2CACHE_MASK)
+ switch ( _prep_type )
{
- case L2CACHE_512KB:
- len += sprintf(buffer+len,"512Kb\n");
- break;
- case L2CACHE_256KB:
- len += sprintf(buffer+len,"256Kb\n");
- break;
- case L2CACHE_1MB:
- len += sprintf(buffer+len,"1MB\n");
+ case _PREP_IBM:
+ if ((*(unsigned char *)0x8000080c) & (1<<6))
+ len += sprintf(buffer+len,"Upgrade CPU\n");
+ len += sprintf(buffer+len,"L2\t\t: ");
+ if ((*(unsigned char *)0x8000080c) & (1<<7))
+ {
+ len += sprintf(buffer+len,"not present\n");
+ goto no_l2;
+ }
+ len += sprintf(buffer+len,"%sKb,",
+ (((*(unsigned char *)0x8000080d)>>2)&1)?"512":"256");
+ len += sprintf(buffer+len,"%sync\n",
+ ((*(unsigned char *)0x8000080d)>>7) ? "":"a");
break;
- case L2CACHE_NONE:
- len += sprintf(buffer+len,"none\n");
+ case _PREP_Motorola:
+ len += sprintf(buffer+len,"L2\t\t: ");
+ switch(*((unsigned char *)CACHECRBA) & L2CACHE_MASK)
+ {
+ case L2CACHE_512KB:
+ len += sprintf(buffer+len,"512Kb");
+ break;
+ case L2CACHE_256KB:
+ len += sprintf(buffer+len,"256Kb");
+ break;
+ case L2CACHE_1MB:
+ len += sprintf(buffer+len,"1MB");
+ break;
+ case L2CACHE_NONE:
+ len += sprintf(buffer+len,"none\n");
+ goto no_l2;
+ break;
+ default:
+ len += sprintf(buffer+len, "%x\n",
+ *((unsigned char *)CACHECRBA));
+ }
+
+ len += sprintf(buffer+len,",parity %s",
+ (*((unsigned char *)CACHECRBA) & L2CACHE_PARITY) ?
+ "enabled" : "disabled");
+
+ len += sprintf(buffer+len, " SRAM:");
+
+ switch ( ((*((unsigned char *)CACHECRBA) & 0xf0) >> 4) & ~(0x3) )
+ {
+ case 1: len += sprintf(buffer+len,
+ "synchronous,parity,flow-through\n");
+ break;
+ case 2: len += sprintf(buffer+len,"asynchronous,no parity\n");
+ break;
+ case 3: len += sprintf(buffer+len,"asynchronous,parity\n");
+ break;
+ default:len += sprintf(buffer+len,
+ "synchronous,pipelined,no parity\n");
+ break;
+ }
break;
- default:
- len += sprintf(buffer+len,"%x\n", *((unsigned char *)CACHECRBA));
}
-
+
+
+no_l2:
if ( res->ResidualLength == 0 )
return len;
@@ -111,20 +155,6 @@ prep_get_cpuinfo(char *buffer)
}
len += sprintf(buffer+len,"\n");
-#if 0
- /* L2 */
- if ( (inb(IBM_EQUIP_PRESENT) & 1) == 0) /* l2 present */
- {
- len += sprintf(buffer+len,"l2\t\t: %dkB %s\n",
- ((inb(IBM_L2_STATUS) >> 5) & 1) ? 512 : 256,
- (inb(IBM_SYS_CTL) & 64) ? "enabled" : "disabled");
- }
- else
- {
- len += sprintf(buffer+len,"l2\t\t: not present\n");
- }
-#endif
-
return len;
}
@@ -155,6 +185,9 @@ prep_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
ROOT_DEV = to_kdev_t(0x0801); /* sda1 */
break;
}
+
+ /* Enable L2. Assume we don't need to flush -- Cort*/
+ *(unsigned char *)(0x8000081c) = *(unsigned char *)(0x8000081c)|3;
/* make the serial port the console */
/* strcat(cmd_line,"console=ttyS0,9600n8"); */
@@ -163,7 +196,7 @@ prep_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
sprintf(cmd_line,"%s console=tty0 console=ttyS0,9600n8", cmd_line);
printk("Boot arguments: %s\n", cmd_line);
-#ifdef CONFIG_CS4232
+#ifdef CONFIG_SOUND_CS4232
/*
* setup proper values for the cs4232 driver so we don't have
* to recompile for the motorola or ibm workstations sound systems.
@@ -200,8 +233,7 @@ prep_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
}
}
}
-#endif /* CONFIG_CS4232 */
-
+#endif /* CONFIG_SOUND_CS4232 */
/*print_residual_device_info();*/
request_region(0x20,0x20,"pic1");
diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
index 9cf88c8a4..5ea55cee9 100644
--- a/arch/ppc/kernel/process.c
+++ b/arch/ppc/kernel/process.c
@@ -163,14 +163,19 @@ switch_to(struct task_struct *prev, struct task_struct *new)
#endif
#ifdef SHOW_TASK_SWITCHES
- printk("%s/%d -> %s/%d NIP %08lx cpu %d sfr %d lock %x\n",
+ printk("%s/%d -> %s/%d NIP %08lx cpu %d lock %x root %x/%x\n",
prev->comm,prev->pid,
new->comm,new->pid,new->tss.regs->nip,new->processor,
- new->tss.smp_fork_ret,scheduler_lock.lock);
+ scheduler_lock.lock,new->fs->root,prev->fs->root);
#endif
#ifdef __SMP__
/* avoid complexity of lazy save/restore of fpu
- * by just saving it every time we switch out -- Cort
+ * by just saving it every time we switch out if
+ * this task used the fpu during the last quantum.
+ *
+ * If it tries to use the fpu again, it'll trap and
+ * reload its fp regs.
+ * -- Cort
*/
if ( prev->tss.regs->msr & MSR_FP )
smp_giveup_fpu(prev);
@@ -349,6 +354,9 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
regs->gpr[1] = sp;
regs->msr = MSR_USER;
shove_aux_table(sp);
+ if (last_task_used_math == current)
+ last_task_used_math = 0;
+ current->tss.fpscr = 0;
}
asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
@@ -380,6 +388,7 @@ asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
{
int res;
+
lock_kernel();
res = do_fork(SIGCHLD, regs->gpr[1], regs);
/* only parent returns here */
@@ -401,18 +410,23 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
{
int error;
char * filename;
-
lock_kernel();
filename = getname((char *) a0);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
+#ifdef __SMP__
+ if ( regs->msr & MSR_FP )
+ smp_giveup_fpu(current);
+#else
if ( last_task_used_math == current )
- last_task_used_math = NULL;
+ giveup_fpu();
+#endif
error = do_execve(filename, (char **) a1, (char **) a2, regs);
putname(filename);
out:
unlock_kernel();
+
return error;
}
@@ -446,7 +460,7 @@ __initfunc(int ll_printk(const char *fmt, ...))
int i;
va_start(args, fmt);
- i=sprintf(buf,fmt,args);
+ i=vsprintf(buf,fmt,args);
ll_puts(buf);
va_end(args);
return i;
@@ -455,6 +469,19 @@ __initfunc(int ll_printk(const char *fmt, ...))
int lines = 24, cols = 80;
int orig_x = 0, orig_y = 0;
+void puthex(unsigned long val)
+{
+ unsigned char buf[10];
+ int i;
+ for (i = 7; i >= 0; i--)
+ {
+ buf[i] = "0123456789ABCDEF"[val & 0x0F];
+ val >>= 4;
+ }
+ buf[8] = '\0';
+ prom_print(buf);
+}
+
__initfunc(void ll_puts(const char *s))
{
int x,y;
diff --git a/arch/ppc/kernel/prom.c b/arch/ppc/kernel/prom.c
index 047d590ed..da9d7a04c 100644
--- a/arch/ppc/kernel/prom.c
+++ b/arch/ppc/kernel/prom.c
@@ -1,5 +1,5 @@
/*
- * $Id: prom.c,v 1.32 1998/07/28 20:28:46 geert Exp $
+ * $Id: prom.c,v 1.46 1998/11/11 03:55:09 paulus Exp $
*
* Procedures for interfacing to the Open Firmware PROM on
* Power Macintosh computers.
@@ -15,11 +15,14 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/version.h>
#include <asm/prom.h>
#include <asm/page.h>
#include <asm/processor.h>
#include <asm/irq.h>
#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/bootx.h>
/*
* Properties whose value is longer than this get excluded from our
@@ -60,6 +63,13 @@ struct isa_reg_property {
unsigned size;
};
+struct pci_intr_map {
+ struct pci_address addr;
+ unsigned dunno;
+ phandle int_ctrler;
+ unsigned intr;
+};
+
typedef unsigned long interpret_func(struct device_node *, unsigned long);
static interpret_func interpret_pci_props;
static interpret_func interpret_dbdma_props;
@@ -67,8 +77,12 @@ static interpret_func interpret_isa_props;
static interpret_func interpret_macio_props;
static interpret_func interpret_root_props;
+#ifndef FB_MAX /* avoid pulling in all of the fb stuff */
+#define FB_MAX 8
+#endif
char *prom_display_paths[FB_MAX] __initdata = { 0, };
unsigned int prom_num_displays = 0;
+char *of_stdout_device = 0;
prom_entry prom = 0;
ihandle prom_chosen = 0, prom_stdout = 0;
@@ -84,20 +98,49 @@ unsigned int old_rtas = 0;
static struct device_node *allnodes = 0;
+static void clearscreen(void);
+
+#ifdef CONFIG_BOOTX_TEXT
+
+static void drawchar(char c);
+static void drawstring(const char *c);
+static void scrollscreen(void);
+
+static void draw_byte(unsigned char c, long locX, long locY);
+static void draw_byte_32(unsigned char *bits, unsigned long *base);
+static void draw_byte_16(unsigned char *bits, unsigned long *base);
+static void draw_byte_8(unsigned char *bits, unsigned long *base);
+
+static long g_loc_X;
+static long g_loc_Y;
+static long g_max_loc_X;
+static long g_max_loc_Y;
+
+#define cmapsz (16*256)
+
+static unsigned char vga_font[cmapsz];
+
+#endif
+
+
static void *call_prom(const char *service, int nargs, int nret, ...);
- void prom_print(const char *msg);
static void prom_exit(void);
static unsigned long copy_device_tree(unsigned long, unsigned long);
static unsigned long inspect_node(phandle, struct device_node *, unsigned long,
unsigned long, struct device_node ***);
static unsigned long finish_node(struct device_node *, unsigned long,
interpret_func *);
+static void relocate_nodes(void);
static unsigned long check_display(unsigned long);
static int prom_next_node(phandle *);
+static void *early_get_property(unsigned long, unsigned long, char *);
extern void enter_rtas(void *);
extern unsigned long reloc_offset(void);
+extern char cmd_line[512]; /* XXX */
+boot_infos_t *boot_infos = 0; /* init it so it's in data segment not bss */
+
/*
* prom_init() is called very early on, before the kernel text
* and data have been mapped to KERNELBASE. At this point the code
@@ -124,7 +167,7 @@ extern unsigned long reloc_offset(void);
#define ALIGN(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
-__openfirmware
+__init
static void
prom_exit()
{
@@ -139,7 +182,7 @@ prom_exit()
;
}
-__openfirmware
+__init
void
prom_enter(void)
{
@@ -152,7 +195,7 @@ prom_enter(void)
RELOC(prom)(&args);
}
-__openfirmware
+__init
static void *
call_prom(const char *service, int nargs, int nret, ...)
{
@@ -174,13 +217,23 @@ call_prom(const char *service, int nargs, int nret, ...)
return prom_args.args[nargs];
}
-__openfirmware
+__init
void
prom_print(const char *msg)
{
const char *p, *q;
unsigned long offset = reloc_offset();
+ if (RELOC(prom_stdout) == 0)
+ {
+#ifdef CONFIG_BOOTX_TEXT
+ if (RELOC(boot_infos) != 0)
+ drawstring(msg);
+#endif
+ return;
+ }
+
+
for (p = msg; *p != 0; p = q) {
for (q = p; *q != 0 && *q != '\n'; ++q)
;
@@ -199,7 +252,7 @@ prom_print(const char *msg)
* We enter here early on, when the Open Firmware prom is still
* handling exceptions and the MMU hash table for us.
*/
-__openfirmware
+__init
void
prom_init(int r3, int r4, prom_entry pp)
{
@@ -208,13 +261,59 @@ prom_init(int r3, int r4, prom_entry pp)
unsigned long offset = reloc_offset();
int l;
char *p, *d;
+
+ /* check if we're apus, return if we are */
+ if ( r3 == 0x61707573 )
+ return;
+
+ /* If we came here from BootX, clear the screen,
+ * set up some pointers and return. */
+ if (r3 == 0x426f6f58 && pp == NULL) {
+ boot_infos_t *bi = (boot_infos_t *) r4;
+ unsigned long space;
+ unsigned long ptr, x;
+ char *model;
+
+ RELOC(boot_infos) = PTRUNRELOC(bi);
+
+ clearscreen();
+
+#ifdef CONFIG_BOOTX_TEXT
+ RELOC(g_loc_X) = 0;
+ RELOC(g_loc_Y) = 0;
+ RELOC(g_max_loc_X) = (bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) / 8;
+ RELOC(g_max_loc_Y) = (bi->dispDeviceRect[3] - bi->dispDeviceRect[1]) / 16;
+ prom_print(RELOC("Welcome to Linux, kernel " UTS_RELEASE " booting...\n"));
+#endif
+
+ /*
+ * XXX If this is an iMac, turn off the USB controller.
+ */
+ model = (char *) early_get_property
+ (r4 + bi->deviceTreeOffset, 4, RELOC("model"));
+ if (model && strcmp(model, RELOC("iMac,1")) == 0) {
+ out_le32((unsigned *)0x80880008, 1); /* XXX */
+ }
+
+ space = bi->deviceTreeOffset + bi->deviceTreeSize;
+ if (bi->ramDisk)
+ space = bi->ramDisk + bi->ramDiskSize;
+ RELOC(klimit) = PTRUNRELOC((char *) bi + space);
+
+ /*
+ * Touch each page to make sure the PTEs for them
+ * are in the hash table - the aim is to try to avoid
+ * getting DSI exceptions while copying the kernel image.
+ */
+ for (ptr = (KERNELBASE + offset) & PAGE_MASK;
+ ptr < (unsigned long)bi + space; ptr += PAGE_SIZE)
+ x = *(volatile unsigned long *)ptr;
- /* check if we're prep, return if we are */
- if ( *(unsigned long *)(0) == 0xdeadc0de )
return;
+ }
- /* check if we're apus, return if we are */
- if ( r3 == 0x61707573 )
+ /* check if we're prep, return if we are */
+ if ( *(unsigned long *)(0) == 0xdeadc0de )
return;
/* First get a handle for the stdout device */
@@ -228,9 +327,16 @@ prom_init(int r3, int r4, prom_entry pp)
sizeof(prom_stdout)) <= 0)
prom_exit();
- /* Get the boot device and translate it to a full OF pathname. */
+ /* Get the full OF pathname of the stdout device */
mem = (unsigned long) RELOC(klimit) + offset;
p = (char *) mem;
+ memset(p, 0, 256);
+ call_prom(RELOC("instance-to-path"), 3, 1, RELOC(prom_stdout), p, 255);
+ RELOC(of_stdout_device) = PTRUNRELOC(p);
+ mem += strlen(p) + 1;
+
+ /* Get the boot device and translate it to a full OF pathname. */
+ p = (char *) mem;
l = (int) call_prom(RELOC("getprop"), 4, 1, RELOC(prom_chosen),
RELOC("bootpath"), p, 1<<20);
if (l > 0) {
@@ -297,14 +403,15 @@ prom_init(int r3, int r4, prom_entry pp)
* So we check whether we will need to open the display,
* and if so, open it now.
*/
-__openfirmware
+__init
static unsigned long
check_display(unsigned long mem)
{
phandle node;
ihandle ih;
+ int i;
unsigned long offset = reloc_offset();
- char type[16], name[16], *path;
+ char type[16], *path;
for (node = 0; prom_next_node(&node); ) {
type[0] = 0;
@@ -323,27 +430,30 @@ check_display(unsigned long mem)
ih = call_prom(RELOC("open"), 1, 1, path);
if (ih == 0 || ih == (ihandle) -1) {
prom_print(RELOC("... failed\n"));
- /* platinum kludge. platinum is a valid display,
- * but not handled by OF. Make sure prom_num_display
- * is incremented anyway
- */
- call_prom(RELOC("getprop"), 4, 1, node, RELOC("name"),
- name, sizeof(name));
- if (strncmp(name, RELOC("platinum"), 8))
- continue;
- } else {
- prom_print(RELOC("... ok\n"));
+ continue;
}
+ prom_print(RELOC("... ok\n"));
+
+ /*
+ * If this display is the device that OF is using for stdout,
+ * move it to the front of the list.
+ */
mem += strlen(path) + 1;
- RELOC(prom_display_paths[RELOC(prom_num_displays)++])
- = PTRUNRELOC(path);
+ i = RELOC(prom_num_displays)++;
+ if (RELOC(of_stdout_device) != 0 && i > 0
+ && strcmp(PTRRELOC(RELOC(of_stdout_device)), path) == 0) {
+ for (; i > 0; --i)
+ RELOC(prom_display_paths[i])
+ = RELOC(prom_display_paths[i-1]);
+ }
+ RELOC(prom_display_paths[i]) = PTRUNRELOC(path);
if (RELOC(prom_num_displays) >= FB_MAX)
break;
}
return ALIGN(mem);
}
-__openfirmware
+__init
static int
prom_next_node(phandle *nodep)
{
@@ -366,7 +476,7 @@ prom_next_node(phandle *nodep)
/*
* Make a copy of the device tree from the PROM.
*/
-__openfirmware
+__init
static unsigned long
copy_device_tree(unsigned long mem_start, unsigned long mem_end)
{
@@ -387,7 +497,7 @@ copy_device_tree(unsigned long mem_start, unsigned long mem_end)
return new_start;
}
-__openfirmware
+__init
static unsigned long
inspect_node(phandle node, struct device_node *dad,
unsigned long mem_start, unsigned long mem_end,
@@ -472,19 +582,41 @@ inspect_node(phandle node, struct device_node *dad,
* It traverses the device tree and fills in the name, type,
* {n_}addrs and {n_}intrs fields of each node.
*/
-__openfirmware
+__init
void
finish_device_tree(void)
{
unsigned long mem = (unsigned long) klimit;
+ if (boot_infos)
+ relocate_nodes();
mem = finish_node(allnodes, mem, NULL);
printk(KERN_INFO "device tree used %lu bytes\n",
mem - (unsigned long) allnodes);
klimit = (char *) mem;
}
-__openfirmware
+/*
+ * early_get_property is used to access the device tree image prepared
+ * by BootX very early on, before the pointers in it have been relocated.
+ */
+__init void *
+early_get_property(unsigned long base, unsigned long node, char *prop)
+{
+ struct device_node *np = (struct device_node *)(base + node);
+ struct property *pp;
+
+ for (pp = np->properties; pp != 0; pp = pp->next) {
+ pp = (struct property *) (base + (unsigned long)pp);
+ if (strcmp((char *)((unsigned long)pp->name + base),
+ prop) == 0) {
+ return (void *)((unsigned long)pp->value + base);
+ }
+ }
+ return 0;
+}
+
+__init
static unsigned long
finish_node(struct device_node *np, unsigned long mem_start,
interpret_func *ifunc)
@@ -505,31 +637,79 @@ finish_node(struct device_node *np, unsigned long mem_start,
ifunc = NULL;
else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci"))
ifunc = interpret_pci_props;
- else if (!strcmp(np->type, "dbdma")
- || (ifunc == interpret_dbdma_props
- && (!strcmp(np->type, "escc")
- || !strcmp(np->type, "media-bay"))))
+ else if (!strcmp(np->type, "dbdma"))
ifunc = interpret_dbdma_props;
- else if (!strcmp(np->type, "mac-io"))
+ else if (!strcmp(np->type, "mac-io")
+ || ifunc == interpret_macio_props)
ifunc = interpret_macio_props;
else if (!strcmp(np->type, "isa"))
ifunc = interpret_isa_props;
- else
+ else if (!((ifunc == interpret_dbdma_props
+ || ifunc == interpret_macio_props)
+ && (!strcmp(np->type, "escc")
+ || !strcmp(np->type, "media-bay"))))
ifunc = NULL;
+ /* if we were booted from BootX, convert the full name */
+ if (boot_infos
+ && strncmp(np->full_name, "Devices:device-tree", 19) == 0) {
+ if (np->full_name[19] == 0) {
+ strcpy(np->full_name, "/");
+ } else if (np->full_name[19] == ':') {
+ char *p = np->full_name + 19;
+ np->full_name = p;
+ for (; *p; ++p)
+ if (*p == ':')
+ *p = '/';
+ }
+ }
+
for (child = np->child; child != NULL; child = child->sibling)
mem_start = finish_node(child, mem_start, ifunc);
return mem_start;
}
-__openfirmware
+/*
+ * When BootX makes a copy of the device tree from the MacOS
+ * Name Registry, it is in the format we use but all of the pointers
+ * are offsets from the start of the tree.
+ * This procedure updates the pointers.
+ */
+__init
+static void relocate_nodes(void)
+{
+ unsigned long base;
+ struct device_node *np;
+ struct property *pp;
+
+#define ADDBASE(x) (x = (x)? ((typeof (x))((unsigned long)(x) + base)): 0)
+
+ base = (unsigned long) boot_infos + boot_infos->deviceTreeOffset;
+ allnodes = (struct device_node *)(base + 4);
+ for (np = allnodes; np != 0; np = np->allnext) {
+ ADDBASE(np->full_name);
+ ADDBASE(np->properties);
+ ADDBASE(np->parent);
+ ADDBASE(np->child);
+ ADDBASE(np->sibling);
+ ADDBASE(np->allnext);
+ for (pp = np->properties; pp != 0; pp = pp->next) {
+ ADDBASE(pp->name);
+ ADDBASE(pp->value);
+ ADDBASE(pp->next);
+ }
+ }
+}
+
+__init
static unsigned long
interpret_pci_props(struct device_node *np, unsigned long mem_start)
{
struct address_range *adr;
struct pci_reg_property *pci_addrs;
- int i, l, *ip;
+ int i, l, *ip, ml;
+ struct pci_intr_map *imp;
pci_addrs = (struct pci_reg_property *)
get_property(np, "assigned-addresses", &l);
@@ -548,6 +728,30 @@ interpret_pci_props(struct device_node *np, unsigned long mem_start)
mem_start += i * sizeof(struct address_range);
}
+ /*
+ * If the pci host bridge has an interrupt-map property,
+ * look for our node in it.
+ */
+ if (np->parent != 0 && pci_addrs != 0
+ && (imp = (struct pci_intr_map *)
+ get_property(np->parent, "interrupt-map", &ml)) != 0
+ && (ip = (int *) get_property(np, "interrupts", &l)) != 0) {
+ unsigned int busdevfn = pci_addrs[0].addr.a_hi & 0xffff00;
+ np->n_intrs = 0;
+ np->intrs = (struct interrupt_info *) mem_start;
+ for (i = 0; (ml -= sizeof(struct pci_intr_map)) >= 0; ++i) {
+ if (imp[i].addr.a_hi == busdevfn) {
+ np->intrs[np->n_intrs].line = imp[i].intr;
+ np->intrs[np->n_intrs].sense = 0;
+ ++np->n_intrs;
+ }
+ }
+ if (np->n_intrs == 0)
+ np->intrs = 0;
+ mem_start += np->n_intrs * sizeof(struct interrupt_info);
+ return mem_start;
+ }
+
ip = (int *) get_property(np, "AAPL,interrupts", &l);
if (ip == 0)
ip = (int *) get_property(np, "interrupts", &l);
@@ -564,7 +768,7 @@ interpret_pci_props(struct device_node *np, unsigned long mem_start)
return mem_start;
}
-__openfirmware
+__init
static unsigned long
interpret_dbdma_props(struct device_node *np, unsigned long mem_start)
{
@@ -613,7 +817,7 @@ interpret_dbdma_props(struct device_node *np, unsigned long mem_start)
return mem_start;
}
-__openfirmware
+__init
static unsigned long
interpret_macio_props(struct device_node *np, unsigned long mem_start)
{
@@ -651,18 +855,28 @@ interpret_macio_props(struct device_node *np, unsigned long mem_start)
ip = (int *) get_property(np, "AAPL,interrupts", &l);
if (ip != 0) {
np->intrs = (struct interrupt_info *) mem_start;
- np->n_intrs = l / (2 * sizeof(int));
- mem_start += np->n_intrs * sizeof(struct interrupt_info);
- for (i = 0; i < np->n_intrs; ++i) {
- np->intrs[i].line = openpic_to_irq(*ip++);
- np->intrs[i].sense = *ip++;
+ if (_machine == _MACH_Pmac) {
+ /* for the iMac */
+ np->n_intrs = l / sizeof(int);
+ for (i = 0; i < np->n_intrs; ++i) {
+ np->intrs[i].line = *ip++;
+ np->intrs[i].sense = 0;
+ }
+ } else {
+ /* CHRP machines */
+ np->n_intrs = l / (2 * sizeof(int));
+ for (i = 0; i < np->n_intrs; ++i) {
+ np->intrs[i].line = openpic_to_irq(*ip++);
+ np->intrs[i].sense = *ip++;
+ }
}
+ mem_start += np->n_intrs * sizeof(struct interrupt_info);
}
return mem_start;
}
-__openfirmware
+__init
static unsigned long
interpret_isa_props(struct device_node *np, unsigned long mem_start)
{
@@ -700,7 +914,7 @@ interpret_isa_props(struct device_node *np, unsigned long mem_start)
return mem_start;
}
-__openfirmware
+__init
static unsigned long
interpret_root_props(struct device_node *np, unsigned long mem_start)
{
@@ -779,6 +993,30 @@ find_type_devices(const char *type)
return head;
}
+/* Checks if the given "compat" string matches one of the strings in
+ * the device's "compatible" property
+ */
+__openfirmware
+int
+device_is_compatible(struct device_node *device, const char *compat)
+{
+ const char* cp;
+ int cplen, l;
+
+ cp = (char *) get_property(device, "compatible", &cplen);
+ if (cp == NULL)
+ return 0;
+ while (cplen > 0) {
+ if (strcasecmp(cp, compat) == 0)
+ return 1;
+ l = strlen(cp) + 1;
+ cp += l;
+ cplen -= l;
+ }
+
+ return 0;
+}
+
/*
* Construct and return a list of the device_nodes with a given type
* and compatible property.
@@ -788,15 +1026,13 @@ struct device_node *
find_compatible_devices(const char *type, const char *compat)
{
struct device_node *head, **prevp, *np;
- const char *cp;
prevp = &head;
for (np = allnodes; np != 0; np = np->allnext) {
if (type != NULL
&& !(np->type != 0 && strcasecmp(np->type, type) == 0))
continue;
- cp = (char *) get_property(np, "compatible", NULL);
- if (cp != NULL && strcasecmp(cp, compat) == 0) {
+ if (device_is_compatible(np, compat)) {
*prevp = np;
prevp = &np->next;
}
@@ -854,6 +1090,7 @@ get_property(struct device_node *np, const char *name, int *lenp)
return 0;
}
+#if 0
__openfirmware
void
print_properties(struct device_node *np)
@@ -904,7 +1141,9 @@ print_properties(struct device_node *np)
}
}
}
+#endif
+/* this can be called after setup -- Cort */
__openfirmware
int
call_rtas(const char *service, int nargs, int nret,
@@ -941,7 +1180,7 @@ call_rtas(const char *service, int nargs, int nret,
return u.words[nargs+3];
}
-__openfirmware
+__init
void
abort()
{
@@ -951,3 +1190,563 @@ abort()
#endif
prom_exit();
}
+
+#define CALC_BASE(y) (bi->dispDeviceBase + bi->dispDeviceRect[0] * \
+ (bi->dispDeviceDepth >> 3) + bi->dispDeviceRowBytes * (y))
+
+__init
+static void
+clearscreen(void)
+{
+ unsigned long offset = reloc_offset();
+ boot_infos_t* bi = PTRRELOC(RELOC(boot_infos));
+ unsigned long *base = (unsigned long *)CALC_BASE(0);
+ unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
+ (bi->dispDeviceDepth >> 3)) >> 2;
+ int i,j;
+
+ for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++)
+ {
+ unsigned long *ptr = base;
+ for(j=width; j; --j)
+ *(ptr++) = 0;
+ base += (bi->dispDeviceRowBytes >> 2);
+ }
+}
+
+#ifdef CONFIG_BOOTX_TEXT
+
+__init
+static void
+scrollscreen(void)
+{
+ unsigned long offset = reloc_offset();
+ boot_infos_t* bi = PTRRELOC(RELOC(boot_infos));
+ unsigned long *src = (unsigned long *)CALC_BASE(16);
+ unsigned long *dst = (unsigned long *)CALC_BASE(0);
+ unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
+ (bi->dispDeviceDepth >> 3)) >> 2;
+ int i,j;
+
+ for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++)
+ {
+ unsigned long *src_ptr = src;
+ unsigned long *dst_ptr = dst;
+ for(j=width; j; --j)
+ *(dst_ptr++) = *(src_ptr++);
+ src += (bi->dispDeviceRowBytes >> 2);
+ dst += (bi->dispDeviceRowBytes >> 2);
+ }
+ for (i=0; i<16; i++)
+ {
+ unsigned long *dst_ptr = dst;
+ for(j=width; j; --j)
+ *(dst_ptr++) = 0;
+ dst += (bi->dispDeviceRowBytes >> 2);
+ }
+}
+
+__init
+static void
+drawchar(char c)
+{
+ unsigned long offset = reloc_offset();
+
+ switch(c)
+ {
+ case '\r': RELOC(g_loc_X) = 0; break;
+ case '\n': RELOC(g_loc_X) = 0; RELOC(g_loc_Y)++; break;
+ default:
+ draw_byte(c, RELOC(g_loc_X)++, RELOC(g_loc_Y));
+ if (RELOC(g_loc_X) >= RELOC(g_max_loc_X))
+ {
+ RELOC(g_loc_X) = 0;
+ RELOC(g_loc_Y)++;
+ }
+ }
+ while (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y))
+ {
+ scrollscreen();
+ RELOC(g_loc_Y)--;
+ }
+}
+
+__init
+static void
+drawstring(const char *c)
+{
+ while(*c)
+ drawchar(*(c++));
+}
+
+__init
+static void
+draw_byte(unsigned char c, long locX, long locY)
+{
+ unsigned long offset = reloc_offset();
+ boot_infos_t* bi = PTRRELOC(RELOC(boot_infos));
+ unsigned char *base = bi->dispDeviceBase
+ + (bi->dispDeviceRowBytes * ((locY * 16) + bi->dispDeviceRect[1]))
+ + (bi->dispDeviceDepth >> 3) * ((locX * 8) + bi->dispDeviceRect[0]);
+ unsigned char *font = &RELOC(vga_font)[((unsigned long)c) * 16];
+
+ switch(bi->dispDeviceDepth)
+ {
+ case 32:
+ draw_byte_32(font, (unsigned long *)base);
+ break;
+ case 16:
+ draw_byte_16(font, (unsigned long *)base);
+ break;
+ case 8:
+ draw_byte_8(font, (unsigned long *)base);
+ break;
+ default:
+ break;
+ }
+}
+
+__init
+static unsigned long expand_bits_8[16] = {
+ 0x00000000,
+ 0x000000ff,
+ 0x0000ff00,
+ 0x0000ffff,
+ 0x00ff0000,
+ 0x00ff00ff,
+ 0x00ffff00,
+ 0x00ffffff,
+ 0xff000000,
+ 0xff0000ff,
+ 0xff00ff00,
+ 0xff00ffff,
+ 0xffff0000,
+ 0xffff00ff,
+ 0xffffff00,
+ 0xffffffff
+};
+
+__init
+static unsigned long expand_bits_16[4] = {
+ 0x00000000,
+ 0x0000ffff,
+ 0xffff0000,
+ 0xffffffff
+};
+
+
+__init
+static void
+draw_byte_32(unsigned char *font, unsigned long *base)
+{
+ unsigned long offset = reloc_offset();
+ boot_infos_t* bi = PTRRELOC(RELOC(boot_infos));
+ int l, bits;
+ int fg = 0xFFFFFFFFUL;
+ int bg = 0x00000000UL;
+
+
+ for (l = 0; l < 16; ++l)
+ {
+ bits = *font++;
+ base[0] = (-(bits >> 7) & fg) ^ bg;
+ base[1] = (-((bits >> 6) & 1) & fg) ^ bg;
+ base[2] = (-((bits >> 5) & 1) & fg) ^ bg;
+ base[3] = (-((bits >> 4) & 1) & fg) ^ bg;
+ base[4] = (-((bits >> 3) & 1) & fg) ^ bg;
+ base[5] = (-((bits >> 2) & 1) & fg) ^ bg;
+ base[6] = (-((bits >> 1) & 1) & fg) ^ bg;
+ base[7] = (-(bits & 1) & fg) ^ bg;
+ base = (unsigned long *) ((char *)base + bi->dispDeviceRowBytes);
+ }
+}
+
+__init
+static void
+draw_byte_16(unsigned char *font, unsigned long *base)
+{
+ unsigned long offset = reloc_offset();
+ boot_infos_t* bi = PTRRELOC(RELOC(boot_infos));
+ int l, bits;
+ int fg = 0xFFFFFFFFUL;
+ int bg = 0x00000000UL;
+ unsigned long *eb = RELOC(expand_bits_16);
+
+ for (l = 0; l < 16; ++l)
+ {
+ bits = *font++;
+ base[0] = (eb[bits >> 6] & fg) ^ bg;
+ base[1] = (eb[(bits >> 4) & 3] & fg) ^ bg;
+ base[2] = (eb[(bits >> 2) & 3] & fg) ^ bg;
+ base[3] = (eb[bits & 3] & fg) ^ bg;
+ base = (unsigned long *) ((char *)base + bi->dispDeviceRowBytes);
+ }
+}
+
+__init
+static void
+draw_byte_8(unsigned char *font, unsigned long *base)
+{
+ unsigned long offset = reloc_offset();
+ boot_infos_t* bi = PTRRELOC(RELOC(boot_infos));
+ int l, bits;
+ int fg = 0x0F0F0F0FUL;
+ int bg = 0x00000000UL;
+ unsigned long *eb = RELOC(expand_bits_8);
+
+ for (l = 0; l < 16; ++l)
+ {
+ bits = *font++;
+ base[0] = (eb[bits >> 4] & fg) ^ bg;
+ base[1] = (eb[bits & 0xf] & fg) ^ bg;
+ base = (unsigned long *) ((char *)base + bi->dispDeviceRowBytes);
+ }
+}
+
+__init
+static unsigned char vga_font[cmapsz] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd,
+0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff,
+0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe,
+0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
+0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd,
+0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e,
+0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30,
+0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63,
+0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8,
+0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e,
+0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb,
+0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6,
+0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
+0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c,
+0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c,
+0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c,
+0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18,
+0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c,
+0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30,
+0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
+0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
+0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe,
+0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
+0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18,
+0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
+0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
+0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
+0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
+0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde,
+0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38,
+0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c,
+0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68,
+0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
+0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60,
+0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7,
+0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66,
+0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c,
+0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c,
+0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
+0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3,
+0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18,
+0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3,
+0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30,
+0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60,
+0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc,
+0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60,
+0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06,
+0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60,
+0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb,
+0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66,
+0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60,
+0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30,
+0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3,
+0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18,
+0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6,
+0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
+0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00,
+0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe,
+0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c,
+0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38,
+0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06,
+0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe,
+0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00,
+0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66,
+0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6,
+0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00,
+0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b,
+0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c,
+0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18,
+0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00,
+0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
+0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
+0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18,
+0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66,
+0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18,
+0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30,
+0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc,
+0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
+0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
+0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06,
+0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30,
+0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
+0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36,
+0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44,
+0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
+0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
+0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
+0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36,
+0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0,
+0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8,
+0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66,
+0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
+0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66,
+0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60,
+0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c,
+0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18,
+0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
+0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00,
+0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
+0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00,
+};
+
+#endif /* CONFIG_BOOTX_TEXT */
diff --git a/arch/ppc/kernel/residual.c b/arch/ppc/kernel/residual.c
index b2e198f68..83333f660 100644
--- a/arch/ppc/kernel/residual.c
+++ b/arch/ppc/kernel/residual.c
@@ -1,5 +1,5 @@
/*
- * $Id: residual.c,v 1.10 1998/07/09 22:23:18 cort Exp $
+ * $Id: residual.c,v 1.14 1998/10/11 17:38:10 cort Exp $
*
* Code to deal with the PReP residual data.
*
@@ -23,7 +23,6 @@
#include <asm/pnp.h>
#include <asm/byteorder.h>
-#if 0
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -50,7 +49,7 @@
#include <asm/ide.h>
-const char * PnP_BASE_TYPES[]= {
+const char * PnP_BASE_TYPES[] __initdata = {
"Reserved",
"MassStorageDevice",
"NetworkInterfaceController",
@@ -66,7 +65,7 @@ const char * PnP_BASE_TYPES[]= {
/* Device Sub Type Codes */
-const unsigned char * PnP_SUB_TYPES[] = {
+const unsigned char * PnP_SUB_TYPES[] __initdata = {
"\001\000SCSIController",
"\001\001IDEController",
"\001\002FloppyController",
@@ -123,7 +122,7 @@ const unsigned char * PnP_SUB_TYPES[] = {
/* Device Interface Type Codes */
-const unsigned char * PnP_INTERFACES[]= {
+const unsigned char * PnP_INTERFACES[] __initdata = {
"\000\000\000General",
"\001\000\000GeneralSCSI",
"\001\001\000GeneralIDE",
@@ -241,7 +240,7 @@ const unsigned char * PnP_INTERFACES[]= {
NULL
};
-static const unsigned char *PnP_SUB_TYPE_STR(unsigned char BaseType,
+static const unsigned char __init *PnP_SUB_TYPE_STR(unsigned char BaseType,
unsigned char SubType) {
const unsigned char ** s=PnP_SUB_TYPES;
while (*s && !((*s)[0]==BaseType
@@ -250,7 +249,7 @@ static const unsigned char *PnP_SUB_TYPE_STR(unsigned char BaseType,
else return("Unknown !");
};
-static const unsigned char *PnP_INTERFACE_STR(unsigned char BaseType,
+static const unsigned char __init *PnP_INTERFACE_STR(unsigned char BaseType,
unsigned char SubType,
unsigned char Interface) {
const unsigned char ** s=PnP_INTERFACES;
@@ -261,7 +260,7 @@ static const unsigned char *PnP_INTERFACE_STR(unsigned char BaseType,
else return NULL;
};
-static void printsmallvendor(PnP_TAG_PACKET *pkt, int size) {
+static void __init printsmallvendor(PnP_TAG_PACKET *pkt, int size) {
int i, c;
char decomp[4];
#define p pkt->S14_Pack.S14_Data.S14_PPCPack
@@ -286,7 +285,7 @@ static void printsmallvendor(PnP_TAG_PACKET *pkt, int size) {
#undef p
}
-static void printsmallpacket(PnP_TAG_PACKET * pkt, int size) {
+static void __init printsmallpacket(PnP_TAG_PACKET * pkt, int size) {
static const unsigned char * intlevel[] = {"high", "low"};
static const unsigned char * intsense[] = {"edge", "level"};
@@ -353,7 +352,7 @@ static void printsmallpacket(PnP_TAG_PACKET * pkt, int size) {
}
}
-static void printlargevendor(PnP_TAG_PACKET * pkt, int size) {
+static void __init printlargevendor(PnP_TAG_PACKET * pkt, int size) {
static const unsigned char * addrtype[] = {"I/O", "Memory", "System"};
static const unsigned char * inttype[] = {"8259", "MPIC", "RS6k BUID %d"};
static const unsigned char * convtype[] = {"Bus Memory", "Bus I/O", "DMA"};
@@ -463,9 +462,7 @@ static void printlargevendor(PnP_TAG_PACKET * pkt, int size) {
}
}
-static void printlargepacket(PnP_TAG_PACKET * pkt, int size) {
- int i;
-
+static void __init printlargepacket(PnP_TAG_PACKET * pkt, int size) {
switch (tag_large_item_name(pkt->S1_Pack.Tag)) {
case LargeVendorItem:
printlargevendor(pkt, size);
@@ -476,8 +473,7 @@ static void printlargepacket(PnP_TAG_PACKET * pkt, int size) {
break;
}
}
-static void printpackets(PnP_TAG_PACKET * pkt, const char * cat) {
- PnP_TAG_PACKET tmp;
+static void __init printpackets(PnP_TAG_PACKET * pkt, const char * cat) {
if (pkt->S1_Pack.Tag== END_TAG) {
printk(" No packets describing %s resources.\n", cat);
return;
@@ -498,13 +494,11 @@ static void printpackets(PnP_TAG_PACKET * pkt, const char * cat) {
} while (pkt->S1_Pack.Tag != END_TAG);
}
-void print_residual_device_info(void)
+void __init print_residual_device_info(void)
{
int i;
- union _PnP_TAG_PACKET *pkt;
PPC_DEVICE *dev;
#define did dev->DeviceId
-return;
/* make sure we have residual data first */
if ( res->ResidualLength == 0 )
@@ -552,18 +546,24 @@ return;
PnP_BASE_TYPES[did.BaseType],
PnP_SUB_TYPE_STR(did.BaseType,did.SubType),
s);
- printpackets( (union _PnP_TAG_PACKET *)
- &res->DevicePnPHeap[dev->AllocatedOffset], "allocated");
- printpackets( (union _PnP_TAG_PACKET *)
- &res->DevicePnPHeap[dev->PossibleOffset], "possible");
- printpackets( (union _PnP_TAG_PACKET *)
- &res->DevicePnPHeap[dev->CompatibleOffset], "compatible");
+ if ( dev->AllocatedOffset )
+ printpackets( (union _PnP_TAG_PACKET *)
+ &res->DevicePnPHeap[dev->AllocatedOffset],
+ "allocated");
+ if ( dev->PossibleOffset )
+ printpackets( (union _PnP_TAG_PACKET *)
+ &res->DevicePnPHeap[dev->PossibleOffset],
+ "possible");
+ if ( dev->CompatibleOffset )
+ printpackets( (union _PnP_TAG_PACKET *)
+ &res->DevicePnPHeap[dev->CompatibleOffset],
+ "compatible");
}
}
-
-static void printVPD(void) {
+#if 0
+static void __init printVPD(void) {
#define vpd res->VitalProductData
int ps=vpd.PageSize, i, j;
static const char* Usage[]={
@@ -628,7 +628,6 @@ static void printVPD(void) {
/*
* Spit out some info about residual data
*/
-#if 0
void print_residual_device_info(void)
{
int i;
@@ -728,7 +727,6 @@ void print_residual_device_info(void)
}
#endif
-#endif /* 0 */
/* Returns the device index in the residual data,
any of the search items may be set as -1 for wildcard,
DevID number field (second halfword) is big endian !
@@ -765,7 +763,7 @@ in this rarely used area we unencode and compare */
little endian in the heap, so we use two parameters to avoid writing
two very similar functions */
-static int same_DevID(unsigned short vendor,
+static int __init same_DevID(unsigned short vendor,
unsigned short Number,
char * str)
{
@@ -781,7 +779,7 @@ static int same_DevID(unsigned short vendor,
return 0;
}
-PPC_DEVICE *residual_find_device(unsigned long BusMask,
+PPC_DEVICE __init *residual_find_device(unsigned long BusMask,
unsigned char * DevID,
int BaseType,
int SubType,
@@ -804,6 +802,28 @@ PPC_DEVICE *residual_find_device(unsigned long BusMask,
return 0;
}
+PPC_DEVICE __init *residual_find_device_id(unsigned long BusMask,
+ unsigned short DevID,
+ int BaseType,
+ int SubType,
+ int Interface,
+ int n)
+{
+ int i;
+ if ( !res->ResidualLength ) return NULL;
+ for (i=0; i<res->ActualNumDevices; i++) {
+#define Dev res->Devices[i].DeviceId
+ if ( (Dev.BusId&BusMask) &&
+ (BaseType==-1 || Dev.BaseType==BaseType) &&
+ (SubType==-1 || Dev.SubType==SubType) &&
+ (Interface==-1 || Dev.Interface==Interface) &&
+ (DevID==0xffff || (Dev.DevId&0xffff) == DevID) &&
+ !(n--) ) return res->Devices+i;
+#undef Dev
+ }
+ return 0;
+}
+
PnP_TAG_PACKET *PnP_find_packet(unsigned char *p,
unsigned packet_tag,
int n)
@@ -823,7 +843,7 @@ PnP_TAG_PACKET *PnP_find_packet(unsigned char *p,
return 0; /* not found */
}
-PnP_TAG_PACKET *PnP_find_small_vendor_packet(unsigned char *p,
+PnP_TAG_PACKET __init *PnP_find_small_vendor_packet(unsigned char *p,
unsigned packet_type,
int n)
{
@@ -837,7 +857,7 @@ PnP_TAG_PACKET *PnP_find_small_vendor_packet(unsigned char *p,
return 0; /* not found */
}
-PnP_TAG_PACKET *PnP_find_large_vendor_packet(unsigned char *p,
+PnP_TAG_PACKET __init *PnP_find_large_vendor_packet(unsigned char *p,
unsigned packet_type,
int n)
{
@@ -850,4 +870,3 @@ PnP_TAG_PACKET *PnP_find_large_vendor_packet(unsigned char *p,
};
return 0; /* not found */
}
-
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 7ea277866..706c1dde2 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -1,9 +1,10 @@
/*
- * $Id: setup.c,v 1.95 1998/07/20 19:03:47 geert Exp $
+ * $Id: setup.c,v 1.117 1998/11/09 19:55:53 geert Exp $
* Common prep/pmac/chrp boot and setup code.
*/
#include <linux/config.h>
+#include <linux/module.h>
#include <linux/string.h>
#include <linux/sched.h>
#include <linux/init.h>
@@ -23,15 +24,22 @@
#include <asm/bootinfo.h>
#include <asm/setup.h>
#include <asm/amigappc.h>
+#include <asm/smp.h>
#ifdef CONFIG_MBX
#include <asm/mbx.h>
#endif
+#include <asm/bootx.h>
/* APUS defs */
extern unsigned long m68k_machtype;
-extern struct mem_info ramdisk;
extern int parse_bootinfo(const struct bi_record *);
extern char _end[];
+#ifdef CONFIG_APUS
+struct mem_info ramdisk;
+unsigned long isa_io_base;
+unsigned long isa_mem_base;
+unsigned long pci_dram_offset;
+#endif
/* END APUS defs */
extern char cmd_line[512];
@@ -52,6 +60,8 @@ RESIDUAL *res = (RESIDUAL *)&__res;
int _prep_type;
+extern boot_infos_t *boot_infos;
+
/*
* Perhaps we can put the pmac screen_info[] here
* on pmac as well so we don't need the ifdef's.
@@ -122,9 +132,7 @@ void machine_restart(char *cmd)
cuda_poll();
break;
case ADB_VIAPMU:
- pmu_request(&req, NULL, 1, PMU_RESET);
- for (;;)
- pmu_poll();
+ pmu_restart();
break;
default:
}
@@ -197,10 +205,7 @@ void machine_power_off(void)
cuda_poll();
break;
case ADB_VIAPMU:
- pmu_request(&req, NULL, 5, PMU_SHUTDOWN,
- 'M', 'A', 'T', 'T');
- for (;;)
- pmu_poll();
+ pmu_shutdown();
break;
default:
}
@@ -217,10 +222,7 @@ void machine_power_off(void)
case _MACH_prep:
machine_restart(NULL);
case _MACH_apus:
-#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
- apm_set_power_state(APM_STATE_OFF);
for (;;);
-#endif
}
for (;;);
#else /* CONFIG_MBX */
@@ -239,14 +241,16 @@ void machine_halt(void)
}
-#ifdef CONFIG_BLK_DEV_IDE
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
{
#if !defined(CONFIG_MBX) && !defined(CONFIG_APUS)
switch (_machine) {
+#if defined(CONFIG_BLK_DEV_IDE_PMAC)
case _MACH_Pmac:
- pmac_ide_init_hwif_ports(p,base,irq);
+ pmac_ide_init_hwif_ports(p,base,irq);
break;
+#endif
case _MACH_chrp:
chrp_ide_init_hwif_ports(p,base,irq);
break;
@@ -256,72 +260,36 @@ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
}
#endif
}
+EXPORT_SYMBOL(ide_init_hwif_ports);
#endif
unsigned long cpu_temp(void)
{
-#if 0
- unsigned long i, temp, thrm1, dir;
- int sanity;
+ unsigned char thres = 0;
- /*
- * setup thrm3 - need to give TAU at least 20us
- * to do the compare so assume a 300MHz clock.
- * We need 300*20 ticks then.
- * -- Cort
- */
- asm("mtspr 1020, %1\n\t"
- "mtspr 1021, %1\n\t"
- "mtspr 1022, %0\n\t"::
- "r" ( ((300*20)<<18) | THRM3_E), "r" (0) );
-
#if 0
- for ( i = 127 ; i >= 0 ; i-- )
- {
- asm("mtspr 1020, %0\n\t"::
- "r" (THRM1_TID|THRM1_V|(i<<2)) );
- /* check value */
- while ( !( thrm1 & THRM1_TIV) )
- asm("mfspr %0, 1020 \n\t": "=r" (thrm1) );
- if ( thrm1 & THRM1_TIN )
- {
- printk("tin set: %x tiv %x\n", thrm1,thrm1&THRM1_TIV);
- goto out;
- }
-
- }
+ /* disable thrm2 */
+ _set_THRM2( 0 );
+ /* threshold 0 C, tid: exceeding threshold, tie: don't generate interrupt */
+ _set_THRM1( THRM1_V );
+
+ /* we need 20us to do the compare - assume 300MHz processor clock */
+ _set_THRM3(0);
+ _set_THRM3(THRM3_E | (300*30)<<18 );
+
+ udelay(100);
+ /* wait for the compare to complete */
+ /*while ( !(_get_THRM1() & THRM1_TIV) ) ;*/
+ if ( !(_get_THRM1() & THRM1_TIV) )
+ printk("no tiv\n");
+ if ( _get_THRM1() & THRM1_TIN )
+ printk("crossed\n");
+ /* turn everything off */
+ _set_THRM3(0);
+ _set_THRM1(0);
#endif
-#if 0
- i = 32; /* increment */
- dir = 1; /* direction we're checking 0=up 1=down */
- temp = 64; /* threshold checking against */
- while ( i )
- {
- _set_THRM1((1<<29) | THRM1_V | (temp<<2) );
- printk("checking %d in dir %d thrm set to %x/%x\n", temp,dir,
- ( (1<<29) | THRM1_V | (temp<<2)),_get_THRM1());
- /* check value */
- sanity = 0x0fffffff;
- while ( (!( thrm1 & THRM1_TIV)) && (sanity--) )
- thrm1 = _get_THRM1();
- /*asm("mfspr %0, 1020 \n\t": "=r" (thrm1) );*/
- if ( ! sanity || sanity==0xffffffff ) printk("no sanity\n");
- /* temp is not in that direction */
- if ( !(thrm1 & THRM1_TIN) )
- {
- printk("not in that dir thrm1 %x\n",thrm1);
- if ( dir == 0 ) dir = 1;
- else dir = 0;
- }
- if ( dir ) temp -= i;
- else temp += i;
- i /= 2;
- }
- asm("mtspr 1020, %0\n\t"
- "mtspr 1022, %0\n\t" ::"r" (0) );
-#endif
-#endif
- return 0;
+
+ return thres;
}
int get_cpuinfo(char *buffer)
@@ -333,14 +301,13 @@ int get_cpuinfo(char *buffer)
unsigned long len = 0;
unsigned long bogosum = 0;
unsigned long i;
- unsigned long cr;
+
#ifdef __SMP__
- extern unsigned long cpu_present_map;
- extern struct cpuinfo_PPC cpu_data[NR_CPUS];
+#define CPU_PRESENT(x) (cpu_callin_map[(x)])
#define GET_PVR ((long int)(cpu_data[i].pvr))
#define CD(x) (cpu_data[i].x)
#else
-#define cpu_present_map 1L
+#define CPU_PRESENT(x) ((x)==0)
#define smp_num_cpus 1
#define GET_PVR ((long int)_get_PVR())
#define CD(x) (x)
@@ -348,7 +315,7 @@ int get_cpuinfo(char *buffer)
for ( i = 0; i < smp_num_cpus ; i++ )
{
- if ( ! ( cpu_present_map & (1<<i) ) )
+ if ( !CPU_PRESENT(i) )
continue;
if ( i )
len += sprintf(len+buffer,"\n");
@@ -374,14 +341,6 @@ int get_cpuinfo(char *buffer)
break;
case 8:
len += sprintf(len+buffer, "750\n");
- cr = _get_L2CR();
- if ( cr & (0x1<<28)) cr = 256;
- else if ( cr & (0x2<<28)) cr = 512;
- else if ( cr & (0x3<<28)) cr = 1024;
- else cr = 0;
- len += sprintf(len+buffer, "on-chip l2\t: "
- "%ld KB (%s)\n",
- cr,(_get_L2CR()&0x80000000) ? "on" : "off");
len += sprintf(len+buffer, "temperature \t: %lu C\n",
cpu_temp());
break;
@@ -436,9 +395,9 @@ int get_cpuinfo(char *buffer)
#else /* CONFIG_MBX */
{
bd_t *bp;
- extern RESIDUAL res;
+ extern RESIDUAL *res;
- bp = (bd_t *)&res;
+ bp = (bd_t *)res;
len += sprintf(len+buffer,"clock\t\t: %dMHz\n"
"bus clock\t: %dMHz\n",
@@ -510,30 +469,41 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7))
{
extern void setup_pci_ptrs(void);
+
+#ifdef __SMP__
+ if ( first_cpu_booted ) return 0;
+#endif /* __SMP__ */
+
#ifndef CONFIG_MBX
#ifndef CONFIG_MACH_SPECIFIC
- char *model;
- /* prep boot loader tells us if we're prep or not */
- if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) )
- {
- _machine = _MACH_prep;
- have_of = 0;
- }
/* boot loader will tell us if we're APUS */
- else if ( r3 == 0x61707573 )
+ if ( r3 == 0x61707573 )
{
_machine = _MACH_apus;
have_of = 0;
r3 = 0;
- } else
- {
+ }
+ /* prep boot loader tells us if we're prep or not */
+ else if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) ) {
+ _machine = _MACH_prep;
+ have_of = 0;
+ } else {
+ char *model;
+
have_of = 1;
/* ask the OF info if we're a chrp or pmac */
- model = get_property(find_path_device("/"), "type", NULL);
- if ( !strncmp("chrp",model,4) )
+ model = get_property(find_path_device("/"), "device_type", NULL);
+ if ( model && !strncmp("chrp",model,4) )
_machine = _MACH_chrp;
- else
- _machine = _MACH_Pmac;
+ else
+ {
+ model = get_property(find_path_device("/"),
+ "model", NULL);
+ if ( model && !strncmp(model, "IBM", 3))
+ _machine = _MACH_chrp;
+ else
+ _machine = _MACH_Pmac;
+ }
}
#endif /* CONFIG_MACH_SPECIFIC */
@@ -556,6 +526,20 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) {
strncpy(cmd_line, (char *)r3 + KERNELBASE,
sizeof(cmd_line));
+ } else if (boot_infos != 0) {
+ /* booted by BootX - check for ramdisk */
+ if (boot_infos->kernelParamsOffset != 0)
+ strncpy(cmd_line, (char *) boot_infos
+ + boot_infos->kernelParamsOffset,
+ sizeof(cmd_line));
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (boot_infos->ramDisk) {
+ initrd_start = (unsigned long) boot_infos
+ + boot_infos->ramDisk;
+ initrd_end = initrd_start + boot_infos->ramDiskSize;
+ initrd_below_start_ok = 1;
+ }
+#endif
} else {
struct device_node *chosen;
char *p;
@@ -568,6 +552,7 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
}
#endif
+ cmd_line[0] = 0;
chosen = find_devices("chosen");
if (chosen != NULL) {
p = get_property(chosen, "bootargs", NULL);
@@ -652,7 +637,6 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
break;
#ifdef CONFIG_APUS
case _MACH_apus:
- setup_pci_ptrs();
/* Parse bootinfo. The bootinfo is located right after
the kernel bss */
parse_bootinfo((const struct bi_record *)&_end);
@@ -677,6 +661,7 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
default:
printk("Unknown machine type in identify_machine!\n");
}
+
#else /* CONFIG_MBX */
if ( r3 )
@@ -702,6 +687,12 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
strcpy(cmd_line, (char *)(r6+KERNELBASE));
}
#endif /* CONFIG_MBX */
+
+ /* Check for nobats option (used in mapin_ram). */
+ if (strstr(cmd_line, "nobats")) {
+ extern int __map_without_bats;
+ __map_without_bats = 1;
+ }
return 0;
}
@@ -722,6 +713,8 @@ __initfunc(void setup_arch(char **cmdline_p,
#ifdef CONFIG_XMON
extern void xmon_map_scc(void);
xmon_map_scc();
+ if (strstr(cmd_line, "xmon"))
+ xmon(0);
#endif /* CONFIG_XMON */
/* reboot on panic */
@@ -739,20 +732,6 @@ __initfunc(void setup_arch(char **cmdline_p,
*memory_start_p = find_available_memory();
*memory_end_p = (unsigned long) end_of_DRAM;
-#ifdef CONFIG_BLK_DEV_INITRD
- /* initrd_start and size are setup by boot/head.S and kernel/head.S */
- if ( initrd_start )
- {
- if (initrd_end > *memory_end_p)
- {
- printk("initrd extends beyond end of memory "
- "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
- initrd_end,*memory_end_p);
- initrd_start = 0;
- }
- }
-#endif
-
#ifdef CONFIG_MBX
mbx_setup_arch(memory_start_p,memory_end_p);
#else /* CONFIG_MBX */
@@ -771,7 +750,7 @@ __initfunc(void setup_arch(char **cmdline_p,
m68k_machtype = MACH_AMIGA;
apus_setup_arch(memory_start_p,memory_end_p);
break;
-#endif
+#endif
default:
printk("Unknown machine %d in setup_arch()\n", _machine);
}
diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
index 6d2d4279e..3ffb7981e 100644
--- a/arch/ppc/kernel/signal.c
+++ b/arch/ppc/kernel/signal.c
@@ -1,7 +1,7 @@
/*
* linux/arch/ppc/kernel/signal.c
*
- * $Id: signal.c,v 1.16 1998/06/16 23:34:10 cort Exp $
+ * $Id: signal.c,v 1.21 1998/10/22 19:37:49 paulus Exp $
*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
@@ -128,6 +128,13 @@ asmlinkage int sys_rt_sigreturn(unsigned long __unused)
do_exit(SIGSEGV);
}
+asmlinkage int
+sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+{
+ struct pt_regs *regs = (struct pt_regs *) &uss;
+ return do_sigaltstack(uss, uoss, regs->gpr[1]);
+}
+
int
sys_sigaction(int sig, const struct old_sigaction *act,
struct old_sigaction *oact)
@@ -238,7 +245,7 @@ int sys_sigreturn(struct pt_regs *regs)
goto badframe;
sr = (struct sigregs *) sigctx.regs;
regs->gpr[3] = ret = sigctx.signal;
- regs->gpr[4] = (unsigned long) sr;
+ regs->gpr[4] = (unsigned long) sc;
regs->link = (unsigned long) &sr->tramp;
regs->nip = sigctx.handler;
@@ -286,7 +293,7 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame,
|| get_user(regs->gpr[3], &sc->signal))
goto badframe;
regs->gpr[1] = newsp;
- regs->gpr[4] = (unsigned long) frame;
+ regs->gpr[4] = (unsigned long) sc;
regs->link = (unsigned long) frame->tramp;
return;
@@ -483,3 +490,4 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
setup_frame(regs, (struct sigregs *) frame, newsp);
return 1;
}
+
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index ca8d81de1..75445925f 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -1,5 +1,5 @@
/*
- * $Id: smp.c,v 1.28 1998/08/04 04:47:45 cort Exp $
+ * $Id: smp.c,v 1.36 1998/10/08 01:17:48 cort Exp $
*
* Smp support for ppc.
*
@@ -35,22 +35,20 @@
int smp_threads_ready = 0;
volatile int smp_commenced = 0;
int smp_num_cpus = 1;
-unsigned long cpu_present_map = 0;
-volatile int cpu_number_map[NR_CPUS];
-volatile unsigned long cpu_callin_map[NR_CPUS] = {0,};
-volatile int __cpu_logical_map[NR_CPUS];
-static unsigned char boot_cpu_id = 0;
struct cpuinfo_PPC cpu_data[NR_CPUS];
struct klock_info_struct klock_info = { KLOCK_CLEAR, 0 };
volatile unsigned char active_kernel_processor = NO_PROC_ID; /* Processor holding kernel spinlock */
volatile unsigned long ipi_count;
spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
-
unsigned int prof_multiplier[NR_CPUS];
unsigned int prof_counter[NR_CPUS];
+int first_cpu_booted = 0;
-int start_secondary(void *);
+/* all cpu mappings are 1-1 -- Cort */
+int cpu_number_map[NR_CPUS] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,};
+volatile unsigned long cpu_callin_map[NR_CPUS] = {0,};
+int start_secondary(void *);
extern int cpu_idle(void *unused);
void smp_local_timer_interrupt(struct pt_regs * regs)
@@ -58,7 +56,6 @@ 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;
@@ -104,7 +101,7 @@ void smp_local_timer_interrupt(struct pt_regs * regs)
* Right now it only works for stop cpu's but will be setup
* later for more general message passing.
*
- * As it is now, if we're sending two message as the same time
+ * As it is now, if we're sending two message at the same time
* we have race conditions. I avoided doing locks here since
* all that works right now is the stop cpu message.
*
@@ -115,17 +112,25 @@ void smp_message_recv(void)
{
int msg = smp_message[smp_processor_id()];
- printk("SMP %d: smp_message_recv() msg %x\n", smp_processor_id(),msg);
+ /* clear interrupt */
+ *(volatile unsigned long *)(0xf80000c0) = ~0L;
+ eieio();
/* make sure msg is for us */
if ( msg == -1 ) return;
-printk("recv after msg check\n");
+
+ ipi_count++;
+ /*printk("SMP %d: smp_message_recv() msg %x\n", smp_processor_id(),msg);*/
+
switch( msg )
{
case MSG_STOP_CPU:
__cli();
while (1) ;
break;
+ case MSG_RESCHEDULE:
+ current->need_resched = 1;
+ break;
case 0xf0f0: /* syncing time bases - just return */
break;
default:
@@ -139,19 +144,17 @@ printk("recv after msg check\n");
void smp_send_reschedule(int cpu)
{
- /* for now, nothing */
+ smp_message_pass(cpu, MSG_RESCHEDULE, 0, 0);
}
-
spinlock_t mesg_pass_lock = SPIN_LOCK_UNLOCKED;
void smp_message_pass(int target, int msg, unsigned long data, int wait)
{
- printk("SMP %d: sending smp message\n", current->processor);
-
- spin_lock(&mesg_pass_lock);
if ( _machine != _MACH_Pmac )
return;
-
+ /*printk("SMP %d: sending smp message\n", current->processor);*/
+if (smp_processor_id() ) printk("pass from cpu 1\n");
+ spin_lock(&mesg_pass_lock);
#define OTHER (~smp_processor_id() & 1)
switch( target )
@@ -167,9 +170,10 @@ void smp_message_pass(int target, int msg, unsigned long data, int wait)
break;
}
/* interrupt secondary processor */
- /**(volatile unsigned long *)(0xf80000c0) = 0xffffffff;
- eieio();*/
- *(volatile unsigned long *)(0xf80000c0) = 0;
+ *(volatile unsigned long *)(0xf80000c0) = ~0L;
+ eieio();
+ *(volatile unsigned long *)(0xf80000c0) = 0L;
+ eieio();
/* interrupt primary */
/**(volatile unsigned long *)(0xf3019000);*/
spin_unlock(&mesg_pass_lock);
@@ -177,29 +181,25 @@ void smp_message_pass(int target, int msg, unsigned long data, int wait)
__initfunc(void smp_boot_cpus(void))
{
- extern unsigned long secondary_entry[];
extern struct task_struct *current_set[NR_CPUS];
- int i, timeout;
+ extern void __secondary_start(void);
+ int i;
struct task_struct *p;
printk("Entering SMP Mode...\n");
+
+ first_cpu_booted = 1;
+ dcbf(&first_cpu_booted);
for (i = 0; i < NR_CPUS; i++) {
- cpu_number_map[i] = -1;
prof_counter[i] = 1;
prof_multiplier[i] = 1;
}
-
- cpu_present_map = 0;
- for(i=0; i < NR_CPUS; i++)
- __cpu_logical_map[i] = -1;
- smp_store_cpu_info(boot_cpu_id);
- active_kernel_processor = boot_cpu_id;
- current->processor = boot_cpu_id;
- cpu_present_map |= 1;
- cpu_number_map[boot_cpu_id] = 0;
- __cpu_logical_map[0] = boot_cpu_id;
+ cpu_callin_map[0] = 1;
+ smp_store_cpu_info(0);
+ active_kernel_processor = 0;
+ current->processor = 0;
if ( _machine != _MACH_Pmac )
{
@@ -207,10 +207,6 @@ __initfunc(void smp_boot_cpus(void))
return;
}
- /* assume a 2nd processor for now */
- cpu_present_map |= (1 << 1);
- smp_num_cpus = 2;
-
/* create a process for second processor */
kernel_thread(start_secondary, NULL, CLONE_PID);
p = task[1];
@@ -218,14 +214,16 @@ __initfunc(void smp_boot_cpus(void))
panic("No idle task for secondary processor\n");
p->processor = 1;
current_set[1] = p;
+
/* need to flush here since secondary bat's aren't setup */
- dcbf((volatile unsigned long *)&current_set[1]);
-
+ dcbf((void *)&current_set[1]);
/* setup entry point of secondary processor */
- *(volatile unsigned long *)(0xf2800000)
- = (unsigned long)secondary_entry-KERNELBASE;
+ *(volatile unsigned long *)(0xf2800000) =
+ (unsigned long)__secondary_start-KERNELBASE;
eieio();
/* interrupt secondary to begin executing code */
+ *(volatile unsigned long *)(0xf80000c0) = ~0L;
+ eieio();
*(volatile unsigned long *)(0xf80000c0) = 0L;
eieio();
/*
@@ -234,24 +232,23 @@ __initfunc(void smp_boot_cpus(void))
* calibrate_delay() so use this value that I found through
* experimentation. -- Cort
*/
- udelay(1);
+ for ( i = 1000; i && !cpu_callin_map[1] ; i-- )
+ udelay(100);
+
if(cpu_callin_map[1]) {
- cpu_number_map[1] = 1;
- __cpu_logical_map[i] = 1;
- printk("Processor 1 found.\n");
-
+ printk("Processor %d found.\n", smp_num_cpus);
+ smp_num_cpus++;
#if 0 /* this sync's the decr's, but we don't want this now -- Cort */
set_dec(decrementer_count);
#endif
- /* interrupt secondary to start decr's again */
- smp_message_pass(1,0xf0f0, 0, 0);
- /* interrupt secondary to begin executing code */
- /**(volatile unsigned long *)(0xf80000c0) = 0L;
- eieio();*/
} else {
- smp_num_cpus--;
- printk("Processor %d is stuck.\n", 1);
+ printk("Processor %d is stuck. \n", smp_num_cpus);
}
+ /* 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);
}
__initfunc(void smp_commence(void))
@@ -271,7 +268,7 @@ __initfunc(void initialize_secondary(void))
}
/* Activate a secondary processor. */
-__initfunc(int start_secondary(void *unused))
+asmlinkage int __init start_secondary(void *unused)
{
printk("SMP %d: start_secondary()\n",current->processor);
smp_callin();
@@ -281,16 +278,14 @@ __initfunc(int start_secondary(void *unused))
__initfunc(void smp_callin(void))
{
printk("SMP %d: smp_callin()\n",current->processor);
- smp_store_cpu_info(1);
+ smp_store_cpu_info(current->processor);
set_dec(decrementer_count);
current->mm->mmap->vm_page_prot = PAGE_SHARED;
current->mm->mmap->vm_start = PAGE_OFFSET;
current->mm->mmap->vm_end = init_task.mm->mmap->vm_end;
-
- /* assume we're just the secondary processor for now */
- cpu_callin_map[1] = 1;
+ cpu_callin_map[current->processor] = current->processor;
while(!smp_commenced)
barrier();
__sti();
@@ -310,6 +305,7 @@ __initfunc(void smp_store_cpu_info(int id))
{
struct cpuinfo_PPC *c = &cpu_data[id];
+ /* assume bogomips are same for everything */
c->loops_per_sec = loops_per_sec;
c->pvr = _get_PVR();
}
diff --git a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c
index 91a8d0ccf..b97456226 100644
--- a/arch/ppc/kernel/syscalls.c
+++ b/arch/ppc/kernel/syscalls.c
@@ -209,7 +209,7 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
goto out;
}
- /*flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);*/
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
ret = do_mmap(file, addr, len, prot, flags, offset);
out:
unlock_kernel();
diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
index 0857c2633..8bada0e69 100644
--- a/arch/ppc/kernel/time.c
+++ b/arch/ppc/kernel/time.c
@@ -1,5 +1,5 @@
/*
- * $Id: time.c,v 1.35 1998/07/24 11:05:47 geert Exp $
+ * $Id: time.c,v 1.36 1998/10/10 12:16:08 geert Exp $
* Common time routines among all ppc machines.
*
* Written by Cort Dougan (cort@cs.nmt.edu) to merge
@@ -106,7 +106,12 @@ void timer_interrupt(struct pt_regs * regs)
#ifdef __SMP__
smp_local_timer_interrupt(regs);
#endif
-
+#ifdef CONFIG_APUS
+ {
+ extern void apus_heartbeat (void);
+ apus_heartbeat ();
+ }
+#endif
hardirq_exit(cpu);
/* restore the HID0 in case dcache was off - see idle.c
* this hack should leave for a better solution -- Cort */
diff --git a/arch/ppc/kernel/totalmp.c b/arch/ppc/kernel/totalmp.c
new file mode 100644
index 000000000..5f87755a7
--- /dev/null
+++ b/arch/ppc/kernel/totalmp.c
@@ -0,0 +1,109 @@
+/*
+ * $Id: totalmp.c,v 1.5 1998/08/26 13:58:50 cort Exp $
+ *
+ * Support for Total Impact's TotalMP PowerPC accelerator board.
+ *
+ * Written by Cort Dougan (cort@cs.nmt.edu)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/openpic.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+
+extern void totalmp_init(void);
+
+extern inline void openpic_writefield(volatile u_int *addr, u_int mask,
+ u_int field);
+__initfunc(void totalmp_init(void))
+{
+ struct pci_dev *dev;
+ u32 val;
+ unsigned long ctl_area, ctl_area_phys;
+
+ /* it's a pci card */
+ if ( !pci_present() ) return;
+
+ /* search for a MPIC. For now, we assume
+ * only one TotalMP card installed. -- Cort
+ */
+ for(dev=pci_devices; dev; dev=dev->next)
+ {
+ if ( (dev->vendor == PCI_VENDOR_ID_IBM)
+ && ((dev->device == PCI_DEVICE_ID_IBM_MPIC)
+ || (dev->device==PCI_DEVICE_ID_IBM_MPIC_2)) )
+ {
+ break;
+ }
+ }
+
+ if ( !dev ) return;
+
+ OpenPIC = (struct OpenPIC *)bus_to_virt(dev->base_address[0]);
+#if 0
+ if ( (ulong)OpenPIC > 0x10000000 )
+ {
+ printk("TotalMP: relocating base %lx -> %lx\n",
+ (ulong)OpenPIC, ((ulong)OpenPIC & 0x00FFFFFF) | 0x01000000);
+ OpenPIC = (struct OpenPIC *)(((ulong)OpenPIC & 0x00FFFFFF) | 0x01000000);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, (ulong)OpenPIC);
+ }*/
+#endif
+ OpenPIC = (struct OpenPIC *)((ulong)OpenPIC + _IO_BASE);
+
+ openpic_init(0);
+
+ /* put openpic in 8259-cascade mode */
+ openpic_writefield(&OpenPIC->Global.Global_Configuration0, 0, 0x20000000);
+ /* set ipi to highest priority */
+ openpic_writefield(&OpenPIC->Global._IPI_Vector_Priority[0].Reg, 0, 0x000f0000);
+
+ /* allocate and remap the control area to be no-cache */
+ ctl_area = __get_free_pages(GFP_ATOMIC, 3);
+ ctl_area_phys = (unsigned long) virt_to_phys((void *)ctl_area);
+ ctl_area = (unsigned long)ioremap(ctl_area, 0x8000);
+
+ /* soft reset cpu 0 */
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &val);
+ openpic_writefield(&OpenPIC->Global._Processor_Initialization.Reg, 0, 0x1);
+
+ /* wait for base address reg to change, signaling that cpu 0 is done */
+#define wait_for(where) { \
+ udelay(100); \
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &val); \
+ if ( val != 0x77700000 ) \
+ { \
+ printk("TotalMP: CPU0 did not respond: val %x %d\n", val, where); \
+ /*free_pages((ulong)phys_to_virt(ctl_area_phys),1);*/ \
+ return; \
+ } }
+
+ /* tell cpu0 where the control area is */
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,(~val) >> 16);
+ wait_for(0);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
+ ((ulong)ctl_area & 0xff000000)>>20);
+ wait_for(1);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
+ ((ulong)ctl_area & 0x00ff0000)>>12);
+ wait_for(2);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
+ ((ulong)ctl_area & 0x0000ff00)>>4);
+ wait_for(3);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
+ ((ulong)ctl_area & 0x000000ff)<<4);
+ wait_for(4);
+#undef wait_for
+ /* wait for cpu0 to "sign-on" */
+}
+
diff --git a/arch/ppc/lib/locks.c b/arch/ppc/lib/locks.c
index 0bb06f808..073e7076c 100644
--- a/arch/ppc/lib/locks.c
+++ b/arch/ppc/lib/locks.c
@@ -1,5 +1,5 @@
/*
- * $Id: locks.c,v 1.18 1998/07/28 03:50:27 cort Exp $
+ * $Id: locks.c,v 1.20 1998/10/08 01:17:32 cort Exp $
*
* Locks for smp ppc
*
@@ -18,13 +18,13 @@
#define DEBUG_LOCKS 1
#undef INIT_STUCK
-#define INIT_STUCK 10000
+#define INIT_STUCK 0xffffffff
void _spin_lock(spinlock_t *lock)
{
int cpu = smp_processor_id();
#ifdef DEBUG_LOCKS
- int stuck = INIT_STUCK;
+ unsigned int stuck = INIT_STUCK;
#endif /* DEBUG_LOCKS */
/* try expensive atomic load/store to get lock */
while((unsigned long )xchg_u32((void *)&lock->lock,0xffffffff)) {
@@ -67,13 +67,13 @@ int spin_trylock(spinlock_t *lock)
void _spin_unlock(spinlock_t *lp)
{
#ifdef DEBUG_LOCKS
- if ( !lp->lock )
- panic("_spin_unlock(%p): no lock cpu %d %s/%d\n", lp,
- smp_processor_id(),current->comm,current->pid);
+ if ( !lp->lock )
+ printk("_spin_unlock(%p): no lock cpu %d %s/%d\n", lp,
+ smp_processor_id(),current->comm,current->pid);
if ( lp->owner_cpu != smp_processor_id() )
- panic("_spin_unlock(%p): cpu %d trying clear of cpu %d pc %lx val %lx\n",
- lp, smp_processor_id(), (int)lp->owner_cpu,
- lp->owner_pc,lp->lock);
+ printk("_spin_unlock(%p): cpu %d trying clear of cpu %d pc %lx val %lx\n",
+ lp, smp_processor_id(), (int)lp->owner_cpu,
+ lp->owner_pc,lp->lock);
#endif /* DEBUG_LOCKS */
lp->owner_pc = lp->owner_cpu = 0;
eieio();
diff --git a/arch/ppc/lib/string.S b/arch/ppc/lib/string.S
index cc59aaa81..2ff171ee3 100644
--- a/arch/ppc/lib/string.S
+++ b/arch/ppc/lib/string.S
@@ -219,12 +219,12 @@ memchr:
.globl __copy_tofrom_user
__copy_tofrom_user:
- rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
+ srwi. r7,r5,3
addi r6,r3,-4
addi r4,r4,-4
- li r3,0 /* success return value */
- beq 2f /* if less than 8 bytes to do */
- andi. r0,r6,3 /* get dest word aligned */
+ li r3,0 /* success return value */
+ beq 2f /* if less than 8 bytes to do */
+ andi. r0,r6,3 /* get dest word aligned */
mtctr r7
bne 5f
1: lwz r7,4(r4)
@@ -238,7 +238,7 @@ __copy_tofrom_user:
14: lwzu r0,4(r4)
addi r5,r5,-4
15: stwu r0,4(r6)
-3: cmpwi 0,r5,0
+3: cmpwi 0,r5,0 /* do 1 byte at a time for the remainder */
beqlr
mtctr r5
addi r4,r4,3
@@ -247,32 +247,78 @@ __copy_tofrom_user:
16: stbu r0,1(r6)
bdnz 4b
blr
-5: subfic r0,r0,4
- mtctr r0
+5: subfic r0,r0,4 /* copy bytes until we have the */
+ mtctr r0 /* destination 4-byte aligned */
+ subf r5,r0,r5
6: lbz r7,4(r4)
addi r4,r4,1
17: stb r7,4(r6)
addi r6,r6,1
bdnz 6b
- subf r5,r0,r5
- rlwinm. r7,r5,32-3,3,31
+ srwi. r7,r5,3
beq 2b
mtctr r7
b 1b
-99: li r3,-EFAULT
+/* we come here on a fault in the 8-byte-at-a-time loop */
+88: subi r4,r4,8 /* compensate for the lwzu */
+98: mfctr r0
+ rlwimi r5,r0,3,0,28 /* use the byte-at-a-time loop to */
+ b 3b /* copy up to the byte at fault */
+/* here on a write fault in the single-word copy */
+96: subi r4,r4,4
+ b 3b
+/* here on a read fault in the initial single-byte copy */
+90: mfctr r3
+ add r3,r3,r5
+ b 70f
+/* here on a read fault in the final single-byte copy */
+99: mfctr r3
+ subi r6,r6,3
+/* clear out the rest of the destination: r3 bytes starting at 4(r6) */
+70: li r0,0
+ mr. r5,r3
+ beq 76f
+71: andi. r4,r6,3
+ beq 72f
+77: stb r0,4(r6)
+ addi r6,r6,1
+ addic. r5,r5,-1
+ bne 71b
+72: srwi. r7,r5,2
+ beq 73f
+ mtctr r7
+74: stwu r0,4(r6)
+ bdnz 74b
+73: andi. r5,r5,3
+ beq 76f
+ mtctr r5
+ addi r6,r6,3
+75: stbu r0,1(r6)
+ bdnz 75b
+76: blr
+/* here on a write fault in the initial single-byte copy */
+80: mfctr r3
+ add r3,r3,r5
blr
+/* here on a write fault in the final single-byte copy */
+81: mfctr r3
+ blr
+
.section __ex_table,"a"
.align 2
- .long 1b,99b
- .long 11b,99b
- .long 12b,99b
- .long 13b,99b
- .long 14b,99b
- .long 15b,99b
+ .long 1b,98b
+ .long 11b,98b
+ .long 12b,88b
+ .long 13b,88b
+ .long 14b,3b
+ .long 15b,96b
.long 4b,99b
- .long 16b,99b
- .long 6b,99b
- .long 17b,99b
+ .long 16b,81b
+ .long 6b,90b
+ .long 17b,80b
+ .long 77b,76b
+ .long 74b,76b
+ .long 75b,76b
.text
#undef CLEAR_USE_DCBZ 1
diff --git a/arch/ppc/mbx_defconfig b/arch/ppc/mbx_defconfig
index 1b8829134..e0b94ce6a 100644
--- a/arch/ppc/mbx_defconfig
+++ b/arch/ppc/mbx_defconfig
@@ -171,7 +171,6 @@ CONFIG_LOCKD=y
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_MOUSE is not set
# CONFIG_QIC02_TAPE is not set
-# CONFIG_APM is not set
# CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set
# CONFIG_VIDEO_DEV is not set
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
index 9f4b287a7..b45f4e6f4 100644
--- a/arch/ppc/mm/fault.c
+++ b/arch/ppc/mm/fault.c
@@ -38,7 +38,7 @@
extern void (*debugger)(struct pt_regs *);
extern void (*debugger_fault_handler)(struct pt_regs *);
extern int (*debugger_dabr_match)(struct pt_regs *);
-int debugger_kernel_faults = 0;
+int debugger_kernel_faults = 1;
#endif
unsigned long htab_reloads = 0; /* updated by head.S:hash_page() */
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index 2bf73835b..44104fd4e 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -1,5 +1,5 @@
/*
- * $Id: init.c,v 1.115 1998/08/04 20:48:38 davem Exp $
+ * $Id: init.c,v 1.130 1998/11/10 10:09:20 paulus Exp $
*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
@@ -33,6 +33,7 @@
#include <linux/stddef.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
+#include <linux/delay.h>
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h> /* for initrd_* */
#endif
@@ -46,6 +47,8 @@
#include <asm/uaccess.h>
#include <asm/8xx_immap.h>
#include <asm/mbx.h>
+#include <asm/smp.h>
+#include <asm/bootx.h>
/* APUS includes */
#include <asm/setup.h>
#include <asm/amigahw.h>
@@ -69,6 +72,7 @@ unsigned long ioremap_bot;
unsigned long avail_start;
struct pgtable_cache_struct quicklists;
struct mem_info memory[NUM_MEMINFO];
+extern boot_infos_t *boot_infos;
void MMU_init(void);
static void *MMU_get_page(void);
@@ -110,7 +114,8 @@ struct batrange { /* stores address ranges mapped by BATs */
* (i.e. page tables) instead of the bats.
* -- Cort
*/
-#undef MAP_RAM_WITH_SEGREGS 1
+int __map_without_bats = 0;
+
/* optimization for 603 to load the tlb directly from the linux table -- Cort */
#define NO_RELOAD_HTAB 1 /* change in kernel/head.S too! */
@@ -229,7 +234,7 @@ void show_mem(void)
{
printk("%-8.8s %3d %3d %8ld %8ld %8ld %c%08lx %08lx ",
p->comm,p->pid,
- p->mm->count,p->mm->context,
+ atomic_read(&p->mm->count),p->mm->context,
p->mm->context<<4, p->tss.last_syscall,
user_mode(p->tss.regs) ? 'u' : 'k', p->tss.regs->nip,
(ulong)p);
@@ -239,20 +244,24 @@ void show_mem(void)
printk("%3d ", p->processor);
if ( (p->processor != NO_PROC_ID) &&
(p == current_set[p->processor]) )
-
+ {
+ iscur = 1;
+ printk("current");
+ }
#else
if ( p == current )
-#endif /* __SMP__ */
{
iscur = 1;
printk("current");
}
+
if ( p == last_task_used_math )
{
if ( iscur )
printk(",");
printk("last math");
}
+#endif /* __SMP__ */
printk("\n");
}
}
@@ -673,18 +682,21 @@ __initfunc(static void sort_mem_pieces(struct mem_pieces *mp))
__initfunc(static void coalesce_mem_pieces(struct mem_pieces *mp))
{
- unsigned long a, e;
+ unsigned long a, s, ns;
int i, j, d;
d = 0;
for (i = 0; i < mp->n_regions; i = j) {
a = mp->regions[i].address;
- e = a + mp->regions[i].size;
+ s = mp->regions[i].size;
for (j = i + 1; j < mp->n_regions
- && mp->regions[j].address <= e; ++j)
- e = mp->regions[j].address + mp->regions[j].size;
+ && mp->regions[j].address - a <= s; ++j) {
+ ns = mp->regions[j].address + mp->regions[j].size - a;
+ if (ns > s)
+ s = ns;
+ }
mp->regions[d].address = a;
- mp->regions[d].size = e - a;
+ mp->regions[d].size = s;
++d;
}
mp->n_regions = d;
@@ -796,33 +808,41 @@ __initfunc(static void mapin_ram(void))
int i;
unsigned long v, p, s, f;
#ifndef CONFIG_8xx
- unsigned long tot, mem_base, bl, done;
-
-#ifndef MAP_RAM_WITH_SEGREGS
- /* Set up BAT2 and if necessary BAT3 to cover RAM. */
- mem_base = __pa(KERNELBASE);
- tot = (unsigned long)end_of_DRAM - KERNELBASE;
- for (bl = 128<<10; bl < 256<<20; bl <<= 1) {
- if (bl * 2 > tot)
- break;
- /* On some APUS systems, memory grows downwards, i.e.,
- 24MB will be 8MB aligned. Handle that properly by
- mapping first 8MB, then 16MB. */
- if (((bl * 2) - 1) & mem_base)
- break;
- }
- setbat(2, KERNELBASE, mem_base, bl, RAM_PAGE);
- done = (unsigned long)bat_addrs[2].limit - KERNELBASE + 1;
- if (done < tot) {
- /* use BAT3 to cover a bit more */
- tot -= done;
- for (bl = 128<<10; bl < 256<<20; bl <<= 1)
+ if (!__map_without_bats) {
+ unsigned long tot, mem_base, bl, done;
+ unsigned long max_size = (256<<20);
+ unsigned long align;
+
+ /* Set up BAT2 and if necessary BAT3 to cover RAM. */
+ mem_base = __pa(KERNELBASE);
+
+ /* Make sure we don't map a block larger than the
+ smallest alignment of the physical address. */
+ /* alignment of mem_base */
+ align = ~(mem_base-1) & mem_base;
+ /* set BAT block size to MIN(max_size, align) */
+ if (align && align < max_size)
+ max_size = align;
+
+ tot = (unsigned long)end_of_DRAM - KERNELBASE;
+ for (bl = 128<<10; bl < max_size; bl <<= 1) {
if (bl * 2 > tot)
break;
- setbat(3, KERNELBASE+done, mem_base+done, bl, RAM_PAGE);
+ }
+
+ setbat(2, KERNELBASE, mem_base, bl, RAM_PAGE);
+ done = (unsigned long)bat_addrs[2].limit - KERNELBASE + 1;
+ if (done < tot) {
+ /* use BAT3 to cover a bit more */
+ tot -= done;
+ for (bl = 128<<10; bl < max_size; bl <<= 1)
+ if (bl * 2 > tot)
+ break;
+ setbat(3, KERNELBASE+done, mem_base+done, bl,
+ RAM_PAGE);
+ }
}
-#endif
v = KERNELBASE;
for (i = 0; i < phys_mem.n_regions; ++i) {
@@ -884,7 +904,6 @@ __initfunc(void free_initmem(void))
unsigned long a;
unsigned long num_freed_pages = 0, num_prep_pages = 0,
num_pmac_pages = 0, num_openfirmware_pages = 0;
-
#define FREESEC(START,END,CNT) do { \
a = (unsigned long)(&START); \
for (; a < (unsigned long)(&END); a += PAGE_SIZE) { \
@@ -899,7 +918,10 @@ __initfunc(void free_initmem(void))
switch (_machine)
{
case _MACH_Pmac:
+ FREESEC(__prep_begin,__prep_end,num_prep_pages);
+ break;
case _MACH_chrp:
+ FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
FREESEC(__prep_begin,__prep_end,num_prep_pages);
break;
case _MACH_prep:
@@ -933,6 +955,11 @@ __initfunc(void free_initmem(void))
*/
__initfunc(void MMU_init(void))
{
+
+#ifdef __SMP__
+ if ( first_cpu_booted ) return;
+#endif /* __SMP__ */
+
#ifndef CONFIG_8xx
if (have_of)
end_of_DRAM = pmac_find_end_of_memory();
@@ -962,12 +989,18 @@ __initfunc(void MMU_init(void))
setbat(0, 0xf8000000, 0xf8000000, 0x08000000, IO_PAGE);
break;
case _MACH_Pmac:
- setbat(0, 0xf3000000, 0xf3000000, 0x100000, IO_PAGE);
- ioremap_base = 0xf0000000;
+ {
+ unsigned long base = 0xf3000000;
+ struct device_node *macio = find_devices("mac-io");
+ if (macio && macio->n_addrs)
+ base = macio->addrs[0].address;
+ setbat(0, base, base, 0x100000, IO_PAGE);
+ ioremap_base = 0xf0000000;
+ }
break;
case _MACH_apus:
/* Map PPC exception vectors. */
- setbat(0, 0xfff00000, 0xfff00000, 0x00010000, RAM_PAGE);
+ setbat(0, 0xfff00000, 0xfff00000, 0x00020000, RAM_PAGE);
/* Map chip and ZorroII memory */
setbat(1, zTwoBase, 0x00000000, 0x01000000, IO_PAGE);
/* Note: a temporary hack in arch/ppc/amiga/setup.c
@@ -997,17 +1030,16 @@ __initfunc(void MMU_init(void))
/*
* Find some memory for setup_arch to return.
- * We use the last chunk of available memory as the area
+ * 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.
*/
__initfunc(unsigned long find_available_memory(void))
{
- int i;
+ int i, rn;
unsigned long a, free;
unsigned long start, end;
- free = 0;
if (_machine == _MACH_mbx) {
/* Return the first, not the last region, because we
* may not yet have properly initialized the additonal
@@ -1018,12 +1050,17 @@ __initfunc(unsigned long find_available_memory(void))
return avail_start;
}
- for (i = 0; i < phys_avail.n_regions - 1; ++i) {
+ 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[i].address);
+ a = PAGE_ALIGN(phys_avail.regions[rn].address);
if (free < 32 * PAGE_SIZE)
a += 32 * PAGE_SIZE - free;
avail_start = (unsigned long) __va(a);
@@ -1082,6 +1119,15 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
}
phys_avail.n_regions = 0;
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* if we are booted from BootX with an initial ramdisk,
+ make sure the ramdisk pages aren't reserved. */
+ if (initrd_start) {
+ for (a = initrd_start; a < initrd_end; a += PAGE_SIZE)
+ clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags);
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
/* free the prom's memory - no-op on prep */
for (i = 0; i < prom_mem.n_regions; ++i) {
a = (unsigned long) __va(prom_mem.regions[i].address);
@@ -1216,8 +1262,13 @@ __initfunc(unsigned long *pmac_find_end_of_memory(void))
phys_mem.n_regions = 1;
}
- /* record which bits the prom is using */
- get_mem_prop("available", &phys_avail);
+ if (boot_infos == 0) {
+ /* record which bits the prom is using */
+ get_mem_prop("available", &phys_avail);
+ } else {
+ /* booted from BootX - it's all available (after klimit) */
+ phys_avail = phys_mem;
+ }
prom_mem = phys_mem;
for (i = 0; i < phys_avail.n_regions; ++i)
remove_mem_piece(&prom_mem, phys_avail.regions[i].address,
@@ -1274,36 +1325,69 @@ __initfunc(unsigned long *prep_find_end_of_memory(void))
#define HARDWARE_MAPPED_SIZE (512*1024)
__initfunc(unsigned long *apus_find_end_of_memory(void))
{
- unsigned long kstart, ksize;
+ int shadow = 0;
- /* Add the chunk that ADOS does not see. This may also
- * include a ROM mapping which we reclaim. The top 512KB is
- * removed again below.
- * Do it by aligning the size to the nearest 2MB limit upwards.
- */
- memory[0].size = ((memory[0].size+0x001fffff) & 0xffe00000);
+ /* The memory size reported by ADOS excludes the 512KB
+ reserved for PPC exception registers and possibly 512KB
+ containing a shadow of the ADOS ROM. */
+ {
+ unsigned long size = memory[0].size;
+
+ /* If 2MB aligned, size was probably user
+ specified. We can't tell anything about shadowing
+ in this case so skip shadow assignment. */
+ if (0 != (size & 0x1fffff)){
+ /* Align to 512KB to ensure correct handling
+ of both memfile and system specified
+ sizes. */
+ size = ((size+0x0007ffff) & 0xfff80000);
+ /* If memory is 1MB aligned, assume
+ shadowing. */
+ shadow = !(size & 0x80000);
+ }
- append_mem_piece(&phys_mem, memory[0].addr, memory[0].size);
+ /* Add the chunk that ADOS does not see. by aligning
+ the size to the nearest 2MB limit upwards. */
+ memory[0].size = ((size+0x001fffff) & 0xffe00000);
+ }
- phys_avail = phys_mem;
- kstart = __pa(_stext);
- ksize = PAGE_ALIGN(klimit - _stext);
- remove_mem_piece(&phys_avail, kstart, ksize, 1);
+ /* Now register the memory block. */
+ {
+ unsigned long kstart, ksize;
- /* Remove the upper HARDWARE_MAPPED_SIZE bytes where the address
- * range 0xfff00000-0xfffx0000 is mapped to.
- * We do it this way to ensure that the memory registered in the
- * system has a power-of-two size.
- */
- remove_mem_piece(&phys_avail,
- (memory[0].addr + memory[0].size
- - HARDWARE_MAPPED_SIZE),
- HARDWARE_MAPPED_SIZE, 1);
+ append_mem_piece(&phys_mem, memory[0].addr, memory[0].size);
+ phys_avail = phys_mem;
+ kstart = __pa(_stext);
+ ksize = PAGE_ALIGN(klimit - _stext);
+ remove_mem_piece(&phys_avail, kstart, ksize, 0);
+ }
+
+ /* Remove the memory chunks that are controlled by special
+ Phase5 hardware. */
+ {
+ unsigned long top = memory[0].addr + memory[0].size;
+
+ /* Remove the upper 512KB if it contains a shadow of
+ the ADOS ROM. FIXME: It might be possible to
+ disable this shadow HW. Check the booter
+ (ppc_boot.c) */
+ if (shadow)
+ {
+ top -= HARDWARE_MAPPED_SIZE;
+ remove_mem_piece(&phys_avail, top,
+ HARDWARE_MAPPED_SIZE, 0);
+ }
+
+ /* Remove the upper 512KB where the PPC exception
+ vectors are mapped. */
+ top -= HARDWARE_MAPPED_SIZE;
+ remove_mem_piece(&phys_avail, top,
+ HARDWARE_MAPPED_SIZE, 0);
+ }
/* FIXME:APUS: Only handles one block of memory! Problem is
- * that the VTOP/PTOV code in head.S would be a mess if it had
- * to handle more than one block.
- */
+ that the VTOP/PTOV code in head.S would be a mess if it had
+ to handle more than one block. */
return __va(memory[0].addr + memory[0].size);
}
@@ -1393,6 +1477,5 @@ __initfunc(static void hash_init(void))
}
else
Hash_end = 0;
-
}
#endif /* ndef CONFIG_8xx */
diff --git a/arch/ppc/pmac_defconfig b/arch/ppc/pmac_defconfig
index 5be933292..ae1303bb4 100644
--- a/arch/ppc/pmac_defconfig
+++ b/arch/ppc/pmac_defconfig
@@ -1,5 +1,5 @@
#
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
#
#
@@ -35,16 +35,20 @@ CONFIG_KERNEL_ELF=y
CONFIG_BINFMT_MISC=m
# CONFIG_BINFMT_JAVA is not set
# CONFIG_PARPORT is not set
-# CONFIG_FB is not set
# CONFIG_VGA_CONSOLE is not set
-# CONFIG_PMAC_PBOOK is not set
+CONFIG_FB=y
+CONFIG_FB_COMPAT_XPMAC=y
+CONFIG_PMAC_PBOOK=y
CONFIG_MAC_KEYBOARD=y
CONFIG_MAC_FLOPPY=y
CONFIG_MAC_SERIAL=y
-CONFIG_MACMOUSE=y
+CONFIG_ADBMOUSE=y
+CONFIG_BLK_DEV_IDE_PMAC=y
CONFIG_PROC_DEVICETREE=y
# CONFIG_KGDB is not set
# CONFIG_XMON is not set
+# CONFIG_TOTALMP is not set
+CONFIG_BOOTX_TEXT=y
#
# Plug and Play support
@@ -56,17 +60,29 @@ CONFIG_PROC_DEVICETREE=y
#
# CONFIG_BLK_DEV_FD is not set
CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
# CONFIG_BLK_DEV_HD_IDE is not set
CONFIG_BLK_DEV_IDEDISK=y
CONFIG_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 is not set
# CONFIG_BLK_DEV_CMD640 is not set
# CONFIG_BLK_DEV_RZ1000 is not set
# CONFIG_BLK_DEV_IDEPCI is not set
# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDE_PMAC=y
+CONFIG_BLK_DEV_IDEDMA_PMAC=y
+CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_PMAC_IDEDMA_AUTO=y
# CONFIG_IDE_CHIPSETS is not set
+
+#
+# Additional Block Devices
+#
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_MD is not set
@@ -98,10 +114,18 @@ CONFIG_IP_MULTICAST=y
# CONFIG_IP_MROUTE is not set
CONFIG_IP_ALIAS=y
# CONFIG_SYN_COOKIES is not set
+
+#
+# (it is safe to leave these untouched)
+#
CONFIG_INET_RARP=y
CONFIG_IP_NOSR=y
CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
+
+#
+#
+#
# CONFIG_IPX is not set
CONFIG_ATALK=m
# CONFIG_X25 is not set
@@ -119,11 +143,19 @@ CONFIG_ATALK=m
# SCSI support
#
CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=y
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
# CONFIG_SCSI_MULTI_LUN is not set
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
@@ -135,7 +167,7 @@ CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_AHA152X is not set
# CONFIG_SCSI_AHA1542 is not set
# CONFIG_SCSI_AHA1740 is not set
-CONFIG_SCSI_AIC7XXX=m
+CONFIG_SCSI_AIC7XXX=y
# CONFIG_OVERRIDE_CMDS is not set
CONFIG_AIC7XXX_PROC_STATS=y
CONFIG_AIC7XXX_RESET_DELAY=15
@@ -192,27 +224,35 @@ CONFIG_NET_EISA=y
# CONFIG_AC3200 is not set
# CONFIG_APRICOT is not set
# CONFIG_CS89x0 is not set
-CONFIG_DE4X5=m
+CONFIG_DE4X5=y
CONFIG_DEC_ELCP=m
# CONFIG_DGRS is not set
# CONFIG_EEXPRESS_PRO100 is not set
# CONFIG_LNE390 is not set
+# CONFIG_NE3210 is not set
# CONFIG_NE2K_PCI is not set
# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
# CONFIG_ES3210 is not set
# CONFIG_EPIC100 is not set
# CONFIG_ZNET is not set
# CONFIG_NET_POCKET is not set
# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
# CONFIG_DLCI is not set
# CONFIG_LTPC is not set
# CONFIG_COPS is not set
# CONFIG_IPDDP is not set
-CONFIG_PPP=m
+CONFIG_PPP=y
+
+#
+# CCP compressors for PPP are only built as modules.
+#
# CONFIG_SLIP is not set
# CONFIG_NET_RADIO is not set
# CONFIG_TR is not set
# CONFIG_SHAPER is not set
+# CONFIG_HOSTESS_SV11 is not set
#
# Amateur Radio support
@@ -230,6 +270,58 @@ CONFIG_PPP=m
# CONFIG_CD_NO_IDESCSI is not set
#
+# Console drivers
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FB_OF=y
+CONFIG_FB_CONTROL=y
+CONFIG_FB_PLATINUM=y
+CONFIG_FB_VALKYRIE=y
+CONFIG_FB_ATY=y
+CONFIG_FB_IMSTT=y
+CONFIG_FB_CT65550=y
+# CONFIG_FB_S3TRIO is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+CONFIG_FBCON_CFB32=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+CONFIG_FONT_SUN8x16=y
+CONFIG_FONT_SUN12x22=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=m
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+# CONFIG_MOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_VIDEO_DEV is not set
+CONFIG_NVRAM=y
+# CONFIG_JOYSTICK is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+
+#
# Filesystems
#
# CONFIG_QUOTA is not set
@@ -244,6 +336,7 @@ CONFIG_VFAT_FS=m
CONFIG_PROC_FS=y
CONFIG_NFS_FS=y
CONFIG_NFSD=y
+# CONFIG_NFSD_SUN is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
# CONFIG_CODA_FS is not set
@@ -252,12 +345,16 @@ CONFIG_LOCKD=y
# CONFIG_NTFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_AFFS_FS is not set
-CONFIG_HFS_FS=m
+CONFIG_HFS_FS=y
# CONFIG_ROMFS_FS is not set
CONFIG_AUTOFS_FS=y
# CONFIG_UFS_FS is not set
-# CONFIG_ADFS_FS is not set
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_SMD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
CONFIG_DEVPTS_FS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
CONFIG_MAC_PARTITION=y
CONFIG_NLS=y
@@ -292,33 +389,13 @@ CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_KOI8_R is not set
#
-# Console drivers
-#
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-# CONFIG_SERIAL is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_MOUSE is not set
-# CONFIG_UMISC is not set
-# CONFIG_QIC02_TAPE is not set
-# CONFIG_APM is not set
-# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-# CONFIG_VIDEO_DEV is not set
-CONFIG_NVRAM=y
-# CONFIG_JOYSTICK is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-
-#
# Sound
#
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+CONFIG_DMASOUND=y
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_OSS is not set
diff --git a/arch/ppc/prep_defconfig b/arch/ppc/prep_defconfig
index c3521f370..41db35a4a 100644
--- a/arch/ppc/prep_defconfig
+++ b/arch/ppc/prep_defconfig
@@ -41,7 +41,7 @@ CONFIG_VGA_CONSOLE=y
# CONFIG_MAC_KEYBOARD is not set
# CONFIG_MAC_FLOPPY is not set
# CONFIG_MAC_SERIAL is not set
-# CONFIG_MACMOUSE is not set
+# CONFIG_ADBMOUSE is not set
# CONFIG_PROC_DEVICETREE is not set
# CONFIG_KGDB is not set
# CONFIG_XMON is not set
@@ -196,9 +196,9 @@ CONFIG_DE4X5=y
# CONFIG_EEXPRESS_PRO100 is not set
# CONFIG_LNE390 is not set
# CONFIG_NE2K_PCI is not set
+# CONFIG_TLAN is not set
# CONFIG_ES3210 is not set
# CONFIG_EPIC100 is not set
-# CONFIG_TLAN is not set
# CONFIG_ZNET is not set
# CONFIG_NET_POCKET is not set
# CONFIG_FDDI is not set
@@ -225,6 +225,39 @@ CONFIG_PPP=m
# CONFIG_CD_NO_IDESCSI is not set
#
+# Console drivers
+#
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_MOUSE=y
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+# CONFIG_UMISC is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_NVRAM is not set
+# CONFIG_JOYSTICK is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+
+#
# Filesystems
#
# CONFIG_QUOTA is not set
@@ -287,41 +320,42 @@ CONFIG_NLS=y
# CONFIG_NLS_KOI8_R is not set
#
-# Console drivers
-#
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_MOUSE=y
-# CONFIG_ATIXL_BUSMOUSE is not set
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MS_BUSMOUSE is not set
-CONFIG_PSMOUSE=y
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
-# CONFIG_UMISC is not set
-# CONFIG_QIC02_TAPE is not set
-# CONFIG_APM is not set
-# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_NVRAM is not set
-# CONFIG_JOYSTICK is not set
-# CONFIG_MISC_RADIO is not set
-
-#
-# Ftape, the floppy tape device driver
+# Sound
#
-# CONFIG_FTAPE is not set
+CONFIG_SOUND=y
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+CONFIG_SOUND_OSS=y
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_ADLIB is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+CONFIG_SOUND_CS4232=y
+CONFIG_CS4232_BASE=530
+CONFIG_CS4232_IRQ=11
+CONFIG_CS4232_DMA=0
+CONFIG_CS4232_DMA2=3
+CONFIG_CS4232_MPU_BASE=330
+CONFIG_CS4232_MPU_IRQ=9
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_SOFTOSS is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_UART6850 is not set
#
-# Sound
+# Additional low level sound drivers
#
-# CONFIG_SOUND is not set
+# CONFIG_LOWLEVEL_SOUND is not set