summaryrefslogtreecommitdiffstats
path: root/arch/ppc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc')
-rw-r--r--arch/ppc/8xx_io/commproc.c7
-rw-r--r--arch/ppc/8xx_io/enet.c175
-rw-r--r--arch/ppc/Makefile9
-rw-r--r--arch/ppc/apus_defconfig1
-rw-r--r--arch/ppc/boot/Makefile86
-rw-r--r--arch/ppc/boot/head.S116
-rw-r--r--arch/ppc/boot/kbd.c55
-rw-r--r--arch/ppc/boot/misc.c695
-rw-r--r--arch/ppc/boot/mkprep.c11
-rw-r--r--arch/ppc/boot/of1275.c427
-rw-r--r--arch/ppc/boot/of1275.h421
-rw-r--r--arch/ppc/boot/piggyback.c64
-rw-r--r--arch/ppc/chrp_defconfig1
-rw-r--r--arch/ppc/chrpboot/Makefile10
-rw-r--r--arch/ppc/coffboot/Makefile10
-rw-r--r--arch/ppc/common_defconfig185
-rw-r--r--arch/ppc/config.in29
-rw-r--r--arch/ppc/defconfig99
-rw-r--r--arch/ppc/kernel/Makefile5
-rw-r--r--arch/ppc/kernel/align.c24
-rw-r--r--arch/ppc/kernel/apus_setup.c231
-rw-r--r--arch/ppc/kernel/chrp_pci.c343
-rw-r--r--arch/ppc/kernel/chrp_setup.c578
-rw-r--r--arch/ppc/kernel/chrp_time.c6
-rw-r--r--arch/ppc/kernel/feature.c4
-rw-r--r--arch/ppc/kernel/head.S454
-rw-r--r--arch/ppc/kernel/i8259.c130
-rw-r--r--arch/ppc/kernel/i8259.h12
-rw-r--r--arch/ppc/kernel/idle.c32
-rw-r--r--arch/ppc/kernel/indirect_pci.c121
-rw-r--r--arch/ppc/kernel/irq.c1012
-rw-r--r--arch/ppc/kernel/local_irq.h45
-rw-r--r--arch/ppc/kernel/mbx_pci.c17
-rw-r--r--arch/ppc/kernel/mbx_setup.c377
-rw-r--r--arch/ppc/kernel/misc.S71
-rw-r--r--arch/ppc/kernel/mk_defs.c3
-rw-r--r--arch/ppc/kernel/open_pic.c48
-rw-r--r--arch/ppc/kernel/open_pic.h11
-rw-r--r--arch/ppc/kernel/openpic.c35
-rw-r--r--arch/ppc/kernel/pci.c254
-rw-r--r--arch/ppc/kernel/pci.h36
-rw-r--r--arch/ppc/kernel/pmac_pci.c69
-rw-r--r--arch/ppc/kernel/pmac_pic.c362
-rw-r--r--arch/ppc/kernel/pmac_pic.h15
-rw-r--r--arch/ppc/kernel/pmac_setup.c245
-rw-r--r--arch/ppc/kernel/ppc8xx_pic.c49
-rw-r--r--arch/ppc/kernel/ppc8xx_pic.h9
-rw-r--r--arch/ppc/kernel/ppc_defs.h69
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c30
-rw-r--r--arch/ppc/kernel/prep_nvram.c173
-rw-r--r--arch/ppc/kernel/prep_pci.c738
-rw-r--r--arch/ppc/kernel/prep_setup.c597
-rw-r--r--arch/ppc/kernel/prep_time.c220
-rw-r--r--arch/ppc/kernel/process.c126
-rw-r--r--arch/ppc/kernel/prom.c263
-rw-r--r--arch/ppc/kernel/ptrace.c19
-rw-r--r--arch/ppc/kernel/setup.c600
-rw-r--r--arch/ppc/kernel/signal.c29
-rw-r--r--arch/ppc/kernel/smp.c249
-rw-r--r--arch/ppc/kernel/softemu8xx.c19
-rw-r--r--arch/ppc/kernel/syscalls.c5
-rw-r--r--arch/ppc/kernel/time.c284
-rw-r--r--arch/ppc/kernel/time.h21
-rw-r--r--arch/ppc/kernel/traps.c9
-rw-r--r--arch/ppc/lib/locks.c91
-rw-r--r--arch/ppc/lib/strcase.c11
-rw-r--r--arch/ppc/lib/string.S19
-rw-r--r--arch/ppc/mbx_defconfig90
-rw-r--r--arch/ppc/mbxboot/Makefile101
-rw-r--r--arch/ppc/mbxboot/head.S200
-rw-r--r--arch/ppc/mbxboot/mbxtty.c (renamed from arch/ppc/boot/mbxtty.c)0
-rw-r--r--arch/ppc/mbxboot/misc.c637
-rw-r--r--arch/ppc/mbxboot/offset4
-rw-r--r--arch/ppc/mbxboot/size4
-rw-r--r--arch/ppc/mm/fault.c3
-rw-r--r--arch/ppc/mm/init.c157
-rw-r--r--arch/ppc/pmac_defconfig2
-rw-r--r--arch/ppc/prep_defconfig1
78 files changed, 8282 insertions, 3488 deletions
diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c
index b1ea955ed..707f3c97c 100644
--- a/arch/ppc/8xx_io/commproc.c
+++ b/arch/ppc/8xx_io/commproc.c
@@ -111,7 +111,12 @@ m8xx_cpm_reset(uint host_page_addr)
*/
((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;
+ (((5)/2) << 13) | CICR_HP_MASK;
+ /* I hard coded the CPM interrupt to 5 above
+ * since the CPM_INTERRUPT define is relative to
+ * the linux irq structure not what the hardware
+ * belives. -- Cort
+ */
((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr = 0;
/* Set our interrupt handler with the core CPU.
*/
diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c
index 126b724be..1c71f473f 100644
--- a/arch/ppc/8xx_io/enet.c
+++ b/arch/ppc/8xx_io/enet.c
@@ -1,5 +1,4 @@
/*
- * $Id: enet.c,v 1.8 1998/11/15 19:58:07 cort Exp $
* Ethernet driver for Motorola MPC8xx.
* Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
*
@@ -22,6 +21,7 @@
* small packets.
*
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
@@ -39,7 +39,7 @@
#include <asm/8xx_immap.h>
#include <asm/pgtable.h>
-#include <asm/mbx.h>
+#include <asm/fads.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include "commproc.h"
@@ -49,7 +49,7 @@
*
* The MPC8xx CPM performs the Ethernet processing on SCC1. It can use
* an aribtrary number of buffers on byte boundaries, but must have at
- * least two receive buffers to prevent constand overrun conditions.
+ * least two receive buffers to prevent constant overrun conditions.
*
* The buffer descriptors are allocated from the CPM dual port memory
* with the data buffers allocated from host memory, just like all other
@@ -94,6 +94,17 @@
* Port C, 15 - SCC1 Ethernet Tx Enable
* Port C, 11 - SCC1 Ethernet Collision
* Port C, 10 - SCC1 Ethernet Rx Enable
+ *
+ * The RPX-Lite (that I had :-), was the MPC850SAR. It has a control
+ * register to enable Ethernet functions in the 68160, and the Ethernet
+ * was controlled by SCC2. So, the pin I/O was like this:
+ * Port A, 13 - SCC2 Ethernet Rx
+ * Port A, 12 - SCC2 Ethernet Tx
+ * Port A, 6 (CLK2) - Ethernet Tx Clk
+ * Port A, 4 (CLK4) - Ethernet Rx Clk
+ * Port B, 18 (RTS2) - Ethernet Tx Enable
+ * Port C, 8 (CD2) - Ethernet Rx Enable
+ * Port C, 9 (CTS2) - SCC Ethernet Collision
*/
/* The number of Tx and Rx buffers. These are allocated from the page
@@ -149,10 +160,26 @@ static int cpm_enet_close(struct device *dev);
static struct net_device_stats *cpm_enet_get_stats(struct device *dev);
static void set_multicast_list(struct device *dev);
-/* GET THIS FROM THE VPD!!!!
+/* Get this from various configuration locations (depends on board).
*/
/*static ushort my_enet_addr[] = { 0x0800, 0x3e26, 0x1559 };*/
+/* Right now, only the boards with an 860 use SCC1 for the Ethernet.
+ * All others use SCC2. We may need to make this board specific someday.
+ */
+#ifndef CONFIG_MPC860
+/*static ushort my_enet_addr[] = { 0x2700, 0x00ec, 0x1000 };*/
+#define CPM_CR_ENET CPM_CR_CH_SCC2
+#define PROFF_ENET PROFF_SCC2
+#define SCC_ENET 1 /* Index, not number! */
+#define CPMVEC_ENET CPMVEC_SCC2
+#else
+#define CPM_CR_ENET CPM_CR_CH_SCC1
+#define PROFF_ENET PROFF_SCC1
+#define SCC_ENET 0
+#define CPMVEC_ENET CPMVEC_SCC1
+#endif
+
static int
cpm_enet_open(struct device *dev)
{
@@ -178,7 +205,7 @@ cpm_enet_start_xmit(struct sk_buff *skb, struct device *dev)
/* Transmitter timeout, serious problems. */
if (dev->tbusy) {
int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 20)
+ if (tickssofar < 200)
return 1;
printk("%s: transmit timed out.\n", dev->name);
cep->stats.tx_errors++;
@@ -186,17 +213,17 @@ cpm_enet_start_xmit(struct sk_buff *skb, struct device *dev)
{
int i;
cbd_t *bdp;
- printk(" Ring data dump: cur_tx %x%s cur_rx %x.\n",
+ printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n",
cep->cur_tx, cep->tx_full ? " (full)" : "",
cep->cur_rx);
bdp = cep->tx_bd_base;
- for (i = 0 ; i < TX_RING_SIZE; i++)
+ for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
printk("%04x %04x %08x\n",
bdp->cbd_sc,
bdp->cbd_datlen,
bdp->cbd_bufaddr);
bdp = cep->rx_bd_base;
- for (i = 0 ; i < RX_RING_SIZE; i++)
+ for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
printk("%04x %04x %08x\n",
bdp->cbd_sc,
bdp->cbd_datlen,
@@ -263,7 +290,7 @@ cpm_enet_start_xmit(struct sk_buff *skb, struct device *dev)
/* Push the data cache so the CPM does not get stale memory
* data.
*/
- /*flush_dcache_range(skb->data, skb->data + skb->len);*/
+ flush_dcache_range(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.
@@ -300,7 +327,7 @@ static void
cpm_enet_interrupt(void *dev_id)
{
struct device *dev = dev_id;
- struct cpm_enet_private *cep;
+ volatile struct cpm_enet_private *cep;
volatile cbd_t *bdp;
ushort int_events;
int must_restart;
@@ -314,6 +341,7 @@ cpm_enet_interrupt(void *dev_id)
/* Get the interrupt events that caused us to be here.
*/
int_events = cep->sccp->scc_scce;
+ cep->sccp->scc_scce = int_events;
must_restart = 0;
/* Handle receive event in its own function.
@@ -329,6 +357,7 @@ cpm_enet_interrupt(void *dev_id)
* I don't know if "normally" implies TXB is set when the buffer
* descriptor is closed.....trial and error :-).
*/
+#if 0
if (int_events & SCCE_ENET_TXE) {
/* Transmission errors.
@@ -359,16 +388,46 @@ cpm_enet_interrupt(void *dev_id)
(BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN))
must_restart = 1;
}
+#endif
/* Transmit OK, or non-fatal error. Update the buffer descriptors.
*/
if (int_events & (SCCE_ENET_TXE | SCCE_ENET_TXB)) {
+#if 1
+ bdp = cep->dirty_tx;
+ while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
+ if ((bdp==cep->cur_tx) && (cep->tx_full == 0))
+ break;
+
+ if (bdp->cbd_sc & BD_ENET_TX_HB) /* No heartbeat */
+ cep->stats.tx_heartbeat_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_LC) /* Late collision */
+ cep->stats.tx_window_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_RL) /* Retrans limit */
+ cep->stats.tx_aborted_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_UN) /* Underrun */
+ cep->stats.tx_fifo_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */
+ cep->stats.tx_carrier_errors++;
+
+
+ /* No heartbeat or Lost carrier are not really bad errors.
+ * The others require a restart transmit command.
+ */
+ if (bdp->cbd_sc &
+ (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
+ must_restart = 1;
+ cep->stats.tx_errors++;
+ }
+
cep->stats.tx_packets++;
+#else
bdp = cep->dirty_tx;
-#ifndef final_version
+#if 1
if (bdp->cbd_sc & BD_ENET_TX_READY)
printk("HEY! Enet xmit interrupt and TX_READY.\n");
#endif
+#endif
/* Deferred means some collisions occurred during transmit,
* but we eventually sent the packet OK.
*/
@@ -406,9 +465,9 @@ cpm_enet_interrupt(void *dev_id)
}
cep->dirty_tx = (cbd_t *)bdp;
- }
+ }
- if (must_restart) {
+ if (must_restart) {
volatile cpm8xx_t *cp;
/* Some transmit errors cause the transmitter to shut
@@ -419,8 +478,9 @@ cpm_enet_interrupt(void *dev_id)
*/
cp = cpmp;
cp->cp_cpcr =
- mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_RESTART_TX) | CPM_CR_FLG;
+ mk_cr_cmd(CPM_CR_ENET, CPM_CR_RESTART_TX) | CPM_CR_FLG;
while (cp->cp_cpcr & CPM_CR_FLG);
+ }
}
/* Check for receive busy, i.e. packets coming but no place to
@@ -432,11 +492,6 @@ cpm_enet_interrupt(void *dev_id)
printk("CPM ENET: BSY can't happen.\n");
}
- /* Write the SCC event register with the events we have handled
- * to clear them. Maybe we should do this sooner?
- */
- cep->sccp->scc_scce = int_events;
-
dev->interrupt = 0;
return;
@@ -576,7 +631,7 @@ static void set_multicast_list(struct device *dev)
int i, j;
cep = (struct cpm_enet_private *)dev->priv;
- /* Get pointer to SCC1 area in parameter RAM.
+ /* Get pointer to SCC area in parameter RAM.
*/
ep = (scc_enet_t *)dev->base_addr;
@@ -627,7 +682,7 @@ static void set_multicast_list(struct device *dev)
/* 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;
+ cpmp->cp_cpcr = mk_cr_cmd(CPM_CR_ENET, CPM_CR_SET_GADDR) | CPM_CR_FLG;
/* this delay is necessary here -- Cort */
udelay(10);
while (cpmp->cp_cpcr & CPM_CR_FLG);
@@ -636,13 +691,15 @@ static void set_multicast_list(struct device *dev)
}
}
-/* Initialize the CPM Ethernet on SCC1. If EPPC-Bug loaded us, or performed
+/* Initialize the CPM Ethernet on SCC. If EPPC-Bug loaded us, or performed
* some other network I/O, a whole bunch of this has already been set up.
* It is no big deal if we do it again, we just have to disable the
* transmit and receive to make sure we don't catch the CPM with some
* inconsistent control information.
*/
-__initfunc(int cpm_enet_init(void))
+/* until this gets cleared up -- Cort */
+int __init cpm_enet_init() { m8xx_enet_init(); }
+int __init m8xx_enet_init(void)
{
struct device *dev;
struct cpm_enet_private *cep;
@@ -650,6 +707,7 @@ __initfunc(int cpm_enet_init(void))
unsigned char *eap;
unsigned long mem_addr;
pte_t *pte;
+ bd_t *bd;
volatile cbd_t *bdp;
volatile cpm8xx_t *cp;
volatile scc_t *sccp;
@@ -660,6 +718,8 @@ __initfunc(int cpm_enet_init(void))
immap = (immap_t *)IMAP_ADDR; /* and to internal registers */
+ bd = (bd_t *)res;
+
/* Allocate some private information.
*/
cep = (struct cpm_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
@@ -670,13 +730,13 @@ __initfunc(int cpm_enet_init(void))
*/
dev = init_etherdev(0, 0);
- /* Get pointer to SCC1 area in parameter RAM.
+ /* Get pointer to SCC area in parameter RAM.
*/
- ep = (scc_enet_t *)(&cp->cp_dparam[PROFF_SCC1]);
+ ep = (scc_enet_t *)(&cp->cp_dparam[PROFF_ENET]);
/* And another to the SCC register area.
*/
- sccp = (volatile scc_t *)(&cp->cp_scc[0]);
+ sccp = (volatile scc_t *)(&cp->cp_scc[SCC_ENET]);
cep->sccp = (scc_t *)sccp; /* Keep the pointer handy */
/* Disable receive and transmit in case EPPC-Bug started it.
@@ -686,6 +746,9 @@ __initfunc(int cpm_enet_init(void))
/* Cookbook style from the MPC860 manual.....
* Not all of this is necessary if EPPC-Bug has initialized
* the network.
+ * So far we are lucky, all board configurations use the same
+ * pins, or at least the same I/O Port for these functions.....
+ * It can't last though......
*/
/* Configure port A pins for Txd and Rxd.
@@ -706,7 +769,7 @@ __initfunc(int cpm_enet_init(void))
immap->im_ioport.iop_padir &= ~(PA_ENET_TCLK | PA_ENET_RCLK);
/* Configure Serial Interface clock routing.
- * First, clear all SCC1 bits to zero, then set the ones we want.
+ * First, clear all SCC bits to zero, then set the ones we want.
*/
cp->cp_sicr &= ~SICR_ENET_MASK;
cp->cp_sicr |= SICR_ENET_CLKRT;
@@ -731,13 +794,13 @@ __initfunc(int cpm_enet_init(void))
cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
cep->cur_rx = cep->rx_bd_base;
- /* Issue init Rx BD command for SCC1.
+ /* Issue init Rx BD command for SCC.
* Manual says to perform an Init Rx parameters here. We have
* to perform both Rx and Tx because the SCC may have been
* already running.
* In addition, we have to do it later because we don't yet have
* all of the BD control/status set properly.
- cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_INIT_RX) | CPM_CR_FLG;
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_ENET, CPM_CR_INIT_RX) | CPM_CR_FLG;
while (cp->cp_cpcr & CPM_CR_FLG);
*/
@@ -781,20 +844,17 @@ __initfunc(int cpm_enet_init(void))
ep->sen_iaddr3 = 0;
ep->sen_iaddr4 = 0;
- /* Set Ethernet station address. This must come from the
- * Vital Product Data (VPD) EEPROM.....as soon as I get the
- * I2C interface working.....
+ /* Set Ethernet station address.
*
- * Since we performed a diskless boot, the Ethernet controller
+ * If we performed a MBX diskless boot, the Ethernet controller
* has been initialized and we copy the address out into our
* own structure.
*/
-#ifdef notdef
- ep->sen_paddrh = my_enet_addr[0];
- ep->sen_paddrm = my_enet_addr[1];
- ep->sen_paddrl = my_enet_addr[2];
-#else
eap = (unsigned char *)&(ep->sen_paddrh);
+#ifndef CONFIG_MBX
+ for (i=5; i>=0; i--)
+ *eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
+#else
for (i=5; i>=0; i--)
dev->dev_addr[i] = *eap++;
#endif
@@ -854,7 +914,7 @@ __initfunc(int cpm_enet_init(void))
* than the manual describes because we have just now finished
* the BD initialization.
*/
- cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_ENET, CPM_CR_INIT_TRX) | CPM_CR_FLG;
while (cp->cp_cpcr & CPM_CR_FLG);
cep->skb_cur = cep->skb_dirty = 0;
@@ -869,7 +929,7 @@ __initfunc(int cpm_enet_init(void))
/* Install our interrupt handler.
*/
- cpm_install_handler(CPMVEC_SCC1, cpm_enet_interrupt, dev);
+ cpm_install_handler(CPMVEC_ENET, cpm_enet_interrupt, dev);
/* Set GSMR_H to enable all normal operating modes.
* Set GSMR_L to enable Ethernet to MC68160.
@@ -884,12 +944,42 @@ __initfunc(int cpm_enet_init(void))
/* Set processing mode. Use Ethernet CRC, catch broadcast, and
* start frame search 22 bit times after RENA.
*/
- sccp->scc_pmsr = (SCC_PMSR_ENCRC | SCC_PMSR_BRO | SCC_PMSR_NIB22);
+ sccp->scc_pmsr = (SCC_PMSR_ENCRC | SCC_PMSR_NIB22);
/* It is now OK to enable the Ethernet transmitter.
- */
+ * Unfortunately, there are board implementation differences here.
+ */
+#ifdef CONFIG_MBX
immap->im_ioport.iop_pcpar |= PC_ENET_TENA;
immap->im_ioport.iop_pcdir &= ~PC_ENET_TENA;
+#endif
+
+#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
+ cp->cp_pbpar |= PB_ENET_TENA;
+ cp->cp_pbdir |= PB_ENET_TENA;
+
+ /* And while we are here, set the configuration to enable ethernet.
+ */
+ *((volatile uint *)RPX_CSR_ADDR) &= ~BCSR0_ETHLPBK;
+ *((volatile uint *)RPX_CSR_ADDR) |=
+ (BCSR0_ETHEN | BCSR0_COLTESTDIS | BCSR0_FULLDPLXDIS);
+#endif
+
+#ifdef CONFIG_BSEIP
+ cp->cp_pbpar |= PB_ENET_TENA;
+ cp->cp_pbdir |= PB_ENET_TENA;
+
+ /* BSE uses port B and C for PHY control.
+ */
+ cp->cp_pbpar &= ~(PB_BSE_POWERUP | PB_BSE_FDXDIS);
+ cp->cp_pbdir |= (PB_BSE_POWERUP | PB_BSE_FDXDIS);
+ cp->cp_pbdat |= (PB_BSE_POWERUP | PB_BSE_FDXDIS);
+
+ immap->im_ioport.iop_pcpar &= ~PC_BSE_LOOPBACK;
+ immap->im_ioport.iop_pcdir |= PC_BSE_LOOPBACK;
+ immap->im_ioport.iop_pcso &= ~PC_BSE_LOOPBACK;
+ immap->im_ioport.iop_pcdat &= ~PC_BSE_LOOPBACK;
+#endif
dev->base_addr = (unsigned long)ep;
dev->priv = cep;
@@ -913,3 +1003,4 @@ __initfunc(int cpm_enet_init(void))
return 0;
}
+
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index 990b24b84..d865053c4 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -45,6 +45,7 @@ endif
MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
MAKECOFFBOOT = $(MAKE) -C arch/$(ARCH)/coffboot
MAKECHRPBOOT = $(MAKE) -C arch/$(ARCH)/chrpboot
+MAKEMBXBOOT = $(MAKE) -C arch/$(ARCH)/mbxboot
ifdef CONFIG_8xx
SUBDIRS += arch/ppc/8xx_io
@@ -63,10 +64,16 @@ checks:
BOOT_TARGETS = netboot znetboot zImage floppy install \
vmlinux.coff znetboot.initrd zImage.initrd vmlinux.coff.initrd
+ifdef CONFIG_MBX
+$(BOOT_TARGETS): $(CHECKS) vmlinux
+ @$(MAKECOFFBOOT) $@
+ @$(MAKEMBXBOOT) $@
+else
$(BOOT_TARGETS): $(CHECKS) vmlinux
@$(MAKECOFFBOOT) $@
@$(MAKEBOOT) $@
@$(MAKECHRPBOOT) $@
+endif
pmac_config:
rm -f .config arch/ppc/defconfig
@@ -100,10 +107,10 @@ archclean:
@$(MAKECOFFBOOT) clean
@$(MAKEBOOT) clean
@$(MAKECHRPBOOT) clean
+ @$(MAKEMBXBOOT) clean
archmrproper:
archdep:
$(MAKEBOOT) fastdep
$(MAKECHRPBOOT) fastdep
-
diff --git a/arch/ppc/apus_defconfig b/arch/ppc/apus_defconfig
index c9f900cfe..5e75d496a 100644
--- a/arch/ppc/apus_defconfig
+++ b/arch/ppc/apus_defconfig
@@ -100,7 +100,6 @@ CONFIG_NETLINK=y
# CONFIG_RTNETLINK is not set
# CONFIG_NETLINK_DEV is not set
# CONFIG_FIREWALL is not set
-CONFIG_NET_ALIAS=y
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
diff --git a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile
index da4945fd7..5a83e79ee 100644
--- a/arch/ppc/boot/Makefile
+++ b/arch/ppc/boot/Makefile
@@ -14,7 +14,7 @@
.s.o:
$(AS) -o $*.o $<
.c.o:
- $(CC) $(CFLAGS) -DINITRD_OFFSET=$(IOFF) -DINITRD_SIZE=$(ISZ) -DZIMAGE_OFFSET=$(ZOFF) -DZIMAGE_SIZE=$(ZSZ) -DKERNELBASE=$(KERNELBASE) -c -o $*.o $<
+ $(CC) $(CFLAGS) -DINITRD_OFFSET=$(IOFF) -DINITRD_SIZE=$(ISZ) -DZIMAGE_OFFSET=$(ZOFF) -DZIMAGE_SIZE=$(ZSZ) -c -o $*.o $<
.S.s:
$(CC) -D__ASSEMBLY__ -traditional -E -o $*.o $<
.S.o:
@@ -25,17 +25,14 @@ 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
+ifeq ($(CONFIG_SMP),y)
+TFTPIMAGE=/tftpboot/zImage.prep.smp
else
-ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00600000
+TFTPIMAGE=/tftpboot/zImage.prep
endif
+ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00800000
+
GZIP_FLAGS = -v9
OBJECTS := head.o misc.o ../coffboot/zlib.o
@@ -43,19 +40,13 @@ CFLAGS = -O2 -DSTDC_HEADERS -fno-builtin -I$(TOPDIR)/include
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJCOPY_ARGS = -O elf32-powerpc
-ifeq ($(CONFIG_MBX),y)
-OBJECTS += mbxtty.o
-CFLAGS += -DCONFIG_MBX
-else
-OBJECTS += vreset.o kbd.o
+OBJECTS += vreset.o kbd.o of1275.o
ifeq ($(CONFIG_SERIAL_CONSOLE),y)
OBJECTS += ns16550.o
endif
-endif
all: zImage
-ifeq ($(CONFIG_PREP),y)
zvmlinux.initrd: zvmlinux
$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
@@ -66,54 +57,19 @@ zvmlinux.initrd: zvmlinux
-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 \
- --add-section=initrd=ramdisk.image.gz \
- --add-section=image=../coffboot/vmlinux.gz \
- zvmlinux.initrd.tmp $@
- rm zvmlinux.initrd.tmp
-endif
-ifeq ($(CONFIG_MBX),y)
-zvmlinux.initrd: zvmlinux
- $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
- $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
- --add-section=initrd=ramdisk.image.gz \
- --add-section=image=../coffboot/vmlinux.gz \
- zvmlinux.initrd.tmp zvmlinux.initrd
- $(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
+ -c -o misc.o misc.c
$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
--add-section=initrd=ramdisk.image.gz \
--add-section=image=../coffboot/vmlinux.gz \
zvmlinux.initrd.tmp $@
rm zvmlinux.initrd.tmp
-endif
-ifeq ($(CONFIG_PREP),y)
zImage: zvmlinux mkprep
./mkprep -pbp zvmlinux zImage
-else
-ifeq ($(CONFIG_MBX),y)
-zImage: zvmlinux
- ln -sf zvmlinux zImage
-else
-zImage:
-endif
-endif
-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
zvmlinux: $(OBJECTS) ../coffboot/vmlinux.gz
#
@@ -128,7 +84,7 @@ zvmlinux: $(OBJECTS) ../coffboot/vmlinux.gz
#
$(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \
-DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux image` \
- -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux image` -DKERNELBASE=$(KERNELBASE) \
+ -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux image` \
-c -o misc.o misc.c
$(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS)
$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \
@@ -136,34 +92,16 @@ zvmlinux: $(OBJECTS) ../coffboot/vmlinux.gz
rm zvmlinux.tmp
floppy: $(TOPDIR)/vmlinux zImage
-ifeq ($(CONFIG_PREP),y)
dd if=zImage of=/dev/fd0H1440 bs=64b
-endif
-ifeq ($(CONFIG_PREP),y)
mkprep : mkprep.c
- $(HOSTCC) -DKERNELBASE=$(KERNELBASE) -o mkprep mkprep.c
-endif
+ $(HOSTCC) -o mkprep mkprep.c
-ifeq ($(CONFIG_PREP),y)
znetboot : zImage
- cp zImage /tftpboot/zImage.prep
-else
-ifeq ($(CONFIG_MBX),y)
-znetboot : zImage
- cp zImage /tftpboot/zImage.mbx
-else
-znetboot :
-endif
-endif
+ cp zImage $(TFTPIMAGE)
znetboot.initrd : zImage.initrd
-ifeq ($(CONFIG_PREP),y)
- cp zImage.initrd /tftpboot/zImage.prep
-endif
-ifeq ($(CONFIG_MBX),y)
- cp zImage.initrd /tftpboot/zImage.mbx
-endif
+ cp zImage.initrd $(TFTPIMAGE)
clean:
rm -f vmlinux* zvmlinux* mkprep zImage*
diff --git a/arch/ppc/boot/head.S b/arch/ppc/boot/head.S
index 43facf7e2..552e82fa1 100644
--- a/arch/ppc/boot/head.S
+++ b/arch/ppc/boot/head.S
@@ -1,4 +1,3 @@
-#include <linux/config.h>
#include "../kernel/ppc_defs.h"
#include "../kernel/ppc_asm.tmpl"
#include <asm/processor.h>
@@ -7,43 +6,24 @@
.text
/*
- * $Id: head.S,v 1.26 1998/09/19 01:21:20 cort Exp $
+ * $Id: head.S,v 1.31 1999/04/22 06:32:00 davem 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.
- *
- * The MBX EPPC-Bug understands ELF, so it loads us into the location
- * specified in the header. This is a two step process. First, EPPC-Bug
- * loads the file into the intermediate buffer memory location specified
- * by the environment parameters. When it discovers this is an ELF
- * binary, it relocates to the link address for us. Unfortunately, the
- * header does not move with the file, so we have to find the
- * intermediate load location and read the header from there. From
- * information provided by Motorola (thank you), we know this intermediate
- * location can be found from the NVRAM environment.
- * All of these addresses must be somewhat carefully chosen to make sure
- * we don't overlap the regions. I chose to load the kernel at 0, the
- * compressed image loads at 0x00100000, and the MBX intermediate buffer
- * was set to 0x00200000. Provided the loaded kernel image never grows
- * over one megabyte (which I am going to ensure never happens :-), these
- * will work fine. When we get called from EPPC-Bug, registers are:
- * R1 - Stack pointer at a high memory address.
- * R3 - Pointer to Board Information Block.
- * R4 - Pointer to argument string.
- * Interrupts masked, cache and MMU disabled.
+ * Boot loader philosophy:
+ * ROM loads us to some arbitrary location
+ * Move the boot code to the link address (8M)
+ * Call decompress_kernel()
+ * Relocate the initrd, zimage and residual data to 8M
+ * Decompress the kernel to 0
+ * Jump to the kernel entry
+ * -- Cort
*/
-
.globl start
start:
bl start_
start_:
mr r11,r3 /* Save pointer to residual/board data */
-
-#ifndef CONFIG_MBX
- mfmsr r3 /* Turn off interrupts */
- li r4,0
- ori r4,r4,MSR_EE
- andc r3,r3,r4
+ mr r25,r5 /* Save OFW pointer */
+ li r3,MSR_IP /* Establish default MSR value */
mtmsr r3
/* check if we need to relocate ourselves to the link addr or were we
@@ -68,25 +48,6 @@ start_:
mr r7,r5
b start_ldr
1010:
-#if 0
-/* Copy relocation code down to location 0x0100 (where we hope it's safe!) */
- mflr r3
- addi r5,r3,start_ldr-start_
- addi r3,r3,relocate-start_
- li r4,0x0100
- mtctr r4
- subi r3,r3,4
- subi r4,r4,4
-00: lwzu r6,4(r3)
- stwu r6,4(r4)
- cmp 0,r3,r5
- bne 00b
- mflr r21
- mfctr r22
- mtlr r21
- mtctr r22
- bctr /* Jump to code */
-#endif
/*
* no matter where we're loaded, move ourselves to -Ttext address
*/
@@ -96,13 +57,8 @@ relocate:
mr r8,r3
lis r4,start@h
ori r4,r4,start@l
-#if 0
- lis r5,edata@h
- ori r5,r5,edata@l
-#else
lis r5,end@h
ori r5,r5,end@l
-#endif
addi r5,r5,3 /* Round up - just in case */
sub r5,r5,r4 /* Compute # longwords to move */
srwi r5,r5,2
@@ -120,7 +76,6 @@ relocate:
mtlr r3 /* Easiest way to do an absolute jump */
blr
start_ldr:
-#endif /* ndef CONFIG_MBX */
/* Clear all of BSS */
lis r3,edata@h
ori r3,r3,edata@l
@@ -140,31 +95,11 @@ start_ldr:
li r2,0x000F /* Mask pointer to 16-byte boundary */
andc r1,r1,r2
/* Run loader */
-#ifdef CONFIG_MBX
- 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
- li r9,end@h
- ori r9,r9,end@l
- sub r7,r8,r9
- srwi r7,r7,2
-#define ILAP_ADDRESS 0xfa000020
- lis r8, ILAP_ADDRESS@h
- lwz r8, ILAP_ADDRESS@l(r8)
- addis r8, r8, 1 /* Add 64K */
-#endif
mr r3,r8 /* Load point */
mr r4,r7 /* Program length */
mr r5,r6 /* Checksum */
mr r6,r11 /* Residual data */
+ mr r7,r25 /* OFW interfaces */
bl decompress_kernel
/* changed to use r3 (as firmware does) for kernel
@@ -193,12 +128,24 @@ start_ldr:
li r9,0x0
lwz r9,0(r9)
mtlr r9
-#ifndef CONFIG_MBX
li r9,0
lis r10,0xdeadc0de@h
ori r10,r10,0xdeadc0de@l
stw r10,0(r9)
-#endif
+/*
+ * The Radstone firmware maps PCI memory at 0xc0000000 using BAT2
+ * so disable BATs before setting this to avoid a clash
+ */
+ li r8,0
+ mtspr DBAT0U,r8
+ mtspr DBAT1U,r8
+ mtspr DBAT2U,r8
+ mtspr DBAT3U,r8
+ mtspr IBAT0U,r8
+ mtspr IBAT1U,r8
+ mtspr IBAT2U,r8
+ mtspr IBAT3U,r8
+
blr
hang:
b hang
@@ -269,7 +216,6 @@ _put_MSR:
_GLOBAL(flush_instruction_cache)
mflr r5
bl flush_data_cache
-#ifndef CONFIG_MBX
mfspr r3,HID0 /* Caches are controlled by this register */
li r4,0
ori r4,r4,(HID0_ICE|HID0_ICFI)
@@ -278,18 +224,12 @@ _GLOBAL(flush_instruction_cache)
andc r3,r3,r4
ori r3,r3,HID0_ICE /* Enable cache */
mtspr HID0,r3
-#endif
mtlr r5
blr
#define NUM_CACHE_LINES 128*8
#define CACHE_LINE_SIZE 32
-#if 0
-cache_flush_buffer:
- .space NUM_CACHE_LINES*CACHE_LINE_SIZE /* CAUTION! these need to match hardware */
-#else
#define cache_flush_buffer 0x1000
-#endif
/*
* Flush data cache
@@ -300,11 +240,7 @@ _GLOBAL(flush_data_cache)
ori r3,r3,cache_flush_buffer@l
li r4,NUM_CACHE_LINES
mtctr r4
-#if 0
-00: dcbz 0,r3 /* Flush cache line with minimal BUS traffic */
-#else
00: lwz r4,0(r3)
-#endif
addi r3,r3,CACHE_LINE_SIZE /* Next line, please */
bdnz 00b
10: blr
diff --git a/arch/ppc/boot/kbd.c b/arch/ppc/boot/kbd.c
index 9f5cd330b..49a102e9c 100644
--- a/arch/ppc/boot/kbd.c
+++ b/arch/ppc/boot/kbd.c
@@ -1,7 +1,6 @@
-
#include <linux/keyboard.h>
-#include <../drivers/char/defkeymap.c> /* yeah I know it's bad */
+#include <../drivers/char/defkeymap.c> /* yeah I know it's bad -- Cort */
unsigned char shfts, ctls, alts, caps;
@@ -119,7 +118,7 @@ enter: /* Wait for key up */
}
break;
}
- if (brk) return (0); /* Ignore initial 'key up' codes */
+ if (brk) return (-1); /* Ignore initial 'key up' codes */
goto loop;
}
@@ -128,6 +127,11 @@ static void kbdreset(void)
unsigned char c;
int i;
+ /* flush input queue */
+ while ((inb(KBSTATP) & KBINRDY))
+ {
+ (void)inb(KBDATAP);
+ }
/* Send self-test */
while (inb(KBSTATP) & KBOUTRDY) ;
outb(KBSTATP,0xAA);
@@ -144,22 +148,63 @@ static void kbdreset(void)
while (inb(KBSTATP) & KBOUTRDY) ;
outb(KBDATAP,0x45);
for (i = 0; i < 10000; i++) udelay(1);
+
+ while (inb(KBSTATP) & KBOUTRDY) ;
+ outb(KBSTATP,0x20);
+ while ((inb(KBSTATP) & KBINRDY) == 0) ; /* wait input ready */
+ if (! (inb(KBDATAP) & 0x40)) {
+ /*
+ * Quote from PS/2 System Reference Manual:
+ *
+ * "Address hex 0060 and address hex 0064 should be
+ * written only when the input-buffer-full bit and
+ * output-buffer-full bit in the Controller Status
+ * register are set 0." (KBINRDY and KBOUTRDY)
+ */
+
+ while (inb(KBSTATP) & (KBINRDY | KBOUTRDY)) ;
+ outb(KBDATAP,0xF0);
+ while (inb(KBSTATP) & (KBINRDY | KBOUTRDY)) ;
+ outb(KBDATAP,0x01);
+ }
+
while (inb(KBSTATP) & KBOUTRDY) ;
outb(KBSTATP,0xAE);
}
+/* We have to actually read the keyboard when CRT_tstc is called,
+ * since the pending data might be a key release code, and therefore
+ * not valid data. In this case, kbd() will return -1, even though there's
+ * data to be read. Of course, we might actually read a valid key press,
+ * in which case it gets queued into key_pending for use by CRT_getc.
+ */
+
static int kbd_reset = 0;
+static int key_pending = -1;
+
int CRT_getc(void)
{
int c;
if (!kbd_reset) {kbdreset(); kbd_reset++; }
+
+ if (key_pending != -1) {
+ c = key_pending;
+ key_pending = -1;
+ return c;
+ } else {
while ((c = kbd(0)) == 0) ;
- return(c);
+ return c;
+ }
}
int CRT_tstc(void)
{
if (!kbd_reset) {kbdreset(); kbd_reset++; }
- return ((inb(KBSTATP) & KBINRDY) != 0);
+
+ while (key_pending == -1 && ((inb(KBSTATP) & KBINRDY) != 0)) {
+ key_pending = kbd(1);
+ }
+
+ return (key_pending != -1);
}
diff --git a/arch/ppc/boot/misc.c b/arch/ppc/boot/misc.c
index 470e1e4a9..15d347df5 100644
--- a/arch/ppc/boot/misc.c
+++ b/arch/ppc/boot/misc.c
@@ -1,7 +1,7 @@
/*
* misc.c
*
- * $Id: misc.c,v 1.53 1998/12/15 17:40:15 cort Exp $
+ * $Id: misc.c,v 1.64 1999/04/30 05:52:46 cort Exp $
*
* Adapted for PowerPC by Gary Thomas
*
@@ -17,13 +17,7 @@
#include <asm/page.h>
#include <asm/processor.h>
#include <asm/mmu.h>
-#ifdef CONFIG_MBX
-#include <asm/mbx.h>
-#endif
-#ifdef CONFIG_FADS
-#include <asm/fads.h>
-#endif
-#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX)
+#if defined(CONFIG_SERIAL_CONSOLE)
#include "ns16550.h"
struct NS16550 *com_port;
#endif /* CONFIG_SERIAL_CONSOLE */
@@ -37,30 +31,18 @@ struct NS16550 *com_port;
*/
char *avail_ram;
char *end_avail;
+extern char _end[];
-/* 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_preset[] = "console=tty0 console=ttyS0,9600n8";
-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);
+#ifdef CONFIG_CMDLINE
+#define CMDLINE CONFIG_CMDLINE
+#else
+#define CMDLINE "";
#endif
+char cmd_preset[] = CMDLINE;
+char cmd_buf[256];
+char *cmd_line = cmd_buf;
+int keyb_present = 1; /* keyboard controller is present by default */
RESIDUAL hold_resid_buf;
RESIDUAL *hold_residual = &hold_resid_buf;
unsigned long initrd_start = 0, initrd_end = 0;
@@ -78,6 +60,8 @@ void _bcopy(char *src, char *dst, int len);
void * memcpy(void * __dest, __const void * __src,
int __n);
void gunzip(void *, int, unsigned char *, int *);
+static int _cvt(unsigned long val, char *buf, long radix, char *digits);
+unsigned char inb(int);
void pause()
{
@@ -90,7 +74,6 @@ void exit()
while(1);
}
-#if !defined(CONFIG_MBX) && !defined(CONFIG_FADS)
static void clear_screen()
{
int i, j;
@@ -113,8 +96,11 @@ static void scroll()
tstc(void)
{
-#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX)
- return (CRT_tstc() || NS16550_tstc(com_port));
+#if defined(CONFIG_SERIAL_CONSOLE)
+ if (keyb_present)
+ return (CRT_tstc() || NS16550_tstc(com_port));
+ else
+ NS16550_tstc(com_port);
#else
return (CRT_tstc() );
#endif /* CONFIG_SERIAL_CONSOLE */
@@ -123,10 +109,11 @@ tstc(void)
getc(void)
{
while (1) {
-#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX)
+#if defined(CONFIG_SERIAL_CONSOLE)
if (NS16550_tstc(com_port)) return (NS16550_getc(com_port));
#endif /* CONFIG_SERIAL_CONSOLE */
- if (CRT_tstc()) return (CRT_getc());
+ if (keyb_present)
+ if (CRT_tstc()) return (CRT_getc());
}
}
@@ -135,7 +122,7 @@ putc(const char c)
{
int x,y;
-#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX)
+#if defined(CONFIG_SERIAL_CONSOLE)
NS16550_putc(com_port, c);
if ( c == '\n' ) NS16550_putc(com_port, '\r');
#endif /* CONFIG_SERIAL_CONSOLE */
@@ -149,6 +136,8 @@ putc(const char c)
scroll();
y--;
}
+ } else if (c == '\r') {
+ x = 0;
} else if (c == '\b') {
if (x > 0) {
x--;
@@ -179,7 +168,7 @@ void puts(const char *s)
y = orig_y;
while ( ( c = *s++ ) != '\0' ) {
-#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX)
+#if defined(CONFIG_SERIAL_CONSOLE)
NS16550_putc(com_port, c);
if ( c == '\n' ) NS16550_putc(com_port, '\r');
#endif /* CONFIG_SERIAL_CONSOLE */
@@ -206,42 +195,11 @@ void puts(const char *s)
}
}
+ cursor(x, y);
+
orig_x = x;
orig_y = y;
}
-#else
-/* The MBX is just the serial port.
-*/
-tstc(void)
-{
- return (serial_tstc());
-}
-
-getc(void)
-{
- while (1) {
- if (serial_tstc()) return (serial_getc());
- }
-}
-
-void
-putc(const char c)
-{
- serial_putchar(c);
-}
-
-void puts(const char *s)
-{
- char c;
-
- while ( ( c = *s++ ) != '\0' ) {
- serial_putchar(c);
- if ( c == '\n' )
- serial_putchar('\r');
- }
-}
-
-#endif /* CONFIG_MBX */
void * memcpy(void * __dest, __const void * __src,
int __n)
@@ -354,7 +312,8 @@ void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
unsigned char sanity[0x2000];
unsigned long
-decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, RESIDUAL *residual)
+decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
+ RESIDUAL *residual, void *OFW_interface)
{
int timer;
extern unsigned long start;
@@ -362,9 +321,13 @@ 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
+ unsigned long TotalMemory;
+ unsigned long orig_MSR;
+ int dev_handle;
+ int mem_info[2];
+ int res, size;
+ unsigned char board_type;
+ unsigned char base_mod;
lines = 25;
cols = 80;
@@ -372,7 +335,6 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
orig_y = 24;
-#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
@@ -381,42 +343,79 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
*/
flush_instruction_cache();
_put_HID0(_get_HID0() & ~0x0000C000);
- _put_MSR(_get_MSR() & ~0x0030);
- vga_init(0xC0000000);
+ _put_MSR((orig_MSR = _get_MSR()) & ~0x0030);
-#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX)
+#if defined(CONFIG_SERIAL_CONSOLE)
com_port = (struct NS16550 *)NS16550_init(0);
#endif /* CONFIG_SERIAL_CONSOLE */
+ vga_init(0xC0000000);
if (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)
- memcpy(hold_residual,residual,sizeof(bd_t));
-#endif /* CONFIG_MBX */
+ {
+ /* Is this Motorola PPCBug? */
+ if ((1 & residual->VitalProductData.FirmwareSupports) &&
+ (1 == residual->VitalProductData.FirmwareSupplier)) {
+ board_type = inb(0x800) & 0xF0;
- /* 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
- */
- if ( INITRD_OFFSET )
- end_avail = (char *)0x01000000;
- else
- end_avail = (char *)0x00400000;
+ /* If this is genesis 2 board then check for no
+ * keyboard controller and more than one processor.
+ */
+ if (board_type == 0xe0) {
+ base_mod = inb(0x803);
+ /* if a MVME2300/2400 or a Sitka then no keyboard */
+ if((base_mod == 0x9) || (base_mod == 0xF9) ||
+ (base_mod == 0xE1)) {
+ keyb_present = 0; /* no keyboard */
+ }
+ }
+ }
+ memcpy(hold_residual,residual,sizeof(RESIDUAL));
+ } else {
+ /* Assume 32M in the absence of more info... */
+ TotalMemory = 0x02000000;
+ /*
+ * This is a 'best guess' check. We want to make sure
+ * we don't try this on a PReP box without OF
+ * -- Cort
+ */
+ while (OFW_interface && ((unsigned long)OFW_interface < 0x10000000) )
+ {
+ /* The MMU needs to be on when we call OFW */
+ _put_MSR(orig_MSR);
+ of_init(OFW_interface);
+
+ /* get handle to memory description */
+ res = of_finddevice("/memory@0",
+ &dev_handle);
+ // puthex(res); puts("\n");
+ if (res) break;
+
+ /* get the info */
+ // puts("get info = ");
+ res = of_getprop(dev_handle,
+ "reg",
+ mem_info,
+ sizeof(mem_info),
+ &size);
+ // puthex(res); puts(", info = "); puthex(mem_info[0]);
+ // puts(" "); puthex(mem_info[1]); puts("\n");
+ if (res) break;
+
+ TotalMemory = mem_info[1];
+ break;
+ }
+ hold_residual->TotalMemory = TotalMemory;
+ residual = hold_residual;
+ /* Turn MMU back off */
+ _put_MSR(orig_MSR & ~0x0030);
+ }
- /* let residual data tell us it's higher */
- if ( (unsigned long)residual > 0x00800000 )
- end_avail = (char *)PAGE_ALIGN((unsigned long)residual);
+ /* assume the chunk below 8M is free */
+ end_avail = (char *)0x00800000;
+ /* tell the user where we were loaded at and where we
+ * were relocated to for debugging this process
+ */
puts("loaded at: "); puthex(load_addr);
puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n");
if ( (unsigned long)load_addr != (unsigned long)&start )
@@ -431,20 +430,12 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
{
puts("board data at: "); puthex((unsigned long)residual);
puts(" ");
-#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: ");
puthex((unsigned long)hold_residual);
puts(" ");
-#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)));
-#endif
puts("\n");
}
@@ -460,33 +451,16 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
initrd_end = INITRD_SIZE + initrd_start;
/*
- * setup avail_ram - this is the first part of ram usable
- * by the uncompress code. -- Cort
+ * Find a place to stick the zimage and initrd and
+ * relocate them if we have to. -- Cort
*/
- avail_ram = (char *)PAGE_ALIGN((unsigned long)zimage_start+zimage_size);
- if ( ((load_addr+(num_words*4)) > (unsigned long) avail_ram)
- && (load_addr <= 0x01000000) )
- avail_ram = (char *)(load_addr+(num_words*4));
- if ( (((unsigned long)&start+(num_words*4)) > (unsigned long) avail_ram)
- && (load_addr <= 0x01000000) )
- avail_ram = (char *)((unsigned long)&start+(num_words*4));
-
- /* relocate zimage */
+ avail_ram = (char *)PAGE_ALIGN((unsigned long)_end);
puts("zimage at: "); puthex((unsigned long)zimage_start);
puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); puts("\n");
- /*
- * 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 ) && initrd_start)
+ if ( (unsigned long)zimage_start <= 0x00800000 )
{
- memcpy ((void *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-zimage_size),
- (void *)zimage_start, zimage_size );
- zimage_start = (char *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-zimage_size);
- end_avail = (char *)zimage_start;
+ memcpy( (void *)avail_ram, (void *)zimage_start, zimage_size );
+ zimage_start = (char *)avail_ram;
puts("relocated to: "); puthex((unsigned long)zimage_start);
puts(" ");
puthex((unsigned long)zimage_size+(unsigned long)zimage_start);
@@ -498,44 +472,24 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
{
puts("initrd at: "); puthex(initrd_start);
puts(" "); puthex(initrd_end); puts("\n");
- /*
- * Memory is really tight on the MBX (we can assume 4M)
- * so put the initrd at the TOP of ram, and set end_avail
- * to right after that.
- *
- * I should do something like this for prep, too and keep
- * a variable end_of_DRAM to keep track of what we think the
- * max ram is.
- * -- Cort
- */
-#if 0
- memcpy ((void *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-INITRD_SIZE),
- (void *)initrd_start,
- INITRD_SIZE );
- initrd_start = PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-INITRD_SIZE);
+#ifdef OMIT
+ avail_ram = (char *)PAGE_ALIGN(
+ (unsigned long)zimage_size+(unsigned long)zimage_start);
+ memcpy ((void *)avail_ram, (void *)initrd_start, INITRD_SIZE );
+ initrd_start = (unsigned long)avail_ram;
initrd_end = initrd_start + INITRD_SIZE;
- end_avail = (char *)initrd_start;
puts("relocated to: "); puthex(initrd_start);
puts(" "); puthex(initrd_end); puts("\n");
-#endif
+#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
+ end_avail = (char *)0x00800000;
puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" ");
puthex((unsigned long)end_avail); puts("\n");
-
-#if !defined(CONFIG_MBX) && !defined(CONFIG_FADS)
- CRT_tstc(); /* Forces keyboard to be initialized */
-#endif
+ if (keyb_present)
+ CRT_tstc(); /* Forces keyboard to be initialized */
puts("\nLinux/PPC load: ");
timer = 0;
@@ -550,13 +504,6 @@ 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);
@@ -567,32 +514,6 @@ 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");
/* mappings on early boot can only handle 16M */
@@ -611,150 +532,6 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
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];
@@ -802,3 +579,243 @@ _bcopy(char *src, char *dst, int len)
{
while (len--) *dst++ = *src++;
}
+
+
+#define FALSE 0
+#define TRUE 1
+#include <stdarg.h>
+
+int
+strlen(char *s)
+{
+ int len = 0;
+ while (*s++) len++;
+ return len;
+}
+
+_printk(char const *fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = _vprintk(putc, fmt, ap);
+ va_end(ap);
+ return (ret);
+}
+
+#define is_digit(c) ((c >= '0') && (c <= '9'))
+
+int
+_vprintk(putc, fmt0, ap)
+int (*putc)();
+const char *fmt0;
+va_list ap;
+{
+ char c, sign, *cp;
+ int left_prec, right_prec, zero_fill, length, pad, pad_on_right;
+ char buf[32];
+ long val;
+ while (c = *fmt0++)
+ {
+ if (c == '%')
+ {
+ c = *fmt0++;
+ left_prec = right_prec = pad_on_right = 0;
+ if (c == '-')
+ {
+ c = *fmt0++;
+ pad_on_right++;
+ }
+ if (c == '0')
+ {
+ zero_fill = TRUE;
+ c = *fmt0++;
+ } else
+ {
+ zero_fill = FALSE;
+ }
+ while (is_digit(c))
+ {
+ left_prec = (left_prec * 10) + (c - '0');
+ c = *fmt0++;
+ }
+ if (c == '.')
+ {
+ c = *fmt0++;
+ zero_fill++;
+ while (is_digit(c))
+ {
+ right_prec = (right_prec * 10) + (c - '0');
+ c = *fmt0++;
+ }
+ } else
+ {
+ right_prec = left_prec;
+ }
+ sign = '\0';
+ switch (c)
+ {
+ case 'd':
+ case 'x':
+ case 'X':
+ val = va_arg(ap, long);
+ switch (c)
+ {
+ case 'd':
+ if (val < 0)
+ {
+ sign = '-';
+ val = -val;
+ }
+ length = _cvt(val, buf, 10, "0123456789");
+ break;
+ case 'x':
+ length = _cvt(val, buf, 16, "0123456789abcdef");
+ break;
+ case 'X':
+ length = _cvt(val, buf, 16, "0123456789ABCDEF");
+ break;
+ }
+ cp = buf;
+ break;
+ case 's':
+ cp = va_arg(ap, char *);
+ length = strlen(cp);
+ break;
+ case 'c':
+ c = va_arg(ap, long /*char*/);
+ (*putc)(c);
+ continue;
+ default:
+ (*putc)('?');
+ }
+ pad = left_prec - length;
+ if (sign != '\0')
+ {
+ pad--;
+ }
+ if (zero_fill)
+ {
+ c = '0';
+ if (sign != '\0')
+ {
+ (*putc)(sign);
+ sign = '\0';
+ }
+ } else
+ {
+ c = ' ';
+ }
+ if (!pad_on_right)
+ {
+ while (pad-- > 0)
+ {
+ (*putc)(c);
+ }
+ }
+ if (sign != '\0')
+ {
+ (*putc)(sign);
+ }
+ while (length-- > 0)
+ {
+ (*putc)(c = *cp++);
+ if (c == '\n')
+ {
+ (*putc)('\r');
+ }
+ }
+ if (pad_on_right)
+ {
+ while (pad-- > 0)
+ {
+ (*putc)(c);
+ }
+ }
+ } else
+ {
+ (*putc)(c);
+ if (c == '\n')
+ {
+ (*putc)('\r');
+ }
+ }
+ }
+}
+
+int _cvt(unsigned long val, char *buf, long radix, char *digits)
+{
+ char temp[80];
+ char *cp = temp;
+ int length = 0;
+ if (val == 0)
+ { /* Special case */
+ *cp++ = '0';
+ } else
+ while (val)
+ {
+ *cp++ = digits[val % radix];
+ val /= radix;
+ }
+ while (cp != temp)
+ {
+ *buf++ = *--cp;
+ length++;
+ }
+ *buf = '\0';
+ return (length);
+}
+
+_dump_buf_with_offset(unsigned char *p, int s, unsigned char *base)
+{
+ int i, c;
+ if ((unsigned int)s > (unsigned int)p)
+ {
+ s = (unsigned int)s - (unsigned int)p;
+ }
+ while (s > 0)
+ {
+ if (base)
+ {
+ _printk("%06X: ", (int)p - (int)base);
+ } else
+ {
+ _printk("%06X: ", p);
+ }
+ for (i = 0; i < 16; i++)
+ {
+ if (i < s)
+ {
+ _printk("%02X", p[i] & 0xFF);
+ } else
+ {
+ _printk(" ");
+ }
+ if ((i % 2) == 1) _printk(" ");
+ if ((i % 8) == 7) _printk(" ");
+ }
+ _printk(" |");
+ for (i = 0; i < 16; i++)
+ {
+ if (i < s)
+ {
+ c = p[i] & 0xFF;
+ if ((c < 0x20) || (c >= 0x7F)) c = '.';
+ } else
+ {
+ c = ' ';
+ }
+ _printk("%c", c);
+ }
+ _printk("|\n");
+ s -= 16;
+ p += 16;
+ }
+}
+
+_dump_buf(unsigned char *p, int s)
+{
+ _printk("\n");
+ _dump_buf_with_offset(p, s, 0);
+}
diff --git a/arch/ppc/boot/mkprep.c b/arch/ppc/boot/mkprep.c
index 7799c9acc..0a596b0ff 100644
--- a/arch/ppc/boot/mkprep.c
+++ b/arch/ppc/boot/mkprep.c
@@ -14,15 +14,8 @@
* Modified for x86 hosted builds by Matt Porter <porter@neta.com>
*/
-#ifdef linux
-#include <linux/types.h>
-/*#include <asm/stat.h>*/
-/*#include <asm/byteorder.h>*/ /* the byte swap funcs don't work here -- Cort */
-#else
#include <unistd.h>
-#endif
#include <sys/stat.h>
-
#include <stdio.h>
#include <errno.h>
@@ -168,10 +161,10 @@ void write_prep_partition(int in, int out)
/* set entry point and boot image size skipping over elf header */
#ifdef __i386__
*entry = 0x400/*+65536*/;
- *length = info.st_size+0x400;
+ *length = info.st_size-elfhdr_size+0x400;
#else
*entry = cpu_to_le32(0x400/*+65536*/);
- *length = cpu_to_le32(info.st_size+0x400);
+ *length = cpu_to_le32(info.st_size-elfhdr_size+0x400);
#endif /* __i386__ */
/* sets magic number for msdos partition (used by linux) */
diff --git a/arch/ppc/boot/of1275.c b/arch/ppc/boot/of1275.c
new file mode 100644
index 000000000..b82fa7a46
--- /dev/null
+++ b/arch/ppc/boot/of1275.c
@@ -0,0 +1,427 @@
+/* Open Firmware Client Interface */
+
+
+#include "of1275.h"
+
+
+static int (*of_server)(void *) = (int(*)(void*))-1;
+
+void
+of_init(void *handler)
+{
+ of_server = (int(*)(void*))handler;
+}
+
+
+/* 6.3.2.1 Client interface */
+
+
+int
+of_test(const char *name, int *missing)
+{
+ int result;
+ static of_test_service s;
+ s.service = "test";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.name = name;
+ result = of_server(&s);
+ *missing = s.missing;
+ return result;
+}
+
+
+/* 6.3.2.2 Device tree */
+
+
+int
+of_peer(int phandle, int *sibling_phandle)
+{
+ int result;
+ static of_peer_service s;
+ s.service = "peer";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ result = of_server(&s);
+ *sibling_phandle = s.sibling_phandle;
+ return result;
+}
+
+int
+of_child(int phandle, int *child_phandle)
+{
+ int result;
+ static of_child_service s;
+ s.service = "child";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ result = of_server(&s);
+ *child_phandle = s.child_phandle;
+ return result;
+}
+
+int
+of_parent(int phandle, int *parent_phandle)
+{
+ int result;
+ static of_parent_service s;
+ s.service = "parent";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ result = of_server(&s);
+ *parent_phandle = s.parent_phandle;
+ return result;
+}
+
+int
+of_instance_to_package(int ihandle, int *phandle)
+{
+ int result;
+ static of_instance_to_package_service s;
+ s.service = "instance-to-package";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.ihandle = ihandle;
+ result = of_server(&s);
+ *phandle = s.phandle;
+ return result;
+}
+
+int
+of_getproplen(int phandle, const char *name, int *proplen)
+{
+ int result;
+ static of_getproplen_service s;
+ s.service = "getproplen";
+ s.n_args = 2;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ s.name = name;
+ result = of_server(&s);
+ *proplen = s.proplen;
+ return result;
+}
+
+int
+of_getprop(int phandle, const char *name, void *buf, int buflen, int *size)
+{
+ int result;
+ static of_getprop_service s;
+ s.service = "getprop";
+ s.n_args = 4;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ s.name = name;
+ s.buf = buf;
+ s.buflen = buflen;
+ result = of_server(&s);
+ *size = s.size;
+ return result;
+}
+
+int
+of_nextprop(int phandle, const char *previous, void *buf, int *flag)
+{
+ int result;
+ static of_nextprop_service s;
+ s.service = "nextprop";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ s.previous = previous;
+ s.buf = buf;
+ result = of_server(&s);
+ *flag = s.flag;
+ return result;
+}
+
+int
+of_setprop(int phandle, const char *name, void *buf, int len, int *size)
+{
+ int result;
+ static of_setprop_service s;
+ s.service = "setprop";
+ s.n_args = 4;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ s.name = name;
+ s.buf = buf;
+ s.len = len;
+ result = of_server(&s);
+ *size = s.size;
+ return result;
+}
+
+int
+of_canon(const char *device_specifier, void *buf, int buflen, int *length)
+{
+ int result;
+ static of_canon_service s;
+ s.service = "canon";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.device_specifier = device_specifier;
+ s.buf = buf;
+ s.buflen = buflen;
+ result = of_server(&s);
+ *length = s.length;
+ return result;
+}
+
+int
+of_finddevice(const char *device_specifier, int *phandle)
+{
+ int result;
+ static of_finddevice_service s;
+ s.service = "finddevice";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.device_specifier = device_specifier;
+ result = of_server(&s);
+ *phandle = s.phandle;
+ return result;
+}
+
+int
+of_instance_to_path(int ihandle, void *buf, int buflen, int *length)
+{
+ int result;
+ static of_instance_to_path_service s;
+ s.service = "instance-to-path";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.ihandle = ihandle;
+ s.buf = buf;
+ s.buflen = buflen;
+ result = of_server(&s);
+ *length = s.length;
+ return result;
+}
+
+int
+of_package_to_path(int phandle, void *buf, int buflen, int *length)
+{
+ int result;
+ static of_package_to_path_service s;
+ s.service = "package-to-path";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ s.buf = buf;
+ s.buflen = buflen;
+ result = of_server(&s);
+ *length = s.length;
+ return result;
+}
+
+/* int of_call_method(const char *method, int ihandle, ...); */
+
+
+/* 6.3.2.3 Device I/O */
+
+
+int
+of_open(const char *device_specifier, int *ihandle)
+{
+ int result;
+ static of_open_service s;
+ s.service = "open";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.device_specifier = device_specifier;
+ result = of_server(&s);
+ *ihandle = s.ihandle;
+ return result;
+}
+
+int
+of_close(int ihandle)
+{
+ int result;
+ static of_close_service s;
+ s.service = "close";
+ s.n_args = 1;
+ s.n_returns = 0;
+ s.ihandle = ihandle;
+ result = of_server(&s);
+ return result;
+}
+
+int
+of_read(int ihandle, void *addr, int len, int *actual)
+{
+ int result;
+ static of_read_service s;
+ s.service = "read";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.ihandle = ihandle;
+ s.addr = addr;
+ s.len = len;
+ result = of_server(&s);
+ *actual = s.actual;
+ return result;
+}
+
+int
+of_write(int ihandle, void *addr, int len, int *actual)
+{
+ int result;
+ static of_write_service s;
+ s.service = "write";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.ihandle = ihandle;
+ s.addr = addr;
+ s.len = len;
+ result = of_server(&s);
+ *actual = s.actual;
+ return result;
+}
+
+int
+of_seek(int ihandle, int pos_hi, int pos_lo, int *status)
+{
+ int result;
+ static of_seek_service s;
+ s.service = "seek";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.ihandle = ihandle;
+ s.pos_hi = pos_hi;
+ s.pos_lo = pos_lo;
+ result = of_server(&s);
+ *status = s.status;
+ return result;
+}
+
+
+/* 6.3.2.4 Memory */
+
+
+int
+of_claim(void *virt, int size, int align, void **baseaddr)
+{
+ int result;
+ static of_claim_service s;
+ s.service = "claim";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.virt = virt;
+ s.size = size;
+ s.align = align;
+ result = of_server(&s);
+ *baseaddr = s.baseaddr;
+ return result;
+}
+
+int
+of_release(void *virt, int size)
+{
+ int result;
+ static of_release_service s;
+ s.service = "release";
+ s.n_args = 2;
+ s.n_returns = 0;
+ s.virt = virt;
+ s.size = size;
+ result = of_server(&s);
+ return result;
+}
+
+
+/* 6.3.2.5 Control transfer */
+
+
+int
+of_boot(const char *bootspec)
+{
+ int result;
+ static of_boot_service s;
+ s.service = "boot";
+ s.n_args = 1;
+ s.n_returns = 0;
+ s.bootspec = bootspec;
+ result = of_server(&s);
+ return result;
+}
+
+int
+of_enter(void)
+{
+ int result;
+ static of_enter_service s;
+ s.service = "enter";
+ s.n_args = 0;
+ s.n_returns = 0;
+ result = of_server(&s);
+ return result;
+}
+
+int
+of_exit(void)
+{
+ int result;
+ static of_exit_service s;
+ s.service = "exit";
+ s.n_args = 0;
+ s.n_returns = 0;
+ result = of_server(&s);
+ return result;
+}
+
+/* int of_chain(void *virt, int size, void *entry, void *args, int len); */
+
+
+/* 6.3.2.6 User interface */
+
+
+/* int of_interpret(const char *arg, ...); */
+
+int
+of_set_callback(void *newfunc, void **oldfunc)
+{
+ int result;
+ static of_set_callback_service s;
+ s.service = "set-callback";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.newfunc = newfunc;
+ result = of_server(&s);
+ *oldfunc = s.oldfunc;
+ return result;
+}
+
+int
+of_set_symbol_lookup(void *sym_to_value, void *value_to_sym)
+{
+ int result;
+ static of_set_symbol_lookup_service s;
+ s.service = "set-symbol-lookup";
+ s.n_args = 2;
+ s.n_returns = 0;
+ s.sym_to_value = sym_to_value;
+ s.value_to_sym = s.value_to_sym;
+ result = of_server(&s);
+ return result;
+}
+
+
+/* 6.3.2.7 Time */
+
+
+int
+of_milliseconds(int *ms)
+{
+ int result;
+ static of_milliseconds_service s;
+ s.service = "milliseconds";
+ s.n_args = 0;
+ s.n_returns = 1;
+ result = of_server(&s);
+ *ms = s.ms;
+ return result;
+}
diff --git a/arch/ppc/boot/of1275.h b/arch/ppc/boot/of1275.h
new file mode 100644
index 000000000..bc050d32b
--- /dev/null
+++ b/arch/ppc/boot/of1275.h
@@ -0,0 +1,421 @@
+/* 6.3.2.1 Client interface */
+
+
+typedef struct _of_test_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ const char *name;
+ /*out*/
+ int missing;
+} of_test_service;
+
+int of_test(const char *name, int *missing);
+
+
+/* 6.3.2.2 Device tree */
+
+
+typedef struct _of_peer_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ int phandle;
+ /*out*/
+ int sibling_phandle;
+} of_peer_service;
+
+int of_peer(int phandle, int *sibling_phandle);
+
+
+typedef struct _of_child_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ int phandle;
+ /*out*/
+ int child_phandle;
+} of_child_service;
+
+int of_child(int phandle, int *child_phandle);
+
+
+typedef struct _of_parent_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ int phandle;
+ /*out*/
+ int parent_phandle;
+} of_parent_service;
+
+int of_child(int phandle, int *parent_phandle);
+
+
+typedef struct _of_instance_to_package_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ int ihandle;
+ /*out*/
+ int phandle;
+} of_instance_to_package_service;
+
+int of_instance_to_package(int ihandle, int *phandle);
+
+
+typedef struct _of_getproplen_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ int phandle;
+ const char *name;
+ /*out*/
+ int proplen;
+} of_getproplen_service;
+
+int of_getproplen(int phandle, const char *name, int *proplen);
+
+
+typedef struct _of_getprop_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ int phandle;
+ const char *name;
+ void *buf;
+ int buflen;
+ /*out*/
+ int size;
+} of_getprop_service;
+
+int of_getprop(int phandle, const char *name, void *buf, int buflen,
+ int *size);
+
+
+typedef struct _of_nextprop_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ int phandle;
+ const char *previous;
+ void *buf;
+ /*out*/
+ int flag;
+} of_nextprop_service;
+
+int of_nextprop(int phandle, const char *previous, void *buf, int *flag);
+
+
+typedef struct _of_setprop_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ int phandle;
+ const char *name;
+ void *buf;
+ int len;
+ /*out*/
+ int size;
+} of_setprop_service;
+
+int of_setprop(int phandle, const char *name, void *buf, int len, int *size);
+
+
+typedef struct _of_canon_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ const char *device_specifier;
+ void *buf;
+ int buflen;
+ /*out*/
+ int length;
+} of_canon_service;
+
+int of_canon(const char *device_specifier, void *buf, int buflen, int *length);
+
+
+typedef struct _of_finddevice_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ const char *device_specifier;
+ /*out*/
+ int phandle;
+} of_finddevice_service;
+
+int of_finddevice(const char *device_specifier, int *phandle);
+
+
+typedef struct _of_instance_to_path_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ int ihandle;
+ void *buf;
+ int buflen;
+ /*out*/
+ int length;
+} of_instance_to_path_service;
+
+int of_instance_to_path(int ihandle, void *buf, int buflen, int *length);
+
+
+typedef struct _of_package_to_path_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ int phandle;
+ void *buf;
+ int buflen;
+ /*out*/
+ int length;
+} of_package_to_path_service;
+
+int of_package_to_path(int phandle, void *buf, int buflen, int *length);
+
+
+typedef struct _of_call_method_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ const char *method;
+ int ihandle;
+ /*...*/
+ int args[0];
+} of_call_method_service;
+
+int of_call_method(const char *method, int ihandle, ...);
+
+
+/* 6.3.2.3 Device I/O */
+
+
+typedef struct _of_open_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ const char *device_specifier;
+ /*out*/
+ int ihandle;
+} of_open_service;
+
+int of_open(const char *device_specifier,
+ int *ihandle);
+
+
+typedef struct _of_close_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ int ihandle;
+ /*out*/
+} of_close_service;
+
+int of_close(int ihandle);
+
+
+typedef struct _of_read_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ int ihandle;
+ void *addr;
+ int len;
+ /*out*/
+ int actual;
+} of_read_service;
+
+int of_read(int ihandle, void *addr, int len, int *actual);
+
+
+typedef struct _of_write_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ int ihandle;
+ void *addr;
+ int len;
+ /*out*/
+ int actual;
+} of_write_service;
+
+int of_write(int ihandle, void *addr, int len, int *actual);
+
+
+typedef struct _of_seek_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ int ihandle;
+ int pos_hi;
+ int pos_lo;
+ /*out*/
+ int status;
+} of_seek_service;
+
+int of_seek(int ihandle, int pos_hi, int pos_lo, int *status);
+
+
+/* 6.3.2.4 Memory */
+
+
+typedef struct _of_claim_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ void *virt;
+ int size;
+ int align;
+ /*out*/
+ void *baseaddr;
+} of_claim_service;
+
+int of_claim(void *virt, int size, int align, void **baseaddr);
+
+
+typedef struct _of_release_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ void *virt;
+ int size;
+ int align;
+ /*out*/
+} of_release_service;
+
+int of_release(void *virt, int size);
+
+
+/* 6.3.2.5 Control transfer */
+
+
+typedef struct _of_boot_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ const char *bootspec;
+ /*out*/
+} of_boot_service;
+
+int of_boot(const char *bootspec);
+
+
+typedef struct _of_enter_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ /*out*/
+} of_enter_service;
+
+int of_enter(void);
+
+
+typedef struct _of_exit_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ /*out*/
+} of_exit_service;
+
+int of_exit(void);
+
+
+typedef struct _of_chain_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ void *virt;
+ int size;
+ void *entry;
+ void *args;
+ int len;
+ /*out*/
+} of_chain_service;
+
+int of_chain(void *virt, int size, void *entry, void *args, int len);
+
+
+/* 6.3.2.6 User interface */
+
+
+typedef struct _of_interpret_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ const char *cmd;
+ int args[0];
+ /*...*/
+ /*out*/
+ /*...*/
+} of_interpret_service;
+
+int of_interpret(const char *arg, ...);
+
+
+typedef struct _of_set_callback_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ void *newfunc;
+ /*out*/
+ void *oldfunc;
+} of_set_callback_service;
+
+int of_set_callback(void *newfunc, void **oldfunc);
+
+
+typedef struct _of_set_symbol_lookup_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ void *sym_to_value;
+ void *value_to_sym;
+ /*out*/
+} of_set_symbol_lookup_service;
+
+int of_set_symbol_lookup(void *sym_to_value, void *value_to_sym);
+
+
+/* 6.3.2.7 Time */
+
+
+typedef struct _of_milliseconds_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in*/
+ /*out*/
+ int ms;
+} of_milliseconds_service;
+
+int of_milliseconds(int *ms);
diff --git a/arch/ppc/boot/piggyback.c b/arch/ppc/boot/piggyback.c
deleted file mode 100644
index ca9fc2957..000000000
--- a/arch/ppc/boot/piggyback.c
+++ /dev/null
@@ -1,64 +0,0 @@
-#include <stdio.h>
-
-extern long ce_exec_config[];
-
-main(int argc, char *argv[])
-{
- int i, cnt, pos, len;
- unsigned int cksum, val;
- unsigned char *lp;
- unsigned char buf[8192];
- if (argc != 1)
- {
- fprintf(stderr, "usage: %s <in-file >out-file\n", argv[0]);
- exit(1);
- }
- fprintf(stdout, "#\n");
- fprintf(stdout, "# Miscellaneous data structures:\n");
- fprintf(stdout, "# WARNING - this file is automatically generated!\n");
- fprintf(stdout, "#\n");
- fprintf(stdout, "\n");
- fprintf(stdout, "\t.data\n");
- fprintf(stdout, "\t.globl input_data\n");
- fprintf(stdout, "input_data:\n");
- pos = 0;
- cksum = 0;
- while ((len = read(0, buf, sizeof(buf))) > 0)
- {
- cnt = 0;
- lp = (unsigned char *)buf;
- len = (len + 3) & ~3; /* Round up to longwords */
- for (i = 0; i < len; i += 4)
- {
- if (cnt == 0)
- {
- fprintf(stdout, "\t.long\t");
- }
- fprintf(stdout, "0x%02X%02X%02X%02X", lp[0], lp[1], lp[2], lp[3]);
- val = *(unsigned long *)lp;
- cksum ^= val;
- lp += 4;
- if (++cnt == 4)
- {
- cnt = 0;
- fprintf(stdout, " # %x \n", pos+i-12);
- fflush(stdout);
- } else
- {
- fprintf(stdout, ",");
- }
- }
- if (cnt)
- {
- fprintf(stdout, "0\n");
- }
- pos += len;
- }
- fprintf(stdout, "\t.globl input_len\n");
- fprintf(stdout, "input_len:\t.long\t0x%x\n", pos);
- fflush(stdout);
- fclose(stdout);
- fprintf(stderr, "cksum = %x\n", cksum);
- exit(0);
-}
-
diff --git a/arch/ppc/chrp_defconfig b/arch/ppc/chrp_defconfig
index 9141b2d90..48e305f44 100644
--- a/arch/ppc/chrp_defconfig
+++ b/arch/ppc/chrp_defconfig
@@ -85,7 +85,6 @@ CONFIG_PARIDE_PARPORT=y
# CONFIG_PACKET is not set
# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
-CONFIG_NET_ALIAS=y
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
diff --git a/arch/ppc/chrpboot/Makefile b/arch/ppc/chrpboot/Makefile
index 946845a5d..cd0336bc9 100644
--- a/arch/ppc/chrpboot/Makefile
+++ b/arch/ppc/chrpboot/Makefile
@@ -28,6 +28,12 @@ ifeq ($(CONFIG_ALL_PPC),y)
CONFIG_CHRP = y
endif
+ifeq ($(CONFIG_SMP),y)
+TFTPIMAGE=/tftpboot/zImage.chrp.smp
+else
+TFTPIMAGE=/tftpboot/zImage.chrp
+endif
+
all: $(TOPDIR)/zImage
#
@@ -36,10 +42,10 @@ all: $(TOPDIR)/zImage
#
ifeq ($(CONFIG_CHRP),y)
znetboot: zImage
- cp zImage /tftpboot/zImage.chrp
+ cp zImage $(TFTPIMAGE)
znetboot.initrd: zImage.initrd
- cp zImage.initrd /tftpboot/zImage.chrp
+ cp zImage.initrd $(TFTPIMAGE)
floppy: zImage
mcopy zImage a:zImage
diff --git a/arch/ppc/coffboot/Makefile b/arch/ppc/coffboot/Makefile
index 4669d2228..9ca967785 100644
--- a/arch/ppc/coffboot/Makefile
+++ b/arch/ppc/coffboot/Makefile
@@ -23,6 +23,12 @@ ifeq ($(CONFIG_ALL_PPC),y)
CONFIG_PMAC = y
endif
+ifeq ($(CONFIG_SMP),y)
+TFTPIMAGE=/tftpboot/zImage.pmac.smp
+else
+TFTPIMAGE=/tftpboot/zImage.pmac
+endif
+
ifeq ($(CONFIG_PMAC),y)
hack-coff: hack-coff.c
$(HOSTCC) $(HOSTCFLAGS) -o hack-coff hack-coff.c
@@ -33,10 +39,10 @@ floppy: zImage
# umount /mnt
znetboot: vmlinux.coff
- cp vmlinux.coff /tftpboot/zImage.pmac
+ cp vmlinux.coff $(TFTPIMAGE)
znetboot.initrd: vmlinux.coff.initrd
- cp vmlinux.coff.initrd /tftpboot/zImage.pmac
+ cp vmlinux.coff.initrd $(TFTPIMAGE)
coffboot: $(OBJS) ld.script
$(LD) -o coffboot $(LD_ARGS) $(OBJS) $(LIBS)
diff --git a/arch/ppc/common_defconfig b/arch/ppc/common_defconfig
index f58965709..131244790 100644
--- a/arch/ppc/common_defconfig
+++ b/arch/ppc/common_defconfig
@@ -1,5 +1,5 @@
#
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
#
#
@@ -21,7 +21,7 @@ CONFIG_ALL_PPC=y
#
CONFIG_EXPERIMENTAL=y
CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
+# CONFIG_MODVERSIONS is not set
CONFIG_KMOD=y
CONFIG_PCI=y
# CONFIG_PCI_QUIRKS is not set
@@ -32,23 +32,23 @@ 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_VGA_CONSOLE is not set
+CONFIG_VGA_CONSOLE=y
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_SERIAL_CONSOLE is not set
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
+# CONFIG_MOTOROLA_HOTSWAP is not set
+# CONFIG_CMDLINE_BOOL is not set
#
# Plug and Play support
@@ -60,18 +60,28 @@ CONFIG_BOOTX_TEXT=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=y
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDE_PMAC=y
+# CONFIG_BLK_DEV_IDEDMA_PMAC is not set
# CONFIG_IDE_CHIPSETS is not set
-CONFIG_BLK_DEV_LOOP=m
+
+#
+# Additional Block Devices
+#
+CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_MD is not set
CONFIG_BLK_DEV_RAM=y
@@ -84,27 +94,36 @@ 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_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 is not set
# CONFIG_IP_ROUTER is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_RARP is not set
-# CONFIG_IP_NOSR is not set
+# CONFIG_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_SKB_LARGE=y
# CONFIG_IPV6 is not set
+
+#
+#
+#
# 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
@@ -124,13 +143,21 @@ CONFIG_SKB_LARGE=y
# SCSI support
#
CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_ST=y
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
-# CONFIG_CHR_DEV_SG is not set
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_CONSTANTS is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
#
@@ -141,7 +168,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
@@ -154,15 +184,20 @@ CONFIG_BLK_DEV_SR_VENDOR=y
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_G_NCR5380_PORT is not set
+# CONFIG_SCSI_G_NCR5380_MEM is not set
# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C416 is not set
# CONFIG_SCSI_NCR53C7xx is not set
CONFIG_SCSI_NCR53C8XX=y
+# CONFIG_SCSI_SYM53C8XX is not set
CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
-CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4
-CONFIG_SCSI_NCR53C8XX_SYNC=5
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
+CONFIG_SCSI_NCR53C8XX_SYNC=20
# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-CONFIG_SCSI_NCR53C8XX_IOMAPPED=y
+# 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
@@ -170,6 +205,7 @@ CONFIG_SCSI_NCR53C8XX_IOMAPPED=y
# CONFIG_SCSI_PSI240I is not set
# CONFIG_SCSI_QLOGIC_FAS is not set
# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_SEAGATE is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_T128 is not set
@@ -187,6 +223,7 @@ 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_MACE=y
CONFIG_BMAC=y
@@ -199,7 +236,7 @@ CONFIG_BMAC=y
# CONFIG_ACENIC is not set
# CONFIG_NET_ISA is not set
CONFIG_NET_EISA=y
-CONFIG_PCNET32=m
+CONFIG_PCNET32=y
# CONFIG_AC3200 is not set
# CONFIG_APRICOT is not set
# CONFIG_CS89x0 is not set
@@ -219,16 +256,21 @@ CONFIG_DE4X5=y
# 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
-CONFIG_SLIP=m
-# CONFIG_SLIP_COMPRESSED is not set
-# CONFIG_SLIP_SMART is not set
-# CONFIG_SLIP_MODE_SLIP6 is not set
+
+#
+# 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
# CONFIG_COSA is not set
+# CONFIG_RCPCI is not set
#
# Amateur Radio support
@@ -241,7 +283,7 @@ CONFIG_SLIP=m
# CONFIG_ISDN is not set
#
-# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
+# Old CD-ROM drivers (not SCSI, not IDE)
#
# CONFIG_CD_NO_IDESCSI is not set
@@ -249,27 +291,42 @@ CONFIG_SLIP=m
# Console drivers
#
CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_PM2 is not set
CONFIG_FB_OF=y
CONFIG_FB_CONTROL=y
CONFIG_FB_PLATINUM=y
CONFIG_FB_VALKYRIE=y
-CONFIG_FB_ATY=y
+# CONFIG_FB_ATY is not set
CONFIG_FB_IMSTT=y
CONFIG_FB_CT65550=y
# CONFIG_FB_S3TRIO is not set
-# CONFIG_FB_MATROX is not set
-CONFIG_FB_ATY=y
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G100=y
+# CONFIG_FB_MATROX_MULTIHEAD is not set
+# CONFIG_FB_ATY is not set
# CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_ADVANCED=y
+# CONFIG_FBCON_MFB is not set
+# CONFIG_FBCON_CFB2 is not set
+# CONFIG_FBCON_CFB4 is not set
CONFIG_FBCON_CFB8=y
CONFIG_FBCON_CFB16=y
CONFIG_FBCON_CFB24=y
CONFIG_FBCON_CFB32=y
+# CONFIG_FBCON_AFB is not set
+# CONFIG_FBCON_ILBM is not set
+# CONFIG_FBCON_IPLAN2P2 is not set
+# CONFIG_FBCON_IPLAN2P4 is not set
+# CONFIG_FBCON_IPLAN2P8 is not set
+# CONFIG_FBCON_MAC is not set
+# CONFIG_FBCON_VGA is not set
# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
CONFIG_FBCON_FONTS=y
-CONFIG_FONT_8x8=y
+# CONFIG_FONT_8x8 is not set
CONFIG_FONT_8x16=y
-# CONFIG_FONT_SUN8x16 is not set
+CONFIG_FONT_SUN8x16=y
CONFIG_FONT_SUN12x22=y
# CONFIG_FONT_6x11 is not set
# CONFIG_FONT_PEARL_8x8 is not set
@@ -283,7 +340,8 @@ CONFIG_VT_CONSOLE=y
CONFIG_SERIAL=m
# CONFIG_SERIAL_EXTENDED is not set
# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_UNIX98_PTYS is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
CONFIG_MOUSE=y
#
@@ -309,30 +367,40 @@ CONFIG_PSMOUSE=y
# Joystick support
#
# CONFIG_JOYSTICK is not set
+# CONFIG_DTLK is not set
#
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
+# CONFIG_FT_NORMAL_DEBUG is not set
+# CONFIG_FT_FULL_DEBUG is not set
+# CONFIG_FT_NO_TRACE is not set
+# CONFIG_FT_NO_TRACE_AT_ALL is not set
+# CONFIG_FT_STD_FDC is not set
+# CONFIG_FT_MACH2 is not set
+# CONFIG_FT_PROBE_FC10 is not set
+# CONFIG_FT_ALT_FDC is not set
#
# Filesystems
#
# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS_FS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
CONFIG_HFS_FS=y
CONFIG_FAT_FS=m
CONFIG_MSDOS_FS=m
# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_VFAT_FS=m
CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
+CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_EXT2_FS=y
@@ -344,7 +412,7 @@ CONFIG_EXT2_FS=y
#
# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
-CONFIG_NFSD=m
+CONFIG_NFSD=y
# CONFIG_NFSD_SUN is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
@@ -364,7 +432,7 @@ 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
@@ -402,30 +470,11 @@ CONFIG_DMASOUND=y
# 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_AD1816 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
+# CONFIG_SOUND_OSS is not set
#
-# Additional low level sound drivers
+# Kernel hacking
#
-# CONFIG_LOWLEVEL_SOUND is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_KGDB is not set
+# CONFIG_XMON is not set
diff --git a/arch/ppc/config.in b/arch/ppc/config.in
index b15e90afd..e10cc51bb 100644
--- a/arch/ppc/config.in
+++ b/arch/ppc/config.in
@@ -19,12 +19,10 @@ choice 'Machine Type' \
APUS CONFIG_APUS \
MBX CONFIG_MBX" PowerMac
+bool 'Symmetric multi-processing support' CONFIG_SMP
if [ "$CONFIG_ALL_PPC" != "y" ];then
define_bool CONFIG_MACH_SPECIFIC y
fi
-
-bool 'Symmetric multi-processing support' CONFIG_SMP
-
endmenu
if [ "$CONFIG_MBX" = "y" ];then
@@ -82,13 +80,20 @@ 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_MAC_SERIAL" = "y" ]; then
+ bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE
+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
+bool 'Support for Motorola Hot Swap' CONFIG_MOTOROLA_HOTSWAP
+if [ "$CONFIG_PREP" = "y" -o "$CONFIG_ALL_PPC" = "y" ]; then
+ bool 'PReP bootloader kernel arguments' CONFIG_CMDLINE_BOOL y
+ if [ "$CONFIG_CMDLINE_BOOL" = "y" ] ; then
+ string 'Initial kernel command string' CONFIG_CMDLINE console=ttyS0,9600 console=tty0 root=/dev/sda2
+ fi
+fi
if [ "$CONFIG_APUS" = "y" ]; then
define_bool CONFIG_FB_CONSOLE y
@@ -152,7 +157,7 @@ fi
endmenu
mainmenu_option next_comment
-comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
+comment 'Old CD-ROM drivers (not SCSI, not IDE)'
bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
@@ -172,8 +177,16 @@ mainmenu_option next_comment
comment 'Sound'
tristate 'Sound card support' CONFIG_SOUND
if [ "$CONFIG_SOUND" != "n" ]; then
- tristate 'Amiga or PowerMac DMA sound support' CONFIG_DMASOUND
+ dep_tristate 'Amiga or PowerMac DMA sound support' CONFIG_DMASOUND $CONFIG_SOUND
source drivers/sound/Config.in
fi
endmenu
+
+mainmenu_option next_comment
+comment 'Kernel hacking'
+
+bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'Include kgdb kernel debugger' CONFIG_KGDB
+bool 'Include xmon kernel debugger' CONFIG_XMON
+endmenu
diff --git a/arch/ppc/defconfig b/arch/ppc/defconfig
index 811d599c0..131244790 100644
--- a/arch/ppc/defconfig
+++ b/arch/ppc/defconfig
@@ -8,13 +8,12 @@
CONFIG_PPC=y
CONFIG_6xx=y
# CONFIG_8xx is not set
-CONFIG_PMAC=y
+# CONFIG_PMAC is not set
# CONFIG_PREP is not set
# CONFIG_CHRP is not set
-# CONFIG_ALL_PPC is not set
+CONFIG_ALL_PPC=y
# CONFIG_APUS is not set
# CONFIG_MBX is not set
-CONFIG_MACH_SPECIFIC=y
# CONFIG_SMP is not set
#
@@ -36,20 +35,20 @@ CONFIG_KERNEL_ELF=y
CONFIG_BINFMT_MISC=m
# CONFIG_BINFMT_JAVA is not set
# CONFIG_PARPORT is not set
-# CONFIG_VGA_CONSOLE is not set
+CONFIG_VGA_CONSOLE=y
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_SERIAL_CONSOLE is not set
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
+# CONFIG_MOTOROLA_HOTSWAP is not set
+# CONFIG_CMDLINE_BOOL is not set
#
# Plug and Play support
@@ -76,15 +75,13 @@ CONFIG_BLK_DEV_IDEFLOPPY=y
# 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_BLK_DEV_IDEDMA_PMAC is not set
# CONFIG_IDE_CHIPSETS is not set
#
# Additional Block Devices
#
-# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_MD is not set
CONFIG_BLK_DEV_RAM=y
@@ -102,7 +99,6 @@ CONFIG_NETLINK=y
# CONFIG_RTNETLINK is not set
# CONFIG_NETLINK_DEV is not set
# CONFIG_FIREWALL is not set
-CONFIG_NET_ALIAS=y
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
@@ -120,7 +116,6 @@ CONFIG_IP_ALIAS=y
# (it is safe to leave these untouched)
#
CONFIG_INET_RARP=y
-CONFIG_IP_NOSR=y
CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
@@ -156,12 +151,12 @@ CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=y
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
-# CONFIG_CHR_DEV_SG is not set
+CONFIG_CHR_DEV_SG=y
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
-# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
@@ -189,16 +184,28 @@ CONFIG_AIC7XXX_RESET_DELAY=15
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_G_NCR5380_PORT is not set
+# CONFIG_SCSI_G_NCR5380_MEM is not set
# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C416 is not set
# CONFIG_SCSI_NCR53C7xx is not set
-# CONFIG_SCSI_NCR53C8XX is not set
+CONFIG_SCSI_NCR53C8XX=y
+# CONFIG_SCSI_SYM53C8XX is not set
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
+CONFIG_SCSI_NCR53C8XX_SYNC=20
+# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
+# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_PCI2000 is not set
# CONFIG_SCSI_PCI2220I is not set
# CONFIG_SCSI_PSI240I is not set
# CONFIG_SCSI_QLOGIC_FAS is not set
# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_SEAGATE is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_T128 is not set
@@ -229,7 +236,7 @@ CONFIG_BMAC=y
# CONFIG_ACENIC is not set
# CONFIG_NET_ISA is not set
CONFIG_NET_EISA=y
-# CONFIG_PCNET32 is not set
+CONFIG_PCNET32=y
# CONFIG_AC3200 is not set
# CONFIG_APRICOT is not set
# CONFIG_CS89x0 is not set
@@ -263,6 +270,7 @@ CONFIG_PPP=y
# CONFIG_SHAPER is not set
# CONFIG_HOSTESS_SV11 is not set
# CONFIG_COSA is not set
+# CONFIG_RCPCI is not set
#
# Amateur Radio support
@@ -275,7 +283,7 @@ CONFIG_PPP=y
# CONFIG_ISDN is not set
#
-# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
+# Old CD-ROM drivers (not SCSI, not IDE)
#
# CONFIG_CD_NO_IDESCSI is not set
@@ -283,22 +291,37 @@ CONFIG_PPP=y
# Console drivers
#
CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_PM2 is not set
CONFIG_FB_OF=y
CONFIG_FB_CONTROL=y
CONFIG_FB_PLATINUM=y
CONFIG_FB_VALKYRIE=y
-CONFIG_FB_ATY=y
+# CONFIG_FB_ATY is not set
CONFIG_FB_IMSTT=y
CONFIG_FB_CT65550=y
# CONFIG_FB_S3TRIO is not set
-# CONFIG_FB_MATROX is not set
-CONFIG_FB_ATY=y
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G100=y
+# CONFIG_FB_MATROX_MULTIHEAD is not set
+# CONFIG_FB_ATY is not set
# CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_ADVANCED=y
+# CONFIG_FBCON_MFB is not set
+# CONFIG_FBCON_CFB2 is not set
+# CONFIG_FBCON_CFB4 is not set
CONFIG_FBCON_CFB8=y
CONFIG_FBCON_CFB16=y
CONFIG_FBCON_CFB24=y
CONFIG_FBCON_CFB32=y
+# CONFIG_FBCON_AFB is not set
+# CONFIG_FBCON_ILBM is not set
+# CONFIG_FBCON_IPLAN2P2 is not set
+# CONFIG_FBCON_IPLAN2P4 is not set
+# CONFIG_FBCON_IPLAN2P8 is not set
+# CONFIG_FBCON_MAC is not set
+# CONFIG_FBCON_VGA is not set
# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
CONFIG_FBCON_FONTS=y
# CONFIG_FONT_8x8 is not set
@@ -314,15 +337,25 @@ CONFIG_FONT_SUN12x22=y
#
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_MOUSE=y
+
+#
+# Mice
+#
+# 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_QIC02_TAPE is not set
# CONFIG_WATCHDOG is not set
-CONFIG_NVRAM=y
+# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
#
@@ -334,11 +367,20 @@ CONFIG_NVRAM=y
# Joystick support
#
# CONFIG_JOYSTICK is not set
+# CONFIG_DTLK is not set
#
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
+# CONFIG_FT_NORMAL_DEBUG is not set
+# CONFIG_FT_FULL_DEBUG is not set
+# CONFIG_FT_NO_TRACE is not set
+# CONFIG_FT_NO_TRACE_AT_ALL is not set
+# CONFIG_FT_STD_FDC is not set
+# CONFIG_FT_MACH2 is not set
+# CONFIG_FT_PROBE_FC10 is not set
+# CONFIG_FT_ALT_FDC is not set
#
# Filesystems
@@ -429,3 +471,10 @@ CONFIG_DMASOUND=y
# CONFIG_SOUND_MSNDCLAS is not set
# CONFIG_SOUND_MSNDPIN is not set
# CONFIG_SOUND_OSS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_KGDB is not set
+# CONFIG_XMON is not set
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index d047c2086..5c8b44a90 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -27,7 +27,7 @@ O_OBJS += totalmp.o
endif
ifeq ($(CONFIG_MBX),y)
-O_OBJS += mbx_setup.o mbx_pci.o softemu8xx.o
+O_OBJS += mbx_setup.o mbx_pci.o softemu8xx.o i8259.o ppc8xx_pic.o
else
ifeq ($(CONFIG_APUS),y)
O_OBJS += apus_setup.o prom.o openpic.o
@@ -36,7 +36,8 @@ ifneq ($(CONFIG_MBX),y)
O_OBJS += prep_time.o pmac_time.o chrp_time.o \
pmac_setup.o pmac_support.o \
prep_pci.o pmac_pci.o chrp_pci.o \
- residual.o prom.o openpic.o feature.o
+ residual.o prom.o openpic.o feature.o \
+ prep_nvram.o open_pic.o i8259.o pmac_pic.o indirect_pci.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 83ee7756d..cf5fcffd3 100644
--- a/arch/ppc/kernel/align.c
+++ b/arch/ppc/kernel/align.c
@@ -194,13 +194,8 @@ fix_alignment(struct pt_regs *regs)
return -EFAULT; /* bad address */
}
-#ifdef __SMP__
- if ((flags & F) && (regs->msr & MSR_FP) )
- smp_giveup_fpu(current);
-#else
- if ((flags & F) && last_task_used_math == current)
- giveup_fpu();
-#endif
+ if ((flags & F) && (regs->msr & MSR_FP))
+ giveup_fpu(current);
if (flags & M)
return 0; /* too hard for now */
@@ -254,27 +249,16 @@ fix_alignment(struct pt_regs *regs)
data.d = current->tss.fpr[reg];
break;
/* these require some floating point conversions... */
- /* note that giveup_fpu enables the FPU for the kernel */
/* we'd like to use the assignment, but we have to compile
* the kernel with -msoft-float so it doesn't use the
* fp regs for copying 8-byte objects. */
case LD+F+S:
-#ifdef __SMP__
- if (regs->msr & MSR_FP )
- smp_giveup_fpu(current);
-#else
- giveup_fpu();
-#endif
+ enable_kernel_fp();
cvt_fd(&data.f, &current->tss.fpr[reg], &current->tss.fpscr);
/* current->tss.fpr[reg] = data.f; */
break;
case ST+F+S:
-#ifdef __SMP__
- if (regs->msr & MSR_FP )
- smp_giveup_fpu(current);
-#else
- giveup_fpu();
-#endif
+ enable_kernel_fp();
cvt_df(&current->tss.fpr[reg], &data.f, &current->tss.fpscr);
/* data.f = current->tss.fpr[reg]; */
break;
diff --git a/arch/ppc/kernel/apus_setup.c b/arch/ppc/kernel/apus_setup.c
index c3a81ad3e..55e57fc5b 100644
--- a/arch/ppc/kernel/apus_setup.c
+++ b/arch/ppc/kernel/apus_setup.c
@@ -14,12 +14,50 @@
#include <linux/sched.h>
#include <linux/kd.h>
#include <linux/init.h>
+#include <linux/hdreg.h>
+
+/* Get the IDE stuff from the 68k file */
+#define ide_init_hwif_ports m68k_ide_init_hwif_ports
+#define ide_default_irq m68k_ide_default_irq
+#define ide_default_io_base m68k_ide_default_io_base
+#define ide_check_region m68k_ide_check_region
+#define ide_request_region m68k_ide_request_region
+#define ide_release_region m68k_ide_release_region
+#define ide_fix_driveid m68k_ide_fix_driveid
+#include <asm-m68k/ide.h>
+#undef ide_init_hwif_ports
+#define ide_default_irq
+#define ide_default_io_base
+#define ide_check_region
+#define ide_request_region
+#define ide_release_region
+#define ide_fix_driveid
+
#include <asm/setup.h>
#include <asm/amigahw.h>
#include <asm/amigappc.h>
#include <asm/pgtable.h>
#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ide.h>
+
+#include "time.h"
+#include "local_irq.h"
+
+unsigned long apus_get_rtc_time(void);
+int apus_set_rtc_time(unsigned long nowtime);
+
+/* APUS defs */
+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 */
unsigned long m68k_machtype;
char debug_device[6] = "";
@@ -72,6 +110,8 @@ __initfunc(void apus_setup_arch(unsigned long * memory_start_p,
int i;
char *p, *q;
+ m68k_machtype = MACH_AMIGA;
+
/* Parse the command line for arch-specific options.
* For the m68k, this is currently only "debug=xxx" to enable printing
* certain kernel messages to some machine-specific device. */
@@ -409,3 +449,194 @@ void cache_clear(__u32 addr, int length)
"isync \n\t"
: : "r" (addr));
}
+
+void
+apus_restart(char *cmd)
+{
+ cli();
+
+ APUS_WRITE(APUS_REG_LOCK,
+ REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK2);
+ APUS_WRITE(APUS_REG_LOCK,
+ REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK3);
+ APUS_WRITE(APUS_REG_LOCK,
+ REGLOCK_BLACKMAGICK2|REGLOCK_BLACKMAGICK3);
+ APUS_WRITE(APUS_REG_SHADOW, REGSHADOW_SELFRESET);
+ APUS_WRITE(APUS_REG_RESET, REGRESET_AMIGARESET);
+ for(;;);
+}
+
+void
+apus_power_off(void)
+{
+ for (;;);
+}
+
+void
+apus_halt(void)
+{
+ apus_restart(NULL);
+}
+
+void
+apus_do_IRQ(struct pt_regs *regs,
+ int cpu,
+ int isfake)
+{
+ int old_level, new_level;
+
+ /* I don't think we need SMP code here - Corey */
+
+ old_level = ~(regs->mq) & IPLEMU_IPLMASK;
+ new_level = (~(regs->mq) >> 3) & IPLEMU_IPLMASK;
+ if (new_level != 0)
+ {
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_IPLMASK);
+ APUS_WRITE(APUS_IPL_EMU, (IPLEMU_SETRESET
+ | (~(new_level) & IPLEMU_IPLMASK)));
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT);
+
+ process_int (VEC_SPUR+new_level, regs);
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_DISABLEINT);
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_IPLMASK);
+ APUS_WRITE(APUS_IPL_EMU, (IPLEMU_SETRESET
+ | (~(old_level) & IPLEMU_IPLMASK)));
+ }
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT);
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */
+void
+apus_ide_insw(ide_ioreg_t port, void *buf, int ns)
+{
+ ide_insw(port, buf, ns);
+}
+
+void
+apus_ide_outsw(ide_ioreg_t port, void *buf, int ns)
+{
+ ide_outsw(port, buf, ns);
+}
+
+int
+apus_ide_default_irq(ide_ioreg_t base)
+{
+ m68k_ide_default_irq(base);
+}
+
+ide_ioreg_t
+apus_ide_default_io_base(int index)
+{
+ m68k_ide_default_io_base(index);
+}
+
+int
+apus_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+ return m68k_ide_check_region(from, extent);
+}
+
+void
+apus_ide_request_region(ide_ioreg_t from,
+ unsigned int extent,
+ const char *name)
+{
+ m68k_ide_request_region(from, extent, name);
+}
+
+void
+apus_ide_release_region(ide_ioreg_t from,
+ unsigned int extent)
+{
+ m68k_ide_release_region(from, extent);
+}
+
+void
+apus_ide_fix_driveid(struct hd_driveid *id)
+{
+ m68k_ide_fix_driveid(id);
+}
+
+__initfunc(void
+apus_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq))
+{
+ m68k_ide_init_hwif_ports(p, base, irq);
+}
+#endif
+
+__initfunc(void
+apus_local_init_IRQ(void))
+{
+ ppc_md.mask_irq = amiga_disable_irq;
+ ppc_md.unmask_irq = amiga_enable_irq;
+ apus_init_IRQ();
+}
+
+__initfunc(void
+apus_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7))
+{
+ /* Parse bootinfo. The bootinfo is located right after
+ the kernel bss */
+ parse_bootinfo((const struct bi_record *)&_end);
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* Take care of initrd if we have one. Use data from
+ bootinfo to avoid the need to initialize PPC
+ registers when kernel is booted via a PPC reset. */
+ if ( ramdisk.addr ) {
+ initrd_start = (unsigned long) __va(ramdisk.addr);
+ initrd_end = (unsigned long)
+ __va(ramdisk.size + ramdisk.addr);
+ }
+ /* Make sure code below is not executed. */
+ r4 = 0;
+ r6 = 0;
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ ISA_DMA_THRESHOLD = 0x00ffffff;
+
+ ppc_md.setup_arch = apus_setup_arch;
+ ppc_md.setup_residual = NULL;
+ ppc_md.get_cpuinfo = apus_get_cpuinfo;
+ ppc_md.irq_cannonicalize = NULL;
+ ppc_md.init_IRQ = apus_init_IRQ;
+ ppc_md.do_IRQ = apus_do_IRQ;
+ ppc_md.get_irq_source = NULL;
+ ppc_md.init = NULL;
+
+ ppc_md.restart = apus_restart;
+ ppc_md.power_off = apus_power_off;
+ ppc_md.halt = apus_halt;
+
+ ppc_md.time_init = NULL;
+ ppc_md.set_rtc_time = apus_set_rtc_time;
+ ppc_md.get_rtc_time = apus_get_rtc_time;
+ ppc_md.calibrate_decr = apus_calibrate_decr;
+
+ /* These should not be used for the APUS yet, since it uses
+ the M68K keyboard now. */
+ ppc_md.kbd_setkeycode = NULL;
+ ppc_md.kbd_getkeycode = NULL;
+ ppc_md.kbd_translate = NULL;
+ ppc_md.kbd_unexpected_up = NULL;
+ ppc_md.kbd_leds = NULL;
+ ppc_md.kbd_init_hw = NULL;
+ ppc_md.kbd_sysrq_xlate = NULL;
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ ppc_ide_md.insw = apus_ide_insw;
+ ppc_ide_md.outsw = apus_ide_outsw;
+ ppc_ide_md.default_irq = apus_ide_default_irq;
+ ppc_ide_md.default_io_base = apus_ide_default_io_base;
+ ppc_ide_md.check_region = apus_ide_check_region;
+ ppc_ide_md.request_region = apus_ide_request_region;
+ ppc_ide_md.release_region = apus_ide_release_region;
+ ppc_ide_md.fix_driveid = apus_ide_fix_driveid;
+ ppc_ide_md.ide_init_hwif = apus_ide_init_hwif_ports;
+
+ ppc_ide_md.io_base = _IO_BASE;
+#endif
+}
diff --git a/arch/ppc/kernel/chrp_pci.c b/arch/ppc/kernel/chrp_pci.c
index 98a3e182e..fa4dda10b 100644
--- a/arch/ppc/kernel/chrp_pci.c
+++ b/arch/ppc/kernel/chrp_pci.c
@@ -15,10 +15,14 @@
#include <asm/hydra.h>
#include <asm/prom.h>
#include <asm/gg2.h>
+#include <asm/ide.h>
+#include <asm/machdep.h>
+
+#include "pci.h"
/* LongTrail */
#define pci_config_addr(bus, dev, offset) \
- (GG2_PCI_CONFIG_BASE | ((bus)<<16) | ((dev)<<8) | (offset))
+(GG2_PCI_CONFIG_BASE | ((bus)<<16) | ((dev)<<8) | (offset))
volatile struct Hydra *Hydra = NULL;
@@ -30,144 +34,136 @@ volatile struct Hydra *Hydra = NULL;
int gg2_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned char *val)
{
- if (bus > 7) {
- *val = 0xff;
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
- *val = in_8((unsigned char *)pci_config_addr(bus, dev_fn, offset));
- return PCIBIOS_SUCCESSFUL;
+ if (bus > 7) {
+ *val = 0xff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ *val = in_8((unsigned char *)pci_config_addr(bus, dev_fn, offset));
+ return PCIBIOS_SUCCESSFUL;
}
int gg2_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned short *val)
{
- if (bus > 7) {
- *val = 0xffff;
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
- *val = in_le16((unsigned short *)pci_config_addr(bus, dev_fn, offset));
- return PCIBIOS_SUCCESSFUL;
+ if (bus > 7) {
+ *val = 0xffff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ *val = in_le16((unsigned short *)pci_config_addr(bus, dev_fn, offset));
+ return PCIBIOS_SUCCESSFUL;
}
int gg2_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned int *val)
{
- if (bus > 7) {
- *val = 0xffffffff;
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
- *val = in_le32((unsigned int *)pci_config_addr(bus, dev_fn, offset));
- return PCIBIOS_SUCCESSFUL;
+ if (bus > 7) {
+ *val = 0xffffffff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ *val = in_le32((unsigned int *)pci_config_addr(bus, dev_fn, offset));
+ return PCIBIOS_SUCCESSFUL;
}
int gg2_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned char val)
{
- if (bus > 7)
- return PCIBIOS_DEVICE_NOT_FOUND;
- out_8((unsigned char *)pci_config_addr(bus, dev_fn, offset), val);
- return PCIBIOS_SUCCESSFUL;
+ if (bus > 7)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ out_8((unsigned char *)pci_config_addr(bus, dev_fn, offset), val);
+ return PCIBIOS_SUCCESSFUL;
}
int gg2_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned short val)
{
- if (bus > 7)
- return PCIBIOS_DEVICE_NOT_FOUND;
- out_le16((unsigned short *)pci_config_addr(bus, dev_fn, offset), val);
- return PCIBIOS_SUCCESSFUL;
+ if (bus > 7)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ out_le16((unsigned short *)pci_config_addr(bus, dev_fn, offset), val);
+ return PCIBIOS_SUCCESSFUL;
}
int gg2_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned int val)
{
- if (bus > 7)
- return PCIBIOS_DEVICE_NOT_FOUND;
- out_le32((unsigned int *)pci_config_addr(bus, dev_fn, offset), val);
- return PCIBIOS_SUCCESSFUL;
+ if (bus > 7)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ out_le32((unsigned int *)pci_config_addr(bus, dev_fn, offset), val);
+ return PCIBIOS_SUCCESSFUL;
}
-extern volatile unsigned int *pci_config_address;
-extern volatile unsigned char *pci_config_data;
-
-#define DEV_FN_MAX (31<<3)
+#define python_config_address(bus) (unsigned *)((0xfef00000+0xf8000)-(bus*0x100000))
+#define python_config_data(bus) ((0xfef00000+0xf8010)-(bus*0x100000))
+#define PYTHON_CFA(b, d, o) (0x80 | ((b<<6) << 8) | ((d) << 16) \
+ | (((o) & ~3) << 24))
+unsigned int python_busnr = 1;
-int raven_pcibios_read_config_byte(unsigned char bus,
- unsigned char dev_fn,
- unsigned char offset,
- unsigned char *val)
+int python_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned char *val)
{
- if (dev_fn >= DEV_FN_MAX) return PCIBIOS_DEVICE_NOT_FOUND;
- out_be32(pci_config_address,
- 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24));
- *val = in_8(pci_config_data+(offset&3));
- return PCIBIOS_SUCCESSFUL;
+ if (bus > python_busnr) {
+ *val = 0xff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
+ *val = in_8((unsigned char *)python_config_data(bus) + (offset&3));
+ return PCIBIOS_SUCCESSFUL;
}
-int raven_pcibios_read_config_word(unsigned char bus,
- unsigned char dev_fn,
- unsigned char offset,
- unsigned short *val)
+int python_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned short *val)
{
- if (dev_fn >= DEV_FN_MAX) return PCIBIOS_DEVICE_NOT_FOUND;
- if (offset&1)return PCIBIOS_BAD_REGISTER_NUMBER;
- out_be32(pci_config_address,
- 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24));
- *val = in_le16((volatile unsigned short *)
- (pci_config_data+(offset&3)));
- return PCIBIOS_SUCCESSFUL;
+ if (bus > python_busnr) {
+ *val = 0xffff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
+ *val = in_le16((unsigned short *)(python_config_data(bus) + (offset&3)));
+ return PCIBIOS_SUCCESSFUL;
}
-int raven_pcibios_read_config_dword(unsigned char bus,
- unsigned char dev_fn,
- unsigned char offset,
- unsigned int *val)
+
+int python_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned int *val)
{
- if (dev_fn >= DEV_FN_MAX) return PCIBIOS_DEVICE_NOT_FOUND;
- if (offset&3)return PCIBIOS_BAD_REGISTER_NUMBER;
- out_be32(pci_config_address,
- 0x80|(bus<<8)|(dev_fn<<16)|(offset<<24));
- *val = in_le32((volatile unsigned int *)(pci_config_data));
- return PCIBIOS_SUCCESSFUL;
+ if (bus > python_busnr) {
+ *val = 0xffffffff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
+ *val = in_le32((unsigned *)python_config_data(bus));
+ return PCIBIOS_SUCCESSFUL;
}
-int raven_pcibios_write_config_byte(unsigned char bus,
- unsigned char dev_fn,
- unsigned char offset,
- unsigned char val)
+int python_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned char val)
{
- if (dev_fn >= DEV_FN_MAX) return PCIBIOS_DEVICE_NOT_FOUND;
- out_be32(pci_config_address,
- 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24));
- out_8(pci_config_data+(offset&3),val);
- return PCIBIOS_SUCCESSFUL;
+ if (bus > python_busnr)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
+ out_8((volatile unsigned char *)python_config_data(bus) + (offset&3), val);
+ return PCIBIOS_SUCCESSFUL;
}
-int raven_pcibios_write_config_word(unsigned char bus,
- unsigned char dev_fn,
- unsigned char offset,
- unsigned short val)
+int python_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned short val)
{
- if (dev_fn >= DEV_FN_MAX) return PCIBIOS_DEVICE_NOT_FOUND;
- if (offset&1)return PCIBIOS_BAD_REGISTER_NUMBER;
- out_be32(pci_config_address,
- 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24));
- out_le16((volatile unsigned short *)(pci_config_data+(offset&3)),val);
- return PCIBIOS_SUCCESSFUL;
+ if (bus > python_busnr)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
+ out_le16((volatile unsigned short *)python_config_data(bus) + (offset&3),
+ val);
+ return PCIBIOS_SUCCESSFUL;
}
-int raven_pcibios_write_config_dword(unsigned char bus,
- unsigned char dev_fn,
- unsigned char offset,
- unsigned int val)
+int python_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned int val)
{
- if (dev_fn >= DEV_FN_MAX) return PCIBIOS_DEVICE_NOT_FOUND;
- if (offset&3)return PCIBIOS_BAD_REGISTER_NUMBER;
- out_be32(pci_config_address,
- 0x80|(bus<<8)|(dev_fn<<16)|(offset<<24));
- out_le32((volatile unsigned int *)pci_config_data,val);
- return PCIBIOS_SUCCESSFUL;
+ if (bus > python_busnr)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
+ out_le32((unsigned *)python_config_data(bus) + (offset&3), val);
+ return PCIBIOS_SUCCESSFUL;
}
/*
@@ -191,7 +187,8 @@ static u_char hydra_openpic_initsenses[] __initdata = {
/* all others are 1 (= default) */
};
-__initfunc(int hydra_init(void))
+int __init
+hydra_init(void)
{
struct device_node *np;
@@ -216,75 +213,95 @@ __initfunc(int hydra_init(void))
return 1;
}
-
-extern int chrp_ide_irq;
-
-__initfunc(int w83c553f_init(void))
+void __init
+chrp_pcibios_fixup(void)
{
- u_char bus, dev;
-#if 0
- unsigned char t8;
- unsigned short t16;
-#endif
- unsigned int t32;
- struct pci_dev *pdev;
- if ((pdev = pci_find_device(PCI_VENDOR_ID_WINBOND,
- PCI_DEVICE_ID_WINBOND_83C553, NULL))) {
- bus = pdev->bus->number;
- dev = pdev->devfn + 1;
- pcibios_read_config_dword(bus, dev, PCI_VENDOR_ID, &t32);
- if (t32 == (PCI_DEVICE_ID_WINBOND_82C105<<16) + PCI_VENDOR_ID_WINBOND) {
-#if 0
- printk("Enabling SL82C105 IDE on W83C553F\n");
- /*
- * FIXME: this doesn't help :-(
- */
-
- /* I/O mapping */
- pcibios_read_config_word(bus, dev, PCI_COMMAND, &t16);
- t16 |= PCI_COMMAND_IO;
- pcibios_write_config_word(bus, dev, PCI_COMMAND, t16);
-
- /* Standard IDE registers */
- pcibios_write_config_dword(bus, dev, PCI_BASE_ADDRESS_0,
- 0xffffffff);
- pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_0, &t32);
- pcibios_write_config_dword(bus, dev, PCI_BASE_ADDRESS_0,
- 0x000001f0 | 1);
- pcibios_write_config_dword(bus, dev, PCI_BASE_ADDRESS_1,
- 0xffffffff);
- pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_1, &t32);
- pcibios_write_config_dword(bus, dev, PCI_BASE_ADDRESS_1,
- 0x000003f4 | 1);
- pcibios_write_config_dword(bus, dev, PCI_BASE_ADDRESS_2,
- 0xffffffff);
- pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_2, &t32);
- pcibios_write_config_dword(bus, dev, PCI_BASE_ADDRESS_2,
- 0x00000170 | 1);
- pcibios_write_config_dword(bus, dev, PCI_BASE_ADDRESS_3,
- 0xffffffff);
- pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_3, &t32);
- pcibios_write_config_dword(bus, dev, PCI_BASE_ADDRESS_3,
- 0x00000374 | 1);
+ struct pci_dev *dev;
+
+ /* some of IBM chrps have > 1 bus */
+ if ( !strncmp("IBM", get_property(find_path_device("/"),
+ "name", NULL),3) )
+ {
+ pci_scan_peer_bridge(1);
+ pci_scan_peer_bridge(2);
+ }
+
+ /* PCI interrupts are controlled by the OpenPIC */
+ for( dev=pci_devices ; dev; dev=dev->next )
+ {
+ if ( dev->irq )
+ dev->irq = openpic_to_irq( dev->irq );
+ /* adjust the io_port for the NCR cards for busses other than 0 -- Cort */
+ if ( (dev->bus->number > 0) && (dev->vendor == PCI_VENDOR_ID_NCR) )
+ dev->base_address[0] += (dev->bus->number*0x08000000);
+ /* these need to be absolute addrs for OF and Matrox FB -- Cort */
+ if ( dev->vendor == PCI_VENDOR_ID_MATROX )
+ {
+ if ( dev->base_address[0] < isa_mem_base )
+ dev->base_address[0] += isa_mem_base;
+ if ( dev->base_address[1] < isa_mem_base )
+ dev->base_address[1] += isa_mem_base;
+ }
+ /* the F50 identifies the amd as a trident */
+ if ( (dev->vendor == PCI_VENDOR_ID_TRIDENT) &&
+ (dev->class == PCI_CLASS_NETWORK_ETHERNET) )
+ {
+ dev->vendor = PCI_VENDOR_ID_AMD;
+ pcibios_write_config_word(dev->bus->number, dev->devfn,
+ PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
+ }
+ }
+}
- /* IDE Bus Master Control */
- pcibios_write_config_dword(bus, dev, PCI_BASE_ADDRESS_4,
- 0xffffffff);
- pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_4, &t32);
- pcibios_write_config_dword(bus, dev, PCI_BASE_ADDRESS_4,
- 0x1000 | 1);
- pcibios_write_config_dword(bus, dev, PCI_BASE_ADDRESS_5,
- 0xffffffff);
- pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_5, &t32);
- pcibios_write_config_dword(bus, dev, PCI_BASE_ADDRESS_5,
- 0x1010 | 1);
+decl_config_access_method(grackle);
+decl_config_access_method(indirect);
- /* IDE Interrupt */
- pcibios_read_config_byte(bus, dev, PCI_INTERRUPT_LINE, &t8);
- chrp_ide_irq = t8;
-#endif
- return 1;
- }
- }
- return 0;
+void __init
+chrp_setup_pci_ptrs(void)
+{
+ struct device_node *py;
+
+ if ( !strncmp("MOT",
+ get_property(find_path_device("/"), "model", NULL),3) )
+ {
+ pci_dram_offset = 0;
+ isa_mem_base = 0xf7000000;
+ isa_io_base = 0xfe000000;
+ set_config_access_method(grackle);
+ }
+ else
+ {
+ if ( (py = find_compatible_devices( "pci", "IBM,python" )) )
+ {
+ /* find out how many pythons */
+ while ( (py = py->next) ) python_busnr++;
+ set_config_access_method(python);
+ /*
+ * We base these values on the machine type but should
+ * try to read them from the python controller itself.
+ * -- Cort
+ */
+ if ( !strncmp("IBM,7025-F50", get_property(find_path_device("/"), "name", NULL),12) )
+ {
+ pci_dram_offset = 0x80000000;
+ isa_mem_base = 0xa0000000;
+ isa_io_base = 0x88000000;
+ } else if ( !strncmp("IBM,7043-260",
+ get_property(find_path_device("/"), "name", NULL),12) )
+ {
+ pci_dram_offset = 0x80000000;
+ isa_mem_base = 0xc0000000;
+ isa_io_base = 0xf8000000;
+ }
+ }
+ else
+ {
+ pci_dram_offset = 0;
+ isa_mem_base = 0xf7000000;
+ isa_io_base = 0xf8000000;
+ set_config_access_method(gg2);
+ }
+ }
+
+ ppc_md.pcibios_fixup = chrp_pcibios_fixup;
}
diff --git a/arch/ppc/kernel/chrp_setup.c b/arch/ppc/kernel/chrp_setup.c
index 5b373c876..2c652f049 100644
--- a/arch/ppc/kernel/chrp_setup.c
+++ b/arch/ppc/kernel/chrp_setup.c
@@ -31,6 +31,7 @@
#include <linux/ioport.h>
#include <linux/console.h>
#include <linux/pci.h>
+#include <linux/openpic.h>
#include <asm/mmu.h>
#include <asm/processor.h>
@@ -40,9 +41,50 @@
#include <asm/prom.h>
#include <asm/gg2.h>
#include <asm/pci-bridge.h>
-
-extern void hydra_init(void);
-extern void w83c553f_init(void);
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/adb.h>
+#include <asm/hydra.h>
+
+#include "time.h"
+#include "local_irq.h"
+#include "i8259.h"
+#include "open_pic.h"
+
+/* Fixme - need to move these into their own .c and .h file */
+extern void i8259_mask_and_ack_irq(unsigned int irq_nr);
+extern void i8259_set_irq_mask(unsigned int irq_nr);
+extern void i8259_mask_irq(unsigned int irq_nr);
+extern void i8259_unmask_irq(unsigned int irq_nr);
+extern void i8259_init(void);
+
+/* Fixme - remove this when it is fixed. - Corey */
+extern volatile unsigned char *chrp_int_ack_special;
+
+unsigned long chrp_get_rtc_time(void);
+int chrp_set_rtc_time(unsigned long nowtime);
+void chrp_calibrate_decr(void);
+void chrp_time_init(void);
+
+void chrp_setup_pci_ptrs(void);
+
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);
+extern unsigned char pckbd_sysrq_xlate[128];
+extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int mackbd_getkeycode(unsigned int scancode);
+extern int mackbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode);
+extern char mackbd_unexpected_up(unsigned char keycode);
+extern void mackbd_leds(unsigned char leds);
+extern void mackbd_init_hw(void);
+extern unsigned char mackbd_sysrq_xlate[128];
/* for the mac fs */
kdev_t boot_dev;
@@ -53,7 +95,6 @@ extern int probingmem;
extern unsigned long loops_per_sec;
unsigned long empty_zero_page[1024];
-extern unsigned char aux_device_present;
#ifdef CONFIG_BLK_DEV_RAM
extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
@@ -62,17 +103,17 @@ extern int rd_image_start; /* starting block # of image */
#endif
static const char *gg2_memtypes[4] = {
- "FPM", "SDRAM", "EDO", "BEDO"
+ "FPM", "SDRAM", "EDO", "BEDO"
};
static const char *gg2_cachesizes[4] = {
- "256 KB", "512 KB", "1 MB", "Reserved"
+ "256 KB", "512 KB", "1 MB", "Reserved"
};
static const char *gg2_cachetypes[4] = {
- "Asynchronous", "Reserved", "Flow-Through Synchronous",
- "Pipelined Synchronous"
+ "Asynchronous", "Reserved", "Flow-Through Synchronous",
+ "Pipelined Synchronous"
};
static const char *gg2_cachemodes[4] = {
- "Disabled", "Write-Through", "Copy-Back", "Transparent Mode"
+ "Disabled", "Write-Through", "Copy-Back", "Transparent Mode"
};
int
@@ -85,53 +126,60 @@ chrp_get_cpuinfo(char *buffer)
root = find_path_device("/");
if (root)
- model = get_property(root, "model", NULL);
+ model = get_property(root, "model", NULL);
len = sprintf(buffer,"machine\t\t: CHRP %s\n", model);
- /* VLSI VAS96011/12 `Golden Gate 2' */
- /* Memory banks */
- sdramen = (in_le32((unsigned *)(GG2_PCI_CONFIG_BASE+GG2_PCI_DRAM_CTRL))
- >>31) & 1;
- for (i = 0; i < (sdramen ? 4 : 6); i++) {
- t = in_le32((unsigned *)(GG2_PCI_CONFIG_BASE+GG2_PCI_DRAM_BANK0+
- i*4));
- if (!(t & 1))
- continue;
- switch ((t>>8) & 0x1f) {
- case 0x1f:
- model = "4 MB";
- break;
- case 0x1e:
- model = "8 MB";
- break;
- case 0x1c:
- model = "16 MB";
- break;
- case 0x18:
- model = "32 MB";
- break;
- case 0x10:
- model = "64 MB";
- break;
- case 0x00:
- model = "128 MB";
- break;
- default:
- model = "Reserved";
- break;
- }
- len += sprintf(buffer+len, "memory bank %d\t: %s %s\n", i, model,
- gg2_memtypes[sdramen ? 1 : ((t>>1) & 3)]);
+ /* longtrail (goldengate) stuff */
+ if ( !strncmp( model, "IBM,LongTrail", 9 ) )
+ {
+ /* VLSI VAS96011/12 `Golden Gate 2' */
+ /* Memory banks */
+ sdramen = (in_le32((unsigned *)(GG2_PCI_CONFIG_BASE+
+ GG2_PCI_DRAM_CTRL))
+ >>31) & 1;
+ for (i = 0; i < (sdramen ? 4 : 6); i++) {
+ t = in_le32((unsigned *)(GG2_PCI_CONFIG_BASE+
+ GG2_PCI_DRAM_BANK0+
+ i*4));
+ if (!(t & 1))
+ continue;
+ switch ((t>>8) & 0x1f) {
+ case 0x1f:
+ model = "4 MB";
+ break;
+ case 0x1e:
+ model = "8 MB";
+ break;
+ case 0x1c:
+ model = "16 MB";
+ break;
+ case 0x18:
+ model = "32 MB";
+ break;
+ case 0x10:
+ model = "64 MB";
+ break;
+ case 0x00:
+ model = "128 MB";
+ break;
+ default:
+ model = "Reserved";
+ break;
+ }
+ len += sprintf(buffer+len, "memory bank %d\t: %s %s\n", i, model,
+ gg2_memtypes[sdramen ? 1 : ((t>>1) & 3)]);
+ }
+ /* L2 cache */
+ t = in_le32((unsigned *)(GG2_PCI_CONFIG_BASE+GG2_PCI_CC_CTRL));
+ len += sprintf(buffer+len, "board l2\t: %s %s (%s)\n",
+ gg2_cachesizes[(t>>7) & 3],
+ gg2_cachetypes[(t>>2) & 3],
+ gg2_cachemodes[t & 3]);
}
- /* L2 cache */
- t = in_le32((unsigned *)(GG2_PCI_CONFIG_BASE+GG2_PCI_CC_CTRL));
- len += sprintf(buffer+len, "board l2\t: %s %s (%s)\n",
- gg2_cachesizes[(t>>7) & 3], gg2_cachetypes[(t>>2) & 3],
- gg2_cachemodes[t & 3]);
return len;
}
- /*
+/*
* Fixes for the National Semiconductor PC78308VUL SuperI/O
*
* Some versions of Open Firmware incorrectly initialize the IRQ settings
@@ -140,57 +188,55 @@ chrp_get_cpuinfo(char *buffer)
__initfunc(static inline void sio_write(u8 val, u8 index))
{
- outb(index, 0x15c);
- outb(val, 0x15d);
+ outb(index, 0x15c);
+ outb(val, 0x15d);
}
__initfunc(static inline u8 sio_read(u8 index))
{
- outb(index, 0x15c);
- return inb(0x15d);
+ outb(index, 0x15c);
+ return inb(0x15d);
}
__initfunc(static void sio_fixup_irq(const char *name, u8 device, u8 level,
u8 type))
{
- u8 level0, type0, active;
-
- /* select logical device */
- sio_write(device, 0x07);
- active = sio_read(0x30);
- level0 = sio_read(0x70);
- type0 = sio_read(0x71);
- printk("sio: %s irq level %d, type %d, %sactive: ", name, level0, type0,
- !active ? "in" : "");
- if (level0 == level && type0 == type && active)
- printk("OK\n");
- else {
- printk("remapping to level %d, type %d, active\n", level, type);
- sio_write(0x01, 0x30);
- sio_write(level, 0x70);
- sio_write(type, 0x71);
- }
+ u8 level0, type0, active;
+
+ /* select logical device */
+ sio_write(device, 0x07);
+ active = sio_read(0x30);
+ level0 = sio_read(0x70);
+ type0 = sio_read(0x71);
+ printk("sio: %s irq level %d, type %d, %sactive: ", name, level0, type0,
+ !active ? "in" : "");
+ if (level0 == level && type0 == type && active)
+ printk("OK\n");
+ else {
+ printk("remapping to level %d, type %d, active\n", level, type);
+ sio_write(0x01, 0x30);
+ sio_write(level, 0x70);
+ sio_write(type, 0x71);
+ }
}
__initfunc(static void sio_init(void))
{
- /* logical device 0 (KBC/Keyboard) */
- sio_fixup_irq("keyboard", 0, 1, 2);
- /* select logical device 1 (KBC/Mouse) */
- sio_fixup_irq("mouse", 1, 12, 2);
+ /* logical device 0 (KBC/Keyboard) */
+ sio_fixup_irq("keyboard", 0, 1, 2);
+ /* select logical device 1 (KBC/Mouse) */
+ sio_fixup_irq("mouse", 1, 12, 2);
}
__initfunc(void
-chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
+ chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
{
extern char cmd_line[];
/* init to some ~sane value until calibrate_delay() runs */
loops_per_sec = 50000000;
-
- aux_device_present = 0xaa;
#ifdef CONFIG_BLK_DEV_INITRD
/* this is fine for chrp */
@@ -219,8 +265,15 @@ chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
* -- Geert
*/
hydra_init(); /* Mac I/O */
- w83c553f_init(); /* PCI-ISA bridge and IDE */
+ /* Some IBM machines don't have the hydra -- Cort */
+ if ( !OpenPIC )
+ {
+ OpenPIC = (struct OpenPIC *)*(unsigned long *)get_property(
+ find_path_device("/"), "platform-open-pic", NULL);
+ OpenPIC = ioremap((unsigned long)OpenPIC, sizeof(struct OpenPIC));
+ }
+
/*
* Fix the Super I/O configuration
*/
@@ -232,27 +285,210 @@ chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
if ( !strncmp("MOT", get_property(find_path_device("/"),
"model", NULL),3) )
*memory_start_p = pmac_find_bridges(*memory_start_p, *memory_end_p);
+ /*
+ * The f50 has a lot of IO space - we need to map some in that
+ * isn't covered by the BAT mappings in MMU_init() -- Cort
+ */
+ if ( !strncmp("F5", get_property(find_path_device("/"),
+ "ibm,model-class", NULL),2) )
+ {
+#if 0
+ /*
+ * This ugly hack allows us to force ioremap() to
+ * create a 1-to-1 mapping for us, even though
+ * the address is < ioremap_base. This is necessary
+ * since we want our PCI IO space to have contiguous
+ * virtual addresses and I think it's worse to have
+ * calls to map_page() here.
+ * -- Cort
+ */
+ unsigned long hold = ioremap_base;
+ ioremap_base = 0;
+ __ioremap(0x90000000, 0x10000000, _PAGE_NO_CACHE);
+ ioremap_base = hold;
+#endif
+ }
}
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+void
+chrp_restart(char *cmd)
+{
+#if 0
+ extern unsigned int rtas_entry, rtas_data, rtas_size;
+ printk("RTAS system-reboot returned %d\n",
+ call_rtas("system-reboot", 0, 1, NULL));
+ printk("rtas_entry: %08lx rtas_data: %08lx rtas_size: %08lx\n",
+ rtas_entry,rtas_data,rtas_size);
+ for (;;);
+#else
+ printk("System Halted\n");
+ while(1);
+#endif
+}
-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_power_off(void)
+{
+ /* RTAS doesn't seem to work on Longtrail.
+ For now, do it the same way as the PReP. */
+#if 0
+ extern unsigned int rtas_entry, rtas_data, rtas_size;
+ printk("RTAS power-off returned %d\n",
+ call_rtas("power-off", 2, 1, NULL, 0, 0));
+ printk("rtas_entry: %08lx rtas_data: %08lx rtas_size: %08lx\n",
+ rtas_entry,rtas_data,rtas_size);
+ for (;;);
+#else
+ chrp_restart(NULL);
+#endif
+}
-void chrp_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+void
+chrp_halt(void)
{
- ide_ioreg_t port = base;
- int i = 8;
+ chrp_restart(NULL);
+}
- while (i--)
- *p++ = port++;
- *p++ = port;
- if (irq != NULL)
- *irq = chrp_ide_irq;
+u_int
+chrp_irq_cannonicalize(u_int irq)
+{
+ if (irq == 2)
+ {
+ return 9;
+ }
+ else
+ {
+ return irq;
+ }
+}
+
+void
+chrp_do_IRQ(struct pt_regs *regs,
+ int cpu,
+ int isfake)
+{
+ int irq;
+ unsigned long bits = 0;
+ int openpic_eoi_done = 0;
+
+#ifdef __SMP__
+ {
+ unsigned int loops = 1000000;
+ while (test_bit(0, &global_irq_lock)) {
+ if (smp_processor_id() == global_irq_holder) {
+ printk("uh oh, interrupt while we hold global irq lock!\n");
+#ifdef CONFIG_XMON
+ xmon(0);
+#endif
+ break;
+ }
+ if (loops-- == 0) {
+ printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
+#ifdef CONFIG_XMON
+ xmon(0);
+#endif
+ }
+ }
+ }
+#endif /* __SMP__ */
+
+ irq = openpic_irq(0);
+ if (irq == IRQ_8259_CASCADE)
+ {
+ /*
+ * This magic address generates a PCI IACK cycle.
+ *
+ * This should go in the above mask/ack code soon. -- Cort
+ */
+ if ( chrp_int_ack_special )
+ irq = *chrp_int_ack_special;
+ else
+ irq = i8259_irq(0);
+ /*
+ * Acknowledge as soon as possible to allow i8259
+ * interrupt nesting */
+ openpic_eoi(0);
+ openpic_eoi_done = 1;
+ }
+ if (irq == OPENPIC_VEC_SPURIOUS)
+ {
+ /*
+ * Spurious interrupts should never be
+ * acknowledged
+ */
+ ppc_spurious_interrupts++;
+ openpic_eoi_done = 1;
+ goto out;
+ }
+ bits = 1UL << irq;
+
+ if (irq < 0)
+ {
+ printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
+ irq, regs->nip);
+ ppc_spurious_interrupts++;
+ }
+ else
+ {
+ ppc_irq_dispatch_handler( regs, irq );
+ }
+out:
+ if (!openpic_eoi_done)
+ openpic_eoi(0);
}
+__initfunc(void
+ chrp_init_IRQ(void))
+{
+ struct device_node *np;
+ int i;
+
+ 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));
+ }
+ for ( i = 16 ; i < NR_IRQS ; i++ )
+ irq_desc[i].ctl = &open_pic;
+ /* openpic knows that it's at irq 16 offset
+ * so we don't need to set it in the pic structure
+ * -- Cort
+ */
+ openpic_init(1);
+ for ( i = 0 ; i < 16 ; i++ )
+ irq_desc[i].ctl = &i8259_pic;
+ i8259_init();
+#ifdef CONFIG_XMON
+ request_irq(openpic_to_irq(HYDRA_INT_ADB_NMI),
+ xmon_irq, 0, "NMI", 0);
+#endif /* CONFIG_XMON */
+#ifdef __SMP__
+ request_irq(openpic_to_irq(OPENPIC_VEC_IPI),
+ openpic_ipi_action, 0, "IPI0", 0);
+#endif /* __SMP__ */
+}
+
+__initfunc(void
+ chrp_init2(void))
+{
+ adb_init();
+
+ /* Should this be here? - Corey */
+ pmac_nvram_init();
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */
+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_probe(void) {
struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL);
@@ -270,9 +506,167 @@ void chrp_ide_probe(void) {
}
}
+void
+chrp_ide_insw(ide_ioreg_t port, void *buf, int ns)
+{
+ ide_insw(port+_IO_BASE, buf, ns);
+}
+
+void
+chrp_ide_outsw(ide_ioreg_t port, void *buf, int ns)
+{
+ ide_outsw(port+_IO_BASE, buf, ns);
+}
+
+int
+chrp_ide_default_irq(ide_ioreg_t base)
+{
+ if (chrp_ide_ports_known == 0)
+ chrp_ide_probe();
+ return chrp_ide_irq;
+}
+
+ide_ioreg_t
+chrp_ide_default_io_base(int index)
+{
+ if (chrp_ide_ports_known == 0)
+ chrp_ide_probe();
+ return chrp_ide_regbase[index];
+}
+
+int
+chrp_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+ return check_region(from, extent);
+}
+
+void
+chrp_ide_request_region(ide_ioreg_t from,
+ unsigned int extent,
+ const char *name)
+{
+ request_region(from, extent, name);
+}
+
+void
+chrp_ide_release_region(ide_ioreg_t from,
+ unsigned int extent)
+{
+ release_region(from, extent);
+}
+
+void
+chrp_ide_fix_driveid(struct hd_driveid *id)
+{
+ ppc_generic_ide_fix_driveid(id);
+}
+
+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;
+}
+
EXPORT_SYMBOL(chrp_ide_irq);
EXPORT_SYMBOL(chrp_ide_ports_known);
EXPORT_SYMBOL(chrp_ide_regbase);
EXPORT_SYMBOL(chrp_ide_probe);
#endif
+
+__initfunc(void
+ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7))
+{
+ chrp_setup_pci_ptrs();
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* take care of initrd if we have one */
+ if ( r3 )
+ {
+ initrd_start = r3 + KERNELBASE;
+ initrd_end = r3 + r4 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ /* pci_dram_offset/isa_io_base/isa_mem_base set by setup_pci_ptrs() */
+ ISA_DMA_THRESHOLD = ~0L;
+ DMA_MODE_READ = 0x44;
+ DMA_MODE_WRITE = 0x48;
+
+ ppc_md.setup_arch = chrp_setup_arch;
+ ppc_md.setup_residual = NULL;
+ ppc_md.get_cpuinfo = chrp_get_cpuinfo;
+ ppc_md.irq_cannonicalize = chrp_irq_cannonicalize;
+ ppc_md.init_IRQ = chrp_init_IRQ;
+ ppc_md.do_IRQ = chrp_do_IRQ;
+
+ ppc_md.init = chrp_init2;
+
+ ppc_md.restart = chrp_restart;
+ ppc_md.power_off = chrp_power_off;
+ ppc_md.halt = chrp_halt;
+
+ ppc_md.time_init = chrp_time_init;
+ ppc_md.set_rtc_time = chrp_set_rtc_time;
+ ppc_md.get_rtc_time = chrp_get_rtc_time;
+ ppc_md.calibrate_decr = chrp_calibrate_decr;
+
+#ifdef CONFIG_VT
+#ifdef CONFIG_MAC_KEYBOAD
+ if ( adb_hardware == ADB_NONE )
+ {
+ ppc_md.kbd_setkeycode = pckbd_setkeycode;
+ ppc_md.kbd_getkeycode = pckbd_getkeycode;
+ ppc_md.kbd_translate = pckbd_translate;
+ ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
+ ppc_md.kbd_leds = pckbd_leds;
+ ppc_md.kbd_init_hw = pckbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.kbd_sysrq_xlate = pckbd_sysrq_xlate;
+#endif
+ }
+ else
+ {
+ ppc_md.kbd_setkeycode = mackbd_setkeycode;
+ ppc_md.kbd_getkeycode = mackbd_getkeycode;
+ ppc_md.kbd_translate = mackbd_translate;
+ ppc_md.kbd_unexpected_up = mackbd_unexpected_up;
+ ppc_md.kbd_leds = mackbd_leds;
+ ppc_md.kbd_init_hw = mackbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.kbd_sysrq_xlate = mackbd_sysrq_xlate;
+#endif
+ }
+#else
+ ppc_md.kbd_setkeycode = pckbd_setkeycode;
+ ppc_md.kbd_getkeycode = pckbd_getkeycode;
+ ppc_md.kbd_translate = pckbd_translate;
+ ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
+ ppc_md.kbd_leds = pckbd_leds;
+ ppc_md.kbd_init_hw = pckbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.kbd_sysrq_xlate = pckbd_sysrq_xlate;
+#endif
+#endif
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ ppc_ide_md.insw = chrp_ide_insw;
+ ppc_ide_md.outsw = chrp_ide_outsw;
+ ppc_ide_md.default_irq = chrp_ide_default_irq;
+ ppc_ide_md.default_io_base = chrp_ide_default_io_base;
+ ppc_ide_md.check_region = chrp_ide_check_region;
+ ppc_ide_md.request_region = chrp_ide_request_region;
+ ppc_ide_md.release_region = chrp_ide_release_region;
+ ppc_ide_md.fix_driveid = chrp_ide_fix_driveid;
+ ppc_ide_md.ide_init_hwif = chrp_ide_init_hwif_ports;
+
+ ppc_ide_md.io_base = _IO_BASE;
+#endif
+}
diff --git a/arch/ppc/kernel/chrp_time.c b/arch/ppc/kernel/chrp_time.c
index 7a2ea7b26..c374c9bd1 100644
--- a/arch/ppc/kernel/chrp_time.c
+++ b/arch/ppc/kernel/chrp_time.c
@@ -154,7 +154,8 @@ unsigned long chrp_get_rtc_time(void)
__initfunc(void chrp_calibrate_decr(void))
{
struct device_node *cpu;
- int freq, *fp, divisor;
+ int *fp, divisor;
+ unsigned long freq;
if (via_calibrate_decr())
return;
@@ -170,10 +171,9 @@ __initfunc(void chrp_calibrate_decr(void))
if (fp != 0)
freq = *fp;
}
-
freq *= 60; /* try to make freq/1e6 an integer */
divisor = 60;
- printk("time_init: decrementer frequency = %d/%d\n", freq, divisor);
+ printk("time_init: decrementer frequency = %lu/%d\n", freq, divisor);
decrementer_count = freq / HZ / divisor;
count_period_num = divisor;
count_period_den = freq / 1000000;
diff --git a/arch/ppc/kernel/feature.c b/arch/ppc/kernel/feature.c
index 48d8bcb39..25ee3424b 100644
--- a/arch/ppc/kernel/feature.c
+++ b/arch/ppc/kernel/feature.c
@@ -41,7 +41,6 @@ static u32 feature_bits_pbook[] = {
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...*/
};
@@ -64,8 +63,7 @@ static u32 feature_bits_heathrow[] = {
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...*/
+ 0x02000000 /* FEATURE_Modem_Reset -> guess...*/
};
/* definition of a feature controller object */
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index d7b791387..b9ecc2dcc 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.114 1998/12/28 10:28:45 paulus Exp $
+ * $Id: head.S,v 1.130 1999/05/09 19:16:43 cort Exp $
*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
@@ -44,8 +44,13 @@
/* optimization for 603 to load the tlb directly from the linux table */
#define NO_RELOAD_HTAB 1
+#ifndef CONFIG_8xx
CACHE_LINE_SIZE = 32
LG_CACHE_LINE_SIZE = 5
+#else
+CACHE_LINE_SIZE = 16
+LG_CACHE_LINE_SIZE = 4
+#endif
#define TOPHYS(x) (x - KERNELBASE)
@@ -81,13 +86,12 @@ LG_CACHE_LINE_SIZE = 5
sync; \
isync
-/* This instruction is not implemented on the PPC 603 or 601 */
#ifndef CONFIG_8xx
/* This instruction is not implemented on the PPC 603 or 601 */
#define tlbia \
li r4,128; \
mtctr r4; \
- lis r4,0xC000; \
+ lis r4,KERNELBASE@h; \
0: tlbie r4; \
addi r4,r4,0x1000; \
bdnz 0b
@@ -212,6 +216,7 @@ __start:
mr r29,r5
mr r28,r6
mr r27,r7
+ li r24,0 /* cpu # */
#ifndef CONFIG_8xx
bl prom_init
.globl __secondary_start
@@ -236,15 +241,33 @@ __secondary_start:
mtspr IBAT1L,r10
b 5f
4:
-#ifndef CONFIG_APUS
- ori r11,r11,0x1fe /* set up BAT registers for 604 */
- li r8,2 /* R/W access */
-#else
+#ifdef CONFIG_APUS
+ ori r11,r11,BL_8M<<2|0x2 /* 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
+#else
+ ori r11,r11,BL_256M<<2|0x2 /* set up BAT registers for 604 */
+ li r8,2 /* R/W access */
+ /*
+ * allow secondary cpus to get at all of ram in early bootup
+ * since their init_task may be up there -- Cort
+ */
+ oris r18,r8,0x10000000@h
+ oris r21,r11,(KERNELBASE+0x10000000)@h
+ mtspr DBAT1L,r18 /* N.B. 6xx (not 601) have valid */
+ mtspr DBAT1U,r21 /* bit in upper BAT register */
+ mtspr IBAT1L,r18
+ mtspr IBAT1U,r21
+
+ oris r18,r8,0x20000000@h
+ oris r21,r11,(KERNELBASE+0x20000000)@h
+ mtspr DBAT2L,r18 /* N.B. 6xx (not 601) have valid */
+ mtspr DBAT2U,r21 /* bit in upper BAT register */
+ mtspr IBAT2L,r28
+ mtspr IBAT2U,r21
#endif
mtspr DBAT0L,r8 /* N.B. 6xx (not 601) have valid */
mtspr DBAT0U,r11 /* bit in upper BAT register */
@@ -327,20 +350,28 @@ __secondary_start:
lis r8, MI_Kp@h /* Set the protection mode */
mtspr MI_AP, r8
mtspr MD_AP, r8
-#ifdef CONFIG_MBX
+
+/* We will get these from a configuration file as soon as I verify
+ * the extraneous bits don't cause problems in the TLB.
+ */
+#if defined(CONFIG_MBX) || defined(CONFIG_RPXLITE)
+#define BOOT_IMMR 0xfa000000
+#endif
+#ifdef CONFIG_BSEIP
+#define BOOT_IMMR 0xff000000
+#endif
/* Map another 8 MByte at 0xfa000000 to get the processor
* internal registers (among other things).
*/
- lis r8, 0xfa000000@h /* Create vaddr for TLB */
+ lis r8, BOOT_IMMR@h /* Create vaddr for TLB */
ori r8, r8, MD_EVALID /* Mark it valid */
mtspr MD_EPN, r8
li r8, MD_PS8MEG /* Set 8M byte page */
ori r8, r8, MD_SVALID /* Make it valid */
mtspr MD_TWC, r8
- lis r8, 0xfa000000@h /* Create paddr for TLB */
+ lis r8, BOOT_IMMR@h /* Create paddr for TLB */
ori r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */
mtspr MD_RPN, r8
-#endif
/* Since the cache is enabled according to the information we
* just loaded into the TLB, invalidate and enable the caches here.
@@ -354,9 +385,8 @@ __secondary_start:
#if 0
mtspr DC_CST, r8
#else
- /* I still have a bug somewhere because the Ethernet driver
- * does not want to work with copyback enabled. For now,
- * at least enable write through.
+ /* For a debug option, I left this here to easily enable
+ * the write through cache mode
*/
lis r8, DC_SFWT@h
mtspr DC_CST, r8
@@ -385,7 +415,7 @@ turn_on_mmu:
* this, we leave this much untouched space on the stack on exception
* entry.
*/
-#define STACK_UNDERHEAD 64
+#define STACK_UNDERHEAD 0
/*
* Exception entry code. This code runs with address translation
@@ -442,7 +472,11 @@ label: \
.long int_return
/* System reset */
+#ifdef CONFIG_SMP /* MVME/MTX start the secondary here */
+ STD_EXCEPTION(0x100, Reset, __secondary_start_psurge)
+#else
STD_EXCEPTION(0x100, Reset, UnknownException)
+#endif
/* Machine check */
STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
@@ -1148,6 +1182,8 @@ transfer_to_handler:
mflr r23
andi. r24,r23,0x3f00 /* get vector offset */
stw r24,TRAP(r21)
+ li r22,RESULT
+ stwcx. r22,r22,r21 /* to clear the reservation */
li r22,0
stw r22,RESULT(r21)
mtspr SPRG2,r22 /* r1 is now kernel sp */
@@ -1155,7 +1191,7 @@ transfer_to_handler:
cmplw 0,r1,r2
cmplw 1,r1,r24
crand 1,1,4
- bgt stack_ovf /* if r2 < r1 < r2+TASK_STRUCT_SIZE */
+ bgt- stack_ovf /* if r2 < r1 < r2+TASK_STRUCT_SIZE */
lwz r24,0(r23) /* virtual address of handler */
lwz r23,4(r23) /* where to go when done */
mtspr SRR0,r24
@@ -1204,13 +1240,10 @@ Hash_base = 0x180000
Hash_bits = 12 /* e.g. 256kB hash table */
Hash_msk = (((1 << Hash_bits) - 1) * 64)
- .globl hash_table_lock
-hash_table_lock:
-.long 0
-
.globl hash_page
hash_page:
#ifdef __SMP__
+ eieio
lis r2,hash_table_lock@h
ori r2,r2,hash_table_lock@l
tophys(r2,r2,r6)
@@ -1226,7 +1259,7 @@ hash_page:
12: cmpw r6,r0
bdnzf 2,10b
tw 31,31,31
-11:
+11: eieio
#endif
/* Get PTE (linux-style) and check access */
lwz r5,PG_TABLES(r5)
@@ -1234,13 +1267,25 @@ hash_page:
rlwimi r5,r3,12,20,29 /* insert top 10 bits of address */
lwz r5,0(r5) /* get pmd entry */
rlwinm. r5,r5,0,0,19 /* extract address of pte page */
+#ifdef __SMP__
beq- hash_page_out /* return if no mapping */
+#else
+ /* XXX it seems like the 601 will give a machine fault on the
+ rfi if its alignment is wrong (bottom 4 bits of address are
+ 8 or 0xc) and we have had a not-taken conditional branch
+ to the address following the rfi. */
+ beqlr-
+#endif
tophys(r2,r5,r2)
rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */
lwz r6,0(r2) /* get linux-style pte */
ori r4,r4,1 /* set _PAGE_PRESENT bit in access */
andc. r0,r4,r6 /* check access & ~permission */
+#ifdef __SMP__
bne- hash_page_out /* return if access not permitted */
+#else
+ bnelr-
+#endif
ori r6,r6,0x100 /* set _PAGE_ACCESSED in pte */
rlwinm r5,r4,5,24,24 /* _PAGE_RW access -> _PAGE_DIRTY */
@@ -1257,7 +1302,9 @@ hash_page:
/* Construct the high word of the PPC-style PTE */
mfsrin r5,r3 /* get segment reg for segment */
rlwinm r5,r5,7,1,24 /* put VSID in 0x7fffff80 bits */
+#ifndef __SMP__ /* do this later for SMP */
oris r5,r5,0x8000 /* set V (valid) bit */
+#endif
rlwimi r5,r3,10,26,31 /* put in API (abbrev page index) */
/* Get the address of the primary PTE group in the hash table */
@@ -1274,9 +1321,6 @@ hash_page_patch_A:
li r2,8 /* PTEs/group */
bne 10f /* no PTE: go look for an empty slot */
tlbie r3 /* invalidate TLB entry */
-#ifdef __SMP__
- tlbsync
-#endif
/* Search the primary PTEG for a PTE whose 1st word matches r5 */
mtctr r2
@@ -1345,18 +1389,43 @@ hash_page_patch_C:
addi r4,r4,1
stw r4,0(r2)
+#ifndef __SMP__
/* Store PTE in PTEG */
found_empty:
stw r5,0(r3)
found_slot:
stw r6,4(r3)
- SYNC
+ sync
+
+#else /* __SMP__ */
/*
- * These nop's seem to be necessary to avoid getting a machine
- * check on the rfi on 601 processors.
+ * Between the tlbie above and updating the hash table entry below,
+ * another CPU could read the hash table entry and put it in its TLB.
+ * There are 3 cases:
+ * 1. using an empty slot
+ * 2. updating an earlier entry to change permissions (i.e. enable write)
+ * 3. taking over the PTE for an unrelated address
+ *
+ * In each case it doesn't really matter if the other CPUs have the old
+ * PTE in their TLB. So we don't need to bother with another tlbie here,
+ * which is convenient as we've overwritten the register that had the
+ * address. :-) The tlbie above is mainly to make sure that this CPU comes
+ * and gets the new PTE from the hash table.
+ *
+ * We do however have to make sure that the PTE is never in an invalid
+ * state with the V bit set.
*/
- nop
- nop
+found_empty:
+found_slot:
+ stw r5,0(r3) /* clear V (valid) bit in PTE */
+ sync
+ tlbsync
+ sync
+ stw r6,4(r3) /* put in correct RPN, WIMG, PP bits */
+ sync
+ oris r5,r5,0x8000
+ stw r5,0(r3) /* finally set V bit in PTE */
+#endif /* __SMP__ */
/*
* Update the hash table miss count. We only want misses here
@@ -1380,6 +1449,7 @@ found_slot:
tophys(r2,r2,r6)
li r0,0
stw r0,hash_table_lock@l(r2)
+ eieio
#endif
/* Return from the exception */
@@ -1398,17 +1468,22 @@ found_slot:
REST_GPR(20, r21)
REST_2GPRS(22, r21)
lwz r21,GPR21(r21)
- SYNC
rfi
-hash_page_out:
#ifdef __SMP__
+hash_page_out:
lis r2,hash_table_lock@ha
tophys(r2,r2,r6)
li r0,0
stw r0,hash_table_lock@l(r2)
-#endif
+ eieio
blr
+
+ .globl hash_table_lock
+hash_table_lock:
+ .long 0
+#endif
+
next_slot:
.long 0
@@ -1420,27 +1495,25 @@ load_up_fpu:
* On SMP we know the fpu is free, since we give it up every
* switch. -- Cort
*/
+ mfmsr r5
+ ori r5,r5,MSR_FP
+ SYNC
+ mtmsr r5 /* enable use of fpu now */
+ SYNC
+/*
+ * For SMP, we don't do lazy FPU switching because it just gets too
+ * horrendously complex, especially when a task switches from one CPU
+ * to another. Instead we call giveup_fpu in switch_to.
+ */
+#ifndef __SMP__
#ifndef CONFIG_APUS
lis r6,-KERNELBASE@h
#else
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 */
-/*
- * 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.
- * -- Cort
- */
-#ifndef __SMP__
- SYNC
cmpi 0,r4,0
beq 1f
add r4,r4,r6
@@ -1454,15 +1527,17 @@ load_up_fpu:
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:
#endif /* __SMP__ */
-1: ori r23,r23,MSR_FP|MSR_FE0|MSR_FE1 /* enable use of FP after return */
+ /* enable use of FP after return */
+ ori r23,r23,MSR_FP|MSR_FE0|MSR_FE1
mfspr r5,SPRG3 /* current task's TSS (phys) */
lfd fr0,TSS_FPSCR-4(r5)
mtfsf 0xff,fr0
REST_32FPRS(0, r5)
+#ifndef __SMP__
subi r4,r5,TSS
sub r4,r4,r6
-#ifndef __SMP__
stw r4,last_task_used_math@l(r3)
#endif /* __SMP__ */
/* restore registers and return */
@@ -1499,48 +1574,44 @@ KernelFP:
.align 4
/*
- * Disable FP for the task which had the FPU previously,
- * and save its floating-point registers in its thread_struct.
+ * giveup_fpu(tsk)
+ * Disable FP for the task given as the argument,
+ * and save the floating-point registers in its thread_struct.
* Enables the FPU for use in the kernel on return.
*/
-/* smp_giveup_fpu() takes an arg to tell it where to save the fpu
- * regs since last_task_used_math can't be trusted (many many race
- * conditions). -- Cort
- */
- .globl smp_giveup_fpu
-smp_giveup_fpu:
- mr r4,r3
- b 12f
.globl giveup_fpu
giveup_fpu:
- lis r3,last_task_used_math@ha
- lwz r4,last_task_used_math@l(r3)
-12:
mfmsr r5
ori r5,r5,MSR_FP
SYNC
mtmsr r5 /* enable use of fpu now */
SYNC
- cmpi 0,r4,0
+ cmpi 0,r3,0
beqlr- /* if no previous owner, done */
- addi r4,r4,TSS /* want TSS of last_task_used_math */
+ addi r3,r3,TSS /* want TSS of task */
+ lwz r5,PT_REGS(r3)
+ cmpi 0,r5,0
+ SAVE_32FPRS(0, r3)
+ mffs fr0
+ stfd fr0,TSS_FPSCR-4(r3)
+ beq 1f
+ lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+ li r3,MSR_FP|MSR_FE0|MSR_FE1
+ andc r4,r4,r3 /* disable FP for previous task */
+ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
#ifndef __SMP__
li r5,0
- stw r5,last_task_used_math@l(r3)
+ lis r4,last_task_used_math@ha
+ stw r5,last_task_used_math@l(r4)
#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|MSR_FE0|MSR_FE1
- andc r3,r3,r4 /* disable FP for previous task */
- stw r3,_MSR-STACK_FRAME_OVERHEAD(r5)
+ blr
+
#else /* CONFIG_8xx */
.globl giveup_fpu
giveup_fpu:
-#endif /* CONFIG_8xx */
blr
+#endif /* CONFIG_8xx */
/*
* This code is jumped to from the startup code to copy
@@ -1600,10 +1671,38 @@ copy_and_flush:
. = 0x4000
#endif
+#ifdef CONFIG_SMP
+ .globl __secondary_start_psurge
+__secondary_start_psurge:
+ li r24,1 /* cpu # */
+ b __secondary_start
+
+ .globl __secondary_hold
+__secondary_hold:
+ /* tell the master we're here */
+ lis r5,0x4@h
+ ori r5,r5,0x4@l
+ stw r3,0(r5)
+ dcbf 0,r5
+100:
+ lis r5,0
+ dcbi 0,r5
+ lwz r4,0(r5)
+ /* wait until we're told to start */
+ cmp 0,r4,r3
+ bne 100b
+ /* our cpu # was at addr 0 - go */
+ lis r5,__secondary_start@h
+ ori r5,r5,__secondary_start@l
+ tophys(r5,r5,r4)
+ mtlr r5
+ mr r24,r3 /* cpu # */
+ blr
+#endif /* CONFIG_SMP */
+
/*
* This is where the main kernel code starts.
*/
-
start_here:
#ifndef CONFIG_8xx
/*
@@ -1650,9 +1749,9 @@ start_here:
/* get current */
lis r2,current_set@h
ori r2,r2,current_set@l
- addi r2,r2,4
+ slwi r24,r24,2 /* cpu # to current_set[cpu#] */
+ add r2,r2,r24
lwz r2,0(r2)
-
b 10f
99:
#endif /* __SMP__ */
@@ -1677,12 +1776,10 @@ start_here:
#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.
*/
@@ -1693,7 +1790,6 @@ 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
@@ -1725,8 +1821,10 @@ start_here:
2:
SYNC /* Force all PTE updates to finish */
tlbia /* Clear all TLB entries */
+ sync /* wait for tlbia/tlbie to finish */
#ifdef __SMP__
- tlbsync
+ tlbsync /* ... on all CPUs */
+ sync
#endif
#ifndef CONFIG_8xx
mtspr SDR1,r6
@@ -1947,8 +2045,9 @@ _GLOBAL(_switch)
stw r0,GPR0(r1)
lwz r0,0(r1)
stw r0,GPR1(r1)
- SAVE_10GPRS(2, r1)
- SAVE_10GPRS(12, r1)
+ /* r3-r13 are caller saved -- Cort */
+ SAVE_GPR(2, r1)
+ SAVE_8GPRS(14, r1)
SAVE_10GPRS(22, r1)
mflr r20 /* Return to switch caller */
mfmsr r22
@@ -1971,46 +2070,71 @@ _GLOBAL(_switch)
mtspr SPRG3,r0 /* Update current TSS phys addr */
SYNC
lwz r1,KSP(r4) /* Load new stack pointer */
+ /* save the old current 'last' for return value */
+ mr r3,r2
addi r2,r4,-TSS /* Update current */
#ifndef CONFIG_8xx
/* Set up segment registers for new task */
rlwinm r5,r5,4,8,27 /* VSID = context << 4 */
addis r5,r5,0x6000 /* Set Ks, Ku bits */
- li r0,8 /* TASK_SIZE / SEGMENT_SIZE */
+ li r0,12 /* TASK_SIZE / SEGMENT_SIZE */
mtctr r0
- li r3,0
-3: mtsrin r5,r3
+ li r9,0
+3: mtsrin r5,r9
addi r5,r5,1 /* next VSID */
- addis r3,r3,0x1000 /* address of next segment */
+ addis r9,r9,0x1000 /* address of next segment */
bdnz 3b
#else
/* On the MPC8xx, we place the physical address of the new task
* page directory loaded into the MMU base register, and set the
* ASID compare register with the new "context".
*/
- lwz r3,MM-TSS(r4) /* Get virtual address of mm */
- lwz r3,PGD(r3) /* get new->mm->pgd */
- addis r3,r3,-KERNELBASE@h /* convert to phys addr */
- mtspr M_TWB, r3 /* Update MMU base address */
+ lwz r9,MM-TSS(r4) /* Get virtual address of mm */
+ lwz r9,PGD(r9) /* get new->mm->pgd */
+ addis r9,r9,-KERNELBASE@h /* convert to phys addr */
+ mtspr M_TWB, r9 /* Update MMU base address */
mtspr M_CASID, r5 /* Update context */
tlbia
#endif
SYNC
-
-/* FALL THROUGH into int_return */
-#ifdef __SMP__
- /* call schedule_tail if this is the first time for a child process */
- lwz r5,TSS_SMP_FORK_RET(r4)
- cmpi 0,r5,0
- beq+ int_return
- li r3,0
- stw r3,TSS_SMP_FORK_RET(r4)
- bl schedule_tail
-#endif /* __SMP__ */
+2: lwz r9,_MSR(r1) /* Returning to user mode? */
+ andi. r9,r9,MSR_PR
+ beq+ 10f /* if not, don't adjust kernel stack */
+8: addi r4,r1,INT_FRAME_SIZE+STACK_UNDERHEAD /* size of frame */
+ stw r4,TSS+KSP(r2) /* save kernel stack pointer */
+ tophys(r9,r1,r9)
+ mtspr SPRG2,r9 /* phys exception stack pointer */
+10: lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ /* r3-r13 are destroyed -- Cort */
+ REST_GPR(14, r1)
+ REST_8GPRS(15, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
/*
* Trap exit.
*/
+#ifdef __SMP__
+ .globl ret_from_smpfork
+ret_from_smpfork:
+ bl schedule_tail
+#endif
.globl ret_from_syscall
ret_from_syscall:
.globl int_return
@@ -2025,8 +2149,8 @@ int_return:
lwz r5,_MSR(r1)
and. r5,r5,r4
beq 2f
-3: lis r4,n_lost_interrupts@ha
- lwz r4,n_lost_interrupts@l(r4)
+3: lis r4,ppc_n_lost_interrupts@ha
+ lwz r4,ppc_n_lost_interrupts@l(r4)
cmpi 0,r4,0
beq+ 1f
addi r3,r1,STACK_FRAME_OVERHEAD
@@ -2118,7 +2242,7 @@ _GLOBAL(fake_interrupt)
_GLOBAL(set_context)
rlwinm r3,r3,4,8,27 /* VSID = context << 4 */
addis r3,r3,0x6000 /* Set Ks, Ku bits */
- li r0,8 /* TASK_SIZE / SEGMENT_SIZE */
+ li r0,12 /* TASK_SIZE / SEGMENT_SIZE */
mtctr r0
li r4,0
3: mtsrin r3,r4
@@ -2177,6 +2301,27 @@ _GLOBAL(flush_icache_range)
blr
/*
+ * Like above, but only do the D-cache. This is used by the 8xx
+ * to push the cache so the CPM doesn't get stale data.
+ *
+ * flush_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(flush_dcache_range)
+ li r5,CACHE_LINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,LG_CACHE_LINE_SIZE
+ beqlr
+ mtctr r4
+
+1: dcbst 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ blr
+
+/*
* Flush a particular page from the DATA cache
* Note: this is necessary because the instruction cache does *not*
* snoop from the data cache.
@@ -2207,25 +2352,35 @@ _GLOBAL(flush_page_to_ram)
blr
/*
+ * Clear a page using the dcbz instruction, which doesn't cause any
+ * memory traffic (except to write out any cache lines which get
+ * displaced). This only works on cacheable memory.
+ */
+_GLOBAL(clear_page)
+ li r0,4096/CACHE_LINE_SIZE
+ mtctr r0
+1: dcbz 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 1b
+ blr
+
+/*
* Flush entries from the hash table with VSIDs in the range
* given.
*/
#ifndef CONFIG_8xx
_GLOBAL(flush_hash_segments)
+ lis r5,Hash@ha
+ lwz r5,Hash@l(r5) /* base of hash table */
#ifdef NO_RELOAD_HTAB
-/*
- * Bitmask of PVR numbers of 603-like chips,
- * for which we don't use the hash table at all.
- */
-#define PVR_603_LIKE 0x13000000 /* bits 3, 6, 7 set */
-
- mfspr r0,PVR
- rlwinm r0,r0,16,27,31
- lis r9,PVR_603_LIKE@h
- rlwnm. r0,r9,r0,0,0
- beq+ 99f
+ cmpwi 0,r5,0
+ bne+ 99f
tlbia
- isync
+ sync
+#ifdef __SMP__
+ tlbsync
+ sync
+#endif
blr
99:
#endif /* NO_RELOAD_HTAB */
@@ -2247,14 +2402,13 @@ _GLOBAL(flush_hash_segments)
bne- 10b
stwcx. r8,0,r9
bne- 10b
+ eieio
#endif
rlwinm r3,r3,7,1,24 /* put VSID lower limit in position */
oris r3,r3,0x8000 /* set V bit */
rlwinm r4,r4,7,1,24 /* put VSID upper limit in position */
oris r4,r4,0x8000
ori r4,r4,0x7f
- lis r5,Hash@ha
- lwz r5,Hash@l(r5) /* base of hash table */
lis r6,Hash_size@ha
lwz r6,Hash_size@l(r6) /* size in bytes */
srwi r6,r6,3 /* # PTEs */
@@ -2270,11 +2424,11 @@ _GLOBAL(flush_hash_segments)
2: bdnz 1b /* continue with loop */
sync
tlbia
- isync
+ sync
#ifdef __SMP__
tlbsync
+ sync
lis r3,hash_table_lock@ha
- li r0,0
stw r0,hash_table_lock@l(r3)
mtmsr r10
SYNC
@@ -2287,14 +2441,17 @@ _GLOBAL(flush_hash_segments)
* flush_hash_page(unsigned context, unsigned long va)
*/
_GLOBAL(flush_hash_page)
+ lis r6,Hash@ha
+ lwz r6,Hash@l(r6) /* hash table base */
#ifdef NO_RELOAD_HTAB
- mfspr r0,PVR
- rlwinm r0,r0,16,27,31
- lis r9,PVR_603_LIKE@h
- rlwnm. r0,r9,r0,0,0
- beq+ 99f
+ cmpwi 0,r6,0 /* hash table in use? */
+ bne+ 99f
tlbie r4 /* in hw tlb too */
- isync
+ sync
+#ifdef __SMP__
+ tlbsync
+ sync
+#endif
blr
99:
#endif /* NO_RELOAD_HTAB */
@@ -2311,11 +2468,12 @@ _GLOBAL(flush_hash_page)
ori r9,r9,hash_table_lock@l
lwz r8,PROCESSOR(r2)
oris r8,r8,9
-10: lwarx r6,0,r9
- cmpi 0,r6,0
+10: lwarx r7,0,r9
+ cmpi 0,r7,0
bne- 10b
stwcx. r8,0,r9
bne- 10b
+ eieio
#endif
rlwinm r3,r3,11,1,20 /* put context into vsid */
rlwimi r3,r4,11,21,24 /* put top 4 bits of va into vsid */
@@ -2328,8 +2486,6 @@ _GLOBAL(flush_hash_page)
lwz r5,Hash_mask@l(r5) /* hash mask */
slwi r5,r5,6 /* << 6 */
and r7,r7,r5
- lis r6,Hash@ha
- lwz r6,Hash@l(r6) /* hash table base */
add r6,r6,r7 /* address of primary PTEG */
li r8,8
mtctr r8
@@ -2350,9 +2506,10 @@ _GLOBAL(flush_hash_page)
stw r0,0(r7) /* invalidate entry */
4: sync
tlbie r4 /* in hw tlb too */
- isync
+ sync
#ifdef __SMP__
tlbsync
+ sync
lis r3,hash_table_lock@h
li r0,0
stw r0,hash_table_lock@l(r3)
@@ -2418,30 +2575,27 @@ enter_rtas:
rfi /* return to caller */
#endif /* CONFIG_8xx */
-#ifdef CONFIG_MBX
-/* Jump into the system reset for the MBX rom.
+#ifdef CONFIG_8xx
+/* Jump into the system reset for the rom.
* We first disable the MMU, and then jump to the ROM reset address.
*
- * This does not work, don't bother trying. There is no place in
- * the ROM we can jump to cause a reset. We will have to program
- * a watchdog of some type that we don't service to cause a processor
- * reset.
+ * r3 is the board info structure, r4 is the location for starting.
+ * I use this for building a small kernel that can load other kernels,
+ * rather than trying to write or rely on a rom monitor that can tftp load.
*/
- .globl MBX_gorom
-MBX_gorom:
- li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
- lis r4,2f@h
- addis r4,r4,-KERNELBASE@h
- ori r4,r4,2f@l
- mtspr SRR0,r4
- mtspr SRR1,r3
- rfi
+ .globl m8xx_gorom
+m8xx_gorom:
+ li r5,MSR_KERNEL & ~(MSR_IR|MSR_DR)
+ lis r6,2f@h
+ addis r6,r6,-KERNELBASE@h
+ ori r6,r6,2f@l
+ mtspr SRR0,r6
+ mtspr SRR1,r5
+ rfi
2:
- lis r4, 0xfe000000@h
- addi r4, r4, 0xfe000000@l
- mtlr r4
- blr
-#endif /* CONFIG_MBX */
+ mtlr r4
+ blr
+#endif /* CONFIG_8xx */
/*
* We put a few things here that have to be page-aligned.
diff --git a/arch/ppc/kernel/i8259.c b/arch/ppc/kernel/i8259.c
new file mode 100644
index 000000000..4ec6d3e11
--- /dev/null
+++ b/arch/ppc/kernel/i8259.c
@@ -0,0 +1,130 @@
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <asm/io.h>
+#include "i8259.h"
+
+unsigned char cached_8259[2] = { 0xff, 0xff };
+#define cached_A1 (cached_8259[0])
+#define cached_21 (cached_8259[1])
+
+int i8259_irq(int cpu)
+{
+ int irq;
+
+ /*
+ * Perform an interrupt acknowledge cycle on controller 1
+ */
+ outb(0x0C, 0x20);
+ irq = inb(0x20) & 7;
+ if (irq == 2)
+ {
+ /*
+ * Interrupt is cascaded so perform interrupt
+ * acknowledge on controller 2
+ */
+ outb(0x0C, 0xA0);
+ irq = (inb(0xA0) & 7) + 8;
+ }
+ else if (irq==7)
+ {
+ /*
+ * This may be a spurious interrupt
+ *
+ * Read the interrupt status register. If the most
+ * significant bit is not set then there is no valid
+ * interrupt
+ */
+ outb(0x0b, 0x20);
+ if(~inb(0x20)&0x80)
+ return -1;
+ }
+ return irq;
+}
+
+static void i8259_mask_and_ack_irq(unsigned int irq_nr)
+{
+ if ( irq_nr >= i8259_pic.irq_offset )
+ irq_nr -= i8259_pic.irq_offset;
+
+ if (irq_nr > 7) {
+ cached_A1 |= 1 << (irq_nr-8);
+ inb(0xA1); /* DUMMY */
+ outb(cached_A1,0xA1);
+ outb(0x20,0xA0); /* Non-specific EOI */
+ outb(0x20,0x20); /* Non-specific EOI to cascade */
+ } else {
+ cached_21 |= 1 << irq_nr;
+ inb(0x21); /* DUMMY */
+ outb(cached_21,0x21);
+ outb(0x20,0x20); /* Non-specific EOI */
+ }
+}
+
+static void i8259_set_irq_mask(int irq_nr)
+{
+ outb(cached_A1,0xA1);
+ outb(cached_21,0x21);
+}
+
+static void i8259_mask_irq(unsigned int irq_nr)
+{
+ if ( irq_nr >= i8259_pic.irq_offset )
+ irq_nr -= i8259_pic.irq_offset;
+ if ( irq_nr < 8 )
+ cached_21 |= 1 << irq_nr;
+ else
+ cached_A1 |= 1 << (irq_nr-8);
+ i8259_set_irq_mask(irq_nr);
+}
+
+static void i8259_unmask_irq(unsigned int irq_nr)
+{
+
+ if ( irq_nr >= i8259_pic.irq_offset )
+ irq_nr -= i8259_pic.irq_offset;
+ if ( irq_nr < 8 )
+ cached_21 &= ~(1 << irq_nr);
+ else
+ cached_A1 &= ~(1 << (irq_nr-8));
+ i8259_set_irq_mask(irq_nr);
+}
+
+struct hw_interrupt_type i8259_pic = {
+ " i8259 ",
+ NULL,
+ NULL,
+ NULL,
+ i8259_unmask_irq,
+ i8259_mask_irq,
+ i8259_mask_and_ack_irq,
+ 0
+};
+
+static void
+no_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+}
+
+void __init i8259_init(void)
+{
+ /* init master interrupt controller */
+ outb(0x11, 0x20); /* Start init sequence */
+ outb(0x00, 0x21); /* Vector base */
+ outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
+ outb(0x01, 0x21); /* Select 8086 mode */
+ outb(0xFF, 0x21); /* Mask all */
+ /* init slave interrupt controller */
+ outb(0x11, 0xA0); /* Start init sequence */
+ outb(0x08, 0xA1); /* Vector base */
+ outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */
+ outb(0x01, 0xA1); /* Select 8086 mode */
+ outb(0xFF, 0xA1); /* Mask all */
+ outb(cached_A1, 0xA1);
+ outb(cached_21, 0x21);
+ request_irq( i8259_pic.irq_offset + 2, no_action, SA_INTERRUPT,
+ "82c59 secondary cascade", NULL );
+ enable_irq(i8259_pic.irq_offset + 2); /* Enable cascade interrupt */
+}
diff --git a/arch/ppc/kernel/i8259.h b/arch/ppc/kernel/i8259.h
new file mode 100644
index 000000000..a1d6df0a1
--- /dev/null
+++ b/arch/ppc/kernel/i8259.h
@@ -0,0 +1,12 @@
+
+#ifndef _PPC_KERNEL_i8259_H
+#define _PPC_KERNEL_i8259_H
+
+#include "local_irq.h"
+
+extern struct hw_interrupt_type i8259_pic;
+
+void i8259_init(void);
+int i8259_irq(int);
+
+#endif /* _PPC_KERNEL_i8259_H */
diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
index af163699b..c68d1e63e 100644
--- a/arch/ppc/kernel/idle.c
+++ b/arch/ppc/kernel/idle.c
@@ -1,5 +1,5 @@
/*
- * $Id: idle.c,v 1.57 1998/12/28 10:28:46 paulus Exp $
+ * $Id: idle.c,v 1.61 1999/03/18 04:15:45 cort Exp $
*
* Idle daemon for PowerPC. Idle daemon will handle any action
* that needs to be taken when the system becomes idle.
@@ -39,6 +39,12 @@ unsigned long htab_reclaim_on = 0;
unsigned long zero_paged_on = 0;
unsigned long powersave_nap = 0;
+unsigned long *zero_cache; /* head linked list of pre-zero'd pages */
+unsigned long zero_sz; /* # currently pre-zero'd pages */
+unsigned long zeropage_hits; /* # zero'd pages request that we've done */
+unsigned long zeropage_calls; /* # zero'd pages request that've been made */
+unsigned long zerototal; /* # pages zero'd over time */
+
int idled(void *unused)
{
/* endless loop with no priority at all */
@@ -108,8 +114,6 @@ void inline htab_reclaim(void)
/* if we don't have a htab */
if ( Hash_size == 0 )
return;
- lock_dcache(1);
-
#if 0
/* find a random place in the htab to start each time */
start = &Hash[jiffies%(Hash_size/sizeof(PTE))];
@@ -147,7 +151,6 @@ void inline htab_reclaim(void)
}
out:
if ( current->need_resched ) printk("need_resched: %lx\n", current->need_resched);
- unlock_dcache();
#endif /* CONFIG_8xx */
}
@@ -159,7 +162,7 @@ unsigned long get_zero_page_fast(void)
{
unsigned long page = 0;
- atomic_inc((atomic_t *)&quicklists.zeropage_calls);
+ atomic_inc((atomic_t *)&zero_cache_calls);
if ( zero_quicklist )
{
/* atomically remove this page from the list */
@@ -177,10 +180,10 @@ unsigned long get_zero_page_fast(void)
#endif /* __SMP__ */
/* we can update zerocount after the fact since it is not
* used for anything but control of a loop which doesn't
- * matter since it won't affect anything if it zero's one
+ * matter since it won't affect anything if it zeros one
* less page -- Cort
*/
- atomic_inc((atomic_t *)&quicklists.zeropage_hits);
+ atomic_inc((atomic_t *)&zero_cache_hits);
atomic_dec((atomic_t *)&zero_cache_sz);
/* zero out the pointer to next in the page */
@@ -222,7 +225,6 @@ void zero_paged(void)
/*
* Make the page no cache so we don't blow our cache with 0's
- * We should just turn off the cache instead. -- Cort
*/
pte = find_pte(init_task.mm, pageptr);
if ( !pte )
@@ -254,8 +256,8 @@ void zero_paged(void)
* So we update the list atomically without locking it.
* -- Cort
*/
+
/* turn cache on for this page */
-
pte_cache(*pte);
flush_tlb_page(find_vma(init_task.mm,pageptr),pageptr);
/* atomically add this page to the list */
@@ -280,7 +282,7 @@ void zero_paged(void)
* reads it. -- Cort
*/
atomic_inc((atomic_t *)&zero_cache_sz);
- atomic_inc((atomic_t *)&quicklists.zerototal);
+ atomic_inc((atomic_t *)&zero_cache_total);
}
}
@@ -301,11 +303,17 @@ void power_save(void)
hid0 &= ~(HID0_NAP | HID0_SLEEP | HID0_DOZE);
hid0 |= (powersave_nap? HID0_NAP: HID0_DOZE) | HID0_DPM;
asm("mtspr 1008,%0" : : "r" (hid0));
- msr |= MSR_POW;
+
+ /* set the POW bit in the MSR, and enable interrupts
+ * so we wake up sometime! */
+ _nmask_and_or_msr(0, MSR_POW | MSR_EE);
+
+ /* Disable interrupts again so restore_flags will
+ * work. */
+ _nmask_and_or_msr(MSR_EE, 0);
}
restore_flags(msr);
default:
return;
}
-
}
diff --git a/arch/ppc/kernel/indirect_pci.c b/arch/ppc/kernel/indirect_pci.c
new file mode 100644
index 000000000..641d77a52
--- /dev/null
+++ b/arch/ppc/kernel/indirect_pci.c
@@ -0,0 +1,121 @@
+/*
+ * Support for indirect PCI bridges.
+ *
+ * Copyright (C) 1998 Gabriel Paubert.
+ *
+ * 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 <asm/io.h>
+#include <asm/system.h>
+
+unsigned int * pci_config_address;
+unsigned char * pci_config_data;
+
+int indirect_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned char *val)
+{
+ unsigned flags;
+
+ save_flags(flags); cli();
+
+ out_be32(pci_config_address,
+ ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80);
+
+ *val= in_8(pci_config_data + (offset&3));
+
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int indirect_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned short *val)
+{
+ unsigned flags;
+
+ if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ save_flags(flags); cli();
+
+ out_be32(pci_config_address,
+ ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80);
+
+ *val= in_le16((unsigned short *)(pci_config_data + (offset&3)));
+
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int indirect_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned int *val)
+{
+ unsigned flags;
+
+ if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ save_flags(flags); cli();
+
+ out_be32(pci_config_address,
+ ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80);
+
+ *val= in_le32((unsigned *)pci_config_data);
+
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int indirect_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned char val)
+{
+ unsigned flags;
+
+ save_flags(flags); cli();
+
+ out_be32(pci_config_address,
+ ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80);
+
+ out_8(pci_config_data + (offset&3), val);
+
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int indirect_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned short val)
+{
+ unsigned flags;
+
+ if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ save_flags(flags); cli();
+
+ out_be32(pci_config_address,
+ ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80);
+
+ out_le16((unsigned short *)(pci_config_data + (offset&3)), val);
+
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int indirect_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned int val)
+{
+ unsigned flags;
+
+ if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ save_flags(flags); cli();
+
+ out_be32(pci_config_address,
+ ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80);
+
+ out_le32((unsigned *)pci_config_data, val);
+
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
index f4a7c7143..461e51aa1 100644
--- a/arch/ppc/kernel/irq.c
+++ b/arch/ppc/kernel/irq.c
@@ -1,5 +1,5 @@
/*
- * $Id: irq.c,v 1.91 1998/12/28 10:28:47 paulus Exp $
+ * $Id: irq.c,v 1.105 1999/03/25 19:51:51 cort Exp $
*
* arch/ppc/kernel/irq.c
*
@@ -42,6 +42,7 @@
#include <linux/malloc.h>
#include <linux/openpic.h>
#include <linux/pci.h>
+#include <linux/delay.h>
#include <asm/bitops.h>
#include <asm/hydra.h>
@@ -56,101 +57,46 @@
#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/ptrace.h>
+
+#include "local_irq.h"
-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);
+void enable_irq(unsigned int irq_nr);
+void disable_irq(unsigned int irq_nr);
+
+/* Fixme - Need to figure out a way to get rid of this - Corey */
+volatile unsigned char *chrp_int_ack_special;
#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
-#ifndef CONFIG_8xx
-void (*mask_and_ack_irq)(int irq_nr);
-void (*mask_irq)(unsigned int irq_nr);
-void (*unmask_irq)(unsigned int irq_nr);
-#else /* CONFIG_8xx */
-/* init_IRQ() happens too late for the MBX because we initialize the
- * CPM early and it calls request_irq() before we have these function
- * pointers initialized.
- */
-#define mask_and_ack_irq(irq) mbx_mask_irq(irq)
-#define mask_irq(irq) mbx_mask_irq(irq)
-#define unmask_irq(irq) mbx_unmask_irq(irq)
-#endif /* CONFIG_8xx */
-
#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;
- unsigned int enable;
- unsigned int ack;
- unsigned int level;
-};
+#endif
-/* XXX these addresses should be obtained from the device tree */
-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 MAXCOUNT 10000000
-/* 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;
+#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
-/* Returns the number of 0's to the left of the most significant 1 bit */
-static inline int cntlzw(int bits)
-{
- int lz;
+int ppc_spurious_interrupts = 0;
- asm ("cntlzw %0,%1" : "=r" (lz) : "r" (bits));
- return lz;
-}
+unsigned int ppc_local_bh_count[NR_CPUS];
+unsigned int ppc_local_irq_count[NR_CPUS];
+struct irqaction *ppc_irq_action[NR_IRQS];
+unsigned int ppc_cached_irq_mask[NR_MASK_WORDS];
+unsigned int ppc_lost_interrupts[NR_MASK_WORDS];
+atomic_t ppc_n_lost_interrupts;
-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.
+ * can't very early in the boot when we need to do a request irq.
* this needs to be removed.
* -- Cort
*/
static char cache_bitmask = 0;
-static struct irqaction malloc_cache[4];
+static struct irqaction malloc_cache[8];
extern int mem_init_done;
void *irq_kmalloc(size_t size, int pri)
@@ -179,168 +125,80 @@ void irq_kfree(void *ptr)
kfree(ptr);
}
-#ifndef CONFIG_8xx
-void i8259_mask_and_ack_irq(int irq_nr)
-{
- /* spin_lock(&irq_controller_lock);*/
- cached_irq_mask[0] |= 1 << irq_nr;
- if (irq_nr > 7) {
- inb(0xA1); /* DUMMY */
- outb(cached_A1,0xA1);
- outb(0x62,0x20); /* Specific EOI to cascade */
- /*outb(0x20,0xA0);*/
- outb(0x60|(irq_nr-8), 0xA0); /* specific eoi */
- } else {
- inb(0x21); /* DUMMY */
- outb(cached_21,0x21);
- /*outb(0x20,0x20);*/
- outb(0x60|irq_nr,0x20); /* specific eoi */
-
- }
- /* spin_unlock(&irq_controller_lock);*/
-}
-
-void __pmac pmac_mask_and_ack_irq(int irq_nr)
-{
- unsigned long bit = 1UL << (irq_nr & 0x1f);
- int i = irq_nr >> 5;
-
- if ((unsigned)irq_nr >= max_irqs)
- return;
- /*spin_lock(&irq_controller_lock);*/
-
- clear_bit(irq_nr, cached_irq_mask);
- if (test_and_clear_bit(irq_nr, lost_interrupts))
- atomic_dec(&n_lost_interrupts);
- 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");*/
-}
+struct irqdesc irq_desc[NR_IRQS] = {{0, 0}, };
-void __openfirmware chrp_mask_and_ack_irq(int irq_nr)
+int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+ unsigned long irqflags, const char * devname, void *dev_id)
{
- /* spinlocks are done by i8259_mask_and_ack() - Cort */
- if (is_8259_irq(irq_nr))
- i8259_mask_and_ack_irq(irq_nr);
-}
-
+ struct irqaction *old, **p, *action;
+ unsigned long flags;
-static void i8259_set_irq_mask(int irq_nr)
-{
- if (irq_nr > 7) {
- outb(cached_A1,0xA1);
- } else {
- outb(cached_21,0x21);
+ if (irq >= NR_IRQS)
+ return -EINVAL;
+ if (!handler)
+ {
+ /* Free */
+ for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next)
+ {
+ /* Found it - now free it */
+ save_flags(flags);
+ cli();
+ *p = action->next;
+ restore_flags(flags);
+ irq_kfree(action);
+ return 0;
+ }
+ return -ENOENT;
}
-}
-
-static void __pmac pmac_set_irq_mask(int irq_nr)
-{
- unsigned long bit = 1UL << (irq_nr & 0x1f);
- int i = irq_nr >> 5;
-
- if ((unsigned)irq_nr >= max_irqs)
- return;
-
- /* enable unmasked interrupts */
- out_le32(&pmac_irq_hw[i]->enable, cached_irq_mask[i]);
-
- /*
- * Unfortunately, setting the bit in the enable register
- * when the device interrupt is already on *doesn't* set
- * the bit in the flag register or request another interrupt.
- */
- if ((bit & cached_irq_mask[i])
- && (ld_le32(&pmac_irq_hw[i]->level) & bit)
- && !(ld_le32(&pmac_irq_hw[i]->flag) & bit)) {
- if (!test_and_set_bit(irq_nr, lost_interrupts))
- atomic_inc(&n_lost_interrupts);
+
+ action = (struct irqaction *)
+ irq_kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+ if (!action)
+ return -ENOMEM;
+
+ save_flags(flags);
+ cli();
+
+ action->handler = handler;
+ action->flags = irqflags;
+ action->mask = 0;
+ action->name = devname;
+ action->dev_id = dev_id;
+ action->next = NULL;
+ enable_irq(irq);
+
+ p = &irq_desc[irq].action;
+
+ if ((old = *p) != NULL) {
+ /* Can't share interrupts unless both agree to */
+ if (!(old->flags & action->flags & SA_SHIRQ))
+ return -EBUSY;
+ /* add new interrupt at end of irq queue */
+ do {
+ p = &old->next;
+ old = *p;
+ } while (old);
}
-}
-
-/*
- * These have to be protected by the spinlock
- * before being called.
- */
-static void i8259_mask_irq(unsigned int irq_nr)
-{
- cached_irq_mask[0] |= 1 << irq_nr;
- i8259_set_irq_mask(irq_nr);
-}
-
-static void i8259_unmask_irq(unsigned int irq_nr)
-{
- cached_irq_mask[0] &= ~(1 << irq_nr);
- i8259_set_irq_mask(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 pmac_unmask_irq(unsigned int irq_nr)
-{
- set_bit(irq_nr, cached_irq_mask);
- pmac_set_irq_mask(irq_nr);
-}
-
-static void __openfirmware chrp_mask_irq(unsigned int irq_nr)
-{
- if (is_8259_irq(irq_nr))
- i8259_mask_irq(irq_nr);
- else
- openpic_disable_irq(irq_to_openpic(irq_nr));
-}
+ *p = action;
-static void __openfirmware chrp_unmask_irq(unsigned int irq_nr)
-{
- if (is_8259_irq(irq_nr))
- i8259_unmask_irq(irq_nr);
- else
- openpic_enable_irq(irq_to_openpic(irq_nr));
-}
-#else /* CONFIG_8xx */
-static void mbx_mask_irq(unsigned int irq_nr)
-{
- cached_irq_mask[0] &= ~(1 << (31-irq_nr));
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
- cached_irq_mask[0];
+ restore_flags(flags);
+ return 0;
}
-static void mbx_unmask_irq(unsigned int irq_nr)
+void free_irq(unsigned int irq, void *dev_id)
{
- cached_irq_mask[0] |= (1 << (31-irq_nr));
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
- cached_irq_mask[0];
+ request_irq(irq, NULL, 0, NULL, dev_id);
}
-#endif /* CONFIG_8xx */
void disable_irq(unsigned int irq_nr)
{
- /*unsigned long flags;*/
-
- /* spin_lock_irqsave(&irq_controller_lock, flags);*/
mask_irq(irq_nr);
- /* spin_unlock_irqrestore(&irq_controller_lock, flags);*/
synchronize_irq();
}
void enable_irq(unsigned int irq_nr)
{
- /*unsigned long flags;*/
-
- /* spin_lock_irqsave(&irq_controller_lock, flags);*/
unmask_irq(irq_nr);
- /* spin_unlock_irqrestore(&irq_controller_lock, flags);*/
}
int get_irq_list(char *buf)
@@ -354,8 +212,8 @@ int get_irq_list(char *buf)
*(char *)(buf+len++) = '\n';
for (i = 0 ; i < NR_IRQS ; i++) {
- action = irq_action[i];
- if ((!action || !action->handler) && (i != second_irq))
+ action = irq_desc[i].action;
+ if ( !action || !action->handler )
continue;
len += sprintf(buf+len, "%3d: ", i);
#ifdef __SMP__
@@ -365,56 +223,83 @@ int get_irq_list(char *buf)
#else
len += sprintf(buf+len, "%10u ", kstat_irqs(i));
#endif /* __SMP__ */
- switch( _machine )
- {
- case _MACH_prep:
- len += sprintf(buf+len, " 82c59 ");
- break;
- case _MACH_Pmac:
- if (i < 64)
- len += sprintf(buf+len, " PMAC-PIC ");
- else
- len += sprintf(buf+len, " GATWICK ");
- break;
- case _MACH_chrp:
- if ( is_8259_irq(i) )
- len += sprintf(buf+len, " 82c59 ");
- else
- len += sprintf(buf+len, " OpenPIC ");
- break;
- case _MACH_mbx:
- len += sprintf(buf+len, " MPC8xx ");
- break;
+ if ( irq_desc[i].ctl )
+ len += sprintf(buf+len, " %s ", irq_desc[i].ctl->typename );
+ len += sprintf(buf+len, " %s",action->name);
+ for (action=action->next; action; action = action->next) {
+ len += sprintf(buf+len, ", %s", action->name);
}
-
- 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");
+ len += sprintf(buf+len, "\n");
}
#ifdef __SMP__
/* should this be per processor send/receive? */
- 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, "IPI: %10lu\n", ipi_count);
#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, "BAD: %10u\n", ppc_spurious_interrupts);
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..
+ * Eventually, this should take an array of interrupts and an array size
+ * so it can dispatch multiple interrupts.
*/
+void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
+{
+ int status;
+ struct irqaction *action;
+ int cpu = smp_processor_id();
+
+ mask_and_ack_irq(irq);
+ status = 0;
+ action = irq_desc[irq].action;
+ kstat.irqs[cpu][irq]++;
+ if (action && action->handler) {
+ if (!(action->flags & SA_INTERRUPT))
+ __sti();
+ do {
+ status |= action->flags;
+ action->handler(irq, action->dev_id, regs);
+ action = action->next;
+ } while ( action );
+ __cli();
+ unmask_irq(irq);
+ } else {
+ ppc_spurious_interrupts++;
+ disable_irq( irq );
+ }
+}
+
+asmlinkage void do_IRQ(struct pt_regs *regs, int isfake)
+{
+ int cpu = smp_processor_id();
+
+ hardirq_enter(cpu);
+ ppc_md.do_IRQ(regs, cpu, isfake);
+ hardirq_exit(cpu);
+}
+
+unsigned long probe_irq_on (void)
+{
+ return 0;
+}
+
+int probe_irq_off (unsigned long irqs)
+{
+ return 0;
+}
+
+void __init init_IRQ(void)
+{
+ static int once = 0;
+
+ if ( once )
+ return;
+ else
+ once++;
+
+ ppc_md.init_IRQ();
+}
+
#ifdef __SMP__
unsigned char global_irq_holder = NO_PROC_ID;
unsigned volatile int global_irq_lock;
@@ -431,9 +316,13 @@ static void show(char * str)
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]);
+ atomic_read(&global_irq_count),
+ ppc_local_irq_count[0],
+ ppc_local_irq_count[1]);
printk("bh: %d [%d %d]\n",
- atomic_read(&global_bh_count), local_bh_count[0], local_bh_count[1]);
+ atomic_read(&global_bh_count),
+ ppc_local_bh_count[0],
+ ppc_local_bh_count[1]);
stack = (unsigned long *) &str;
for (i = 40; i ; i--) {
unsigned long x = *++stack;
@@ -443,7 +332,6 @@ static void show(char * str)
}
}
-#define MAXCOUNT 100000000
static inline void wait_on_bh(void)
{
int count = MAXCOUNT;
@@ -469,7 +357,8 @@ static inline void wait_on_irq(int cpu)
* already executing in one..
*/
if (!atomic_read(&global_irq_count)) {
- if (local_bh_count[cpu] || !atomic_read(&global_bh_count))
+ if (ppc_local_bh_count[cpu]
+ || !atomic_read(&global_bh_count))
break;
}
@@ -490,7 +379,8 @@ static inline void wait_on_irq(int cpu)
continue;
if (global_irq_lock)
continue;
- if (!local_bh_count[cpu] && atomic_read(&global_bh_count))
+ if (!ppc_local_bh_count[cpu]
+ && atomic_read(&global_bh_count))
continue;
if (!test_and_set_bit(0,&global_irq_lock))
break;
@@ -512,7 +402,6 @@ void synchronize_bh(void)
wait_on_bh();
}
-
/*
* This is called when we want to synchronize with
* interrupts. We may for example tell a device to
@@ -581,7 +470,7 @@ void __global_cli(void)
if (flags & (1 << 15)) {
int cpu = smp_processor_id();
__cli();
- if (!local_irq_count[cpu])
+ if (!ppc_local_irq_count[cpu])
get_irqlock(cpu);
}
}
@@ -590,7 +479,7 @@ void __global_sti(void)
{
int cpu = smp_processor_id();
- if (!local_irq_count[cpu])
+ if (!ppc_local_irq_count[cpu])
release_irqlock(cpu);
__sti();
}
@@ -614,7 +503,7 @@ unsigned long __global_save_flags(void)
retval = 2 + local_enabled;
/* check for global flags if we're not in an interrupt */
- if (!local_irq_count[smp_processor_id()]) {
+ if (!ppc_local_irq_count[smp_processor_id()]) {
if (local_enabled)
retval = 1;
if (global_irq_holder == (unsigned char) smp_processor_id())
@@ -623,6 +512,31 @@ unsigned long __global_save_flags(void)
return retval;
}
+int
+tb(long vals[],
+ int max_size)
+{
+ register unsigned long *orig_sp __asm__ ("r1");
+ register unsigned long lr __asm__ ("r3");
+ unsigned long *sp;
+ int i;
+
+ asm volatile ("mflr 3");
+ vals[0] = lr;
+ sp = (unsigned long *) *orig_sp;
+ sp = (unsigned long *) *sp;
+ for (i=1; i<max_size; i++) {
+ if (sp == 0) {
+ break;
+ }
+
+ vals[i] = *(sp+1);
+ sp = (unsigned long *) *sp;
+ }
+
+ return i;
+}
+
void __global_restore_flags(unsigned long flags)
{
switch (flags) {
@@ -639,559 +553,21 @@ void __global_restore_flags(unsigned long flags)
__sti();
break;
default:
- printk("global_restore_flags: %08lx (%08lx)\n",
- flags, (&flags)[-1]);
- }
-}
-
-#endif /* __SMP__ */
-
-asmlinkage void do_IRQ(struct pt_regs *regs, int isfake)
-{
- int irq;
- unsigned long bits;
- struct irqaction *action;
- int cpu = smp_processor_id();
- int status;
- int openpic_eoi_done = 0;
-
- /* save the HID0 in case dcache was off - see idle.c
- * this hack should leave for a better solution -- Cort */
- unsigned dcache_locked;
-
- dcache_locked = unlock_dcache();
- hardirq_enter(cpu);
-#ifndef CONFIG_8xx
-#ifdef __SMP__
- if ( cpu != 0 )
- {
- if (!isfake)
- {
- extern void smp_message_recv(void);
-#ifdef CONFIG_XMON
- static int xmon_2nd;
- if (xmon_2nd)
- xmon(regs);
-#endif
- smp_message_recv();
- goto out;
- }
- /* could be here due to a do_fake_interrupt call but we don't
- mess with the controller from the second cpu -- Cort */
- goto out;
- }
-
- {
- unsigned int loops = MAXCOUNT;
- while (test_bit(0, &global_irq_lock)) {
- if (smp_processor_id() == global_irq_holder) {
- printk("uh oh, interrupt while we hold global irq lock!\n");
-#ifdef CONFIG_XMON
- xmon(0);
-#endif
- break;
- }
- if (loops-- == 0) {
- printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
-#ifdef CONFIG_XMON
- xmon(0);
-#endif
- }
- }
- }
-#endif /* __SMP__ */
-
- switch ( _machine )
- {
- case _MACH_Pmac:
- 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;
- 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);
- if (irq == IRQ_8259_CASCADE)
- {
- /*
- * This magic address generates a PCI IACK cycle.
- *
- * This should go in the above mask/ack code soon. -- Cort
- */
- irq = *chrp_int_ack_special;
- /*
- * Acknowledge as soon as possible to allow i8259
- * interrupt nesting
- */
- openpic_eoi(0);
- openpic_eoi_done = 1;
- }
- else if (irq >= OPENPIC_VEC_TIMER)
- {
- /*
- * OpenPIC interrupts >64 will be used for other purposes
- * like interprocessor interrupts and hardware errors
- */
- if (irq == OPENPIC_VEC_SPURIOUS) {
- /*
- * Spurious interrupts should never be
- * acknowledged
- */
- spurious_interrupts++;
- openpic_eoi_done = 1;
- } else {
- /*
- * Here we should process IPI timer
- * for now the interrupt is dismissed.
- */
- }
- goto out;
- }
- break;
- case _MACH_prep:
- outb(0x0C, 0x20);
- irq = inb(0x20) & 7;
- if (irq == 2)
- {
-retry_cascade:
- outb(0x0C, 0xA0);
- irq = inb(0xA0);
- /* if no intr left */
- if ( !(irq & 128 ) )
- goto out;
- irq = (irq&7) + 8;
- }
- bits = 1UL << irq;
- break;
-#ifdef CONFIG_APUS
- case _MACH_apus:
{
- int old_level, new_level;
-
- old_level = ~(regs->mq) & IPLEMU_IPLMASK;
- new_level = (~(regs->mq) >> 3) & IPLEMU_IPLMASK;
-
- if (new_level == 0)
- {
- goto apus_out;
- }
-
- APUS_WRITE(APUS_IPL_EMU, IPLEMU_IPLMASK);
- APUS_WRITE(APUS_IPL_EMU, (IPLEMU_SETRESET
- | (~(new_level) & IPLEMU_IPLMASK)));
- APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT);
-
- process_int (VEC_SPUR+new_level, regs);
-
- APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_DISABLEINT);
- APUS_WRITE(APUS_IPL_EMU, IPLEMU_IPLMASK);
- APUS_WRITE(APUS_IPL_EMU, (IPLEMU_SETRESET
- | (~(old_level) & IPLEMU_IPLMASK)));
-
-apus_out:
- hardirq_exit(cpu);
- APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT);
- goto out2;
- }
-#endif
- }
-
- if (irq < 0) {
- /* we get here with Gatwick but the 'bogus' isn't correct in that case -- Cort */
- if ( irq != second_irq )
- {
- 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
- * to get the irq number.
- */
- bits = ((immap_t *)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]++;
- if (action && action->handler) {
- if (!(action->flags & SA_INTERRUPT))
- __sti();
- do {
- status |= action->flags;
- action->handler(irq, action->dev_id, regs);
- action = action->next;
- } while ( action );
- __cli();
- unmask_irq(irq);
- } else {
-#ifndef CONFIG_8xx
- if ( irq == 7 ) /* i8259 gives us irq 7 on 'short' intrs */
-#endif
- spurious_interrupts++;
- 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
- if ( is_prep && (irq > 7) )
- goto retry_cascade;
- /* do_bottom_half is called if necessary from int_return in head.S */
-out:
- if (_machine == _MACH_chrp && !openpic_eoi_done)
- openpic_eoi(0);
-#endif /* CONFIG_8xx */
- hardirq_exit(cpu);
-
-#ifdef CONFIG_APUS
-out2:
-#endif
- /* restore the HID0 in case dcache was off - see idle.c
- * this hack should leave for a better solution -- Cort */
- lock_dcache(dcache_locked);
-}
-
-int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
- unsigned long irqflags, const char * devname, void *dev_id)
-{
- struct irqaction *old, **p, *action;
- unsigned long flags;
-
-#ifdef SHOW_IRQ
- printk("request_irq(): irq %d handler %08x name %s dev_id %04x\n",
- 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;
+ unsigned long trace[5];
+ int count;
+ int i;
- if (!handler)
- {
- /* Free */
- for (p = irq + irq_action; (action = *p) != NULL; p = &action->next)
- {
- /* Found it - now free it */
- save_flags(flags);
- cli();
- *p = action->next;
- restore_flags(flags);
- irq_kfree(action);
- return 0;
- }
- return -ENOENT;
- }
-
- action = (struct irqaction *)
- irq_kmalloc(sizeof(struct irqaction), GFP_KERNEL);
- if (!action)
- return -ENOMEM;
- save_flags(flags);
- cli();
-
- action->handler = handler;
- action->flags = irqflags;
- action->mask = 0;
- action->name = devname;
- action->dev_id = dev_id;
- action->next = NULL;
- enable_irq(irq);
- p = irq_action + irq;
-
- if ((old = *p) != NULL) {
- /* Can't share interrupts unless both agree to */
- if (!(old->flags & action->flags & SA_SHIRQ))
- return -EBUSY;
- /* add new interrupt at end of irq queue */
- do {
- p = &old->next;
- old = *p;
- } while (old);
- }
- *p = action;
-
- restore_flags(flags);
- return 0;
-}
-
-void free_irq(unsigned int irq, void *dev_id)
-{
- request_irq(irq, NULL, 0, NULL, dev_id);
-}
-
-unsigned long probe_irq_on (void)
-{
- return 0;
-}
-
-int probe_irq_off (unsigned long irqs)
-{
- return 0;
-}
-
-#ifndef CONFIG_8xx
-__initfunc(static void i8259_init(void))
-{
- /* init master interrupt controller */
- outb(0x11, 0x20); /* Start init sequence */
- outb(0x00, 0x21); /* Vector base */
- outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
- outb(0x01, 0x21); /* Select 8086 mode */
- outb(0xFF, 0x21); /* Mask all */
-
- /* init slave interrupt controller */
- outb(0x11, 0xA0); /* Start init sequence */
- outb(0x08, 0xA1); /* Vector base */
- outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */
- outb(0x01, 0xA1); /* Select 8086 mode */
- outb(0xFF, 0xA1); /* Mask all */
- outb(cached_A1, 0xA1);
- outb(cached_21, 0x21);
- if (request_irq(2, no_action, SA_INTERRUPT, "cascade", NULL) != 0)
- panic("Could not allocate cascade IRQ!");
- enable_irq(2); /* Enable cascade interrupt */
-}
-#endif /* CONFIG_8xx */
-
-/* On MBX8xx, the interrupt control (SIEL) was set by EPPC-bug. External
- * interrupts can be either edge or level triggered, but there is no
- * reason for us to change the EPPC-bug values (it would not work if we did).
- */
-__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)
- {
- case _MACH_Pmac:
- mask_and_ack_irq = pmac_mask_and_ack_irq;
- mask_irq = pmac_mask_irq;
- unmask_irq = pmac_unmask_irq;
-
- /* 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(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;
-
- 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
- request_irq(openpic_to_irq(HYDRA_INT_ADB_NMI),
- xmon_irq, 0, "NMI", 0);
-#endif /* CONFIG_XMON */
- break;
- case _MACH_prep:
- mask_and_ack_irq = i8259_mask_and_ack_irq;
- mask_irq = i8259_mask_irq;
- unmask_irq = i8259_unmask_irq;
- cached_irq_mask[0] = ~0UL;
-
- i8259_init();
- /*
- * According to the Carolina spec from ibm irqs 0,1,2, and 8
- * must be edge triggered. Also, the pci intrs must be level
- * triggered and _only_ isa intrs can be level sensitive
- * which are 3-7,9-12,14-15. 13 is special - it can be level.
- *
- * power on default is 0's in both regs - all edge.
- *
- * These edge/level control regs allow edge/level status
- * to be decided on a irq basis instead of on a PIC basis.
- * It's still pretty ugly.
- * - Cort
- */
- {
- unsigned char irq_mode1 = 0, irq_mode2 = 0;
- irq_mode1 = 0; /* to get rid of compiler warnings */
- /*
- * On Carolina, irq 15 and 13 must be level (scsi/ide/net).
- */
- if ( _prep_type == _PREP_IBM )
- irq_mode2 |= 0xa0;
+ printk("global_restore_flags: %08lx (%08lx)\n",
+ flags, (&flags)[-1]);
+ count = tb(trace, 5);
+ printk("tb:");
+ for(i=0; i<count; i++) {
+ printk(" %8.8lx", trace[i]);
}
- break;
-#ifdef CONFIG_APUS
- case _MACH_apus:
- mask_irq = amiga_disable_irq;
- unmask_irq = amiga_enable_irq;
- apus_init_IRQ();
- break;
-#endif
+ printk("\n");
}
-#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
- */
-static void __init 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;
}
-
}
+#endif /* __SMP__ */
diff --git a/arch/ppc/kernel/local_irq.h b/arch/ppc/kernel/local_irq.h
new file mode 100644
index 000000000..5149c291a
--- /dev/null
+++ b/arch/ppc/kernel/local_irq.h
@@ -0,0 +1,45 @@
+
+#ifndef _PPC_KERNEL_LOCAL_IRQ_H
+#define _PPC_KERNEL_LOCAL_IRQ_H
+
+#include <linux/kernel_stat.h>
+#include <linux/interrupt.h>
+
+void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq);
+
+/* Structure describing interrupts */
+struct hw_interrupt_type {
+ const char * typename;
+ void (*startup)(unsigned int irq);
+ void (*shutdown)(unsigned int irq);
+ void (*handle)(unsigned int irq, struct pt_regs * regs);
+ void (*enable)(unsigned int irq);
+ void (*disable)(unsigned int irq);
+ void (*mask_and_ack)(unsigned int irq);
+ int irq_offset;
+};
+
+#define mask_irq(irq) ({if (irq_desc[irq].ctl && irq_desc[irq].ctl->disable) irq_desc[irq].ctl->disable(irq);})
+#define unmask_irq(irq) ({if (irq_desc[irq].ctl && irq_desc[irq].ctl->enable) irq_desc[irq].ctl->enable(irq);})
+#define mask_and_ack_irq(irq) ({if (irq_desc[irq].ctl && irq_desc[irq].ctl->mask_and_ack) irq_desc[irq].ctl->mask_and_ack(irq);})
+
+struct irqdesc {
+ struct irqaction *action;
+ struct hw_interrupt_type *ctl;
+};
+
+extern struct irqdesc irq_desc[NR_IRQS];
+
+
+#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
+
+extern int ppc_spurious_interrupts;
+extern int ppc_second_irq;
+extern struct irqaction *ppc_irq_action[NR_IRQS];
+extern unsigned int ppc_local_bh_count[NR_CPUS];
+extern unsigned int ppc_local_irq_count[NR_CPUS];
+extern unsigned int ppc_cached_irq_mask[NR_MASK_WORDS];
+extern unsigned int ppc_lost_interrupts[NR_MASK_WORDS];
+extern atomic_t ppc_n_lost_interrupts;
+
+#endif /* _PPC_KERNEL_LOCAL_IRQ_H */
diff --git a/arch/ppc/kernel/mbx_pci.c b/arch/ppc/kernel/mbx_pci.c
index 30b7b1184..5114c3cfb 100644
--- a/arch/ppc/kernel/mbx_pci.c
+++ b/arch/ppc/kernel/mbx_pci.c
@@ -252,3 +252,20 @@ int mbx_pcibios_find_class(unsigned int class_code, unsigned short index,
}
return PCIBIOS_DEVICE_NOT_FOUND;
}
+
+__initfunc(
+void
+mbx_pcibios_fixup(void))
+{
+ /* Nothing to do here? */
+}
+
+__initfunc(
+void
+mbx_setup_pci_ptrs(void))
+{
+ set_config_access_method(mbx);
+
+ ppc_md.pcibios_fixup = mbx_pcibios_fixup;
+}
+
diff --git a/arch/ppc/kernel/mbx_setup.c b/arch/ppc/kernel/mbx_setup.c
index 90647dcd9..0f1eb3eb5 100644
--- a/arch/ppc/kernel/mbx_setup.c
+++ b/arch/ppc/kernel/mbx_setup.c
@@ -1,5 +1,5 @@
/*
- * $Id: mbx_setup.c,v 1.5 1998/12/29 18:55:07 cort Exp $
+ * $Id: mbx_setup.c,v 1.9 1999/04/28 11:54:09 davem Exp $
*
* linux/arch/ppc/kernel/setup.c
*
@@ -39,6 +39,22 @@
#include <asm/pgtable.h>
#include <asm/ide.h>
#include <asm/mbx.h>
+#include <asm/machdep.h>
+
+#include "time.h"
+#include "local_irq.h"
+
+static int mbx_set_rtc_time(unsigned long time);
+unsigned long mbx_get_rtc_time(void);
+void mbx_calibrate_decr(void);
+
+extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int mackbd_getkeycode(unsigned int scancode);
+extern int mackbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode);
+extern char mackbd_unexpected_up(unsigned char keycode);
+extern void mackbd_leds(unsigned char leds);
+extern void mackbd_init_hw(void);
extern unsigned long loops_per_sec;
@@ -55,35 +71,10 @@ extern char saved_command_line[256];
extern unsigned long find_available_memory(void);
extern void m8xx_cpm_reset(uint);
-/* this really does make things cleaner -- Cort */
-void __init powermac_init(void)
-{
-}
-
void __init adbdev_init(void)
{
}
-void __init mbx_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++ = base + 0x206;
- if (irq != NULL)
- *irq = 0;
-#ifdef ATA_FLASH
- base = (unsigned long) ioremap(PCMCIA_MEM_ADDR, 0x200);
- for (i = 0; i < 8; ++i)
- *p++ = base++;
- *p = ++base; /* Does not matter */
- if (irq)
- *irq = 13;
-#endif
-}
-
__initfunc(void
mbx_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
{
@@ -145,3 +136,337 @@ abort(void)
#endif
machine_restart(NULL);
}
+
+/* The decrementer counts at the system (internal) clock frequency divided by
+ * sixteen, or external oscillator divided by four. Currently, we only
+ * support the MBX, which is system clock divided by sixteen.
+ */
+__initfunc(void mbx_calibrate_decr(void))
+{
+ bd_t *binfo = (bd_t *)&res;
+ int freq, fp, divisor;
+
+ if ((((immap_t *)MBX_IMAP_ADDR)->im_clkrst.car_sccr & 0x02000000) == 0)
+ printk("WARNING: Wrong decrementer source clock.\n");
+
+ /* The manual says the frequency is in Hz, but it is really
+ * as MHz. The value 'fp' is the number of decrementer ticks
+ * per second.
+ */
+ fp = (binfo->bi_intfreq * 1000000) / 16;
+ freq = fp*60; /* try to make freq/1e6 an integer */
+ divisor = 60;
+ printk("time_init: decrementer frequency = %d/%d\n", freq, divisor);
+ decrementer_count = freq / HZ / divisor;
+ count_period_num = divisor;
+ count_period_den = freq / 1000000;
+}
+
+/* A place holder for time base interrupts, if they are ever enabled.
+*/
+void timebase_interrupt(int irq, void * dev, struct pt_regs * regs)
+{
+ printk("timebase_interrupt()\n");
+}
+
+/* The RTC on the MPC8xx is an internal register.
+ * We want to protect this during power down, so we need to unlock,
+ * modify, and re-lock.
+ */
+static int
+mbx_set_rtc_time(unsigned long time)
+{
+ ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY;
+ ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtc = time;
+ ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY;
+ return(0);
+}
+
+initfunc(unsigned long
+mbx_get_rtc_time(void)
+{
+ /* First, unlock all of the registers we are going to modify.
+ * To protect them from corruption during power down, registers
+ * that are maintained by keep alive power are "locked". To
+ * modify these registers we have to write the key value to
+ * the key location associated with the register.
+ */
+ ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_tbscrk = KAPWR_KEY;
+ ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtcsck = KAPWR_KEY;
+
+
+ /* Disable the RTC one second and alarm interrupts.
+ */
+ ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtcsc &=
+ ~(RTCSC_SIE | RTCSC_ALE);
+
+ /* Enabling the decrementer also enables the timebase interrupts
+ * (or from the other point of view, to get decrementer interrupts
+ * we have to enable the timebase). The decrementer interrupt
+ * is wired into the vector table, nothing to do here for that.
+ */
+ ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_tbscr =
+ ((mk_int_int_mask(DEC_INTERRUPT) << 8) |
+ (TBSCR_TBF | TBSCR_TBE));
+ if (request_irq(DEC_INTERRUPT, timebase_interrupt, 0, "tbint", NULL) != 0)
+ panic("Could not allocate timer IRQ!");
+
+ /* Get time from the RTC.
+ */
+ return ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtc;
+}
+
+void
+mbx_restart(char *cmd)
+{
+ extern void MBX_gorom(void);
+
+ MBX_gorom();
+}
+
+void
+mbx_power_off(void)
+{
+ mbx_restart(NULL);
+}
+
+void
+mbx_halt(void)
+{
+ mbx_restart(NULL)
+}
+
+
+int mbx_setup_residual(char *buffer)
+{
+ int len = 0;
+ bd_t *bp;
+ extern RESIDUAL *res;
+
+ bp = (bd_t *)res;
+
+ len += sprintf(len+buffer,"clock\t\t: %dMHz\n"
+ "bus clock\t: %dMHz\n",
+ bp->bi_intfreq /*/ 1000000*/,
+ bp->bi_busfreq /*/ 1000000*/);
+
+ return len;
+}
+
+void
+mbx_do_IRQ(struct pt_regs *regs,
+ int cpu,
+ int isfake)
+{
+ int irq;
+ unsigned long bits = 0;
+
+ /* For MPC8xx, read the SIVEC register and shift the bits down
+ * to get the irq number. */
+ bits = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec;
+ irq = bits >> 26;
+ irq += ppc8xx_pic.irq_offset;
+ bits = 1UL << irq;
+
+ if (irq < 0) {
+ printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
+ irq, regs->nip);
+ spurious_interrupts++;
+ }
+ else {
+ ppc_irq_dispatch_handler( regs, irq );
+ }
+
+}
+
+static void mbx_i8259_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+ int bits, irq;
+
+ /* A bug in the QSpan chip causes it to give us 0xff always
+ * when doing a character read. So read 32 bits and shift.
+ * This doesn't seem to return useful values anyway, but
+ * read it to make sure things are acked.
+ * -- Cort
+ */
+ irq = (inl(0x508) >> 24)&0xff;
+ if ( irq != 0xff ) printk("iack %d\n", irq);
+
+ outb(0x0C, 0x20);
+ irq = inb(0x20) & 7;
+ if (irq == 2)
+ {
+ outb(0x0C, 0xA0);
+ irq = inb(0xA0);
+ irq = (irq&7) + 8;
+ }
+ bits = 1UL << irq;
+ irq += i8259_pic.irq_offset;
+ ppc_irq_dispatch_handler( regs, irq );
+}
+
+
+/* On MBX8xx, the interrupt control (SIEL) was set by EPPC-bug. External
+ * interrupts can be either edge or level triggered, but there is no
+ * reason for us to change the EPPC-bug values (it would not work if we did).
+ */
+__initfunc(void
+mbx_init_IRQ(void))
+{
+ int i;
+
+ ppc8xx_pic.irq_offset = 16;
+ for ( i = 16 ; i < 32 ; i++ )
+ irq_desc[i].ctl = &ppc8xx_pic;
+ unmask_irq(CPM_INTERRUPT);
+
+ for ( i = 0 ; i < 16 ; i++ )
+ irq_desc[i].ctl = &i8259_pic;
+ i8259_init();
+ request_irq(ISA_BRIDGE_INT, mbx_i8259_action, 0, "8259 cascade", NULL);
+ enable_irq(ISA_BRIDGE_INT);
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */
+void
+mbx_ide_insw(ide_ioreg_t port, void *buf, int ns)
+{
+ ide_insw(port+_IO_BASE), buf, ns);
+}
+
+void
+mbx_ide_outsw(ide_ioreg_t port, void *buf, int ns)
+{
+ ide_outsw(port+_IO_BASE, buf, ns);
+}
+
+int
+mbx_ide_default_irq(ide_ioreg_t base)
+{
+ return 14;
+}
+
+ide_ioreg_t
+mbx_ide_default_io_base(int index)
+{
+ return index;
+}
+
+int
+mbx_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+ return 0
+}
+
+void
+mbx_ide_request_region(ide_ioreg_t from,
+ unsigned int extent,
+ const char *name)
+{
+}
+
+void
+mbx_ide_release_region(ide_ioreg_t from,
+ unsigned int extent)
+{
+}
+
+void
+mbx_ide_fix_driveid(struct hd_driveid *id)
+{
+ ppc_generic_ide_fix_driveid(id);
+}
+
+void __init mbx_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++ = base + 0x206;
+ if (irq != NULL)
+ *irq = 0;
+#ifdef ATA_FLASH
+ base = (unsigned long) ioremap(PCMCIA_MEM_ADDR, 0x200);
+ for (i = 0; i < 8; ++i)
+ *p++ = base++;
+ *p = ++base; /* Does not matter */
+ if (irq)
+ *irq = 13;
+#endif
+}
+#endif
+
+__initfunc(void
+mbx_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7))
+{
+
+ if ( r3 )
+ memcpy( (void *)&res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+
+#ifdef CONFIG_PCI
+ mbx_setup_pci_ptrs();
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* take care of initrd if we have one */
+ if ( r4 )
+ {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+ /* take care of cmd line */
+ if ( r6 )
+ {
+
+ *(char *)(r7+KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6+KERNELBASE));
+ }
+
+ ppc_md.setup_arch = mbx_setup_arch;
+ ppc_md.setup_residual = mbx_setup_residual;
+ ppc_md.get_cpuinfo = NULL;
+ ppc_md.irq_cannonicalize = NULL;
+ ppc_md.init_IRQ = mbx_init_IRQ;
+ ppc_md.do_IRQ = mbx_do_IRQ;
+ ppc_md.init = NULL;
+
+ ppc_md.restart = mbx_restart;
+ ppc_md.power_off = mbx_power_off;
+ ppc_md.halt = mbx_halt;
+
+ ppc_md.time_init = NULL;
+ ppc_md.set_rtc_time = mbx_set_rtc_time;
+ ppc_md.get_rtc_time = mbx_get_rtc_time;
+ ppc_md.calibrate_decr = mbx_calibrate_decr;
+
+ ppc_md.kbd_setkeycode = pckbd_setkeycode;
+ ppc_md.kbd_getkeycode = pckbd_getkeycode;
+ ppc_md.kbd_translate = pckbd_translate;
+ ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
+ ppc_md.kbd_leds = pckbd_leds;
+ ppc_md.kbd_init_hw = pckbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.kbd_sysrq_xlate = pckbd_sysrq_xlate;
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ ppc_ide_md.insw = mbx_ide_insw;
+ ppc_ide_md.outsw = mbx_ide_outsw;
+ ppc_ide_md.default_irq = mbx_ide_default_irq;
+ ppc_ide_md.default_io_base = mbx_ide_default_io_base;
+ ppc_ide_md.check_region = mbx_ide_check_region;
+ ppc_ide_md.request_region = mbx_ide_request_region;
+ ppc_ide_md.release_region = mbx_ide_release_region;
+ ppc_ide_md.fix_driveid = mbx_ide_fix_driveid;
+ ppc_ide_md.ide_init_hwif = mbx_ide_init_hwif_ports;
+
+ ppc_ide_md.io_base = _IO_BASE;
+#endif
+}
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index e4589b1e0..cbeb4ffce 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -36,6 +36,7 @@
* Returns (address we're running at) - (address we were linked at)
* for use before the text and data are mapped to KERNELBASE.
*/
+
_GLOBAL(reloc_offset)
mflr r0
bl 1f
@@ -72,8 +73,8 @@ _GLOBAL(_enable_interrupts)
beqlr /* nothing to do if state == 0 */
_GLOBAL(__sti)
_GLOBAL(_hard_sti)
- lis r4,n_lost_interrupts@ha
- lwz r4,n_lost_interrupts@l(r4)
+ lis r4,ppc_n_lost_interrupts@ha
+ lwz r4,ppc_n_lost_interrupts@l(r4)
mfmsr r3 /* Get current state */
ori r3,r3,MSR_EE /* Turn on 'EE' bit */
cmpi 0,r4,0 /* lost interrupts to process first? */
@@ -93,8 +94,8 @@ do_lost_interrupts:
stw r0,20(r1)
stw r3,8(r1)
1: bl fake_interrupt
- lis r4,n_lost_interrupts@ha
- lwz r4,n_lost_interrupts@l(r4)
+ lis r4,ppc_n_lost_interrupts@ha
+ lwz r4,ppc_n_lost_interrupts@l(r4)
cmpi 0,r4,0
bne- 1b
lwz r3,8(r1)
@@ -105,11 +106,31 @@ do_lost_interrupts:
addi r1,r1,16
blr
+
+/*
+ * complement mask on the msr then "or" some values on.
+ * _nmask_and_or_msr(nmask, value_to_or)
+ */
+ _GLOBAL(_nmask_and_or_msr)
+ mfmsr r0 /* Get current msr */
+ andc r0,r0,r3 /* And off the bits set in r3 (first parm) */
+ or r0,r0,r4 /* Or on the bits in r4 (second parm) */
+ sync /* Some chip revs have problems here... */
+ mtmsr r0 /* Update machine state */
+ blr /* Done */
+
+
/*
* Flush MMU TLB
*/
_GLOBAL(_tlbia)
+ sync
tlbia
+ sync
+#ifdef __SMP__
+ tlbsync
+ sync
+#endif
blr
/*
@@ -117,11 +138,17 @@ _GLOBAL(_tlbia)
*/
_GLOBAL(_tlbie)
tlbie r3
+ sync
+#ifdef __SMP__
+ tlbsync
+ sync
+#endif
blr
+
/*
* Atomic [test&set] exchange
*
- * void *xchg_u32(void *ptr, unsigned long val)
+ * unsigned long xchg_u32(void *ptr, unsigned long val)
* Changes the memory location '*ptr' to be val and returns
* the previous value stored there.
*/
@@ -133,6 +160,27 @@ _GLOBAL(xchg_u32)
blr
/*
+ * Try to acquire a spinlock.
+ * Only does the stwcx. if the load returned 0 - the Programming
+ * Environments Manual suggests not doing unnecessary stcwx.'s
+ * since they may inhibit forward progress by other CPUs in getting
+ * a lock.
+ */
+_GLOBAL(__spin_trylock)
+ mr r4,r3
+ eieio /* prevent reordering of stores */
+ li r5,-1
+ lwarx r3,0,r4 /* fetch old value, establish reservation */
+ cmpwi 0,r3,0 /* is it 0? */
+ bnelr- /* return failure if not */
+ stwcx. r5,0,r4 /* try to update with new value */
+ bne- 1f /* if we failed */
+ eieio /* prevent reordering of stores */
+ blr
+1: li r3,1 /* return non-zero for failure */
+ blr
+
+/*
* Atomic add/sub/inc/dec operations
*
* void atomic_add(int c, int *v)
@@ -590,6 +638,16 @@ cvt_df:
stfd 0,-4(r5)
blr
+ .globl __clear_msr_me
+__clear_msr_me:
+ mfmsr r0 /* Get current interrupt state */
+ lis r3,0
+ ori r3,r3,MSR_ME
+ andc r0,r0,r3 /* Clears bit in (r4) */
+ sync /* Some chip revs have problems here */
+ mtmsr r0 /* Update machine state */
+ blr
+
/*
* Fetch the current SR register
* get_SR(int index)
@@ -608,6 +666,8 @@ _GLOBAL(__kernel_thread)
sc
cmpi 0,r3,0 /* parent or child? */
bnelr /* return if parent */
+ li r0,0 /* clear out p->tss.regs */
+ stw r0,TSS+PT_REGS(r2) /* since we don't have user ctx */
mtlr r4 /* fn addr in lr */
mr r3,r5 /* load arg and call fn */
blrl
@@ -836,4 +896,5 @@ sys_call_table:
.long sys_sendfile
.long sys_ni_syscall /* streams1 */
.long sys_ni_syscall /* streams2 */
+ .long sys_vfork
.space (NR_syscalls-183)*4
diff --git a/arch/ppc/kernel/mk_defs.c b/arch/ppc/kernel/mk_defs.c
index 9b51a6cc1..b66ccffa8 100644
--- a/arch/ppc/kernel/mk_defs.c
+++ b/arch/ppc/kernel/mk_defs.c
@@ -29,7 +29,7 @@
int
main(void)
{
- DEFINE(KERNELBASE, KERNELBASE);
+ /*DEFINE(KERNELBASE, KERNELBASE);*/
DEFINE(STATE, offsetof(struct task_struct, state));
DEFINE(NEXT_TASK, offsetof(struct task_struct, next_task));
DEFINE(COUNTER, offsetof(struct task_struct, counter));
@@ -48,7 +48,6 @@ main(void)
DEFINE(NEED_RESCHED, offsetof(struct task_struct, need_resched));
DEFINE(TSS_FPR0, offsetof(struct thread_struct, fpr[0]));
DEFINE(TSS_FPSCR, offsetof(struct thread_struct, fpscr));
- DEFINE(TSS_SMP_FORK_RET, offsetof(struct thread_struct, smp_fork_ret));
/* Interrupt register frame */
DEFINE(TASK_UNION_SIZE, sizeof(union task_union));
DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
diff --git a/arch/ppc/kernel/open_pic.c b/arch/ppc/kernel/open_pic.c
new file mode 100644
index 000000000..2ca879dd8
--- /dev/null
+++ b/arch/ppc/kernel/open_pic.c
@@ -0,0 +1,48 @@
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/openpic.h>
+#include <asm/irq.h>
+#include "open_pic.h"
+#include "i8259.h"
+
+#ifdef __SMP__
+void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+ smp_message_recv();
+}
+#endif /* __SMP__ */
+
+void chrp_mask_and_ack_irq(unsigned int irq_nr)
+{
+ if (is_8259_irq(irq_nr))
+ i8259_pic.mask_and_ack(irq_nr);
+}
+
+static void chrp_mask_irq(unsigned int irq_nr)
+{
+ if (is_8259_irq(irq_nr))
+ i8259_pic.disable(irq_nr);
+ else
+ openpic_disable_irq(irq_to_openpic(irq_nr));
+}
+
+static void chrp_unmask_irq(unsigned int irq_nr)
+{
+ if (is_8259_irq(irq_nr))
+ i8259_pic.enable(irq_nr);
+ else
+ openpic_enable_irq(irq_to_openpic(irq_nr));
+}
+
+struct hw_interrupt_type open_pic = {
+ " OpenPIC ",
+ NULL,
+ NULL,
+ NULL,
+ chrp_unmask_irq,
+ chrp_mask_irq,
+ chrp_mask_and_ack_irq,
+ 0
+};
diff --git a/arch/ppc/kernel/open_pic.h b/arch/ppc/kernel/open_pic.h
new file mode 100644
index 000000000..77b8a46d0
--- /dev/null
+++ b/arch/ppc/kernel/open_pic.h
@@ -0,0 +1,11 @@
+
+#ifndef _PPC_KERNEL_OPEN_PIC_H
+#define _PPC_KERNEL_OPEN_PIC_H
+
+#include "local_irq.h"
+
+extern struct hw_interrupt_type open_pic;
+
+void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs);
+
+#endif /* _PPC_KERNEL_OPEN_PIC_H */
diff --git a/arch/ppc/kernel/openpic.c b/arch/ppc/kernel/openpic.c
index ec60ca5a6..f7893dd79 100644
--- a/arch/ppc/kernel/openpic.c
+++ b/arch/ppc/kernel/openpic.c
@@ -107,7 +107,7 @@ static inline void out_le32(volatile u_int *addr, u_int val)
}
#endif
-static inline u_int openpic_read(volatile u_int *addr)
+u_int openpic_read(volatile u_int *addr)
{
u_int val;
@@ -176,8 +176,8 @@ static void openpic_safe_writefield(volatile u_int *addr, u_int mask,
__initfunc(void openpic_init(int main_pic))
{
u_int t, i;
- u_int vendorid, devid, stepping, timerfreq;
- const char *version, *vendor, *device;
+ u_int timerfreq;
+ const char *version;
if (!OpenPIC)
panic("No OpenPIC found");
@@ -190,6 +190,9 @@ __initfunc(void openpic_init(int main_pic))
case 2:
version = "1.2";
break;
+ case 3:
+ version = "1.3";
+ break;
default:
version = "?";
break;
@@ -200,32 +203,6 @@ __initfunc(void openpic_init(int main_pic))
OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1;
printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at %p\n", version,
NumProcessors, NumSources, OpenPIC);
-
- t = openpic_read(&OpenPIC->Global.Vendor_Identification);
- vendorid = t & OPENPIC_VENDOR_ID_VENDOR_ID_MASK;
- devid = (t & OPENPIC_VENDOR_ID_DEVICE_ID_MASK) >>
- OPENPIC_VENDOR_ID_DEVICE_ID_SHIFT;
- stepping = (t & OPENPIC_VENDOR_ID_STEPPING_MASK) >>
- OPENPIC_VENDOR_ID_STEPPING_SHIFT;
- switch (vendorid) {
- case OPENPIC_VENDOR_ID_APPLE:
- vendor = "Apple";
- break;
- default:
- vendor = "Unknown";
- break;
- }
- switch (devid) {
- case OPENPIC_DEVICE_ID_APPLE_HYDRA:
- device = "Hydra";
- break;
- default:
- device = "Unknown";
- break;
- }
- printk("OpenPIC Vendor %d (%s), Device %d (%s), Stepping %d\n", vendorid,
- vendor, devid, device, stepping);
-
timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency);
printk("OpenPIC timer frequency is ");
if (timerfreq)
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 1dfa3a6c8..ccef5f36a 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -1,5 +1,5 @@
/*
- * $Id: pci.c,v 1.43 1998/12/29 18:55:11 cort Exp $
+ * $Id: pci.c,v 1.54 1999/03/18 04:16:04 cort Exp $
* Common pmac/prep/chrp pci routines. -- Cort
*/
@@ -21,94 +21,41 @@
#include <asm/irq.h>
#include <asm/gg2.h>
-unsigned long isa_io_base;
-unsigned long isa_mem_base;
-unsigned long pci_dram_offset;
+#include "pci.h"
-unsigned int * pci_config_address;
-unsigned char * pci_config_data;
-
-/*
- * It would be nice if we could create a include/asm/pci.h and have just
- * function ptrs for all these in there, but that isn't the case.
- * We have a function, pcibios_*() which calls the function ptr ptr_pcibios_*()
- * which has been setup by pcibios_init(). This is all to avoid a check
- * for pmac/prep every time we call one of these. It should also make the move
- * to a include/asm/pcibios.h easier, we can drop the ptr_ on these functions
- * and create pci.h
- * -- Cort
- */
-int (*ptr_pcibios_read_config_byte)(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned char *val);
-int (*ptr_pcibios_read_config_word)(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned short *val);
-int (*ptr_pcibios_read_config_dword)(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned int *val);
-int (*ptr_pcibios_write_config_byte)(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned char val);
-int (*ptr_pcibios_write_config_word)(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned short val);
-int (*ptr_pcibios_write_config_dword)(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned int val);
-
-#define decl_config_access_method(name) \
-extern int name##_pcibios_read_config_byte(unsigned char bus, \
- unsigned char dev_fn, unsigned char offset, unsigned char *val); \
-extern int name##_pcibios_read_config_word(unsigned char bus, \
- unsigned char dev_fn, unsigned char offset, unsigned short *val); \
-extern int name##_pcibios_read_config_dword(unsigned char bus, \
- unsigned char dev_fn, unsigned char offset, unsigned int *val); \
-extern int name##_pcibios_write_config_byte(unsigned char bus, \
- unsigned char dev_fn, unsigned char offset, unsigned char val); \
-extern int name##_pcibios_write_config_word(unsigned char bus, \
- unsigned char dev_fn, unsigned char offset, unsigned short val); \
-extern int name##_pcibios_write_config_dword(unsigned char bus, \
- unsigned char dev_fn, unsigned char offset, unsigned int val)
-
-#define set_config_access_method(name) \
- ptr_pcibios_read_config_byte = name##_pcibios_read_config_byte; \
- ptr_pcibios_read_config_word = name##_pcibios_read_config_word; \
- ptr_pcibios_read_config_dword = name##_pcibios_read_config_dword; \
- ptr_pcibios_write_config_byte = name##_pcibios_write_config_byte; \
- ptr_pcibios_write_config_word = name##_pcibios_write_config_word; \
- ptr_pcibios_write_config_dword = name##_pcibios_write_config_dword
-
-decl_config_access_method(pmac);
-decl_config_access_method(grackle);
-decl_config_access_method(gg2);
-decl_config_access_method(raven);
-decl_config_access_method(prep);
-decl_config_access_method(mbx);
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+unsigned long pci_dram_offset = 0;
int pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned char *val)
{
- return ptr_pcibios_read_config_byte(bus,dev_fn,offset,val);
+ return ppc_md.pcibios_read_config_byte(bus,dev_fn,offset,val);
}
int pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned short *val)
{
- return ptr_pcibios_read_config_word(bus,dev_fn,offset,val);
+ return ppc_md.pcibios_read_config_word(bus,dev_fn,offset,val);
}
int pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned int *val)
{
- return ptr_pcibios_read_config_dword(bus,dev_fn,offset,val);
+ return ppc_md.pcibios_read_config_dword(bus,dev_fn,offset,val);
}
int pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned char val)
{
- return ptr_pcibios_write_config_byte(bus,dev_fn,offset,val);
+ return ppc_md.pcibios_write_config_byte(bus,dev_fn,offset,val);
}
int pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned short val)
{
- return ptr_pcibios_write_config_word(bus,dev_fn,offset,val);
+ return ppc_md.pcibios_write_config_word(bus,dev_fn,offset,val);
}
int pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned int val)
{
- return ptr_pcibios_write_config_dword(bus,dev_fn,offset,val);
+ return ppc_md.pcibios_write_config_dword(bus,dev_fn,offset,val);
}
int pcibios_present(void)
@@ -116,167 +63,46 @@ int pcibios_present(void)
return 1;
}
-__initfunc(void pcibios_init(void))
+void __init pcibios_init(void)
{
}
-__initfunc(void
- setup_pci_ptrs(void))
+
+void __init pcibios_fixup(void)
{
-#ifndef CONFIG_MBX
- PPC_DEVICE *hostbridge;
- switch (_machine) {
- case _MACH_prep:
- hostbridge=residual_find_device(PROCESSORDEVICE, NULL,
- BridgeController, PCIBridge,
- -1, 0);
- if (hostbridge &&
- hostbridge->DeviceId.Interface == PCIBridgeIndirect) {
- PnP_TAG_PACKET * pkt;
- set_config_access_method(raven);
- pkt=PnP_find_large_vendor_packet(
- res->DevicePnPHeap+hostbridge->AllocatedOffset,
- 3, 0);
- if(pkt) {
-#define p pkt->L4_Pack.L4_Data.L4_PPCPack
- pci_config_address= (unsigned *)
- ld_le32((unsigned *) p.PPCData);
- pci_config_data= (unsigned char *)
- ld_le32((unsigned *) (p.PPCData+8));
- } else {/* default values */
- pci_config_address= (unsigned *) 0x80000cf8;
- pci_config_data= (unsigned char *) 0x80000cfc;
- }
- } else {
- set_config_access_method(prep);
- }
- break;
- case _MACH_Pmac:
- if (find_devices("pci") != 0) {
- /* looks like a G3 powermac */
- set_config_access_method(grackle);
- } else {
- set_config_access_method(pmac);
- }
- break;
- case _MACH_chrp:
- if ( !strncmp("MOT",
- get_property(find_path_device("/"), "model", NULL),3) )
- {
- isa_io_base = 0xfe000000;
- set_config_access_method(grackle);
- }
- else
- {
- isa_io_base = GG2_ISA_IO_BASE;
- set_config_access_method(gg2);
- }
- break;
- default:
- printk("setup_pci_ptrs(): unknown machine type!\n");
- }
-#else /* CONFIG_MBX */
- set_config_access_method(mbx);
-#endif /* CONFIG_MBX */
-#undef set_config_access_method
+ ppc_md.pcibios_fixup();
}
-__initfunc(void pcibios_fixup(void))
+void __init pcibios_fixup_bus(struct pci_bus *bus)
{
- extern unsigned long route_pci_interrupts(void);
- struct pci_dev *dev;
- extern struct bridge_data **bridges;
- extern unsigned char *Motherboard_map;
- extern unsigned char *Motherboard_routes;
- unsigned char i;
-#ifndef CONFIG_MBX
- switch (_machine )
- {
- case _MACH_prep:
- 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]];
- for ( i = 0 ; i <= 5 ; i++ )
- {
- if ( dev->base_address[i] > 0x10000000 )
- {
- printk("Relocating PCI address %x -> %x\n",
- dev->base_address[i],
- (dev->base_address[i] & 0x00FFFFFF)
- | 0x01000000);
- dev->base_address[i] =
- (dev->base_address[i] & 0x00FFFFFF) | 0x01000000;
- pci_write_config_dword(dev,
- PCI_BASE_ADDRESS_0+(i*0x4),
- dev->base_address[i] );
- }
- }
-#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:
- /* PCI interrupts are controlled by the OpenPIC */
- for(dev=pci_devices; dev; dev=dev->next)
- if (dev->irq)
- dev->irq = openpic_to_irq(dev->irq);
- break;
- case _MACH_Pmac:
- for(dev=pci_devices; dev; dev=dev->next)
- {
- /*
- * Open Firmware often doesn't initialize the,
- * PCI_INTERRUPT_LINE config register properly, so we
- * should find the device node and se if it has an
- * AAPL,interrupts property.
- */
- struct bridge_data *bp = bridges[dev->bus->number];
- struct device_node *node;
- unsigned int *reg;
- unsigned char pin;
-
- if (pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin) ||
- !pin)
- continue; /* No interrupt generated -> no fixup */
- for (node = bp->node->child; node != 0;
- node = node->sibling) {
- reg = (unsigned int *) get_property(node, "reg", 0);
- if (reg == 0 || ((reg[0] >> 8) & 0xff) != dev->devfn)
- continue;
- /* this is the node, see if it has interrupts */
- if (node->n_intrs > 0)
- dev->irq = node->intrs[0].line;
- break;
- }
- }
- break;
- }
-#else /* CONFIG_MBX */
- for(dev=pci_devices; dev; dev=dev->next)
- {
- }
-#endif /* CONFIG_MBX */
}
-__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
+char __init *pcibios_setup(char *str)
{
+ return str;
}
-__initfunc(char *pcibios_setup(char *str))
+#ifndef CONFIG_MBX
+/* Recursively searches any node that is of type PCI-PCI bridge. Without
+ * this, the old code would miss children of P2P bridges and hence not
+ * fix IRQ's for cards located behind P2P bridges.
+ * - Ranjit Deshpande, 01/20/99
+ */
+void __init fix_intr(struct device_node *node, struct pci_dev *dev)
{
- return str;
+ unsigned int *reg, *class_code;
+
+ for (; node != 0;node = node->sibling) {
+ class_code = (unsigned int *) get_property(node, "class-code", 0);
+ if((*class_code >> 8) == PCI_CLASS_BRIDGE_PCI)
+ fix_intr(node->child, dev);
+ reg = (unsigned int *) get_property(node, "reg", 0);
+ if (reg == 0 || ((reg[0] >> 8) & 0xff) != dev->devfn)
+ continue;
+ /* this is the node, see if it has interrupts */
+ if (node->n_intrs > 0)
+ dev->irq = node->intrs[0].line;
+ break;
+ }
}
+#endif
diff --git a/arch/ppc/kernel/pci.h b/arch/ppc/kernel/pci.h
new file mode 100644
index 000000000..231f1d952
--- /dev/null
+++ b/arch/ppc/kernel/pci.h
@@ -0,0 +1,36 @@
+
+#ifndef __PPC_KERNEL_PCI_H__
+#define __PPC_KERNEL_PCI_H__
+
+extern unsigned long isa_io_base;
+extern unsigned long isa_mem_base;
+extern unsigned long pci_dram_offset;
+
+extern unsigned int *pci_config_address;
+extern unsigned char *pci_config_data;
+
+void fix_intr(struct device_node *node, struct pci_dev *dev);
+
+#define decl_config_access_method(name) \
+extern int name##_pcibios_read_config_byte(unsigned char bus, \
+ unsigned char dev_fn, unsigned char offset, unsigned char *val); \
+extern int name##_pcibios_read_config_word(unsigned char bus, \
+ unsigned char dev_fn, unsigned char offset, unsigned short *val); \
+extern int name##_pcibios_read_config_dword(unsigned char bus, \
+ unsigned char dev_fn, unsigned char offset, unsigned int *val); \
+extern int name##_pcibios_write_config_byte(unsigned char bus, \
+ unsigned char dev_fn, unsigned char offset, unsigned char val); \
+extern int name##_pcibios_write_config_word(unsigned char bus, \
+ unsigned char dev_fn, unsigned char offset, unsigned short val); \
+extern int name##_pcibios_write_config_dword(unsigned char bus, \
+ unsigned char dev_fn, unsigned char offset, unsigned int val)
+
+#define set_config_access_method(name) \
+ ppc_md.pcibios_read_config_byte = name##_pcibios_read_config_byte; \
+ ppc_md.pcibios_read_config_word = name##_pcibios_read_config_word; \
+ ppc_md.pcibios_read_config_dword = name##_pcibios_read_config_dword; \
+ ppc_md.pcibios_write_config_byte = name##_pcibios_write_config_byte; \
+ ppc_md.pcibios_write_config_word = name##_pcibios_write_config_word; \
+ ppc_md.pcibios_write_config_dword = name##_pcibios_write_config_dword
+
+#endif /* __PPC_KERNEL_PCI_H__ */
diff --git a/arch/ppc/kernel/pmac_pci.c b/arch/ppc/kernel/pmac_pci.c
index 7763059f7..089169e37 100644
--- a/arch/ppc/kernel/pmac_pci.c
+++ b/arch/ppc/kernel/pmac_pci.c
@@ -21,6 +21,9 @@
#include <asm/pgtable.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+
+#include "pci.h"
struct bridge_data **bridges, *bridge_list;
static int max_bus;
@@ -84,7 +87,12 @@ int pmac_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
(1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8)
+ (offset & ~3));
} else {
- out_le32(bp->cfg_addr, (dev_fn << 8) + (offset & ~3) + 1);
+ /* Bus number once again taken into consideration.
+ * Change applied from 2.1.24. This makes devices located
+ * behind PCI-PCI bridges visible.
+ * -Ranjit Deshpande, 01/20/99
+ */
+ out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + (offset & ~3) + 1);
}
udelay(2);
*val = in_8(bp->cfg_data + (offset & 3));
@@ -109,7 +117,8 @@ int pmac_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
(1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8)
+ (offset & ~3));
} else {
- out_le32(bp->cfg_addr, (dev_fn << 8) + (offset & ~3) + 1);
+ /* See pci_read_config_byte */
+ out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + (offset & ~3) + 1);
}
udelay(2);
*val = in_le16((volatile unsigned short *)(bp->cfg_data + (offset & 3)));
@@ -134,7 +143,8 @@ int pmac_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
(1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8)
+ offset);
} else {
- out_le32(bp->cfg_addr, (dev_fn << 8) + offset + 1);
+ /* See pci_read_config_byte */
+ out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + offset + 1);
}
udelay(2);
*val = in_le32((volatile unsigned int *)bp->cfg_data);
@@ -156,7 +166,8 @@ int pmac_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
(1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8)
+ (offset & ~3));
} else {
- out_le32(bp->cfg_addr, (dev_fn << 8) + (offset & ~3) + 1);
+ /* See pci_read_config_byte */
+ out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + (offset & ~3) + 1);
}
udelay(2);
out_8(bp->cfg_data + (offset & 3), val);
@@ -180,7 +191,8 @@ int pmac_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
(1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8)
+ (offset & ~3));
} else {
- out_le32(bp->cfg_addr, (dev_fn << 8) + (offset & ~3) + 1);
+ /* See pci_read_config_byte */
+ out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + (offset & ~3) + 1);
}
udelay(2);
out_le16((volatile unsigned short *)(bp->cfg_data + (offset & 3)), val);
@@ -204,7 +216,8 @@ int pmac_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
(1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8)
+ offset);
} else {
- out_le32(bp->cfg_addr, (dev_fn << 8) + offset + 1);
+ /* See pci_read_config_byte */
+ out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + (offset & ~3) + 1);
}
udelay(2);
out_le32((volatile unsigned int *)bp->cfg_data, val);
@@ -429,3 +442,47 @@ __initfunc(static void add_bridges(struct device_node *dev, unsigned long *mem_p
}
}
+__initfunc(
+void
+pmac_pcibios_fixup(void))
+{
+ struct pci_dev *dev;
+
+ /*
+ * FIXME: This is broken: We should not assign IRQ's to IRQless
+ * devices (look at PCI_INTERRUPT_PIN) and we also should
+ * honor the existence of multi-function devices where
+ * different functions have different interrupt pins. [mj]
+ */
+ for(dev=pci_devices; dev; dev=dev->next)
+ {
+ /*
+ * Open Firmware often doesn't initialize the,
+ * PCI_INTERRUPT_LINE config register properly, so we
+ * should find the device node and se if it has an
+ * AAPL,interrupts property.
+ */
+ struct bridge_data *bp = bridges[dev->bus->number];
+ unsigned char pin;
+
+ if (pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin) ||
+ !pin)
+ continue; /* No interrupt generated -> no fixup */
+ fix_intr(bp->node->child, dev);
+ }
+}
+
+__initfunc(
+void
+pmac_setup_pci_ptrs(void))
+{
+ if (find_devices("pci") != 0) {
+ /* looks like a G3 powermac */
+ set_config_access_method(grackle);
+ } else {
+ set_config_access_method(pmac);
+ }
+
+ ppc_md.pcibios_fixup = pmac_pcibios_fixup;
+}
+
diff --git a/arch/ppc/kernel/pmac_pic.c b/arch/ppc/kernel/pmac_pic.c
new file mode 100644
index 000000000..6a49f1405
--- /dev/null
+++ b/arch/ppc/kernel/pmac_pic.c
@@ -0,0 +1,362 @@
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/prom.h>
+#include "pmac_pic.h"
+
+/* pmac */struct pmac_irq_hw {
+ unsigned int flag;
+ unsigned int enable;
+ unsigned int ack;
+ unsigned int level;
+};
+
+/* XXX these addresses should be obtained from the device tree */
+static 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,
+};
+
+static int max_irqs;
+static int max_real_irqs;
+
+#define MAXCOUNT 10000000
+
+#define GATWICK_IRQ_POOL_SIZE 10
+static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE];
+
+static void __pmac pmac_mask_and_ack_irq(unsigned int irq_nr)
+{
+ unsigned long bit = 1UL << (irq_nr & 0x1f);
+ int i = irq_nr >> 5;
+
+ if ((unsigned)irq_nr >= max_irqs)
+ return;
+
+ clear_bit(irq_nr, ppc_cached_irq_mask);
+ if (test_and_clear_bit(irq_nr, ppc_lost_interrupts))
+ atomic_dec(&ppc_n_lost_interrupts);
+ out_le32(&pmac_irq_hw[i]->ack, bit);
+ out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
+ out_le32(&pmac_irq_hw[i]->ack, bit);
+ do {
+ /* make sure ack gets to controller before we enable
+ interrupts */
+ mb();
+ } while(in_le32(&pmac_irq_hw[i]->flag) & bit);
+}
+
+static void __pmac pmac_set_irq_mask(unsigned int irq_nr)
+{
+ unsigned long bit = 1UL << (irq_nr & 0x1f);
+ int i = irq_nr >> 5;
+
+ if ((unsigned)irq_nr >= max_irqs)
+ return;
+
+ /* enable unmasked interrupts */
+ out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
+
+ do {
+ /* make sure mask gets to controller before we
+ return to user */
+ mb();
+ } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
+ != (ppc_cached_irq_mask[i] & bit));
+
+ /*
+ * Unfortunately, setting the bit in the enable register
+ * when the device interrupt is already on *doesn't* set
+ * the bit in the flag register or request another interrupt.
+ */
+ if ((bit & ppc_cached_irq_mask[i])
+ && (ld_le32(&pmac_irq_hw[i]->level) & bit)
+ && !(ld_le32(&pmac_irq_hw[i]->flag) & bit)) {
+ if (!test_and_set_bit(irq_nr, ppc_lost_interrupts))
+ atomic_inc(&ppc_n_lost_interrupts);
+ }
+}
+
+static void __pmac pmac_mask_irq(unsigned int irq_nr)
+{
+ clear_bit(irq_nr, ppc_cached_irq_mask);
+ pmac_set_irq_mask(irq_nr);
+ mb();
+}
+
+static void __pmac pmac_unmask_irq(unsigned int irq_nr)
+{
+ set_bit(irq_nr, ppc_cached_irq_mask);
+ pmac_set_irq_mask(irq_nr);
+}
+
+struct hw_interrupt_type pmac_pic = {
+ " PMAC-PIC ",
+ NULL,
+ NULL,
+ NULL,
+ pmac_unmask_irq,
+ pmac_mask_irq,
+ pmac_mask_and_ack_irq,
+ 0
+};
+
+struct hw_interrupt_type gatwick_pic = {
+ " GATWICK ",
+ NULL,
+ NULL,
+ NULL,
+ pmac_unmask_irq,
+ pmac_mask_irq,
+ pmac_mask_and_ack_irq,
+ 0
+};
+
+static void gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+ int irq, bits;
+
+ for (irq = max_irqs - 1; irq > max_real_irqs; irq -= 32) {
+ int i = irq >> 5;
+ bits = ld_le32(&pmac_irq_hw[i]->flag)
+ | ppc_lost_interrupts[i];
+ if (bits == 0)
+ continue;
+ irq -= cntlzw(bits);
+ break;
+ }
+ /* The previous version of this code allowed for this case, we
+ * don't. Put this here to check for it.
+ * -- Cort
+ */
+ if ( irq_desc[irq].ctl != &gatwick_pic )
+ printk("gatwick irq not from gatwick pic\n");
+ else
+ ppc_irq_dispatch_handler( regs, irq );
+}
+
+void
+pmac_do_IRQ(struct pt_regs *regs,
+ int cpu,
+ int isfake)
+{
+ int irq;
+ unsigned long bits = 0;
+
+#ifdef __SMP__
+ /* IPI's are a hack on the powersurge -- Cort */
+ if ( cpu != 0 )
+ {
+ if (!isfake)
+ {
+#ifdef CONFIG_XMON
+ static int xmon_2nd;
+ if (xmon_2nd)
+ xmon(regs);
+#endif
+ smp_message_recv();
+ goto out;
+ }
+ /* could be here due to a do_fake_interrupt call but we don't
+ mess with the controller from the second cpu -- Cort */
+ goto out;
+ }
+
+ {
+ unsigned int loops = MAXCOUNT;
+ while (test_bit(0, &global_irq_lock)) {
+ if (smp_processor_id() == global_irq_holder) {
+ printk("uh oh, interrupt while we hold global irq lock!\n");
+#ifdef CONFIG_XMON
+ xmon(0);
+#endif
+ break;
+ }
+ if (loops-- == 0) {
+ printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
+#ifdef CONFIG_XMON
+ xmon(0);
+#endif
+ }
+ }
+ }
+#endif /* __SMP__ */
+
+ for (irq = max_real_irqs - 1; irq > 0; irq -= 32) {
+ int i = irq >> 5;
+ bits = ld_le32(&pmac_irq_hw[i]->flag)
+ | ppc_lost_interrupts[i];
+ if (bits == 0)
+ continue;
+ irq -= cntlzw(bits);
+ break;
+ }
+
+ if (irq < 0)
+ {
+ printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
+ irq, regs->nip);
+ ppc_spurious_interrupts++;
+ }
+ else
+ {
+ ppc_irq_dispatch_handler( regs, irq );
+ }
+#ifdef CONFIG_SMP
+out:
+#endif /* CONFIG_SMP */
+}
+
+/* This routine will fix some missing interrupt values in the device tree
+ * on the gatwick mac-io controller used by some PowerBooks
+ */
+static void __init pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
+{
+ struct device_node *node;
+ int count;
+
+ memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool));
+ node = gw->child;
+ count = 0;
+ while(node)
+ {
+ /* Fix SCC */
+ if (strcasecmp(node->name, "escc") == 0)
+ if (node->child) {
+ if (node->child->n_intrs < 3) {
+ node->child->intrs = &gatwick_int_pool[count];
+ count += 3;
+ }
+ node->child->n_intrs = 3;
+ node->child->intrs[0].line = 15+irq_base;
+ node->child->intrs[1].line = 4+irq_base;
+ node->child->intrs[2].line = 5+irq_base;
+ printk(KERN_INFO "irq: fixed SCC on second controller (%d,%d,%d)\n",
+ node->child->intrs[0].line,
+ node->child->intrs[1].line,
+ node->child->intrs[2].line);
+ }
+ /* Fix media-bay & left SWIM */
+ if (strcasecmp(node->name, "media-bay") == 0) {
+ struct device_node* ya_node;
+
+ if (node->n_intrs == 0)
+ node->intrs = &gatwick_int_pool[count++];
+ node->n_intrs = 1;
+ node->intrs[0].line = 29+irq_base;
+ printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n",
+ node->intrs[0].line);
+
+ ya_node = node->child;
+ while(ya_node)
+ {
+ if (strcasecmp(ya_node->name, "floppy") == 0) {
+ if (ya_node->n_intrs < 2) {
+ ya_node->intrs = &gatwick_int_pool[count];
+ count += 2;
+ }
+ ya_node->n_intrs = 2;
+ ya_node->intrs[0].line = 19+irq_base;
+ ya_node->intrs[1].line = 1+irq_base;
+ printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n",
+ ya_node->intrs[0].line, ya_node->intrs[1].line);
+ }
+ if (strcasecmp(ya_node->name, "ata4") == 0) {
+ if (ya_node->n_intrs < 2) {
+ ya_node->intrs = &gatwick_int_pool[count];
+ count += 2;
+ }
+ ya_node->n_intrs = 2;
+ ya_node->intrs[0].line = 14+irq_base;
+ ya_node->intrs[1].line = 3+irq_base;
+ printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n",
+ ya_node->intrs[0].line, ya_node->intrs[1].line);
+ }
+ ya_node = ya_node->sibling;
+ }
+ }
+ node = node->sibling;
+ }
+ if (count > 10) {
+ printk("WARNING !! Gatwick interrupt pool overflow\n");
+ printk(" GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE);
+ printk(" requested = %d\n", count);
+ }
+}
+
+__initfunc(void
+pmac_pic_init(void))
+{
+ int i;
+ struct device_node *irqctrler;
+ unsigned long addr;
+ int second_irq = -999;
+
+
+ /* 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;
+ }
+ for ( i = 0; i < max_real_irqs ; i++ )
+ irq_desc[i].ctl = &pmac_pic;
+
+ /* 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);
+ for ( i = max_real_irqs ; i < max_irqs ; i++ )
+ irq_desc[i].ctl = &gatwick_pic;
+ request_irq( second_irq, gatwick_action, SA_INTERRUPT,
+ "gatwick cascade", 0 );
+ }
+ 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(20, xmon_irq, 0, "NMI - XMON", 0);
+#endif /* CONFIG_XMON */
+}
diff --git a/arch/ppc/kernel/pmac_pic.h b/arch/ppc/kernel/pmac_pic.h
new file mode 100644
index 000000000..335a9ef69
--- /dev/null
+++ b/arch/ppc/kernel/pmac_pic.h
@@ -0,0 +1,15 @@
+#ifndef _PPC_KERNEL_PMAC_PIC_H
+#define _PPC_KERNEL_PMAC_PIC_H
+
+#include "local_irq.h"
+
+extern struct hw_interrupt_type pmac_pic;
+
+void pmac_pic_init(void);
+void pmac_do_IRQ(struct pt_regs *regs,
+ int cpu,
+ int isfake);
+
+
+#endif /* _PPC_KERNEL_PMAC_PIC_H */
+
diff --git a/arch/ppc/kernel/pmac_setup.c b/arch/ppc/kernel/pmac_setup.c
index 499e8b6a5..9f8638021 100644
--- a/arch/ppc/kernel/pmac_setup.c
+++ b/arch/ppc/kernel/pmac_setup.c
@@ -44,6 +44,7 @@
#include <asm/prom.h>
#include <asm/system.h>
#include <asm/pgtable.h>
+#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/pci-bridge.h>
#include <asm/adb.h>
@@ -52,10 +53,44 @@
#include <asm/ohare.h>
#include <asm/mediabay.h>
#include <asm/feature.h>
+#include <asm/ide.h>
+#include <asm/machdep.h>
+
#include "time.h"
+#include "local_irq.h"
+#include "pmac_pic.h"
+
+#undef SHOW_GATWICK_IRQS
+
+unsigned long pmac_get_rtc_time(void);
+int pmac_set_rtc_time(unsigned long nowtime);
+void pmac_read_rtc_time(void);
+void pmac_calibrate_decr(void);
+void pmac_setup_pci_ptrs(void);
+
+extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int mackbd_getkeycode(unsigned int scancode);
+extern int mackbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode);
+extern char mackbd_unexpected_up(unsigned char keycode);
+extern void mackbd_leds(unsigned char leds);
+extern void mackbd_init_hw(void);
+#ifdef CONFIG_MAGIC_SYSRQ
+unsigned char mackbd_sysrq_xlate[128];
+#endif /* CONFIG_MAGIC_SYSRQ */
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);
unsigned char drive_info;
+int ppc_override_l2cr = 0;
+int ppc_override_l2cr_value;
+
extern char saved_command_line[];
#define DEFAULT_ROOT_DEVICE 0x0801 /* sda1 - slightly silly choice */
@@ -132,6 +167,16 @@ pmac_get_cpuinfo(char *buffer)
}
}
+ /* Checks "l2cr-value" property in the registry */
+ np = find_devices("cpus");
+ if (np != 0) {
+ unsigned int *l2cr = (unsigned int *)
+ get_property(np, "l2cr-value", NULL);
+ if (l2cr != 0) {
+ len += sprintf(buffer+len, "l2cr override\t: 0x%x\n", *l2cr);
+ }
+ }
+
return len;
}
@@ -210,6 +255,26 @@ pmac_setup_arch(unsigned long *memory_start_p, unsigned long *memory_end_p))
*memory_start_p = pmac_find_bridges(*memory_start_p, *memory_end_p);
+ /* Checks "l2cr-value" property in the registry */
+ if ( (_get_PVR() >> 16) == 8) {
+ struct device_node *np = find_devices("cpus");
+ if (np != 0) {
+ unsigned int *l2cr = (unsigned int *)
+ get_property(np, "l2cr-value", NULL);
+ if (l2cr != 0) {
+ ppc_override_l2cr = 1;
+ ppc_override_l2cr_value = *l2cr;
+ _set_L2CR(0);
+ _set_L2CR(ppc_override_l2cr_value);
+ }
+ }
+ }
+
+ if (ppc_override_l2cr)
+ printk(KERN_INFO "L2CR overriden (0x%x), backside cache is %s\n",
+ ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000)
+ ? "enabled" : "disabled");
+
feature_init();
#ifdef CONFIG_KGDB
@@ -258,15 +323,12 @@ int boot_target;
int boot_part;
kdev_t boot_dev;
-void __init powermac_init(void)
+__initfunc(void
+pmac_init2(void))
{
- if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )
- return;
adb_init();
pmac_nvram_init();
- if (_machine == _MACH_Pmac) {
- media_bay_init();
- }
+ media_bay_init();
}
#ifdef CONFIG_SCSI
@@ -371,3 +433,174 @@ void note_bootable_part(kdev_t dev, int part)
}
}
+void
+pmac_restart(char *cmd)
+{
+ struct adb_request req;
+
+ switch (adb_hardware) {
+ case ADB_VIACUDA:
+ cuda_request(&req, NULL, 2, CUDA_PACKET,
+ CUDA_RESET_SYSTEM);
+ for (;;)
+ cuda_poll();
+ break;
+
+ case ADB_VIAPMU:
+ pmu_restart();
+ break;
+ default:
+ }
+}
+
+void
+pmac_power_off(void)
+{
+ struct adb_request req;
+
+ switch (adb_hardware) {
+ case ADB_VIACUDA:
+ cuda_request(&req, NULL, 2, CUDA_PACKET,
+ CUDA_POWERDOWN);
+ for (;;)
+ cuda_poll();
+ break;
+
+ case ADB_VIAPMU:
+ pmu_shutdown();
+ break;
+ default:
+ }
+}
+
+void
+pmac_halt(void)
+{
+ pmac_power_off();
+}
+
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */
+void
+pmac_ide_insw(ide_ioreg_t port, void *buf, int ns)
+{
+ ide_insw(port, buf, ns);
+}
+
+void
+pmac_ide_outsw(ide_ioreg_t port, void *buf, int ns)
+{
+ ide_outsw(port, buf, ns);
+}
+
+int
+pmac_ide_default_irq(ide_ioreg_t base)
+{
+ return 0;
+}
+
+ide_ioreg_t
+pmac_ide_default_io_base(int index)
+{
+#if defined(CONFIG_BLK_DEV_IDE_PMAC)
+ return pmac_ide_regbase[index];
+#else
+ return 0;
+#endif
+}
+
+int
+pmac_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+ return 0;
+}
+
+void
+pmac_ide_request_region(ide_ioreg_t from,
+ unsigned int extent,
+ const char *name)
+{
+}
+
+void
+pmac_ide_release_region(ide_ioreg_t from,
+ unsigned int extent)
+{
+}
+
+/* Convert the shorts/longs in hd_driveid from little to big endian;
+ * chars are endian independant, of course, but strings need to be flipped.
+ * (Despite what it says in drivers/block/ide.h, they come up as little
+ * endian...)
+ *
+ * Changes to linux/hdreg.h may require changes here. */
+void
+pmac_ide_fix_driveid(struct hd_driveid *id)
+{
+ ppc_generic_ide_fix_driveid(id);
+}
+
+/* This is declared in drivers/block/ide-pmac.c */
+void pmac_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq);
+#endif
+
+__initfunc(void
+pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7))
+{
+ pmac_setup_pci_ptrs();
+
+ /* isa_io_base gets set in pmac_find_bridges */
+ isa_mem_base = PMAC_ISA_MEM_BASE;
+ pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
+ ISA_DMA_THRESHOLD = ~0L;
+ DMA_MODE_READ = 1;
+ DMA_MODE_WRITE = 2;
+
+ ppc_md.setup_arch = pmac_setup_arch;
+ ppc_md.setup_residual = NULL;
+ ppc_md.get_cpuinfo = pmac_get_cpuinfo;
+ ppc_md.irq_cannonicalize = NULL;
+ ppc_md.init_IRQ = pmac_pic_init;
+ ppc_md.do_IRQ = pmac_do_IRQ;
+ ppc_md.init = pmac_init2;
+
+ ppc_md.restart = pmac_restart;
+ ppc_md.power_off = pmac_power_off;
+ ppc_md.halt = pmac_halt;
+
+ ppc_md.time_init = NULL;
+ ppc_md.set_rtc_time = pmac_set_rtc_time;
+ ppc_md.get_rtc_time = pmac_get_rtc_time;
+ ppc_md.calibrate_decr = pmac_calibrate_decr;
+
+#if defined(CONFIG_VT) && defined(CONFIG_MAC_KEYBOARD)
+ ppc_md.kbd_setkeycode = mackbd_setkeycode;
+ ppc_md.kbd_getkeycode = mackbd_getkeycode;
+ ppc_md.kbd_translate = mackbd_translate;
+ ppc_md.kbd_unexpected_up = mackbd_unexpected_up;
+ ppc_md.kbd_leds = mackbd_leds;
+ ppc_md.kbd_init_hw = mackbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.kbd_sysrq_xlate = mackbd_sysrq_xlate;
+#endif
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE_PMAC)
+ ppc_ide_md.insw = pmac_ide_insw;
+ ppc_ide_md.outsw = pmac_ide_outsw;
+ ppc_ide_md.default_irq = pmac_ide_default_irq;
+ ppc_ide_md.default_io_base = pmac_ide_default_io_base;
+ ppc_ide_md.check_region = pmac_ide_check_region;
+ ppc_ide_md.request_region = pmac_ide_request_region;
+ ppc_ide_md.release_region = pmac_ide_release_region;
+ ppc_ide_md.fix_driveid = pmac_ide_fix_driveid;
+ ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports;
+
+ ppc_ide_md.io_base = 0;
+#endif
+}
+
diff --git a/arch/ppc/kernel/ppc8xx_pic.c b/arch/ppc/kernel/ppc8xx_pic.c
new file mode 100644
index 000000000..87bc6d0f8
--- /dev/null
+++ b/arch/ppc/kernel/ppc8xx_pic.c
@@ -0,0 +1,49 @@
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <asm/irq.h>
+#include <asm/8xx_immap.h>
+#include <asm/mbx.h>
+#include "ppc8xx_pic.h"
+
+
+static void mbx_mask_irq(unsigned int irq_nr)
+{
+ if ( irq_nr == ISA_BRIDGE_INT ) return;
+ if ( irq_nr >= ppc8xx_pic.irq_offset )
+ irq_nr -= ppc8xx_pic.irq_offset;
+ ppc_cached_irq_mask[0] &= ~(1 << (31-irq_nr));
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask[0];
+}
+
+static void mbx_unmask_irq(unsigned int irq_nr)
+{
+ if ( irq_nr >= ppc8xx_pic.irq_offset )
+ irq_nr -= ppc8xx_pic.irq_offset;
+ ppc_cached_irq_mask[0] |= (1 << (31-irq_nr));
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask[0];
+}
+
+static void mbx_mask_and_ack(unsigned int irq_nr)
+{
+ /* this shouldn't be masked, we mask the 8259 if we need to -- Cort */
+ if ( irq_nr != ISA_BRIDGE_INT )
+ mbx_mask_irq(irq_nr);
+ if ( irq_nr >= ppc8xx_pic.irq_offset )
+ irq_nr -= ppc8xx_pic.irq_offset;
+ /* clear the pending bits */
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = 1 << (31-irq_nr);
+}
+
+struct hw_interrupt_type ppc8xx_pic = {
+ " 8xx SIU ",
+ NULL,
+ NULL,
+ NULL,
+ mbx_unmask_irq,
+ mbx_mask_irq,
+ mbx_mask_and_ack,
+ 0
+};
diff --git a/arch/ppc/kernel/ppc8xx_pic.h b/arch/ppc/kernel/ppc8xx_pic.h
new file mode 100644
index 000000000..d6b424fec
--- /dev/null
+++ b/arch/ppc/kernel/ppc8xx_pic.h
@@ -0,0 +1,9 @@
+
+#ifndef _PPC_KERNEL_PPC8xx_H
+#define _PPC_KERNEL_PPC8xx_H
+
+#include "local_irq.h"
+
+extern struct hw_interrupt_type ppc8xx_pic;
+
+#endif /* _PPC_KERNEL_PPC8xx_H */
diff --git a/arch/ppc/kernel/ppc_defs.h b/arch/ppc/kernel/ppc_defs.h
deleted file mode 100644
index 83315a2ae..000000000
--- a/arch/ppc/kernel/ppc_defs.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 1b7753dd0..834bdf102 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -8,11 +8,12 @@
#include <linux/vt_kern.h>
#include <linux/nvram.h>
+#include <asm/page.h>
#include <asm/semaphore.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
-#include <asm/ide.h>
#include <asm/io.h>
+#include <asm/ide.h>
#include <asm/atomic.h>
#include <asm/bitops.h>
#include <asm/checksum.h>
@@ -26,6 +27,8 @@
#include <asm/irq.h>
#include <asm/feature.h>
#include <asm/spinlock.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
#define __KERNEL_SYSCALLS__
#include <linux/unistd.h>
@@ -39,13 +42,14 @@ extern void AlignmentException(struct pt_regs *regs);
extern void ProgramCheckException(struct pt_regs *regs);
extern void SingleStepException(struct pt_regs *regs);
extern int sys_sigreturn(struct pt_regs *regs);
-extern atomic_t n_lost_interrupts;
+extern atomic_t ppc_n_lost_interrupts;
extern void do_lost_interrupts(unsigned long);
extern int do_signal(sigset_t *, struct pt_regs *);
asmlinkage long long __ashrdi3(long long, int);
asmlinkage int abs(int);
+EXPORT_SYMBOL(clear_page);
EXPORT_SYMBOL(do_signal);
EXPORT_SYMBOL(syscall_trace);
EXPORT_SYMBOL(transfer_to_handler);
@@ -57,16 +61,21 @@ EXPORT_SYMBOL(AlignmentException);
EXPORT_SYMBOL(ProgramCheckException);
EXPORT_SYMBOL(SingleStepException);
EXPORT_SYMBOL(sys_sigreturn);
-EXPORT_SYMBOL(n_lost_interrupts);
+EXPORT_SYMBOL(ppc_n_lost_interrupts);
EXPORT_SYMBOL(do_lost_interrupts);
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
-EXPORT_SYMBOL(local_irq_count);
-EXPORT_SYMBOL(local_bh_count);
+EXPORT_SYMBOL(ppc_local_irq_count);
+EXPORT_SYMBOL(ppc_local_bh_count);
EXPORT_SYMBOL(isa_io_base);
EXPORT_SYMBOL(isa_mem_base);
EXPORT_SYMBOL(pci_dram_offset);
+EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
+EXPORT_SYMBOL(DMA_MODE_READ);
+EXPORT_SYMBOL(DMA_MODE_WRITE);
+EXPORT_SYMBOL(_prep_type);
+EXPORT_SYMBOL(ucSystemType);
EXPORT_SYMBOL(atomic_add);
EXPORT_SYMBOL(atomic_sub);
@@ -155,6 +164,7 @@ EXPORT_SYMBOL(_enable_interrupts);
EXPORT_SYMBOL(flush_instruction_cache);
EXPORT_SYMBOL(_get_PVR);
EXPORT_SYMBOL(giveup_fpu);
+EXPORT_SYMBOL(enable_kernel_fp);
EXPORT_SYMBOL(flush_icache_range);
EXPORT_SYMBOL(xchg_u32);
#ifdef __SMP__
@@ -171,18 +181,14 @@ EXPORT_SYMBOL(_write_lock);
EXPORT_SYMBOL(_write_unlock);
#endif
-#ifndef CONFIG_MACH_SPECIFIC
EXPORT_SYMBOL(_machine);
-#endif
+EXPORT_SYMBOL(ppc_md);
EXPORT_SYMBOL(adb_request);
-EXPORT_SYMBOL(adb_autopoll);
EXPORT_SYMBOL(adb_register);
EXPORT_SYMBOL(cuda_request);
-EXPORT_SYMBOL(cuda_send_request);
EXPORT_SYMBOL(cuda_poll);
EXPORT_SYMBOL(pmu_request);
-EXPORT_SYMBOL(pmu_send_request);
EXPORT_SYMBOL(pmu_poll);
#ifdef CONFIG_PMAC_PBOOK
EXPORT_SYMBOL(sleep_notifier_list);
@@ -194,7 +200,6 @@ EXPORT_SYMBOL(find_compatible_devices);
EXPORT_SYMBOL(find_path_device);
EXPORT_SYMBOL(find_phandle);
EXPORT_SYMBOL(get_property);
-EXPORT_SYMBOL(device_is_compatible);
EXPORT_SYMBOL(pci_io_base);
EXPORT_SYMBOL(pci_device_loc);
EXPORT_SYMBOL(feature_set);
@@ -209,9 +214,8 @@ EXPORT_SYMBOL(nvram_read_byte);
EXPORT_SYMBOL(nvram_write_byte);
#endif /* CONFIG_PMAC */
-#ifdef CONFIG_SOUND_MODULE
EXPORT_SYMBOL(abs);
-#endif
+EXPORT_SYMBOL(device_is_compatible);
/* The following are special because they're not called
explicitly (the C compiler generates them). Fortunately,
diff --git a/arch/ppc/kernel/prep_nvram.c b/arch/ppc/kernel/prep_nvram.c
new file mode 100644
index 000000000..e69563c8a
--- /dev/null
+++ b/arch/ppc/kernel/prep_nvram.c
@@ -0,0 +1,173 @@
+/*
+ * linux/arch/ppc/kernel/prep_nvram.c
+ *
+ * Copyright (C) 1998 Corey Minyard
+ *
+ */
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/ioport.h>
+
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/machdep.h>
+#include <asm/prep_nvram.h>
+
+/*
+ * Allow for a maximum of 32K of PReP NvRAM data
+ */
+#define MAX_PREP_NVRAM 0x8000
+static char nvramData[MAX_PREP_NVRAM];
+static NVRAM_MAP *nvram=(NVRAM_MAP *)&nvramData[0];
+
+#define PREP_NVRAM_AS0 0x74
+#define PREP_NVRAM_AS1 0x75
+#define PREP_NVRAM_DATA 0x77
+
+unsigned char *rs_pcNvRAM;
+
+unsigned char prep_nvram_read_val(int addr)
+{
+ outb(addr, PREP_NVRAM_AS0);
+ outb(addr>>8, PREP_NVRAM_AS1);
+ return inb(PREP_NVRAM_DATA);
+}
+
+void prep_nvram_write_val(int addr,
+ unsigned char val)
+{
+ outb(addr, PREP_NVRAM_AS0);
+ outb(addr>>8, PREP_NVRAM_AS1);
+ outb(val, PREP_NVRAM_DATA);
+}
+
+/*
+ * Most Radstone boards have NvRAM memory mapped at offset 8M in ISA space
+ */
+unsigned char rs_nvram_read_val(int addr)
+{
+ return rs_pcNvRAM[addr];
+}
+
+void rs_nvram_write_val(int addr,
+ unsigned char val)
+{
+ rs_pcNvRAM[addr]=val;
+}
+
+__initfunc(void init_prep_nvram(void))
+{
+ unsigned char *nvp;
+ int i;
+ int nvramSize;
+
+ /*
+ * I'm making the assumption that 32k will always cover the
+ * nvramsize. If this isn't the case please let me know and we can
+ * map the header, then get the size from the header, then map
+ * the whole size. -- Cort
+ */
+ if ( _prep_type == _PREP_Radstone )
+ rs_pcNvRAM = (unsigned char *)ioremap(_ISA_MEM_BASE+0x00800000,
+ 32<<10);
+ request_region(PREP_NVRAM_AS0, 0x8, "PReP NVRAM");
+ /*
+ * The following could fail if the NvRAM were corrupt but
+ * we expect the boot firmware to have checked its checksum
+ * before boot
+ */
+ nvp = (char *) &nvram->Header;
+ for (i=0; i<sizeof(HEADER); i++)
+ {
+ *nvp = ppc_md.nvram_read_val(i);
+ nvp++;
+ }
+
+ /*
+ * The PReP NvRAM may be any size so read in the header to
+ * determine how much we must read in order to get the complete
+ * GE area
+ */
+ nvramSize=(int)nvram->Header.GEAddress+nvram->Header.GELength;
+ if(nvramSize>MAX_PREP_NVRAM)
+ {
+ /*
+ * NvRAM is too large
+ */
+ nvram->Header.GELength=0;
+ return;
+ }
+
+ /*
+ * Read the remainder of the PReP NvRAM
+ */
+ nvp = (char *) &nvram->GEArea[0];
+ for (i=sizeof(HEADER); i<nvramSize; i++)
+ {
+ *nvp = ppc_md.nvram_read_val(i);
+ nvp++;
+ }
+}
+
+__prep
+char *prep_nvram_get_var(const char *name)
+{
+ char *cp;
+ int namelen;
+
+ namelen = strlen(name);
+ cp = prep_nvram_first_var();
+ while (cp != NULL) {
+ if ((strncmp(name, cp, namelen) == 0)
+ && (cp[namelen] == '='))
+ {
+ return cp+namelen+1;
+ }
+ cp = prep_nvram_next_var(cp);
+ }
+
+ return NULL;
+}
+
+__prep
+char *prep_nvram_first_var(void)
+{
+ if (nvram->Header.GELength == 0) {
+ return NULL;
+ } else {
+ return (((char *)nvram)
+ + ((unsigned int) nvram->Header.GEAddress));
+ }
+}
+
+__prep
+char *prep_nvram_next_var(char *name)
+{
+ char *cp;
+
+
+ cp = name;
+ while (((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength)
+ && (*cp != '\0'))
+ {
+ cp++;
+ }
+
+ /* Skip over any null characters. */
+ while (((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength)
+ && (*cp == '\0'))
+ {
+ cp++;
+ }
+
+ if ((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength) {
+ return cp;
+ } else {
+ return NULL;
+ }
+}
+
+
+
diff --git a/arch/ppc/kernel/prep_pci.c b/arch/ppc/kernel/prep_pci.c
index b48f7a1fc..dd7f1eee1 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.24 1998/12/10 02:39:51 cort Exp $
+ * $Id: prep_pci.c,v 1.33 1999/05/09 20:15:54 cort Exp $
* PReP pci functions.
* Originally by Gary Thomas
* rewritten and updated by Cort Dougan (cort@cs.nmt.edu)
@@ -11,11 +11,19 @@
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/openpic.h>
#include <asm/byteorder.h>
#include <asm/io.h>
#include <asm/ptrace.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/residual.h>
#include <asm/processor.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+
+#include "pci.h"
#define MAX_DEVNR 22
@@ -27,6 +35,9 @@ unsigned char *Motherboard_map_name;
/* How is the 82378 PIRQ mapping setup? */
unsigned char *Motherboard_routes;
+/* Used for Motorola to store system config register */
+static unsigned long *ProcInfo;
+
/* Tables for known hardware */
/* Motorola PowerStackII - Utah */
@@ -34,38 +45,39 @@ static char Utah_pci_IRQ_map[23] __prepdata =
{
0, /* Slot 0 - unused */
0, /* Slot 1 - unused */
- 4, /* Slot 2 - SCSI - NCR825A */
+ 5, /* Slot 2 - SCSI - NCR825A */
0, /* Slot 3 - unused */
1, /* Slot 4 - Ethernet - DEC2114x */
0, /* Slot 5 - unused */
- 2, /* Slot 6 - PCI Card slot #1 */
- 3, /* Slot 7 - PCI Card slot #2 */
- 4, /* Slot 8 - PCI Card slot #3 */
- 4, /* Slot 9 - PCI Bridge */
+ 3, /* Slot 6 - PCI Card slot #1 */
+ 4, /* Slot 7 - PCI Card slot #2 */
+ 5, /* Slot 8 - PCI Card slot #3 */
+ 5, /* Slot 9 - PCI Bridge */
/* added here in case we ever support PCI bridges */
/* Secondary PCI bus cards are at slot-9,6 & slot-9,7 */
0, /* Slot 10 - unused */
0, /* Slot 11 - unused */
- 4, /* Slot 12 - SCSI - NCR825A */
+ 5, /* Slot 12 - SCSI - NCR825A */
0, /* Slot 13 - unused */
- 2, /* Slot 14 - enet */
+ 3, /* Slot 14 - enet */
0, /* Slot 15 - unused */
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
+ 2, /* Slot 16 - unused */
+ 3, /* Slot 17 - unused */
+ 5, /* Slot 18 - unused */
+ 0, /* Slot 19 - unused */
+ 0, /* Slot 20 - unused */
+ 0, /* Slot 21 - unused */
+ 0, /* Slot 22 - unused */
};
static char Utah_pci_IRQ_routes[] __prepdata =
{
0, /* Line 0 - Unused */
9, /* Line 1 */
- 11, /* Line 2 */
- 14, /* Line 3 */
- 15, /* Line 4 */
+ 10, /* Line 2 */
+ 11, /* Line 3 */
+ 14, /* Line 4 */
+ 15, /* Line 5 */
};
/* Motorola PowerStackII - Omaha */
@@ -125,9 +137,9 @@ static char Blackhawk_pci_IRQ_map[19] __prepdata =
0, /* Slot 13 - unused */
1, /* Slot 14 - Ethernet */
0, /* Slot 15 - unused */
- 1, /* Slot P7 */
- 2, /* Slot P6 */
- 3, /* Slot P5 */
+ 1, /* Slot P7 */
+ 2, /* Slot P6 */
+ 3, /* Slot P5 */
};
static char Blackhawk_pci_IRQ_routes[] __prepdata =
@@ -139,6 +151,122 @@ static char Blackhawk_pci_IRQ_routes[] __prepdata =
15 /* Line 4 */
};
+/* Motorola Mesquite */
+static char Mesquite_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 - unxued */
+ 0, /* Slot 11 - unused */
+ 0, /* Slot 12 - unused */
+ 0, /* Slot 13 - unused */
+ 2, /* Slot 14 - Ethernet */
+ 0, /* Slot 15 - unused */
+ 3, /* Slot 16 - PMC */
+ 0, /* Slot 17 - unused */
+ 0, /* Slot 18 - unused */
+ 0, /* Slot 19 - unused */
+ 0, /* Slot 20 - unused */
+ 0, /* Slot 21 - unused */
+ 0, /* Slot 22 - unused */
+};
+
+/* Motorola Sitka */
+static char Sitka_pci_IRQ_map[21] __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 - unxued */
+ 0, /* Slot 11 - unused */
+ 0, /* Slot 12 - unused */
+ 0, /* Slot 13 - unused */
+ 2, /* Slot 14 - Ethernet */
+ 0, /* Slot 15 - unused */
+ 9, /* Slot 16 - PMC 1 */
+ 12, /* Slot 17 - PMC 2 */
+ 0, /* Slot 18 - unused */
+ 0, /* Slot 19 - unused */
+ 4, /* Slot 20 - NT P2P bridge */
+};
+
+/* Motorola MTX */
+static char MTX_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 - unused */
+ 3, /* Slot 12 - SCSI */
+ 0, /* Slot 13 - unused */
+ 2, /* Slot 14 - Ethernet */
+ 0, /* Slot 15 - unused */
+ 9, /* Slot 16 - PCI/PMC slot 1 */
+ 10, /* Slot 17 - PCI/PMC slot 2 */
+ 11, /* Slot 18 - PCI slot 3 */
+ 0, /* Slot 19 - unused */
+ 0, /* Slot 20 - unused */
+ 0, /* Slot 21 - unused */
+ 0, /* Slot 22 - unused */
+};
+
+/* Motorola MTX Plus */
+/* Secondary bus interrupt routing is not supported yet */
+static char MTXplus_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 - unused */
+ 3, /* Slot 12 - SCSI */
+ 0, /* Slot 13 - unused */
+ 2, /* Slot 14 - Ethernet 1 */
+ 0, /* Slot 15 - unused */
+ 9, /* Slot 16 - PCI slot 1P */
+ 10, /* Slot 17 - PCI slot 2P */
+ 11, /* Slot 18 - PCI slot 3P */
+ 10, /* Slot 19 - Ethernet 2 */
+ 0, /* Slot 20 - P2P Bridge */
+ 0, /* Slot 21 - unused */
+ 0, /* Slot 22 - unused */
+};
+
+static char Raven_pci_IRQ_routes[] __prepdata =
+{
+ 0, /* This is a dummy structure */
+};
+
/* Motorola MVME16xx */
static char Genesis_pci_IRQ_map[16] __prepdata =
{
@@ -169,8 +297,35 @@ static char Genesis_pci_IRQ_routes[] __prepdata =
15 /* Line 4 */
};
+static char Genesis2_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 - Ethernet */
+ 0, /* Slot 11 - Universe PCI - VME Bridge */
+ 3, /* Slot 12 - unused */
+ 0, /* Slot 13 - unused */
+ 2, /* Slot 14 - SCSI */
+ 0, /* Slot 15 - graphics on 3600 */
+ 9, /* Slot 16 - PMC */
+ 12, /* Slot 17 - pci */
+ 11, /* Slot 18 - pci */
+ 10, /* Slot 19 - pci */
+ 0, /* Slot 20 - pci */
+ 0, /* Slot 21 - unused */
+ 0, /* Slot 22 - unused */
+};
+
/* Motorola Series-E */
-static char Comet_pci_IRQ_map[16] __prepdata =
+static char Comet_pci_IRQ_map[23] __prepdata =
{
0, /* Slot 0 - unused */
0, /* Slot 1 - unused */
@@ -188,6 +343,13 @@ static char Comet_pci_IRQ_map[16] __prepdata =
0, /* Slot 13 - unused */
1, /* Slot 14 - Ethernet */
0, /* Slot 15 - unused */
+ 1, /* Slot 16 - PCI slot 1 */
+ 2, /* Slot 17 - PCI slot 2 */
+ 3, /* Slot 18 - PCI slot 3 */
+ 4, /* Slot 19 - PCI bridge */
+ 0,
+ 0,
+ 0,
};
static char Comet_pci_IRQ_routes[] __prepdata =
@@ -199,6 +361,43 @@ static char Comet_pci_IRQ_routes[] __prepdata =
15 /* Line 4 */
};
+/* Motorola Series-EX */
+static char Comet2_pci_IRQ_map[23] __prepdata =
+{
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 3, /* Slot 2 - SCSI - NCR825A */
+ 0, /* Slot 3 - unused */
+ 1, /* Slot 4 - Ethernet - DEC2104X */
+ 0, /* Slot 5 - unused */
+ 1, /* Slot 6 - PCI slot 1 */
+ 2, /* Slot 7 - PCI slot 2 */
+ 3, /* Slot 8 - PCI slot 3 */
+ 4, /* Slot 9 - PCI bridge */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - unused */
+ 3, /* Slot 12 - SCSI - NCR825A */
+ 0, /* Slot 13 - unused */
+ 1, /* Slot 14 - Ethernet - DEC2104X */
+ 0, /* Slot 15 - unused */
+ 1, /* Slot 16 - PCI slot 1 */
+ 2, /* Slot 17 - PCI slot 2 */
+ 3, /* Slot 18 - PCI slot 3 */
+ 4, /* Slot 19 - PCI bridge */
+ 0,
+ 0,
+ 0,
+};
+
+static char Comet2_pci_IRQ_routes[] __prepdata =
+{
+ 0, /* Line 0 - Unused */
+ 10, /* Line 1 */
+ 11, /* Line 2 */
+ 14, /* Line 3 */
+ 15, /* Line 4 */
+};
+
/*
* ibm 830 (and 850?).
* This is actually based on the Carolina motherboard
@@ -312,22 +511,40 @@ static char Nobis_pci_IRQ_routes[] __prepdata = {
#define CAROLINA_IRQ_EDGE_MASK_LO 0x00 /* IRQ's 0-7 */
#define CAROLINA_IRQ_EDGE_MASK_HI 0xA4 /* IRQ's 8-15 [10,13,15] */
+/*
+ * 8259 edge/level control definitions
+ */
+#define ISA8259_M_ELCR 0x4d0
+#define ISA8259_S_ELCR 0x4d1
+
+#define ELCRS_INT15_LVL 0x80
+#define ELCRS_INT14_LVL 0x40
+#define ELCRS_INT12_LVL 0x10
+#define ELCRS_INT11_LVL 0x08
+#define ELCRS_INT10_LVL 0x04
+#define ELCRS_INT9_LVL 0x02
+#define ELCRS_INT8_LVL 0x01
+#define ELCRM_INT7_LVL 0x80
+#define ELCRM_INT5_LVL 0x20
+
+#define CFGPTR(dev) (0x80800000 | (1<<(dev>>3)) | ((dev&7)<<8) | offset)
+#define DEVNO(dev) (dev>>3)
+
__prep
int
prep_pcibios_read_config_dword (unsigned char bus,
unsigned char dev, unsigned char offset, unsigned int *val)
{
- unsigned long _val;
+ unsigned long _val;
unsigned long *ptr;
- dev >>= 3;
-
- if ((bus != 0) || (dev > MAX_DEVNR))
- {
+
+ if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR))
+ {
*val = 0xFFFFFFFF;
- return PCIBIOS_DEVICE_NOT_FOUND;
- } else
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ } else
{
- ptr = (unsigned long *)(0x80800000 | (1<<dev) | offset);
+ ptr = (unsigned long *)CFGPTR(dev);
_val = le32_to_cpu(*ptr);
}
*val = _val;
@@ -339,16 +556,16 @@ int
prep_pcibios_read_config_word (unsigned char bus,
unsigned char dev, unsigned char offset, unsigned short *val)
{
- unsigned short _val;
+ unsigned short _val;
unsigned short *ptr;
- dev >>= 3;
- if ((bus != 0) || (dev > MAX_DEVNR))
- {
- *val = (unsigned short)0xFFFFFFFF;
- return PCIBIOS_DEVICE_NOT_FOUND;
- } else
+
+ if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR))
+ {
+ *val = 0xFFFF;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ } else
{
- ptr = (unsigned short *)(0x80800000 | (1<<dev) | offset);
+ ptr = (unsigned short *)CFGPTR(dev);
_val = le16_to_cpu(*ptr);
}
*val = _val;
@@ -360,16 +577,16 @@ int
prep_pcibios_read_config_byte (unsigned char bus,
unsigned char dev, unsigned char offset, unsigned char *val)
{
- unsigned char _val;
- volatile unsigned char *ptr;
- dev >>= 3;
- if ((bus != 0) || (dev > MAX_DEVNR))
- {
- *(unsigned long *)val = (unsigned long) 0xFFFFFFFF;
- return PCIBIOS_DEVICE_NOT_FOUND;
- } else
+ unsigned char _val;
+ unsigned char *ptr;
+
+ if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR))
+ {
+ *val = 0xFF;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ } else
{
- ptr = (unsigned char *)(0x80800000 | (1<<dev) | (offset ^ 1));
+ ptr = (unsigned char *)CFGPTR(dev);
_val = *ptr;
}
*val = _val;
@@ -383,14 +600,14 @@ prep_pcibios_write_config_dword (unsigned char bus,
{
unsigned long _val;
unsigned long *ptr;
- dev >>= 3;
+
_val = le32_to_cpu(val);
- if ((bus != 0) || (dev > MAX_DEVNR))
+ if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR))
{
return PCIBIOS_DEVICE_NOT_FOUND;
} else
{
- ptr = (unsigned long *)(0x80800000 | (1<<dev) | offset);
+ ptr = (unsigned long *)CFGPTR(dev);
*ptr = _val;
}
return PCIBIOS_SUCCESSFUL;
@@ -403,14 +620,14 @@ prep_pcibios_write_config_word (unsigned char bus,
{
unsigned short _val;
unsigned short *ptr;
- dev >>= 3;
+
_val = le16_to_cpu(val);
- if ((bus != 0) || (dev > MAX_DEVNR))
+ if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR))
{
return PCIBIOS_DEVICE_NOT_FOUND;
} else
{
- ptr = (unsigned short *)(0x80800000 | (1<<dev) | offset);
+ ptr = (unsigned short *)CFGPTR(dev);
*ptr = _val;
}
return PCIBIOS_SUCCESSFUL;
@@ -423,20 +640,151 @@ prep_pcibios_write_config_byte (unsigned char bus,
{
unsigned char _val;
unsigned char *ptr;
- dev >>= 3;
+
_val = val;
- if ((bus != 0) || (dev > MAX_DEVNR))
+ if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR))
{
return PCIBIOS_DEVICE_NOT_FOUND;
} else
{
- ptr = (unsigned char *)(0x80800000 | (1<<dev) | (offset^1));
+ ptr = (unsigned char *)CFGPTR(dev);
*ptr = _val;
}
return PCIBIOS_SUCCESSFUL;
}
-__initfunc(unsigned long route_pci_interrupts(void))
+#define MOTOROLA_CPUTYPE_REG 0x800
+#define MOTOROLA_BASETYPE_REG 0x803
+#define MPIC_RAVEN_ID 0x48010000
+#define MPIC_HAWK_ID 0x48030000
+#define MOT_PROC2_BIT 0x800
+
+static u_char mvme2600_openpic_initsenses[] __initdata = {
+ 1, /* MVME2600_INT_SIO */
+ 0, /* MVME2600_INT_FALCN_ECC_ERR */
+ 1, /* MVME2600_INT_PCI_ETHERNET */
+ 1, /* MVME2600_INT_PCI_SCSI */
+ 1, /* MVME2600_INT_PCI_GRAPHICS */
+ 1, /* MVME2600_INT_PCI_VME0 */
+ 1, /* MVME2600_INT_PCI_VME1 */
+ 1, /* MVME2600_INT_PCI_VME2 */
+ 1, /* MVME2600_INT_PCI_VME3 */
+ 1, /* MVME2600_INT_PCI_INTA */
+ 1, /* MVME2600_INT_PCI_INTB */
+ 1, /* MVME2600_INT_PCI_INTC */
+ 1, /* MVME2600_INT_PCI_INTD */
+ 1, /* MVME2600_INT_LM_SIG0 */
+ 1, /* MVME2600_INT_LM_SIG1 */
+};
+
+#define MOT_RAVEN_PRESENT 0x1
+#define MOT_HAWK_PRESENT 0x2
+
+int prep_keybd_present = 1;
+int MotMPIC = 0;
+
+__initfunc(int raven_init(void))
+{
+ unsigned int devid;
+ unsigned int pci_membase;
+ unsigned char base_mod;
+
+ /* Check to see if the Raven chip exists. */
+ if ( _prep_type != _PREP_Motorola) {
+ OpenPIC = NULL;
+ return 0;
+ }
+
+ /* Check to see if this board is a type that might have a Raven. */
+ if ((inb(MOTOROLA_CPUTYPE_REG) & 0xF0) != 0xE0) {
+ OpenPIC = NULL;
+ return 0;
+ }
+
+ /* Check the first PCI device to see if it is a Raven. */
+ pcibios_read_config_dword(0, 0, PCI_VENDOR_ID, &devid);
+
+ switch (devid & 0xffff0000) {
+ case MPIC_RAVEN_ID:
+ MotMPIC = MOT_RAVEN_PRESENT;
+ break;
+ case MPIC_HAWK_ID:
+ MotMPIC = MOT_HAWK_PRESENT;
+ break;
+ default:
+ OpenPIC = NULL;
+ return 0;
+ }
+
+
+ /* Read the memory base register. */
+ pcibios_read_config_dword(0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
+
+ if (pci_membase == 0) {
+ OpenPIC = NULL;
+ return 0;
+ }
+
+ /* Map the Raven MPIC registers to virtual memory. */
+ OpenPIC = (struct OpenPIC *)ioremap(pci_membase+0xC0000000, 0x22000);
+
+ OpenPIC_InitSenses = mvme2600_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof(mvme2600_openpic_initsenses);
+
+ /* If raven is present on Motorola store the system config register
+ * for later use.
+ */
+ ProcInfo = (unsigned long *)ioremap(0xfef80400, 4);
+
+ /* This is a hack. If this is a 2300 or 2400 mot board then there is
+ * no keyboard controller and we have to indicate that.
+ */
+ base_mod = inb(MOTOROLA_BASETYPE_REG);
+ if ((MotMPIC == MOT_HAWK_PRESENT) || (base_mod == 0xF9) ||
+ (base_mod == 0xFA) || (base_mod == 0xE1))
+ prep_keybd_present = 0;
+
+ return 1;
+}
+
+struct mot_info {
+ int cpu_type; /* 0x100 mask assumes for Raven and Hawk boards that the level/edge are set */
+ /* 0x200 if this board has a Hawk chip. */
+ int base_type;
+ int max_cpu; /* ored with 0x80 if this board should be checked for multi CPU */
+ const char *name;
+ unsigned char *map;
+ unsigned char *routes;
+} mot_info[] = {
+ {0x300, 0x00, 0x00, "MVME 2400", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x010, 0x00, 0x00, "Genesis", Genesis_pci_IRQ_map, Genesis_pci_IRQ_routes},
+ {0x020, 0x00, 0x00, "Powerstack (Series E)", Comet_pci_IRQ_map, Comet_pci_IRQ_routes},
+ {0x040, 0x00, 0x00, "Blackhawk (Powerstack)", Blackhawk_pci_IRQ_map, Blackhawk_pci_IRQ_routes},
+ {0x050, 0x00, 0x00, "Omaha (PowerStack II Pro3000)", Omaha_pci_IRQ_map, Omaha_pci_IRQ_routes},
+ {0x060, 0x00, 0x00, "Utah (Powerstack II Pro4000)", Utah_pci_IRQ_map, Utah_pci_IRQ_routes},
+ {0x0A0, 0x00, 0x00, "Powerstack (Series EX)", Comet2_pci_IRQ_map, Comet2_pci_IRQ_routes},
+ {0x1E0, 0xE0, 0x00, "Mesquite cPCI (MCP750)", Mesquite_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xE1, 0x00, "Sitka cPCI (MCPN750)", Sitka_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xE2, 0x00, "Mesquite cPCI (MCP750) w/ HAC", Mesquite_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xF6, 0x80, "MTX Plus", MTXplus_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xF6, 0x81, "Dual MTX Plus", MTXplus_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xF7, 0x80, "MTX wo/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xF7, 0x81, "Dual MTX wo/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xF8, 0x80, "MTX w/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xF8, 0x81, "Dual MTX w/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xF9, 0x00, "MVME 2300", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xFA, 0x00, "MVME 2300SC/2600", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xFB, 0x00, "MVME 2600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xFC, 0x00, "MVME 2600/2700 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xFD, 0x80, "MVME 3600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xFD, 0x81, "MVME 4600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xFE, 0x80, "MVME 3600 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xFE, 0x81, "MVME 4600 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xFF, 0x00, "MVME 1600-001 or 1600-011", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x000, 0x00, 0x00, "", NULL, NULL}
+};
+
+__initfunc(unsigned long prep_route_pci_interrupts(void))
{
unsigned char *ibc_pirq = (unsigned char *)0x80800860;
unsigned char *ibc_pcicon = (unsigned char *)0x80800840;
@@ -445,49 +793,66 @@ __initfunc(unsigned long route_pci_interrupts(void))
if ( _prep_type == _PREP_Motorola)
{
unsigned short irq_mode;
+ unsigned char cpu_type;
+ unsigned char base_mod;
+ int entry;
+ int mot_entry = -1;
- switch (inb(0x800) & 0xF0)
- {
- case 0x10: /* MVME16xx */
- Motherboard_map_name = "Genesis";
- Motherboard_map = Genesis_pci_IRQ_map;
- Motherboard_routes = Genesis_pci_IRQ_routes;
- break;
- case 0x20: /* Series E */
- Motherboard_map_name = "Powerstack (Series E)";
- Motherboard_map = Comet_pci_IRQ_map;
- Motherboard_routes = Comet_pci_IRQ_routes;
- break;
- case 0x50: /* PowerStackII Pro3000 */
- Motherboard_map_name = "Omaha (PowerStack II Pro3000)";
- Motherboard_map = Omaha_pci_IRQ_map;
- Motherboard_routes = Omaha_pci_IRQ_routes;
- break;
- case 0x60: /* PowerStackII Pro4000 */
- Motherboard_map_name = "Utah (Powerstack II Pro4000)";
- 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)";
- Motherboard_map = Blackhawk_pci_IRQ_map;
- Motherboard_routes = Blackhawk_pci_IRQ_routes;
- break;
+ cpu_type = inb(MOTOROLA_CPUTYPE_REG) & 0xF0;
+ base_mod = inb(MOTOROLA_BASETYPE_REG);
+
+ for (entry = 0; mot_info[entry].cpu_type != 0; entry++) {
+ if (mot_info[entry].cpu_type & 0x200) { /* Check for Hawk chip */
+ if (!(MotMPIC & MOT_HAWK_PRESENT))
+ continue;
+ } else { /* Check non hawk boards */
+ if ((mot_info[entry].cpu_type & 0xff) != cpu_type)
+ continue;
+
+ if (mot_info[entry].base_type == 0) {
+ mot_entry = entry;
+ break;
+ }
+
+ if (mot_info[entry].base_type != base_mod)
+ continue;
+ }
+
+ if (!(mot_info[entry].max_cpu & 0x80)) {
+ mot_entry = entry;
+ break;
+ }
+
+ /* processor 1 not present and max processor zero indicated */
+ if ((*ProcInfo & MOT_PROC2_BIT) && !(mot_info[entry].max_cpu & 0x7f)) {
+ mot_entry = entry;
+ break;
+ }
+
+ /* processor 1 present and max processor zero indicated */
+ if (!(*ProcInfo & MOT_PROC2_BIT) && (mot_info[entry].max_cpu & 0x7f)) {
+ mot_entry = entry;
+ break;
+ }
}
- /* AJF adjust level/edge control according to routes */
- irq_mode = 0;
- for (i = 1; i <= 4; i++)
- {
- irq_mode |= ( 1 << Motherboard_routes[i] );
+
+ if (mot_entry == -1) /* No particular cpu type found - assume Blackhawk */
+ mot_entry = 3;
+
+ Motherboard_map_name = (unsigned char *)mot_info[mot_entry].name;
+ Motherboard_map = mot_info[mot_entry].map;
+ Motherboard_routes = mot_info[mot_entry].routes;
+
+ if (!(mot_info[entry].cpu_type & 0x100)) {
+ /* AJF adjust level/edge control according to routes */
+ irq_mode = 0;
+ for (i = 1; i <= 4; i++)
+ {
+ irq_mode |= ( 1 << Motherboard_routes[i] );
+ }
+ outb( irq_mode & 0xff, 0x4d0 );
+ outb( (irq_mode >> 8) & 0xff, 0x4d1 );
}
- outb( irq_mode & 0xff, 0x4d0 );
- outb( (irq_mode >> 8) & 0xff, 0x4d1 );
} else if ( _prep_type == _PREP_IBM )
{
unsigned char pl_id;
@@ -526,6 +891,71 @@ __initfunc(unsigned long route_pci_interrupts(void))
outb(pl_id|CAROLINA_IRQ_EDGE_MASK_HI, 0x04d1);
pl_id=inb(0x04d1);
/*printk("Hi mask now %#0x\n", pl_id);*/
+ } else if ( _prep_type == _PREP_Radstone )
+ {
+ unsigned char ucElcrM, ucElcrS;
+
+ /*
+ * Set up edge/level
+ */
+ switch(ucSystemType)
+ {
+ case RS_SYS_TYPE_PPC1:
+ {
+ if(ucBoardRevMaj<5)
+ {
+ ucElcrS=ELCRS_INT15_LVL;
+ }
+ else
+ {
+ ucElcrS=ELCRS_INT9_LVL |
+ ELCRS_INT11_LVL |
+ ELCRS_INT14_LVL |
+ ELCRS_INT15_LVL;
+ }
+ ucElcrM=ELCRM_INT5_LVL | ELCRM_INT7_LVL;
+ break;
+ }
+
+ case RS_SYS_TYPE_PPC1a:
+ {
+ ucElcrS=ELCRS_INT9_LVL |
+ ELCRS_INT11_LVL |
+ ELCRS_INT14_LVL |
+ ELCRS_INT15_LVL;
+ ucElcrM=ELCRM_INT5_LVL;
+ break;
+ }
+
+ case RS_SYS_TYPE_PPC2:
+ case RS_SYS_TYPE_PPC2a:
+ case RS_SYS_TYPE_PPC2ep:
+ case RS_SYS_TYPE_PPC4:
+ case RS_SYS_TYPE_PPC4a:
+ default:
+ {
+ ucElcrS=ELCRS_INT9_LVL |
+ ELCRS_INT10_LVL |
+ ELCRS_INT11_LVL |
+ ELCRS_INT14_LVL |
+ ELCRS_INT15_LVL;
+ ucElcrM=ELCRM_INT5_LVL |
+ ELCRM_INT7_LVL;
+ break;
+ }
+ }
+
+ /*
+ * Write edge/level selection
+ */
+ outb(ucElcrS, ISA8259_S_ELCR);
+ outb(ucElcrM, ISA8259_M_ELCR);
+
+ /*
+ * Radstone boards have PCI interrupts all set up
+ * so leave well alone
+ */
+ return 0;
} else
{
printk("No known machine pci routing!\n");
@@ -542,3 +972,117 @@ __initfunc(unsigned long route_pci_interrupts(void))
return 0;
}
+__initfunc(
+void
+prep_pcibios_fixup(void))
+{
+ struct pci_dev *dev;
+ extern unsigned char *Motherboard_map;
+ extern unsigned char *Motherboard_routes;
+ unsigned char i;
+
+ if ( _prep_type == _PREP_Radstone )
+ {
+ printk("Radstone boards require no PCI fixups\n");
+ return;
+ }
+
+ prep_route_pci_interrupts();
+
+ printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name);
+ if (OpenPIC) {
+ /* PCI interrupts are controlled by the OpenPIC */
+ for(dev=pci_devices; dev; dev=dev->next) {
+ if (dev->bus->number == 0) {
+ dev->irq = openpic_to_irq(Motherboard_map[PCI_SLOT(dev->devfn)]);
+ pcibios_write_config_byte(dev->bus->number, dev->devfn, PCI_INTERRUPT_PIN, dev->irq);
+ }
+ }
+ return;
+ }
+
+ 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]];
+
+ for ( i = 0 ; i <= 5 ; i++ )
+ {
+ if ( dev->base_address[i] > 0x10000000 )
+ {
+ printk("Relocating PCI address %lx -> %lx\n",
+ dev->base_address[i],
+ (dev->base_address[i] & 0x00FFFFFF)
+ | 0x01000000);
+ dev->base_address[i] =
+ (dev->base_address[i] & 0x00FFFFFF) | 0x01000000;
+ pci_write_config_dword(dev,
+ PCI_BASE_ADDRESS_0+(i*0x4),
+ dev->base_address[i] );
+ }
+ }
+#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
+ }
+}
+
+decl_config_access_method(indirect);
+
+__initfunc(
+void
+prep_setup_pci_ptrs(void))
+{
+ PPC_DEVICE *hostbridge;
+
+ printk("PReP architecture\n");
+ if ( _prep_type == _PREP_Radstone )
+ {
+ pci_config_address = (unsigned *)0x80000cf8;
+ pci_config_data = (char *)0x80000cfc;
+ set_config_access_method(indirect);
+ }
+ else
+ {
+ hostbridge = residual_find_device(PROCESSORDEVICE, NULL,
+ BridgeController, PCIBridge, -1, 0);
+ if (hostbridge &&
+ hostbridge->DeviceId.Interface == PCIBridgeIndirect) {
+ PnP_TAG_PACKET * pkt;
+ set_config_access_method(indirect);
+ pkt = PnP_find_large_vendor_packet(
+ res->DevicePnPHeap+hostbridge->AllocatedOffset,
+ 3, 0);
+ if(pkt)
+ {
+#define p pkt->L4_Pack.L4_Data.L4_PPCPack
+ pci_config_address= (unsigned *)ld_le32((unsigned *) p.PPCData);
+ pci_config_data= (unsigned char *)ld_le32((unsigned *) (p.PPCData+8));
+ }
+ else
+ {
+ pci_config_address= (unsigned *) 0x80000cf8;
+ pci_config_data= (unsigned char *) 0x80000cfc;
+ }
+ }
+ else
+ {
+ set_config_access_method(prep);
+ }
+
+ }
+
+ ppc_md.pcibios_fixup = prep_pcibios_fixup;
+}
+
diff --git a/arch/ppc/kernel/prep_setup.c b/arch/ppc/kernel/prep_setup.c
index 72752e11f..de18f465a 100644
--- a/arch/ppc/kernel/prep_setup.c
+++ b/arch/ppc/kernel/prep_setup.c
@@ -30,6 +30,9 @@
#include <linux/blk.h>
#include <linux/ioport.h>
#include <linux/console.h>
+#include <linux/timex.h>
+#include <linux/pci.h>
+#include <linux/openpic.h>
#include <asm/mmu.h>
#include <asm/processor.h>
@@ -38,12 +41,57 @@
#include <asm/pgtable.h>
#include <asm/ide.h>
#include <asm/cache.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/mk48t59.h>
+#include <asm/prep_nvram.h>
+#include <asm/raven.h>
+
+
+#include "time.h"
+#include "local_irq.h"
+#include "i8259.h"
+#include "open_pic.h"
#if defined(CONFIG_SOUND) || defined(CONFIG_SOUND_MODULE)
#include <../drivers/sound/sound_config.h>
#include <../drivers/sound/dev_table.h>
#endif
+unsigned char ucSystemType;
+unsigned char ucBoardRev;
+unsigned char ucBoardRevMaj, ucBoardRevMin;
+
+extern unsigned long mc146818_get_rtc_time(void);
+extern int mc146818_set_rtc_time(unsigned long nowtime);
+extern unsigned long mk48t59_get_rtc_time(void);
+extern int mk48t59_set_rtc_time(unsigned long nowtime);
+
+extern unsigned char prep_nvram_read_val(int addr);
+extern void prep_nvram_write_val(int addr,
+ unsigned char val);
+extern unsigned char rs_nvram_read_val(int addr);
+extern void rs_nvram_write_val(int addr,
+ unsigned char val);
+
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);
+extern unsigned char pckbd_sysrq_xlate[128];
+
+extern void prep_setup_pci_ptrs(void);
+extern void chrp_do_IRQ(struct pt_regs *regs, int cpu, int isfake);
+extern char saved_command_line[256];
+
+int _prep_type;
+
+#define cached_21 (((char *)(ppc_cached_irq_mask))[3])
+#define cached_A1 (((char *)(ppc_cached_irq_mask))[2])
+
/* for the mac fs */
kdev_t boot_dev;
/* used in nasty hack for sound - see prep_setup_arch() -- Cort */
@@ -54,13 +102,15 @@ extern PTE *Hash, *Hash_end;
extern unsigned long Hash_size, Hash_mask;
extern int probingmem;
extern unsigned long loops_per_sec;
-extern unsigned char aux_device_present;
#ifdef CONFIG_BLK_DEV_RAM
extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
extern int rd_image_start; /* starting block # of image */
#endif
+#ifdef CONFIG_VGA_CONSOLE
+unsigned long vgacon_remap_base;
+#endif
__prep
int
@@ -136,6 +186,8 @@ prep_get_cpuinfo(char *buffer)
break;
}
break;
+ default:
+ break;
}
@@ -163,11 +215,12 @@ prep_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
{
extern char cmd_line[];
unsigned char reg;
+ unsigned char ucMothMemType;
+ unsigned char ucEquipPres1;
/* init to some ~sane value until calibrate_delay() runs */
loops_per_sec = 50000000;
- aux_device_present = 0xaa;
/* Set up floppy in PS/2 mode */
outb(0x09, SIO_CONFIG_RA);
reg = inb(SIO_CONFIG_RD);
@@ -175,20 +228,78 @@ prep_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
outb(reg, SIO_CONFIG_RD);
outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */
+ /*
+ * We need to set up the NvRAM access routines early as prep_init
+ * has yet to be called
+ */
+ ppc_md.nvram_read_val = prep_nvram_read_val;
+ ppc_md.nvram_write_val = prep_nvram_write_val;
+
/* we should determine this according to what we find! -- Cort */
switch ( _prep_type )
{
case _PREP_IBM:
+ /* Enable L2. Assume we don't need to flush -- Cort*/
+ *(unsigned char *)(0x8000081c) |= 3;
ROOT_DEV = to_kdev_t(0x0301); /* hda1 */
break;
case _PREP_Motorola:
+ /* Enable L2. Assume we don't need to flush -- Cort*/
+ *(unsigned char *)(0x8000081c) |= 3;
ROOT_DEV = to_kdev_t(0x0801); /* sda1 */
break;
+ case _PREP_Radstone:
+ ROOT_DEV = to_kdev_t(0x0801); /* sda1 */
+
+ /*
+ * Determine system type
+ */
+ ucMothMemType=inb(0x866);
+ ucEquipPres1=inb(0x80c);
+
+ ucSystemType=((ucMothMemType&0x03)<<1) |
+ ((ucEquipPres1&0x80)>>7);
+ ucSystemType^=7;
+
+ /*
+ * Determine board revision for use by
+ * rev. specific code
+ */
+ ucBoardRev=inb(0x854);
+ ucBoardRevMaj=ucBoardRev>>5;
+ ucBoardRevMin=ucBoardRev&0x1f;
+
+ /*
+ * Most Radstone boards have memory mapped NvRAM
+ */
+ if((ucSystemType==RS_SYS_TYPE_PPC1) && (ucBoardRevMaj<5))
+ {
+ ppc_md.nvram_read_val = prep_nvram_read_val;
+ ppc_md.nvram_write_val = prep_nvram_write_val;
+ }
+ else
+ {
+ ppc_md.nvram_read_val = rs_nvram_read_val;
+ ppc_md.nvram_write_val = rs_nvram_write_val;
+ }
+ break;
}
- /* Enable L2. Assume we don't need to flush -- Cort*/
- *(unsigned char *)(0x8000081c) = *(unsigned char *)(0x8000081c)|3;
-
+ /* Read in NVRAM data */
+ init_prep_nvram();
+
+ /* if no bootargs, look in NVRAM */
+ if ( cmd_line[0] == '\0' ) {
+ char *bootargs;
+ bootargs = prep_nvram_get_var("bootargs");
+ if (bootargs != NULL) {
+ strcpy(cmd_line, bootargs);
+
+ /* again.. */
+ strcpy(saved_command_line, cmd_line);
+ }
+ }
+
printk("Boot arguments: %s\n", cmd_line);
#ifdef CONFIG_SOUND_CS4232
@@ -238,12 +349,349 @@ prep_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
request_region(0x80,0x10,"dma page reg");
request_region(0xc0,0x20,"dma2");
+ raven_init();
+
#ifdef CONFIG_VGA_CONSOLE
+ /* remap the VGA memory */
+ vgacon_remap_base = 0xf0000000;
+ /*vgacon_remap_base = ioremap(0xc0000000, 0xba000);*/
conswitchp = &vga_con;
#endif
}
-__initfunc(void prep_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq))
+/*
+ * Determine the decrementer frequency from the residual data
+ * This allows for a faster boot as we do not need to calibrate the
+ * decrementer against another clock. This is important for embedded systems.
+ */
+__initfunc(void prep_res_calibrate_decr(void))
+{
+ int freq, divisor;
+
+ freq = res->VitalProductData.ProcessorBusHz;
+ divisor = 4;
+ printk("time_init: decrementer frequency = %d/%d\n", freq, divisor);
+ decrementer_count = freq / HZ / divisor;
+ count_period_num = divisor;
+ count_period_den = freq / 1000000;
+}
+
+/*
+ * Uses the on-board timer to calibrate the on-chip decrementer register
+ * for prep systems. On the pmac the OF tells us what the frequency is
+ * but on prep we have to figure it out.
+ * -- Cort
+ */
+int calibrate_done = 0;
+volatile int *done_ptr = &calibrate_done;
+
+__initfunc(void
+prep_calibrate_decr_handler(int irq,
+ void *dev,
+ struct pt_regs *regs))
+{
+ unsigned long freq, divisor;
+ static unsigned long t1 = 0, t2 = 0;
+
+ if ( !t1 )
+ t1 = get_dec();
+ else if (!t2)
+ {
+ t2 = get_dec();
+ t2 = t1-t2; /* decr's in 1/HZ */
+ t2 = t2*HZ; /* # decrs in 1s - thus in Hz */
+ freq = t2 * 60; /* try to make freq/1e6 an integer */
+ divisor = 60;
+ printk("time_init: decrementer frequency = %lu/%lu (%luMHz)\n",
+ freq, divisor,t2>>20);
+ decrementer_count = freq / HZ / divisor;
+ count_period_num = divisor;
+ count_period_den = freq / 1000000;
+ *done_ptr = 1;
+ }
+}
+
+__initfunc(void prep_calibrate_decr(void))
+{
+ unsigned long flags;
+
+
+ save_flags(flags);
+
+#define TIMER0_COUNT 0x40
+#define TIMER_CONTROL 0x43
+ /* set timer to periodic mode */
+ outb_p(0x34,TIMER_CONTROL);/* binary, mode 2, LSB/MSB, ch 0 */
+ /* set the clock to ~100 Hz */
+ outb_p(LATCH & 0xff , TIMER0_COUNT); /* LSB */
+ outb(LATCH >> 8 , TIMER0_COUNT); /* MSB */
+
+ if (request_irq(0, prep_calibrate_decr_handler, 0, "timer", NULL) != 0)
+ panic("Could not allocate timer IRQ!");
+ __sti();
+ while ( ! *done_ptr ) /* nothing */; /* wait for calibrate */
+ restore_flags(flags);
+ free_irq( 0, NULL);
+}
+
+
+/* We use the NVRAM RTC to time a second to calibrate the decrementer. */
+__initfunc(void mk48t59_calibrate_decr(void))
+{
+ unsigned long freq, divisor;
+ unsigned long t1, t2;
+ unsigned char save_control;
+ long i;
+ unsigned char sec;
+
+
+ /* Make sure the time is not stopped. */
+ save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB);
+
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
+ (save_control & (~MK48T59_RTC_CB_STOP)));
+
+ /* Now make sure the read bit is off so the value will change. */
+ save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
+ save_control &= ~MK48T59_RTC_CA_READ;
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
+
+
+ /* Read the seconds value to see when it changes. */
+ sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
+ for (i = 0 ; i < 1000000 ; i++) { /* may take up to 1 second... */
+ if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) {
+ break;
+ }
+ }
+ t1 = get_dec();
+
+ sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
+ for (i = 0 ; i < 1000000 ; i++) { /* Should take up 1 second... */
+ if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) {
+ break;
+ }
+ }
+
+ t2 = t1 - get_dec();
+
+ freq = t2 * 60; /* try to make freq/1e6 an integer */
+ divisor = 60;
+ printk("time_init: decrementer frequency = %lu/%lu (%luMHz)\n",
+ freq, divisor,t2>>20);
+ decrementer_count = freq / HZ / divisor;
+ count_period_num = divisor;
+ count_period_den = freq / 1000000;
+}
+
+void
+prep_restart(char *cmd)
+{
+ unsigned long i = 10000;
+
+
+ _disable_interrupts();
+
+ /* set exception prefix high - to the prom */
+ _nmask_and_or_msr(0, MSR_IP);
+
+ /* make sure bit 0 (reset) is a 0 */
+ outb( inb(0x92) & ~1L , 0x92 );
+ /* signal a reset to system control port A - soft reset */
+ outb( inb(0x92) | 1 , 0x92 );
+
+ while ( i != 0 ) i++;
+ panic("restart failed\n");
+}
+
+/*
+ * This function will restart a board regardless of port 92 functionality
+ */
+void
+prep_direct_restart(char *cmd)
+{
+ u32 jumpaddr=0xfff00100;
+ u32 defaultmsr=MSR_IP;
+
+ /*
+ * This will ALWAYS work regardless of port 92
+ * functionality
+ */
+ _disable_interrupts();
+
+ __asm__ __volatile__("\n\
+ mtspr 26, %1 /* SRR0 */
+ mtspr 27, %0 /* SRR1 */
+ rfi"
+ :
+ : "r" (defaultmsr), "r" (jumpaddr));
+ /*
+ * Not reached
+ */
+}
+
+void
+prep_halt(void)
+{
+ unsigned long flags;
+ _disable_interrupts();
+ /* set exception prefix high - to the prom */
+ save_flags( flags );
+ restore_flags( flags|MSR_IP );
+
+ /* make sure bit 0 (reset) is a 0 */
+ outb( inb(0x92) & ~1L , 0x92 );
+ /* signal a reset to system control port A - soft reset */
+ outb( inb(0x92) | 1 , 0x92 );
+
+ while ( 1 ) ;
+ /*
+ * Not reached
+ */
+}
+
+void
+prep_power_off(void)
+{
+ prep_halt();
+}
+
+int prep_setup_residual(char *buffer)
+{
+ int len = 0;
+
+
+ /* PREP's without residual data will give incorrect values here */
+ len += sprintf(len+buffer, "clock\t\t: ");
+ if ( res->ResidualLength )
+ len += sprintf(len+buffer, "%ldMHz\n",
+ (res->VitalProductData.ProcessorHz > 1024) ?
+ res->VitalProductData.ProcessorHz>>20 :
+ res->VitalProductData.ProcessorHz);
+ else
+ len += sprintf(len+buffer, "???\n");
+
+ return len;
+}
+
+u_int
+prep_irq_cannonicalize(u_int irq)
+{
+ if (irq == 2)
+ {
+ return 9;
+ }
+ else
+ {
+ return irq;
+ }
+}
+
+void
+prep_do_IRQ(struct pt_regs *regs, int cpu, int isfake)
+{
+ int irq;
+
+ if ( (irq = i8259_irq(0)) < 0 )
+ {
+ printk(KERN_DEBUG "Bogus interrupt from PC = %lx\n",
+ regs->nip);
+ ppc_spurious_interrupts++;
+ return;
+ }
+ ppc_irq_dispatch_handler( regs, irq );
+}
+
+__initfunc(void
+prep_init_IRQ(void))
+{
+ int i;
+
+ if (OpenPIC != NULL) {
+ for ( i = 16 ; i < 36 ; i++ )
+ irq_desc[i].ctl = &open_pic;
+ openpic_init(1);
+ }
+
+ for ( i = 0 ; i < 16 ; i++ )
+ irq_desc[i].ctl = &i8259_pic;
+ i8259_init();
+#ifdef __SMP__
+ request_irq(openpic_to_irq(OPENPIC_VEC_SPURIOUS), openpic_ipi_action,
+ 0, "IPI0", 0);
+#endif /* __SMP__ */
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */
+void
+prep_ide_insw(ide_ioreg_t port, void *buf, int ns)
+{
+ _insw((unsigned short *)((port)+_IO_BASE), buf, ns);
+}
+
+void
+prep_ide_outsw(ide_ioreg_t port, void *buf, int ns)
+{
+ _outsw((unsigned short *)((port)+_IO_BASE), buf, ns);
+}
+
+int
+prep_ide_default_irq(ide_ioreg_t base)
+{
+ switch (base) {
+ case 0x1f0: return 13;
+ case 0x170: return 13;
+ case 0x1e8: return 11;
+ case 0x168: return 10;
+ default:
+ return 0;
+ }
+}
+
+ide_ioreg_t
+prep_ide_default_io_base(int index)
+{
+ switch (index) {
+ case 0: return 0x1f0;
+ case 1: return 0x170;
+ case 2: return 0x1e8;
+ case 3: return 0x168;
+ default:
+ return 0;
+ }
+}
+
+int
+prep_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+ return check_region(from, extent);
+}
+
+void
+prep_ide_request_region(ide_ioreg_t from,
+ unsigned int extent,
+ const char *name)
+{
+ request_region(from, extent, name);
+}
+
+void
+prep_ide_release_region(ide_ioreg_t from,
+ unsigned int extent)
+{
+ release_region(from, extent);
+}
+
+void
+prep_ide_fix_driveid(struct hd_driveid *id)
+{
+}
+
+__initfunc(void
+prep_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq))
{
ide_ioreg_t port = base;
int i = 8;
@@ -254,6 +702,143 @@ __initfunc(void prep_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int
if (irq != NULL)
*irq = 0;
}
+#endif
+
+__initfunc(void
+prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7))
+{
+ /* make a copy of residual data */
+ if ( r3 )
+ {
+ memcpy((void *)res,(void *)(r3+KERNELBASE),
+ sizeof(RESIDUAL));
+ }
+
+ isa_io_base = PREP_ISA_IO_BASE;
+ isa_mem_base = PREP_ISA_MEM_BASE;
+ pci_dram_offset = PREP_PCI_DRAM_OFFSET;
+ ISA_DMA_THRESHOLD = 0x00ffffff;
+ DMA_MODE_READ = 0x44;
+ DMA_MODE_WRITE = 0x48;
+
+ /* figure out what kind of prep workstation we are */
+ if ( res->ResidualLength != 0 )
+ {
+ if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) )
+ _prep_type = _PREP_IBM;
+ else if (!strncmp(res->VitalProductData.PrintableModel,
+ "Radstone",8))
+ {
+ extern char *Motherboard_map_name;
+
+ _prep_type = _PREP_Radstone;
+ Motherboard_map_name=
+ res->VitalProductData.PrintableModel;
+ }
+ else
+ _prep_type = _PREP_Motorola;
+ }
+ else /* assume motorola if no residual (netboot?) */
+ {
+ _prep_type = _PREP_Motorola;
+ }
+
+ prep_setup_pci_ptrs();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* take care of initrd if we have one */
+ if ( r4 )
+ {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ /* take care of cmd line */
+ if ( r6 && (((char *) r6) != '\0'))
+ {
+ *(char *)(r7+KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6+KERNELBASE));
+ }
+
+ ppc_md.setup_arch = prep_setup_arch;
+ ppc_md.setup_residual = prep_setup_residual;
+ ppc_md.get_cpuinfo = prep_get_cpuinfo;
+ ppc_md.irq_cannonicalize = prep_irq_cannonicalize;
+ ppc_md.init_IRQ = prep_init_IRQ;
+ if ( !OpenPIC )
+ ppc_md.do_IRQ = prep_do_IRQ;
+ else
+ ppc_md.do_IRQ = chrp_do_IRQ;
+ ppc_md.init = NULL;
+
+ ppc_md.restart = prep_restart;
+ ppc_md.power_off = prep_power_off;
+ ppc_md.halt = prep_halt;
+
+ ppc_md.time_init = NULL;
+ if (_prep_type == _PREP_Radstone) {
+ /*
+ * We require a direct restart as port 92 does not work on
+ * all Radstone boards
+ */
+ ppc_md.restart = prep_direct_restart;
+ /*
+ * The RTC device used varies according to board type
+ */
+ if(((ucSystemType==RS_SYS_TYPE_PPC1) && (ucBoardRevMaj>=5)) ||
+ (ucSystemType==RS_SYS_TYPE_PPC1a))
+ {
+ ppc_md.set_rtc_time = mk48t59_set_rtc_time;
+ ppc_md.get_rtc_time = mk48t59_get_rtc_time;
+ }
+ else
+ {
+ ppc_md.set_rtc_time = mc146818_set_rtc_time;
+ ppc_md.get_rtc_time = mc146818_get_rtc_time;
+ }
+ /*
+ * Determine the decrementer rate from the residual data
+ */
+ ppc_md.calibrate_decr = prep_res_calibrate_decr;
+ }
+ else if (_prep_type == _PREP_IBM) {
+ ppc_md.set_rtc_time = mc146818_set_rtc_time;
+ ppc_md.get_rtc_time = mc146818_get_rtc_time;
+ ppc_md.calibrate_decr = prep_calibrate_decr;
+ }
+ else {
+ ppc_md.set_rtc_time = mk48t59_set_rtc_time;
+ ppc_md.get_rtc_time = mk48t59_get_rtc_time;
+ ppc_md.calibrate_decr = mk48t59_calibrate_decr;
+ }
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ ppc_ide_md.insw = prep_ide_insw;
+ ppc_ide_md.outsw = prep_ide_outsw;
+ ppc_ide_md.default_irq = prep_ide_default_irq;
+ ppc_ide_md.default_io_base = prep_ide_default_io_base;
+ ppc_ide_md.check_region = prep_ide_check_region;
+ ppc_ide_md.request_region = prep_ide_request_region;
+ ppc_ide_md.release_region = prep_ide_release_region;
+ ppc_ide_md.fix_driveid = prep_ide_fix_driveid;
+ ppc_ide_md.ide_init_hwif = prep_ide_init_hwif_ports;
+#endif
+ ppc_ide_md.io_base = _IO_BASE;
+
+#ifdef CONFIG_VT
+ ppc_md.kbd_setkeycode = pckbd_setkeycode;
+ ppc_md.kbd_getkeycode = pckbd_getkeycode;
+ ppc_md.kbd_translate = pckbd_translate;
+ ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
+ ppc_md.kbd_leds = pckbd_leds;
+ ppc_md.kbd_init_hw = pckbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.kbd_sysrq_xlate = pckbd_sysrq_xlate;
+#endif
+#endif
+}
#ifdef CONFIG_SOUND_MODULE
EXPORT_SYMBOL(ppc_cs4232_dma);
diff --git a/arch/ppc/kernel/prep_time.c b/arch/ppc/kernel/prep_time.c
index f1dff8f13..5b8873d79 100644
--- a/arch/ppc/kernel/prep_time.c
+++ b/arch/ppc/kernel/prep_time.c
@@ -22,7 +22,9 @@
#include <asm/segment.h>
#include <asm/io.h>
#include <asm/processor.h>
-#include <asm/nvram.h>
+#include <asm/machdep.h>
+#include <asm/prep_nvram.h>
+#include <asm/mk48t59.h>
#include "time.h"
@@ -41,73 +43,29 @@
* is setup at boot time to use the correct addresses.
* -- Cort
*/
-/*
- * translate from mc146818 to m48t18 addresses
- */
-unsigned int clock_transl[] __prepdata = { MOTO_RTC_SECONDS,0 /* alarm */,
- MOTO_RTC_MINUTES,0 /* alarm */,
- MOTO_RTC_HOURS,0 /* alarm */, /* 4,5 */
- MOTO_RTC_DAY_OF_WEEK,
- MOTO_RTC_DAY_OF_MONTH,
- MOTO_RTC_MONTH,
- MOTO_RTC_YEAR, /* 9 */
- MOTO_RTC_CONTROLA, MOTO_RTC_CONTROLB /* 10,11 */
-};
-
-__prep
-int prep_cmos_clock_read(int addr)
-{
- if ( _prep_type == _PREP_IBM )
- return CMOS_READ(addr);
- else if ( _prep_type == _PREP_Motorola )
- {
- outb(clock_transl[addr]>>8, NVRAM_AS1);
- outb(clock_transl[addr], NVRAM_AS0);
- return (inb(NVRAM_DATA));
- }
-
- printk("Unknown machine in prep_cmos_clock_read()!\n");
- return -1;
-}
-
-__prep
-void prep_cmos_clock_write(unsigned long val, int addr)
-{
- if ( _prep_type == _PREP_IBM )
- {
- CMOS_WRITE(val,addr);
- return;
- }
- else if ( _prep_type == _PREP_Motorola )
- {
- outb(clock_transl[addr]>>8, NVRAM_AS1);
- outb(clock_transl[addr], NVRAM_AS0);
- outb(val,NVRAM_DATA);
- return;
- }
- printk("Unknown machine in prep_cmos_clock_write()!\n");
-}
/*
* Set the hardware clock. -- Cort
*/
__prep
-int prep_set_rtc_time(unsigned long nowtime)
+int mc146818_set_rtc_time(unsigned long nowtime)
{
unsigned char save_control, save_freq_select;
struct rtc_time tm;
to_tm(nowtime, &tm);
- save_control = prep_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */
-
- prep_cmos_clock_write((save_control|RTC_SET), RTC_CONTROL);
-
- save_freq_select = prep_cmos_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */
+ /* tell the clock it's being set */
+ save_control = CMOS_READ(RTC_CONTROL);
- prep_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
-
- tm.tm_year -= 1900;
+ CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+ /* stop and reset prescaler */
+ save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
+
+ CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+ tm.tm_year = (tm.tm_year - 1900) % 100;
if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
BIN_TO_BCD(tm.tm_sec);
BIN_TO_BCD(tm.tm_min);
@@ -116,12 +74,12 @@ int prep_set_rtc_time(unsigned long nowtime)
BIN_TO_BCD(tm.tm_mday);
BIN_TO_BCD(tm.tm_year);
}
- prep_cmos_clock_write(tm.tm_sec,RTC_SECONDS);
- prep_cmos_clock_write(tm.tm_min,RTC_MINUTES);
- prep_cmos_clock_write(tm.tm_hour,RTC_HOURS);
- prep_cmos_clock_write(tm.tm_mon,RTC_MONTH);
- prep_cmos_clock_write(tm.tm_mday,RTC_DAY_OF_MONTH);
- prep_cmos_clock_write(tm.tm_year,RTC_YEAR);
+ CMOS_WRITE(tm.tm_sec, RTC_SECONDS);
+ CMOS_WRITE(tm.tm_min, RTC_MINUTES);
+ CMOS_WRITE(tm.tm_hour, RTC_HOURS);
+ CMOS_WRITE(tm.tm_mon, RTC_MONTH);
+ CMOS_WRITE(tm.tm_mday, RTC_DAY_OF_MONTH);
+ CMOS_WRITE(tm.tm_year, RTC_YEAR);
/* The following flags have to be released exactly in this order,
* otherwise the DS12887 (popular MC146818A clone with integrated
@@ -130,16 +88,14 @@ int prep_set_rtc_time(unsigned long nowtime)
* the Dallas Semiconductor data sheets, but who believes data
* sheets anyway ... -- Markus Kuhn
*/
- prep_cmos_clock_write(save_control, RTC_CONTROL);
- prep_cmos_clock_write(save_freq_select, RTC_FREQ_SELECT);
+ CMOS_WRITE(save_control, RTC_CONTROL);
+ CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
- if ( (time_state == TIME_ERROR) || (time_state == TIME_BAD) )
- time_state = TIME_OK;
return 0;
}
__prep
-unsigned long prep_get_rtc_time(void)
+unsigned long mc146818_get_rtc_time(void)
{
unsigned int year, mon, day, hour, min, sec;
int i;
@@ -151,29 +107,123 @@ unsigned long prep_get_rtc_time(void)
*/
/* read RTC exactly on falling edge of update flag */
for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (prep_cmos_clock_read(RTC_FREQ_SELECT) & RTC_UIP)
+ if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
break;
for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
- if (!(prep_cmos_clock_read(RTC_FREQ_SELECT) & RTC_UIP))
+ if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
break;
do { /* Isn't this overkill ? UIP above should guarantee consistency */
- sec = prep_cmos_clock_read(RTC_SECONDS);
- min = prep_cmos_clock_read(RTC_MINUTES);
- hour = prep_cmos_clock_read(RTC_HOURS);
- day = prep_cmos_clock_read(RTC_DAY_OF_MONTH);
- mon = prep_cmos_clock_read(RTC_MONTH);
- year = prep_cmos_clock_read(RTC_YEAR);
- } while (sec != prep_cmos_clock_read(RTC_SECONDS));
- if (!(prep_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
- {
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
- }
+ sec = CMOS_READ(RTC_SECONDS);
+ min = CMOS_READ(RTC_MINUTES);
+ hour = CMOS_READ(RTC_HOURS);
+ day = CMOS_READ(RTC_DAY_OF_MONTH);
+ mon = CMOS_READ(RTC_MONTH);
+ year = CMOS_READ(RTC_YEAR);
+ } while (sec != CMOS_READ(RTC_SECONDS));
+ if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
+ || RTC_ALWAYS_BCD)
+ {
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+ }
if ((year += 1900) < 1970)
year += 100;
return mktime(year, mon, day, hour, min, sec);
}
+
+__prep
+int mk48t59_set_rtc_time(unsigned long nowtime)
+{
+ unsigned char save_control;
+ struct rtc_time tm;
+
+
+ to_tm(nowtime, &tm);
+
+ /* tell the clock it's being written */
+ save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
+
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
+ (save_control | MK48T59_RTC_CA_WRITE));
+
+ tm.tm_year = (tm.tm_year - 1900) % 100;
+ BIN_TO_BCD(tm.tm_sec);
+ BIN_TO_BCD(tm.tm_min);
+ BIN_TO_BCD(tm.tm_hour);
+ BIN_TO_BCD(tm.tm_mon);
+ BIN_TO_BCD(tm.tm_mday);
+ BIN_TO_BCD(tm.tm_year);
+
+ ppc_md.nvram_write_val(MK48T59_RTC_SECONDS, tm.tm_sec);
+ ppc_md.nvram_write_val(MK48T59_RTC_MINUTES, tm.tm_min);
+ ppc_md.nvram_write_val(MK48T59_RTC_HOURS, tm.tm_hour);
+ ppc_md.nvram_write_val(MK48T59_RTC_MONTH, tm.tm_mon);
+ ppc_md.nvram_write_val(MK48T59_RTC_DAY_OF_MONTH, tm.tm_mday);
+ ppc_md.nvram_write_val(MK48T59_RTC_YEAR, tm.tm_year);
+
+ /* Turn off the write bit. */
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
+
+ return 0;
+}
+
+__prep
+unsigned long mk48t59_get_rtc_time(void)
+{
+ unsigned char save_control;
+ unsigned int year, mon, day, hour, min, sec;
+ int i;
+
+ /* Make sure the time is not stopped. */
+ save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB);
+
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
+ (save_control & (~MK48T59_RTC_CB_STOP)));
+
+ /* Now make sure the read bit is off so the value will change. */
+ save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
+ save_control &= ~MK48T59_RTC_CA_READ;
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
+
+ /* Read the seconds value to see when it changes. */
+ sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
+
+ /* Wait until the seconds value changes, then read the value. */
+ for (i = 0 ; i < 1000000 ; i++) { /* may take up to 1 second... */
+ if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) {
+ break;
+ }
+ }
+
+ /* Set the register to read the value. */
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
+ (save_control | MK48T59_RTC_CA_READ));
+
+ sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
+ min = ppc_md.nvram_read_val(MK48T59_RTC_MINUTES);
+ hour = ppc_md.nvram_read_val(MK48T59_RTC_HOURS);
+ day = ppc_md.nvram_read_val(MK48T59_RTC_DAY_OF_MONTH);
+ mon = ppc_md.nvram_read_val(MK48T59_RTC_MONTH);
+ year = ppc_md.nvram_read_val(MK48T59_RTC_YEAR);
+
+ /* Let the time values change again. */
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
+
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+
+ year = year + 1900;
+ if (year < 1970) {
+ year += 100;
+ }
+
+ return mktime(year, mon, day, hour, min, sec);
+}
diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
index ebe64a429..db87c2384 100644
--- a/arch/ppc/kernel/process.c
+++ b/arch/ppc/kernel/process.c
@@ -1,5 +1,5 @@
/*
- * $Id: process.c,v 1.70 1999/01/07 16:28:59 cort Exp $
+ * $Id: process.c,v 1.83 1999/05/10 04:43:43 cort Exp $
*
* linux/arch/ppc/kernel/process.c
*
@@ -43,12 +43,18 @@
#include <asm/prom.h>
int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs);
-void switch_to(struct task_struct *, struct task_struct *);
-
extern unsigned long _get_SP(void);
-extern spinlock_t scheduler_lock;
struct task_struct *last_task_used_math = NULL;
+static struct vm_area_struct init_mmap = INIT_MMAP;
+static struct fs_struct init_fs = INIT_FS;
+static struct file * init_fd_array[NR_OPEN] = { NULL, };
+static struct files_struct init_files = INIT_FILES;
+static struct signal_struct init_signals = INIT_SIGNALS;
+struct mm_struct init_mm = INIT_MM;
+union task_union init_task_union = { INIT_TASK };
+/* only used to get secondary processor up */
+struct task_struct *current_set[NR_CPUS] = {&init_task, };
#undef SHOW_TASK_SWITCHES 1
#undef CHECK_STACK 1
@@ -65,32 +71,28 @@ task_top(struct task_struct *tsk)
return ((unsigned long)tsk) + sizeof(struct task_struct);
}
-static struct vm_area_struct init_mmap = INIT_MMAP;
-static struct fs_struct init_fs = INIT_FS;
-static struct file * init_fd_array[NR_OPEN] = { NULL, };
-static struct files_struct init_files = INIT_FILES;
-static struct signal_struct init_signals = INIT_SIGNALS;
-
-struct mm_struct init_mm = INIT_MM;
-union task_union init_task_union = { INIT_TASK };
-
-/* only used to get secondary processor up */
-struct task_struct *current_set[NR_CPUS] = {&init_task, };
-
int
dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs)
{
-#ifdef __SMP__
- if ( regs->msr & MSR_FP )
- smp_giveup_fpu(current);
-#else
- if (last_task_used_math == current)
- giveup_fpu();
-#endif
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
memcpy(fpregs, &current->tss.fpr[0], sizeof(*fpregs));
return 1;
}
+void
+enable_kernel_fp(void)
+{
+#ifdef __SMP__
+ if (current->tss.regs && (current->tss.regs->msr & MSR_FP))
+ giveup_fpu(current);
+ else
+ giveup_fpu(NULL); /* just enables FP for kernel */
+#else
+ giveup_fpu(last_task_used_math);
+#endif /* __SMP__ */
+}
+
/* check to make sure the kernel stack is healthy */
int check_stack(struct task_struct *tsk)
{
@@ -155,7 +157,8 @@ int check_stack(struct task_struct *tsk)
}
void
-switch_to(struct task_struct *prev, struct task_struct *new)
+_switch_to(struct task_struct *prev, struct task_struct *new,
+ struct task_struct **last)
{
struct thread_struct *new_tss, *old_tss;
int s = _disable_interrupts();
@@ -165,10 +168,10 @@ switch_to(struct task_struct *prev, struct task_struct *new)
#endif
#ifdef SHOW_TASK_SWITCHES
- printk("%s/%d -> %s/%d NIP %08lx cpu %d lock %x root %x/%x\n",
+ printk("%s/%d -> %s/%d NIP %08lx cpu %d root %x/%x\n",
prev->comm,prev->pid,
new->comm,new->pid,new->tss.regs->nip,new->processor,
- scheduler_lock.lock,new->fs->root,prev->fs->root);
+ new->fs->root,prev->fs->root);
#endif
#ifdef __SMP__
/* avoid complexity of lazy save/restore of fpu
@@ -176,18 +179,19 @@ switch_to(struct task_struct *prev, struct task_struct *new)
* 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.
+ * reload its fp regs. So we don't have to do a restore
+ * every switch, just a save.
* -- Cort
*/
- if ( prev->tss.regs->msr & MSR_FP )
- smp_giveup_fpu(prev);
+ if (prev->tss.regs && (prev->tss.regs->msr & MSR_FP))
+ giveup_fpu(prev);
prev->last_processor = prev->processor;
current_set[smp_processor_id()] = new;
#endif /* __SMP__ */
new_tss = &new->tss;
old_tss = &current->tss;
- _switch(old_tss, new_tss, new->mm->context);
+ *last = _switch(old_tss, new_tss, new->mm->context);
_enable_interrupts(s);
}
@@ -240,7 +244,12 @@ void instruction_dump (unsigned long *pc)
printk("Instruction DUMP:");
for(i = -3; i < 6; i++)
- printk("%c%08lx%c",i?' ':'<',pc[i],i?' ':'>');
+ {
+ unsigned long p;
+ if (__get_user( p, &pc[i] ))
+ break;
+ printk("%c%08lx%c",i?' ':'<',p,i?' ':'>');
+ }
printk("\n");
}
@@ -268,8 +277,12 @@ int
copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
struct task_struct * p, struct pt_regs * regs)
{
- struct pt_regs * childregs;
-
+ struct pt_regs * childregs, *kregs;
+#ifdef __SMP__
+ extern void ret_from_smpfork(void);
+#else
+ extern void ret_from_syscall(void);
+#endif
/* Copy registers */
childregs = ((struct pt_regs *)
((unsigned long)p + sizeof(union task_union)
@@ -278,8 +291,19 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
if ((childregs->msr & MSR_PR) == 0)
childregs->gpr[2] = (unsigned long) p; /* `current' in new task */
childregs->gpr[3] = 0; /* Result from fork() */
+ p->tss.regs = childregs;
p->tss.ksp = (unsigned long) childregs - STACK_FRAME_OVERHEAD;
- p->tss.regs = childregs;
+ p->tss.ksp -= sizeof(struct pt_regs ) + STACK_FRAME_OVERHEAD;
+ kregs = (struct pt_regs *)(p->tss.ksp + STACK_FRAME_OVERHEAD);
+#ifdef __SMP__
+ kregs->nip = (unsigned long)ret_from_smpfork;
+#else
+ kregs->nip = (unsigned long)ret_from_syscall;
+#endif
+ kregs->msr = MSR_KERNEL;
+ kregs->gpr[1] = (unsigned long)childregs - STACK_FRAME_OVERHEAD;
+ kregs->gpr[2] = (unsigned long)p;
+
if (usp >= (unsigned long) regs) {
/* Stack is in kernel space - must adjust */
childregs->gpr[1] = (unsigned long)(childregs + 1);
@@ -293,21 +317,14 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
* copy fpu info - assume lazy fpu switch now always
* -- Cort
*/
-#ifdef __SMP__
- if ( regs->msr & MSR_FP )
- smp_giveup_fpu(current);
-#else
- if ( last_task_used_math == current )
- giveup_fpu();
-#endif
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
memcpy(&p->tss.fpr, &current->tss.fpr, sizeof(p->tss.fpr));
p->tss.fpscr = current->tss.fpscr;
childregs->msr &= ~MSR_FP;
#ifdef __SMP__
- if ( (p->pid != 0) || !(clone_flags & CLONE_PID) )
- p->tss.smp_fork_ret = 1;
p->last_processor = NO_PROC_ID;
#endif /* __SMP__ */
return 0;
@@ -374,11 +391,6 @@ asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
int res;
lock_kernel();
res = do_fork(clone_flags, regs->gpr[1], regs);
- /*
- * only parent returns here, child returns to either
- * syscall_ret_1() or kernel_thread()
- * -- Cort
- */
#ifdef __SMP__
/* When we clone the idle task we keep the same pid but
* the return value of 0 for both causes problems.
@@ -397,9 +409,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 */
#ifdef __SMP__
/* When we clone the idle task we keep the same pid but
* the return value of 0 for both causes problems.
@@ -408,10 +418,15 @@ asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
if ((current->pid == 0) && (current == &init_task))
res = 1;
#endif /* __SMP__ */
- unlock_kernel();
return res;
}
+asmlinkage int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6,
+ struct pt_regs *regs)
+{
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs);
+}
+
asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
unsigned long a3, unsigned long a4, unsigned long a5,
struct pt_regs *regs)
@@ -423,13 +438,8 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
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 )
- giveup_fpu();
-#endif
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
error = do_execve(filename, (char **) a1, (char **) a2, regs);
putname(filename);
out:
diff --git a/arch/ppc/kernel/prom.c b/arch/ppc/kernel/prom.c
index da9d7a04c..b2221481a 100644
--- a/arch/ppc/kernel/prom.c
+++ b/arch/ppc/kernel/prom.c
@@ -1,5 +1,5 @@
/*
- * $Id: prom.c,v 1.46 1998/11/11 03:55:09 paulus Exp $
+ * $Id: prom.c,v 1.54 1999/05/10 04:43:46 cort Exp $
*
* Procedures for interfacing to the Open Firmware PROM on
* Power Macintosh computers.
@@ -16,6 +16,7 @@
#include <linux/string.h>
#include <linux/init.h>
#include <linux/version.h>
+#include <asm/spinlock.h>
#include <asm/prom.h>
#include <asm/page.h>
#include <asm/processor.h>
@@ -99,10 +100,12 @@ unsigned int old_rtas = 0;
static struct device_node *allnodes = 0;
static void clearscreen(void);
+static void flushscreen(void);
#ifdef CONFIG_BOOTX_TEXT
static void drawchar(char c);
+static void drawhex(unsigned long v);
static void drawstring(const char *c);
static void scrollscreen(void);
@@ -167,6 +170,11 @@ boot_infos_t *boot_infos = 0; /* init it so it's in data segment not bss */
#define ALIGN(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
+/* Is boot-info compatible ? */
+#define BOOT_INFO_IS_COMPATIBLE(bi) ((bi)->compatible_version <= BOOT_INFO_VERSION)
+#define BOOT_INFO_IS_V2_COMPATIBLE(bi) ((bi)->version >= 2)
+#define BOOT_INFO_IS_V4_COMPATIBLE(bi) ((bi)->version >= 4)
+
__init
static void
prom_exit()
@@ -256,6 +264,11 @@ __init
void
prom_init(int r3, int r4, prom_entry pp)
{
+#ifdef CONFIG_SMP
+ int cpu = 0, i;
+ phandle node;
+ char type[16], *path;
+#endif
unsigned long mem;
ihandle prom_rtas;
unsigned long offset = reloc_offset();
@@ -273,6 +286,9 @@ prom_init(int r3, int r4, prom_entry pp)
unsigned long space;
unsigned long ptr, x;
char *model;
+#ifdef CONFIG_BOOTX_TEXT
+ unsigned long flags;
+#endif
RELOC(boot_infos) = PTRUNRELOC(bi);
@@ -283,32 +299,72 @@ prom_init(int r3, int r4, prom_entry pp)
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"));
+
+ /* Test if boot-info is compatible. Done only in config CONFIG_BOOTX_TEXT since
+ there is nothing much we can do with an incompatible version, except display
+ a message and eventually hang the processor...
+
+ I'll try to keep enough of boot-info compatible in the future to always allow
+ display of this message;
+ */
+ if (!BOOT_INFO_IS_COMPATIBLE(bi))
+ prom_print(RELOC(" !!! WARNING - Incompatible version of BootX !!!\n\n\n"));
+
+ prom_print(RELOC("Welcome to Linux, kernel " UTS_RELEASE "\n"));
+ prom_print(RELOC("\nstarted at : 0x"));
+ drawhex(reloc_offset() + KERNELBASE);
+ prom_print(RELOC("\nlinked at : 0x"));
+ drawhex(KERNELBASE);
+ prom_print(RELOC("\nframe buffer at : 0x"));
+ drawhex((unsigned long)bi->dispDeviceBase);
+ prom_print(RELOC(" (phys), 0x"));
+ drawhex((unsigned long)bi->logicalDisplayBase);
+ prom_print(RELOC(" (log)"));
+ prom_print(RELOC("\nMSR : 0x"));
+ __asm__ __volatile__ ("mfmsr %0" : "=r" ((flags)) : : "memory");
+ drawhex(flags);
+ prom_print(RELOC("\n\n"));
#endif
-
- /*
- * XXX If this is an iMac, turn off the USB controller.
+ /* Out of the #if/#endif since it flushes the clearscreen too */
+ flushscreen();
+
+ /* New BootX enters kernel with MMU off, i/os are not allowed
+ here. This hack will have been done by the boostrap anyway.
*/
- 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 */
+ if (bi->version < 4) {
+ /*
+ * 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.
+ /* New BootX will have flushed all TLBs and enters kernel with
+ MMU switched OFF, so this should not be useful anymore.
*/
- for (ptr = (KERNELBASE + offset) & PAGE_MASK;
- ptr < (unsigned long)bi + space; ptr += PAGE_SIZE)
- x = *(volatile unsigned long *)ptr;
-
+ if (bi->version < 4) {
+ /*
+ * 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;
+ }
+
+#ifdef CONFIG_BOOTX_TEXT
+ prom_print(RELOC("booting...\n"));
+ flushscreen();
+#endif
return;
}
@@ -379,7 +435,7 @@ prom_init(int r3, int r4, prom_entry pp)
prom_args.nret = 2;
prom_args.args[0] = RELOC("instantiate-rtas");
prom_args.args[1] = prom_rtas;
- prom_args.args[2] = ((void *)RELOC(rtas_data)-KERNELBASE-offset);
+ prom_args.args[2] = ((void *)(RELOC(rtas_data)-KERNELBASE));
RELOC(prom)(&prom_args);
if (prom_args.args[nargs] != 0)
i = 0;
@@ -393,6 +449,81 @@ prom_init(int r3, int r4, prom_entry pp)
prom_print(RELOC(" done\n"));
}
RELOC(klimit) = (char *) (mem - offset);
+#ifdef CONFIG_SMP
+ /*
+ * With CHRP SMP we need to use the OF to start the other
+ * processors so we can't wait until smp_boot_cpus (the OF is
+ * trashed by then) so we have to put the processors into
+ * a holding pattern controlled by the kernel (not OF) before
+ * we destroy the OF.
+ *
+ * This uses a chunk of high memory, puts some holding pattern
+ * code there and sends the other processors off to there until
+ * smp_boot_cpus tells them to do something. We do that by using
+ * physical address 0x0. The holding pattern checks that address
+ * until its cpu # is there, when it is that cpu jumps to
+ * __secondary_start(). smp_boot_cpus() takes care of setting those
+ * values.
+ *
+ * We also use physical address 0x4 here to tell when a cpu
+ * is in its holding pattern code.
+ *
+ * -- Cort
+ */
+ {
+ extern void __secondary_hold(void);
+ unsigned long i;
+ char type[16];
+
+
+ /*
+ * XXX: hack to make sure we're chrp, assume that if we're
+ * chrp we have a device_type property -- Cort
+ */
+ node = call_prom(RELOC("finddevice"), 1, 1, RELOC("/"));
+ if ( (int)call_prom(RELOC("getprop"), 4, 1, node,
+ RELOC("device_type"),type, sizeof(type)) <= 0)
+ return;
+
+ /* copy the holding pattern code to someplace safe (8M) */
+ memcpy( (void *)(8<<20), RELOC(__secondary_hold), 0x10000 );
+ for (i = 8<<20; i < ((8<<20)+0x10000); i += 32)
+ {
+ asm volatile("dcbf 0,%0" : : "r" (i) : "memory");
+ asm volatile("icbi 0,%0" : : "r" (i) : "memory");
+ }
+ }
+
+ /* look for cpus */
+ for (node = 0; prom_next_node(&node);)
+ {
+ type[0] = 0;
+ call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
+ type, sizeof(type));
+ if (strcmp(type, RELOC("cpu")) != 0)
+ continue;
+ path = (char *) mem;
+ memset(path, 0, 256);
+ if ((int) call_prom(RELOC("package-to-path"), 3, 1,
+ node, path, 255) < 0)
+ continue;
+ /* XXX: hack - don't start cpu 0, this cpu -- Cort */
+ if ( cpu++ == 0 )
+ continue;
+ prom_print(RELOC("starting cpu "));
+ prom_print(path);
+ *(unsigned long *)(0x4) = 0;
+ asm volatile("dcbf 0,%0": : "r" (0x4) : "memory");
+ call_prom(RELOC("start-cpu"), 3, 0, node, 8<<20, cpu-1);
+ for ( i = 0 ; (i < 10000) &&
+ (*(ulong *)(0x4) == (ulong)0); i++ )
+ ;
+ if (*(ulong *)(0x4) == (ulong)cpu-1 )
+ prom_print(RELOC("...ok\n"));
+ else
+ prom_print(RELOC("...failed\n"));
+ }
+#endif
}
/*
@@ -631,6 +762,12 @@ finish_node(struct device_node *np, unsigned long mem_start,
mem_start = ifunc(np, mem_start);
}
+ /* the f50 sets the name to 'display' and 'compatible' to what we
+ * expect for the name -- Cort
+ */
+ if (!strcmp(np->name, "display"))
+ np->name = get_property(np, "compatible", 0);
+
if (!strcmp(np->name, "device-tree"))
ifunc = interpret_root_props;
else if (np->type == 0)
@@ -1007,7 +1144,7 @@ device_is_compatible(struct device_node *device, const char *compat)
if (cp == NULL)
return 0;
while (cplen > 0) {
- if (strcasecmp(cp, compat) == 0)
+ if (strncasecmp(cp, compat, strlen(compat)) == 0)
return 1;
l = strlen(cp) + 1;
cp += l;
@@ -1143,6 +1280,8 @@ print_properties(struct device_node *np)
}
#endif
+spinlock_t rtas_lock = SPIN_LOCK_UNLOCKED;
+
/* this can be called after setup -- Cort */
__openfirmware
int
@@ -1173,7 +1312,9 @@ call_rtas(const char *service, int nargs, int nret,
for (i = 0; i < nargs; ++i)
u.words[i+3] = va_arg(list, unsigned long);
va_end(list);
+ spin_lock(&rtas_lock);
enter_rtas((void *)__pa(&u));
+ spin_unlock(&rtas_lock);
if (nret > 1 && outputs != NULL)
for (i = 0; i < nret-1; ++i)
outputs[i] = u.words[i+nargs+4];
@@ -1191,8 +1332,11 @@ abort()
prom_exit();
}
-#define CALC_BASE(y) (bi->dispDeviceBase + bi->dispDeviceRect[0] * \
- (bi->dispDeviceDepth >> 3) + bi->dispDeviceRowBytes * (y))
+/* Calc the base address of a given point (x,y) */
+#define CALC_BASE(x,y) ((BOOT_INFO_IS_V2_COMPATIBLE(bi) ? bi->logicalDisplayBase : \
+ bi->dispDeviceBase) + (bi->dispDeviceRect[0] + (x)) * \
+ (bi->dispDeviceDepth >> 3) + bi->dispDeviceRowBytes * \
+ ((y) + bi->dispDeviceRect[1]))
__init
static void
@@ -1200,7 +1344,7 @@ 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 *base = (unsigned long *)CALC_BASE(0,0);
unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
(bi->dispDeviceDepth >> 3)) >> 2;
int i,j;
@@ -1214,6 +1358,33 @@ clearscreen(void)
}
}
+__inline__ void dcbst(const void* addr)
+{
+ __asm__ __volatile__ ("dcbst 0,%0" :: "r" (addr));
+}
+
+__init
+static void
+flushscreen(void)
+{
+ unsigned long offset = reloc_offset();
+ boot_infos_t* bi = PTRRELOC(RELOC(boot_infos));
+ unsigned long *base = (unsigned long *)CALC_BASE(0,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>0; j-=8) {
+ dcbst(ptr);
+ ptr += 8;
+ }
+ base += (bi->dispDeviceRowBytes >> 2);
+ }
+}
+
#ifdef CONFIG_BOOTX_TEXT
__init
@@ -1222,8 +1393,8 @@ 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 *src = (unsigned long *)CALC_BASE(0,16);
+ unsigned long *dst = (unsigned long *)CALC_BASE(0,0);
unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
(bi->dispDeviceDepth >> 3)) >> 2;
int i,j;
@@ -1252,20 +1423,17 @@ 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;
+ 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))
- {
+ 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))
- {
+ while (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) {
scrollscreen();
RELOC(g_loc_Y)--;
}
@@ -1281,17 +1449,32 @@ drawstring(const char *c)
__init
static void
+drawhex(unsigned long v)
+{
+ static char hex_table[] = "0123456789abcdef";
+ unsigned long offset = reloc_offset();
+
+ drawchar(RELOC(hex_table)[(v >> 28) & 0x0000000FUL]);
+ drawchar(RELOC(hex_table)[(v >> 24) & 0x0000000FUL]);
+ drawchar(RELOC(hex_table)[(v >> 20) & 0x0000000FUL]);
+ drawchar(RELOC(hex_table)[(v >> 16) & 0x0000000FUL]);
+ drawchar(RELOC(hex_table)[(v >> 12) & 0x0000000FUL]);
+ drawchar(RELOC(hex_table)[(v >> 8) & 0x0000000FUL]);
+ drawchar(RELOC(hex_table)[(v >> 4) & 0x0000000FUL]);
+ drawchar(RELOC(hex_table)[(v >> 0) & 0x0000000FUL]);
+}
+
+
+__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];
+ boot_infos_t* bi = PTRRELOC(RELOC(boot_infos));
+ unsigned char *base = CALC_BASE(locX << 3, locY << 4);
+ unsigned char *font = &RELOC(vga_font)[((unsigned long)c) * 16];
- switch(bi->dispDeviceDepth)
- {
+ switch(bi->dispDeviceDepth) {
case 32:
draw_byte_32(font, (unsigned long *)base);
break;
diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c
index e2c6b13a0..b3a25fd2b 100644
--- a/arch/ppc/kernel/ptrace.c
+++ b/arch/ppc/kernel/ptrace.c
@@ -392,14 +392,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
tmp = get_reg(child, addr);
}
else if (addr >= PT_FPR0 && addr <= PT_FPSCR) {
-#ifdef __SMP__
- if (child->tss.regs->msr & MSR_FP )
- smp_giveup_fpu(child);
-#else
- /* only current can be last task to use math on SMP */
- if (last_task_used_math == child)
- giveup_fpu();
-#endif
+ if (child->tss.regs->msr & MSR_FP)
+ giveup_fpu(child);
tmp = ((long *)child->tss.fpr)[addr - PT_FPR0];
}
else
@@ -433,13 +427,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
goto out;
}
if (addr >= PT_FPR0 && addr < PT_FPR0 + 64) {
-#ifndef __SMP__
- if (last_task_used_math == child)
- giveup_fpu();
-#else
- if (child->tss.regs->msr & MSR_FP )
- smp_giveup_fpu(child);
-#endif
+ if (child->tss.regs->msr & MSR_FP)
+ giveup_fpu(child);
((long *)child->tss.fpr)[addr - PT_FPR0] = data;
ret = 0;
goto out;
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 50cd70889..2d38f3adc 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -1,5 +1,5 @@
/*
- * $Id: setup.c,v 1.122 1998/12/31 20:51:19 cort Exp $
+ * $Id: setup.c,v 1.132 1999/03/24 00:32:19 cort Exp $
* Common prep/pmac/chrp boot and setup code.
*/
@@ -27,40 +27,74 @@
#include <asm/smp.h>
#ifdef CONFIG_MBX
#include <asm/mbx.h>
+#include <asm/8xx_immap.h>
#endif
#include <asm/bootx.h>
+#include <asm/machdep.h>
+#include <asm/ide.h>
-/* APUS defs */
-extern unsigned long m68k_machtype;
-extern int parse_bootinfo(const struct bi_record *);
-extern char _end[];
-#ifdef CONFIG_APUS
-extern struct mem_info ramdisk;
-unsigned long isa_io_base;
-unsigned long isa_mem_base;
-unsigned long pci_dram_offset;
-#endif
-/* END APUS defs */
+extern void pmac_init(unsigned long r3,
+ unsigned long r4,
+ unsigned long r5,
+ unsigned long r6,
+ unsigned long r7);
+
+extern void chrp_init(unsigned long r3,
+ unsigned long r4,
+ unsigned long r5,
+ unsigned long r6,
+ unsigned long r7);
+
+extern void prep_init(unsigned long r3,
+ unsigned long r4,
+ unsigned long r5,
+ unsigned long r6,
+ unsigned long r7);
+
+extern void mbx_init(unsigned long r3,
+ unsigned long r4,
+ unsigned long r5,
+ unsigned long r6,
+ unsigned long r7);
+
+extern void apus_init(unsigned long r3,
+ unsigned long r4,
+ unsigned long r5,
+ unsigned long r6,
+ unsigned long r7);
+extern boot_infos_t *boot_infos;
extern char cmd_line[512];
char saved_command_line[256];
unsigned char aux_device_present;
-#if !defined(CONFIG_MACH_SPECIFIC)
+struct ide_machdep_calls ppc_ide_md;
+
unsigned long ISA_DMA_THRESHOLD;
unsigned long DMA_MODE_READ, DMA_MODE_WRITE;
-int _machine;
-/* if we have openfirmware */
-unsigned long have_of;
-#endif /* ! CONFIG_MACH_SPECIFIC */
+
+/* Temporary hacks until machdep.h is fully done. */
+int _machine = 0;
+/* do we have OF? */
+int have_of = 0;
+int is_prep = 0;
+int is_chrp = 0;
+/* For MTX/MVME boards.. with Raven/Falcon Chipset
+ Real close to CHRP, but boot like PReP (via PPCbug)
+ There's probably a nicer way to do this.. --Troy */
+int is_powerplus = 0;
+
+struct machdep_calls ppc_md;
+
/* copy of the residual data */
+#ifndef CONFIG_MBX
unsigned char __res[sizeof(RESIDUAL)] __prepdata = {0,};
-RESIDUAL *res = (RESIDUAL *)&__res;
-
-int _prep_type;
+#else
+unsigned char __res[sizeof(bd_t)] = {0,};
+#endif
-extern boot_infos_t *boot_infos;
+RESIDUAL *res = (RESIDUAL *)&__res;
/*
* Perhaps we can put the pmac screen_info[] here
@@ -110,160 +144,28 @@ struct screen_info screen_info = {
};
#endif /* CONFIG_MBX */
-/* cmd is ignored for now... */
void machine_restart(char *cmd)
{
-#ifndef CONFIG_MBX
- struct adb_request req;
- unsigned long flags;
- unsigned long i = 10000;
-#if 0
- int err;
-#endif
-
- switch(_machine)
- {
- case _MACH_Pmac:
- switch (adb_hardware) {
- case ADB_VIACUDA:
- cuda_request(&req, NULL, 2, CUDA_PACKET,
- CUDA_RESET_SYSTEM);
- for (;;)
- cuda_poll();
- break;
- case ADB_VIAPMU:
- pmu_restart();
- break;
- default:
- }
- break;
-
- case _MACH_chrp:
-#if 0 /* RTAS doesn't seem to work on Longtrail.
- For now, do it the same way as the PReP. */
- /*err = call_rtas("system-reboot", 0, 1, NULL);
- printk("RTAS system-reboot returned %d\n", err);
- for (;;);*/
-
- {
- extern unsigned int rtas_entry, rtas_data, rtas_size;
- unsigned long status, value;
- printk("rtas_entry: %08x rtas_data: %08x rtas_size: %08x\n",
- rtas_entry,rtas_data,rtas_size);
- }
-#endif
- case _MACH_prep:
- _disable_interrupts();
-
- /* set exception prefix high - to the prom */
- save_flags( flags );
- restore_flags( flags|MSR_IP );
-
- /* make sure bit 0 (reset) is a 0 */
- outb( inb(0x92) & ~1L , 0x92 );
- /* signal a reset to system control port A - soft reset */
- outb( inb(0x92) | 1 , 0x92 );
-
- while ( i != 0 ) i++;
- panic("restart failed\n");
- break;
- case _MACH_apus:
- cli();
-
- APUS_WRITE(APUS_REG_LOCK,
- REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK2);
- APUS_WRITE(APUS_REG_LOCK,
- REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK3);
- APUS_WRITE(APUS_REG_LOCK,
- REGLOCK_BLACKMAGICK2|REGLOCK_BLACKMAGICK3);
- APUS_WRITE(APUS_REG_SHADOW, REGSHADOW_SELFRESET);
- APUS_WRITE(APUS_REG_RESET, REGRESET_AMIGARESET);
- for(;;);
- break;
- }
-#else /* CONFIG_MBX */
- extern void MBX_gorom(void);
- MBX_gorom();
-#endif /* CONFIG_MBX */
+ ppc_md.restart(cmd);
}
-
+
void machine_power_off(void)
{
-#ifndef CONFIG_MBX
- struct adb_request req;
-#if 0
- int err;
-#endif
-
- switch (_machine) {
- case _MACH_Pmac:
- switch (adb_hardware) {
- case ADB_VIACUDA:
- cuda_request(&req, NULL, 2, CUDA_PACKET,
- CUDA_POWERDOWN);
- for (;;)
- cuda_poll();
- break;
- case ADB_VIAPMU:
- pmu_shutdown();
- break;
- default:
- }
- break;
-
- case _MACH_chrp:
-#if 0 /* RTAS doesn't seem to work on Longtrail.
- For now, do it the same way as the PReP. */
- err = call_rtas("power-off", 2, 1, NULL, 0, 0);
- printk("RTAS system-reboot returned %d\n", err);
- for (;;);
-#endif
-
- case _MACH_prep:
- machine_restart(NULL);
- case _MACH_apus:
- for (;;);
- }
- for (;;);
-#else /* CONFIG_MBX */
- machine_restart(NULL);
-#endif /* CONFIG_MBX */
+ ppc_md.power_off();
}
-
+
void machine_halt(void)
{
- if ( _machine == _MACH_Pmac )
- {
- machine_power_off();
- }
- else /* prep, chrp or apus */
- machine_restart(NULL);
-
+ ppc_md.halt();
}
-
+
#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);
- break;
-#endif
- case _MACH_chrp:
- chrp_ide_init_hwif_ports(p,base,irq);
- break;
- case _MACH_prep:
- prep_ide_init_hwif_ports(p,base,irq);
- break;
+ if (ppc_ide_md.ide_init_hwif != NULL) {
+ ppc_ide_md.ide_init_hwif(p, base, irq);
}
-#endif
-#if defined(CONFIG_MBX)
- mbx_ide_init_hwif_ports(p,base,irq);
-#endif
}
-EXPORT_SYMBOL(ide_init_hwif_ports);
#endif
unsigned long cpu_temp(void)
@@ -297,10 +199,6 @@ unsigned long cpu_temp(void)
int get_cpuinfo(char *buffer)
{
- extern int pmac_get_cpuinfo(char *);
- extern int chrp_get_cpuinfo(char *);
- extern int prep_get_cpuinfo(char *);
- extern int apus_get_cpuinfo(char *);
unsigned long len = 0;
unsigned long bogosum = 0;
unsigned long i;
@@ -364,7 +262,6 @@ int get_cpuinfo(char *buffer)
break;
}
-#ifndef CONFIG_MBX
/*
* Assume here that all clock rates are the same in a
* smp system. -- Cort
@@ -381,33 +278,11 @@ int get_cpuinfo(char *buffer)
len += sprintf(len+buffer, "clock\t\t: %dMHz\n",
*fp / 1000000);
}
-
- /* PREP's without residual data for some reason will give
- incorrect values here */
- if ( is_prep )
- {
- len += sprintf(len+buffer, "clock\t\t: ");
- if ( res->ResidualLength )
- len += sprintf(len+buffer, "%ldMHz\n",
- (res->VitalProductData.ProcessorHz > 1024) ?
- res->VitalProductData.ProcessorHz>>20 :
- res->VitalProductData.ProcessorHz);
- else
- len += sprintf(len+buffer, "???\n");
- }
-#else /* CONFIG_MBX */
+
+ if (ppc_md.setup_residual != NULL)
{
- bd_t *bp;
- extern RESIDUAL *res;
-
- bp = (bd_t *)res;
-
- len += sprintf(len+buffer,"clock\t\t: %dMHz\n"
- "bus clock\t: %dMHz\n",
- bp->bi_intfreq /*/ 1000000*/,
- bp->bi_busfreq /*/ 1000000*/);
+ len += ppc_md.setup_residual(buffer + len);
}
-#endif /* CONFIG_MBX */
len += sprintf(len+buffer, "revision\t: %ld.%ld\n",
(GET_PVR & 0xff00) >> 8, GET_PVR & 0xff);
@@ -422,8 +297,8 @@ int get_cpuinfo(char *buffer)
if ( i )
len += sprintf(buffer+len, "\n");
len += sprintf(buffer+len,"total bogomips\t: %lu.%02lu\n",
- (bogosum+2500)/500000,
- (bogosum+2500)/5000 % 100);
+ (bogosum+2500)/500000,
+ (bogosum+2500)/5000 % 100);
#endif /* __SMP__ */
/*
@@ -432,34 +307,21 @@ int get_cpuinfo(char *buffer)
{
len += sprintf(buffer+len,"zero pages\t: total %lu (%luKb) "
"current: %lu (%luKb) hits: %lu/%lu (%lu%%)\n",
- quicklists.zerototal,
- (quicklists.zerototal*PAGE_SIZE)>>10,
- quicklists.zero_sz,
- (quicklists.zero_sz*PAGE_SIZE)>>10,
- quicklists.zeropage_hits,quicklists.zeropage_calls,
+ zero_cache_total,
+ (zero_cache_total*PAGE_SIZE)>>10,
+ zero_cache_sz,
+ (zero_cache_sz*PAGE_SIZE)>>10,
+ zero_cache_hits,zero_cache_calls,
/* : 1 below is so we don't div by zero */
- (quicklists.zeropage_hits*100) /
- ((quicklists.zeropage_calls)?quicklists.zeropage_calls:1));
+ (zero_cache_hits*100) /
+ ((zero_cache_calls)?zero_cache_calls:1));
}
-#ifndef CONFIG_MBX
- switch (_machine)
+ if (ppc_md.get_cpuinfo != NULL)
{
- case _MACH_Pmac:
- len += pmac_get_cpuinfo(buffer+len);
- break;
- case _MACH_prep:
- len += prep_get_cpuinfo(buffer+len);
- break;
- case _MACH_chrp:
- len += chrp_get_cpuinfo(buffer+len);
- break;
- case _MACH_apus:
- /* Not much point in printing m68k info when it is not
- used. */
- break;
+ len += ppc_md.get_cpuinfo(buffer+len);
}
-#endif /* ndef CONFIG_MBX */
+
return len;
}
@@ -471,25 +333,22 @@ unsigned long __init
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
/* boot loader will tell us if we're APUS */
if ( r3 == 0x61707573 )
{
_machine = _MACH_apus;
- have_of = 0;
r3 = 0;
}
/* prep boot loader tells us if we're prep or not */
else if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) ) {
_machine = _MACH_prep;
- have_of = 0;
+ is_prep = 1;
} else {
char *model;
@@ -500,19 +359,49 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
/* ask the OF info if we're a chrp or pmac */
model = get_property(find_path_device("/"), "device_type", NULL);
if ( model && !strncmp("chrp",model,4) )
+ {
_machine = _MACH_chrp;
+ is_chrp = 1;
+ }
else
{
model = get_property(find_path_device("/"),
"model", NULL);
if ( model && !strncmp(model, "IBM", 3))
+ {
_machine = _MACH_chrp;
+ is_chrp = 1;
+ }
else
+ {
_machine = _MACH_Pmac;
+ is_prep = 1;
+ }
}
}
-#endif /* CONFIG_MACH_SPECIFIC */
+#else /* CONFIG_MACH_SPECIFIC */
+
+#ifdef CONFIG_PREP
+ _machine = _MACH_prep;
+ is_prep = 1;
+#elif defined(CONFIG_CHRP)
+ _machine = _MACH_chrp;
+ is_chrp = 1;
+ have_of = 1;
+#elif defined(CONFIG_PMAC)
+ _machine = _MACH_Pmac;
+ have_of = 1;
+#elif defined(CONFIG_MBX)
+ _machine = _MACH_mbx;
+#elif defined(CONFIG_FADS)
+ _machine = _MACH_fads;
+#elif defined(CONFIG_APUS)
+ _machine = _MACH_apus;
+#else
+#error "Machine not defined correctly"
+#endif /* CONFIG_APUS */
+#endif /* CONFIG_MACH_SPECIFIC */
if ( have_of )
{
@@ -571,131 +460,31 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
cmd_line[sizeof(cmd_line) - 1] = 0;
}
-
switch (_machine)
{
case _MACH_Pmac:
- setup_pci_ptrs();
- /* isa_io_base gets set in pmac_find_bridges */
- isa_mem_base = PMAC_ISA_MEM_BASE;
- pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
-#if !defined(CONFIG_MACH_SPECIFIC)
- ISA_DMA_THRESHOLD = ~0L;
- DMA_MODE_READ = 1;
- DMA_MODE_WRITE = 2;
-#endif /* ! CONFIG_MACH_SPECIFIC */
+ pmac_init(r3, r4, r5, r6, r7);
break;
case _MACH_prep:
- /* make a copy of residual data */
- if ( r3 )
- memcpy((void *)res,(void *)(r3+KERNELBASE),
- sizeof(RESIDUAL));
- setup_pci_ptrs();
- isa_io_base = PREP_ISA_IO_BASE;
- isa_mem_base = PREP_ISA_MEM_BASE;
- pci_dram_offset = PREP_PCI_DRAM_OFFSET;
-#if !defined(CONFIG_MACH_SPECIFIC)
- ISA_DMA_THRESHOLD = 0x00ffffff;
- DMA_MODE_READ = 0x44;
- DMA_MODE_WRITE = 0x48;
-#endif /* ! CONFIG_MACH_SPECIFIC */
- /* figure out what kind of prep workstation we are */
- if ( res->ResidualLength != 0 )
- {
- if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) )
- _prep_type = _PREP_IBM;
- else
- _prep_type = _PREP_Motorola;
- }
- else /* assume motorola if no residual (netboot?) */
- _prep_type = _PREP_Motorola;
-#ifdef CONFIG_BLK_DEV_INITRD
- /* take care of initrd if we have one */
- if ( r4 )
- {
- initrd_start = r4 + KERNELBASE;
- initrd_end = r5 + KERNELBASE;
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
- /* take care of cmd line */
- if ( r6 )
- {
- *(char *)(r7+KERNELBASE) = 0;
- strcpy(cmd_line, (char *)(r6+KERNELBASE));
- }
+ prep_init(r3, r4, r5, r6, r7);
break;
case _MACH_chrp:
- setup_pci_ptrs();
-#ifdef CONFIG_BLK_DEV_INITRD
- /* take care of initrd if we have one */
- if ( r3 )
- {
- initrd_start = r3 + KERNELBASE;
- initrd_end = r3 + r4 + KERNELBASE;
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
- /* isa_io_base set by setup_pci_ptrs() */
- isa_mem_base = CHRP_ISA_MEM_BASE;
- pci_dram_offset = CHRP_PCI_DRAM_OFFSET;
-#if !defined(CONFIG_MACH_SPECIFIC)
- ISA_DMA_THRESHOLD = ~0L;
- DMA_MODE_READ = 0x44;
- DMA_MODE_WRITE = 0x48;
-#endif /* ! CONFIG_MACH_SPECIFIC */
+ chrp_init(r3, r4, r5, r6, r7);
break;
-#ifdef CONFIG_APUS
+#ifdef CONFIG_APUS
case _MACH_apus:
- /* Parse bootinfo. The bootinfo is located right after
- the kernel bss */
- parse_bootinfo((const struct bi_record *)&_end);
-#ifdef CONFIG_BLK_DEV_INITRD
- /* Take care of initrd if we have one. Use data from
- bootinfo to avoid the need to initialize PPC
- registers when kernel is booted via a PPC reset. */
- if ( ramdisk.addr ) {
- initrd_start = (unsigned long) __va(ramdisk.addr);
- initrd_end = (unsigned long)
- __va(ramdisk.size + ramdisk.addr);
- }
- /* Make sure code below is not executed. */
- r4 = 0;
- r6 = 0;
-#endif /* CONFIG_BLK_DEV_INITRD */
-#if !defined(CONFIG_MACH_SPECIFIC)
- ISA_DMA_THRESHOLD = 0x00ffffff;
-#endif /* ! CONFIG_MACH_SPECIFIC */
+ apus_init(r3, r4, r5, r6, r7);
break;
#endif
+#ifdef CONFIG_MBX
+ case _MACH_mbx:
+ mbx_init(r3, r4, r5, r6, r7);
+ break;
+#endif
default:
printk("Unknown machine type in identify_machine!\n");
}
-#else /* CONFIG_MBX */
-
- if ( r3 )
- memcpy( (void *)res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
-
-#ifdef CONFIG_PCI
- setup_pci_ptrs();
-#endif
-
-#ifdef CONFIG_BLK_DEV_INITRD
- /* take care of initrd if we have one */
- if ( r4 )
- {
- initrd_start = r4 + KERNELBASE;
- initrd_end = r5 + KERNELBASE;
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
- /* take care of cmd line */
- if ( r6 )
- {
-
- *(char *)(r7+KERNELBASE) = 0;
- strcpy(cmd_line, (char *)(r6+KERNELBASE));
- }
-#endif /* CONFIG_MBX */
-
/* Check for nobats option (used in mapin_ram). */
if (strstr(cmd_line, "nobats")) {
extern int __map_without_bats;
@@ -717,14 +506,17 @@ void ppc_setup_l2cr(char *str, int *ints)
}
}
+__initfunc(void
+ ppc_init(void))
+{
+ if (ppc_md.init != NULL) {
+ ppc_md.init();
+ }
+}
+
__initfunc(void setup_arch(char **cmdline_p,
- unsigned long * memory_start_p, unsigned long * memory_end_p))
+ unsigned long * memory_start_p, unsigned long * memory_end_p))
{
- extern void pmac_setup_arch(unsigned long *, unsigned long *);
- extern void chrp_setup_arch(unsigned long *, unsigned long *);
- extern void prep_setup_arch(unsigned long *, unsigned long *);
- extern void mbx_setup_arch(unsigned long *, unsigned long *);
- extern void apus_setup_arch(unsigned long *, unsigned long *);
extern int panic_timeout;
extern char _etext[], _edata[];
extern char *klimit;
@@ -737,7 +529,7 @@ __initfunc(void setup_arch(char **cmdline_p,
if (strstr(cmd_line, "xmon"))
xmon(0);
#endif /* CONFIG_XMON */
-
+
/* reboot on panic */
panic_timeout = 180;
@@ -753,27 +545,113 @@ __initfunc(void setup_arch(char **cmdline_p,
*memory_start_p = find_available_memory();
*memory_end_p = (unsigned long) end_of_DRAM;
-#ifdef CONFIG_MBX
- mbx_setup_arch(memory_start_p,memory_end_p);
-#else /* CONFIG_MBX */
- switch (_machine) {
- case _MACH_Pmac:
- pmac_setup_arch(memory_start_p, memory_end_p);
- break;
- case _MACH_prep:
- prep_setup_arch(memory_start_p, memory_end_p);
- break;
- case _MACH_chrp:
- chrp_setup_arch(memory_start_p, memory_end_p);
- break;
-#ifdef CONFIG_APUS
- case _MACH_apus:
- m68k_machtype = MACH_AMIGA;
- apus_setup_arch(memory_start_p,memory_end_p);
- break;
-#endif
- default:
- printk("Unknown machine %d in setup_arch()\n", _machine);
- }
-#endif /* CONFIG_MBX */
+ ppc_md.setup_arch(memory_start_p, memory_end_p);
+}
+
+void ppc_generic_ide_fix_driveid(struct hd_driveid *id)
+{
+ int i;
+ unsigned short *stringcast;
+
+
+ id->config = __le16_to_cpu(id->config);
+ id->cyls = __le16_to_cpu(id->cyls);
+ id->reserved2 = __le16_to_cpu(id->reserved2);
+ id->heads = __le16_to_cpu(id->heads);
+ id->track_bytes = __le16_to_cpu(id->track_bytes);
+ id->sector_bytes = __le16_to_cpu(id->sector_bytes);
+ id->sectors = __le16_to_cpu(id->sectors);
+ id->vendor0 = __le16_to_cpu(id->vendor0);
+ id->vendor1 = __le16_to_cpu(id->vendor1);
+ id->vendor2 = __le16_to_cpu(id->vendor2);
+ stringcast = (unsigned short *)&id->serial_no[0];
+ for (i=0; i<(20/2); i++)
+ stringcast[i] = __le16_to_cpu(stringcast[i]);
+ id->buf_type = __le16_to_cpu(id->buf_type);
+ id->buf_size = __le16_to_cpu(id->buf_size);
+ id->ecc_bytes = __le16_to_cpu(id->ecc_bytes);
+ stringcast = (unsigned short *)&id->fw_rev[0];
+ for (i=0; i<(8/2); i++)
+ stringcast[i] = __le16_to_cpu(stringcast[i]);
+ stringcast = (unsigned short *)&id->model[0];
+ for (i=0; i<(40/2); i++)
+ stringcast[i] = __le16_to_cpu(stringcast[i]);
+ id->dword_io = __le16_to_cpu(id->dword_io);
+ id->reserved50 = __le16_to_cpu(id->reserved50);
+ id->field_valid = __le16_to_cpu(id->field_valid);
+ id->cur_cyls = __le16_to_cpu(id->cur_cyls);
+ id->cur_heads = __le16_to_cpu(id->cur_heads);
+ id->cur_sectors = __le16_to_cpu(id->cur_sectors);
+ id->cur_capacity0 = __le16_to_cpu(id->cur_capacity0);
+ id->cur_capacity1 = __le16_to_cpu(id->cur_capacity1);
+ id->lba_capacity = __le32_to_cpu(id->lba_capacity);
+ id->dma_1word = __le16_to_cpu(id->dma_1word);
+ id->dma_mword = __le16_to_cpu(id->dma_mword);
+ id->eide_pio_modes = __le16_to_cpu(id->eide_pio_modes);
+ id->eide_dma_min = __le16_to_cpu(id->eide_dma_min);
+ id->eide_dma_time = __le16_to_cpu(id->eide_dma_time);
+ id->eide_pio = __le16_to_cpu(id->eide_pio);
+ id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy);
+ id->word69 = __le16_to_cpu(id->word69);
+ id->word70 = __le16_to_cpu(id->word70);
+ id->word71 = __le16_to_cpu(id->word71);
+ id->word72 = __le16_to_cpu(id->word72);
+ id->word73 = __le16_to_cpu(id->word73);
+ id->word74 = __le16_to_cpu(id->word74);
+ id->word75 = __le16_to_cpu(id->word75);
+ id->word76 = __le16_to_cpu(id->word76);
+ id->word77 = __le16_to_cpu(id->word77);
+ id->word78 = __le16_to_cpu(id->word78);
+ id->word79 = __le16_to_cpu(id->word79);
+ id->word80 = __le16_to_cpu(id->word80);
+ id->word81 = __le16_to_cpu(id->word81);
+ id->command_sets = __le16_to_cpu(id->command_sets);
+ id->word83 = __le16_to_cpu(id->word83);
+ id->word84 = __le16_to_cpu(id->word84);
+ id->word85 = __le16_to_cpu(id->word85);
+ id->word86 = __le16_to_cpu(id->word86);
+ id->word87 = __le16_to_cpu(id->word87);
+ id->dma_ultra = __le16_to_cpu(id->dma_ultra);
+ id->word89 = __le16_to_cpu(id->word89);
+ id->word90 = __le16_to_cpu(id->word90);
+ id->word91 = __le16_to_cpu(id->word91);
+ id->word92 = __le16_to_cpu(id->word92);
+ id->word93 = __le16_to_cpu(id->word93);
+ id->word94 = __le16_to_cpu(id->word94);
+ id->word95 = __le16_to_cpu(id->word95);
+ id->word96 = __le16_to_cpu(id->word96);
+ id->word97 = __le16_to_cpu(id->word97);
+ id->word98 = __le16_to_cpu(id->word98);
+ id->word99 = __le16_to_cpu(id->word99);
+ id->word100 = __le16_to_cpu(id->word100);
+ id->word101 = __le16_to_cpu(id->word101);
+ id->word102 = __le16_to_cpu(id->word102);
+ id->word103 = __le16_to_cpu(id->word103);
+ id->word104 = __le16_to_cpu(id->word104);
+ id->word105 = __le16_to_cpu(id->word105);
+ id->word106 = __le16_to_cpu(id->word106);
+ id->word107 = __le16_to_cpu(id->word107);
+ id->word108 = __le16_to_cpu(id->word108);
+ id->word109 = __le16_to_cpu(id->word109);
+ id->word110 = __le16_to_cpu(id->word110);
+ id->word111 = __le16_to_cpu(id->word111);
+ id->word112 = __le16_to_cpu(id->word112);
+ id->word113 = __le16_to_cpu(id->word113);
+ id->word114 = __le16_to_cpu(id->word114);
+ id->word115 = __le16_to_cpu(id->word115);
+ id->word116 = __le16_to_cpu(id->word116);
+ id->word117 = __le16_to_cpu(id->word117);
+ id->word118 = __le16_to_cpu(id->word118);
+ id->word119 = __le16_to_cpu(id->word119);
+ id->word120 = __le16_to_cpu(id->word120);
+ id->word121 = __le16_to_cpu(id->word121);
+ id->word122 = __le16_to_cpu(id->word122);
+ id->word123 = __le16_to_cpu(id->word123);
+ id->word124 = __le16_to_cpu(id->word124);
+ id->word125 = __le16_to_cpu(id->word125);
+ id->word126 = __le16_to_cpu(id->word126);
+ id->word127 = __le16_to_cpu(id->word127);
+ id->security = __le16_to_cpu(id->security);
+ for (i=0; i<127; i++)
+ id->reserved[i] = __le16_to_cpu(id->reserved[i]);
}
diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
index 3ffb7981e..17c0f55d1 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.21 1998/10/22 19:37:49 paulus Exp $
+ * $Id: signal.c,v 1.24 1999/04/03 11:25:16 paulus Exp $
*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
@@ -218,13 +218,8 @@ int sys_sigreturn(struct pt_regs *regs)
if (sc == (struct sigcontext_struct *)(sigctx.regs)) {
/* Last stacked signal - restore registers */
sr = (struct sigregs *) sigctx.regs;
-#ifdef __SMP__
- if ( regs->msr & MSR_FP )
- smp_giveup_fpu(current);
-#else
- if (last_task_used_math == current)
- giveup_fpu();
-#endif
+ if (regs->msr & MSR_FP )
+ giveup_fpu(current);
if (copy_from_user(saved_regs, &sr->gp_regs,
sizeof(sr->gp_regs)))
goto badframe;
@@ -271,13 +266,8 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame,
if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
goto badframe;
-#ifdef __SMP__
- if ( regs->msr & MSR_FP )
- smp_giveup_fpu(current);
-#else
- if (last_task_used_math == current)
- giveup_fpu();
-#endif
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE)
|| __copy_to_user(&frame->fp_regs, current->tss.fpr,
ELF_NFPREG * sizeof(double))
@@ -374,7 +364,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
if (!oldset)
oldset = &current->blocked;
- newsp = frame = regs->gpr[1] - sizeof(struct sigregs);
+ newsp = frame = 0;
for (;;) {
unsigned long signr;
@@ -471,6 +461,13 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
}
}
+ if ( (ka->sa.sa_flags & SA_ONSTACK)
+ && (! on_sig_stack(regs->gpr[1])))
+ newsp = (current->sas_ss_sp + current->sas_ss_size);
+ else
+ newsp = regs->gpr[1];
+ newsp = frame = newsp - sizeof(struct sigregs);
+
/* Whee! Actually deliver the signal. */
handle_signal(signr, ka, &info, oldset, regs, &newsp, frame);
}
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index ba505e133..c38fc3108 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -1,10 +1,13 @@
/*
- * $Id: smp.c,v 1.39 1998/12/28 10:28:51 paulus Exp $
+ * $Id: smp.c,v 1.49 1999/03/18 04:16:31 cort Exp $
*
* Smp support for ppc.
*
* Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great
* deal of code from the sparc and intel versions.
+ *
+ * Support for PReP (Motorola MTX/MVME) SMP by Troy Benjegerdes
+ * (troy@microux.com, hozer@drgw.net)
*/
#include <linux/kernel.h>
@@ -18,6 +21,7 @@
#define __KERNEL_SYSCALLS__
#include <linux/unistd.h>
#include <linux/init.h>
+#include <linux/openpic.h>
#include <asm/ptrace.h>
#include <asm/atomic.h>
@@ -29,9 +33,10 @@
#include <asm/softirq.h>
#include <asm/init.h>
#include <asm/io.h>
+#include <asm/prom.h>
#include "time.h"
-
+int first_cpu_booted = 0;
int smp_threads_ready = 0;
volatile int smp_commenced = 0;
int smp_num_cpus = 1;
@@ -42,7 +47,6 @@ 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;
cycles_t cacheflush_time;
/* all cpu mappings are 1-1 -- Cort */
@@ -51,6 +55,10 @@ volatile unsigned long cpu_callin_map[NR_CPUS] = {0,};
int start_secondary(void *);
extern int cpu_idle(void *unused);
+u_int openpic_read(volatile u_int *addr);
+
+/* register for interrupting the secondary processor on the powersurge */
+#define PSURGE_INTR ((volatile unsigned *)0xf80000c0)
void smp_local_timer_interrupt(struct pt_regs * regs)
{
@@ -99,29 +107,33 @@ void smp_local_timer_interrupt(struct pt_regs * regs)
/*
* Dirty hack to get smp message passing working.
- * 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 at the same time
- * we have race conditions. I avoided doing locks here since
- * all that works right now is the stop cpu message.
+ * we have race conditions. The PowerSurge doesn't easily
+ * allow us to send IPI messages so we put the messages in
+ * smp_message[].
*
+ * This is because don't have several IPI's on the PowerSurge even though
+ * we do on the chrp. It would be nice to use the actual IPI's on the chrp
+ * rather than this but having two methods of doing IPI isn't a good idea
+ * right now.
* -- Cort
*/
int smp_message[NR_CPUS];
void smp_message_recv(void)
{
int msg = smp_message[smp_processor_id()];
-
- /* clear interrupt */
- *(volatile unsigned long *)(0xf80000c0) = ~0L;
- eieio();
+
+ if ( _machine == _MACH_Pmac )
+ {
+ /* clear interrupt */
+ out_be32(PSURGE_INTR, ~0);
+ }
/* make sure msg is for us */
if ( msg == -1 ) return;
ipi_count++;
- /*printk("SMP %d: smp_message_recv() msg %x\n", smp_processor_id(),msg);*/
switch( msg )
{
@@ -158,12 +170,17 @@ void smp_send_stop(void)
spinlock_t mesg_pass_lock = SPIN_LOCK_UNLOCKED;
void smp_message_pass(int target, int msg, unsigned long data, int wait)
{
- if ( _machine != _MACH_Pmac )
+ int i;
+ if ( !(_machine & (_MACH_Pmac|_MACH_chrp)) )
return;
-printk("SMP %d: sending smp message %x\n", current->processor, msg);
-if (smp_processor_id() ) printk("pass from cpu 1\n");
+
spin_lock(&mesg_pass_lock);
-#define OTHER (~smp_processor_id() & 1)
+
+ /*
+ * We assume here that the msg is not -1. If it is,
+ * the recipient won't know the message was destined
+ * for it. -- Cort
+ */
switch( target )
{
@@ -171,105 +188,180 @@ if (smp_processor_id() ) printk("pass from cpu 1\n");
smp_message[smp_processor_id()] = msg;
/* fall through */
case MSG_ALL_BUT_SELF:
- smp_message[OTHER] = msg;
+ for ( i = 0 ; i < smp_num_cpus ; i++ )
+ if ( i != smp_processor_id () )
+ smp_message[i] = msg;
break;
default:
smp_message[target] = msg;
break;
}
- /* interrupt secondary processor */
- *(volatile unsigned long *)(0xf80000c0) = ~0L;
- eieio();
- *(volatile unsigned long *)(0xf80000c0) = 0L;
- eieio();
- /* interrupt primary */
- /**(volatile unsigned long *)(0xf3019000);*/
- spin_unlock(&mesg_pass_lock);
+
+ if ( _machine == _MACH_Pmac )
+ {
+ /* interrupt secondary processor */
+ out_be32(PSURGE_INTR, ~0);
+ out_be32(PSURGE_INTR, 0);
+ /*
+ * Assume for now that the secondary doesn't send
+ * IPI's -- Cort
+ */
+ /* interrupt primary */
+ /**(volatile unsigned long *)(0xf3019000);*/
+ }
+
+ if ( _machine == _MACH_chrp )
+ {
+ /*
+ * There has to be some way of doing this better -
+ * perhaps a sent-to-all or send-to-all-but-self
+ * in the openpic. This gets us going for now, though.
+ * -- Cort
+ */
+ switch ( target )
+ {
+ case MSG_ALL:
+ for ( i = 0 ; i < smp_num_cpus ; i++ )
+ openpic_cause_IPI(i, 0, 0xffffffff );
+ break;
+ case MSG_ALL_BUT_SELF:
+ for ( i = 0 ; i < smp_num_cpus ; i++ )
+ if ( i != smp_processor_id () )
+ openpic_cause_IPI(i, 0,
+ 0xffffffff & ~(1 << smp_processor_id()));
+ break;
+ default:
+ openpic_cause_IPI(target, 0, 1U << target);
+ break;
+ }
+ }
+
+ spin_unlock(&mesg_pass_lock);
}
void __init smp_boot_cpus(void)
{
extern struct task_struct *current_set[NR_CPUS];
- extern void __secondary_start(void);
+ extern void __secondary_start_psurge(void);
int i;
struct task_struct *p;
unsigned long a;
printk("Entering SMP Mode...\n");
-
+ /* let other processors know to not do certain initialization */
first_cpu_booted = 1;
- /*dcbf(&first_cpu_booted);*/
+
+ /*
+ * assume for now that the first cpu booted is
+ * cpu 0, the master -- Cort
+ */
+ cpu_callin_map[0] = 1;
+ cpu_callin_map[1] = 0;
+ smp_store_cpu_info(0);
+ active_kernel_processor = 0;
+ current->processor = 0;
for (i = 0; i < NR_CPUS; i++) {
prof_counter[i] = 1;
prof_multiplier[i] = 1;
}
- cpu_callin_map[0] = 1;
- smp_store_cpu_info(0);
- active_kernel_processor = 0;
- current->processor = 0;
-
/*
* XXX very rough, assumes 20 bus cycles to read a cache line,
* timebase increments every 4 bus cycles, 32kB L1 data cache.
*/
cacheflush_time = 5 * 1024;
- if ( _machine != _MACH_Pmac )
+ if ( !(_machine & (_MACH_Pmac|_MACH_chrp)) )
{
printk("SMP not supported on this machine.\n");
return;
}
- /* create a process for second processor */
- kernel_thread(start_secondary, NULL, CLONE_PID);
- p = task[1];
- if ( !p )
- panic("No idle task for secondary processor\n");
- p->processor = 1;
- p->has_cpu = 1;
- current_set[1] = p;
-
- /* need to flush here since secondary bat's aren't setup */
- /* XXX ??? */
- for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32)
- asm volatile("dcbf 0,%0" : : "r" (a) : "memory");
- asm volatile("sync");
-
- /*dcbf((void *)&current_set[1]);*/
- /* setup entry point of secondary processor */
- *(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();
+ switch ( _machine )
+ {
+ case _MACH_Pmac:
+ /* assume powersurge board - 2 processors -- Cort */
+ smp_num_cpus = 2;
+ break;
+ case _MACH_chrp:
+ smp_num_cpus = ((openpic_read(&OpenPIC->Global.Feature_Reporting0)
+ & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
+ OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT)+1;
+ /* get our processor # - we may not be cpu 0 */
+ printk("SMP %d processors, boot CPU is %d (should be 0)\n",
+ smp_num_cpus,
+ 10/*openpic_read(&OpenPIC->Processor[0]._Who_Am_I)*/);
+ break;
+ }
+
/*
- * wait to see if the secondary made a callin (is actually up).
- * udelay() isn't accurate here since we haven't yet called
- * calibrate_delay() so use this value that I found through
- * experimentation. -- Cort
+ * only check for cpus we know exist. We keep the callin map
+ * with cpus at the bottom -- Cort
*/
- for ( i = 1000; i && !cpu_callin_map[1] ; i-- )
- udelay(100);
+ for ( i = 1 ; i < smp_num_cpus; i++ )
+ {
+ int c;
+
+ /* create a process for the processor */
+ kernel_thread(start_secondary, NULL, CLONE_PID);
+ p = task[i];
+ if ( !p )
+ panic("No idle task for secondary processor\n");
+ p->processor = i;
+ p->has_cpu = 1;
+ current_set[i] = p;
+
+ /* need to flush here since secondary bats aren't setup */
+ for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32)
+ asm volatile("dcbf 0,%0" : : "r" (a) : "memory");
+ asm volatile("sync");
+
+ /* wake up cpus */
+ switch ( _machine )
+ {
+ case _MACH_Pmac:
+ /* setup entry point of secondary processor */
+ *(volatile unsigned long *)(0xf2800000) =
+ (unsigned long)__secondary_start_psurge-KERNELBASE;
+ eieio();
+ /* interrupt secondary to begin executing code */
+ out_be32(PSURGE_INTR, ~0);
+ out_be32(PSURGE_INTR, 0);
+ break;
+ case _MACH_chrp:
+ *(unsigned long *)KERNELBASE = i;
+ asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
+ break;
+ }
+
+ /*
+ * wait to see if the cpu made a callin (is actually up).
+ * use this value that I found through experimentation.
+ * -- Cort
+ */
+ for ( c = 1000; c && !cpu_callin_map[i] ; c-- )
+ udelay(100);
+
+ if ( cpu_callin_map[i] )
+ {
+ printk("Processor %d found.\n", i);
+ /* this sync's the decr's -- Cort */
+ if ( _machine == _MACH_Pmac )
+ set_dec(decrementer_count);
+ } else {
+ printk("Processor %d is stuck.\n", i);
+ }
+ }
- if(cpu_callin_map[1]) {
- printk("Processor %d found.\n", smp_num_cpus);
- smp_num_cpus++;
-#if 1 /* this sync's the decr's, but we don't want this now -- Cort */
- set_dec(decrementer_count);
-#endif
- } else {
- printk("Processor %d is stuck. \n", smp_num_cpus);
+ if ( _machine == _MACH_Pmac )
+ {
+ /* 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);
}
- /* 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);
}
void __init smp_commence(void)
@@ -308,7 +400,6 @@ void __init smp_callin(void)
while(!smp_commenced)
barrier();
__sti();
- printk("SMP %d: smp_callin done\n", current->processor);
}
void __init smp_setup(char *str, int *ints)
diff --git a/arch/ppc/kernel/softemu8xx.c b/arch/ppc/kernel/softemu8xx.c
index ae44266f7..b90760d7e 100644
--- a/arch/ppc/kernel/softemu8xx.c
+++ b/arch/ppc/kernel/softemu8xx.c
@@ -38,6 +38,7 @@
#define LFDU 51
#define STFD 54
#define STFDU 55
+#define FMR 63
/*
* We return 0 on success, 1 on unimplemented instruction, and EFAULT
@@ -49,6 +50,7 @@ Soft_emulate_8xx(struct pt_regs *regs)
uint inst, instword;
uint flreg, idxreg, disp;
uint retval;
+ signed short sdisp;
uint *ea, *ip;
retval = 0;
@@ -66,6 +68,11 @@ Soft_emulate_8xx(struct pt_regs *regs)
switch ( inst )
{
case LFD:
+ /* this is a 16 bit quantity that is sign extended
+ * so use a signed short here -- Cort
+ */
+ sdisp = (instword & 0xffff);
+ ea = (uint *)(regs->gpr[idxreg] + sdisp);
if (copy_from_user(ip, ea, sizeof(double)))
retval = EFAULT;
break;
@@ -77,6 +84,11 @@ Soft_emulate_8xx(struct pt_regs *regs)
regs->gpr[idxreg] = (uint)ea;
break;
case STFD:
+ /* this is a 16 bit quantity that is sign extended
+ * so use a signed short here -- Cort
+ */
+ sdisp = (instword & 0xffff);
+ ea = (uint *)(regs->gpr[idxreg] + sdisp);
if (copy_to_user(ea, ip, sizeof(double)))
retval = EFAULT;
break;
@@ -87,6 +99,11 @@ Soft_emulate_8xx(struct pt_regs *regs)
else
regs->gpr[idxreg] = (uint)ea;
break;
+ case FMR:
+ /* assume this is a fp move -- Cort */
+ memcpy( ip, &current->tss.fpr[(instword>>11)&0x1f],
+ sizeof(double) );
+ break;
default:
retval = 1;
printk("Bad emulation %s/%d\n"
@@ -98,7 +115,7 @@ Soft_emulate_8xx(struct pt_regs *regs)
(instword>>16)&0x1f,
(instword>>11)&0x1f,
(instword>>6)&0x1f,
- (instword>>1)&0x1f,
+ (instword>>1)&0x3ff,
instword&1);
{
int pa;
diff --git a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c
index b97456226..4d96a6f0a 100644
--- a/arch/ppc/kernel/syscalls.c
+++ b/arch/ppc/kernel/syscalls.c
@@ -205,12 +205,15 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
lock_kernel();
if (!(flags & MAP_ANONYMOUS)) {
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ file = fget(fd);
+ if (!file)
goto out;
}
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
ret = do_mmap(file, addr, len, prot, flags, offset);
+ if (file)
+ fput(file);
out:
unlock_kernel();
return ret;
diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
index 32f60a236..6f0eb798b 100644
--- a/arch/ppc/kernel/time.c
+++ b/arch/ppc/kernel/time.c
@@ -1,5 +1,5 @@
/*
- * $Id: time.c,v 1.39 1998/12/28 10:28:51 paulus Exp $
+ * $Id: time.c,v 1.47 1999/03/18 05:11:11 cort Exp $
* Common time routines among all ppc machines.
*
* Written by Cort Dougan (cort@cs.nmt.edu) to merge
@@ -18,8 +18,8 @@
* Since it is not possible to get a nice 100 Hz clock out of this, without
* creating a software PLL, I have set HZ to 128. -- Dan
*
- * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
- * "A Kernel Model for Precision Timekeeping" by Dave Mills
+ * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
+ * "A Kernel Model for Precision Timekeeping" by Dave Mills
*/
#include <linux/config.h>
@@ -41,18 +41,14 @@
#include <asm/processor.h>
#include <asm/nvram.h>
#include <asm/cache.h>
-#ifdef CONFIG_MBX
-#include <asm/mbx.h>
-#endif
+/* Fixme - Why is this here? - Corey */
#ifdef CONFIG_8xx
#include <asm/8xx_immap.h>
#endif
+#include <asm/machdep.h>
#include "time.h"
-/* this is set to the appropriate pmac/prep/chrp func in init_IRQ() */
-int (*set_rtc_time)(unsigned long);
-
void smp_local_timer_interrupt(struct pt_regs *);
/* keep track of when we need to update the rtc */
@@ -76,9 +72,6 @@ void timer_interrupt(struct pt_regs * regs)
{
int dval, d;
unsigned long cpu = smp_processor_id();
- /* save the HID0 in case dcache was off - see idle.c
- * this hack should leave for a better solution -- Cort */
- unsigned dcache_locked = unlock_dcache();
hardirq_enter(cpu);
#ifdef __SMP__
@@ -119,16 +112,21 @@ void timer_interrupt(struct pt_regs * regs)
*/
if ( xtime.tv_sec > last_rtc_update + 660 )
{
- if (set_rtc_time(xtime.tv_sec) == 0)
+ if (ppc_md.set_rtc_time(xtime.tv_sec) == 0) {
last_rtc_update = xtime.tv_sec;
- else
- last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+ }
+ else {
+ /* do it again in 60 s */
+ last_rtc_update = xtime.tv_sec - 60;
+ }
}
}
}
#ifdef __SMP__
smp_local_timer_interrupt(regs);
#endif
+
+ /* Fixme - make this more generic - Corey */
#ifdef CONFIG_APUS
{
extern void apus_heartbeat (void);
@@ -136,33 +134,8 @@ void timer_interrupt(struct pt_regs * regs)
}
#endif
hardirq_exit(cpu);
- /* restore the HID0 in case dcache was off - see idle.c
- * this hack should leave for a better solution -- Cort */
- lock_dcache(dcache_locked);
}
-#ifdef CONFIG_MBX
-/* A place holder for time base interrupts, if they are ever enabled.
-*/
-void timebase_interrupt(int irq, void * dev, struct pt_regs * regs)
-{
- printk("timebase_interrupt()\n");
-}
-
-/* The RTC on the MPC8xx is an internal register.
- * We want to protect this during power down, so we need to unlock,
- * modify, and re-lock.
- */
-static int
-mbx_set_rtc_time(unsigned long time)
-{
- ((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY;
- ((immap_t *)IMAP_ADDR)->im_sit.sit_rtc = time;
- ((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY;
- return(0);
-}
-#endif /* CONFIG_MBX */
-
/*
* This version of gettimeofday has microsecond resolution.
*/
@@ -198,9 +171,9 @@ void do_settimeofday(struct timeval *tv)
xtime.tv_sec = tv->tv_sec;
xtime.tv_usec = tv->tv_usec - frac_tick;
set_dec(frac_tick * count_period_den / count_period_num);
- time_adjust = 0; /* stop active adjtime() */
+ time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
- time_state = TIME_ERROR; /* p. 24, (a) */
+ time_state = TIME_ERROR; /* p. 24, (a) */
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
restore_flags(flags);
@@ -209,81 +182,23 @@ void do_settimeofday(struct timeval *tv)
__initfunc(void time_init(void))
{
-#ifndef CONFIG_MBX
+ if (ppc_md.time_init != NULL)
+ {
+ ppc_md.time_init();
+ }
+
if ((_get_PVR() >> 16) == 1) {
/* 601 processor: dec counts down by 128 every 128ns */
decrementer_count = DECREMENTER_COUNT_601;
count_period_num = COUNT_PERIOD_NUM_601;
count_period_den = COUNT_PERIOD_DEN_601;
+ } else if (!smp_processor_id()) {
+ ppc_md.calibrate_decr();
}
- switch (_machine) {
- case _MACH_Pmac:
- xtime.tv_sec = pmac_get_rtc_time();
- if ( (_get_PVR() >> 16) != 1 && (!smp_processor_id()) )
- pmac_calibrate_decr();
- if ( !smp_processor_id() )
- set_rtc_time = pmac_set_rtc_time;
- break;
- case _MACH_chrp:
- chrp_time_init();
- xtime.tv_sec = chrp_get_rtc_time();
- if ((_get_PVR() >> 16) != 1)
- chrp_calibrate_decr();
- set_rtc_time = chrp_set_rtc_time;
- break;
- case _MACH_prep:
- xtime.tv_sec = prep_get_rtc_time();
- prep_calibrate_decr();
- set_rtc_time = prep_set_rtc_time;
- break;
-#ifdef CONFIG_APUS
- case _MACH_apus:
- {
- xtime.tv_sec = apus_get_rtc_time();
- apus_calibrate_decr();
- set_rtc_time = apus_set_rtc_time;
- break;
- }
-#endif
- }
- xtime.tv_usec = 0;
-#else /* CONFIG_MBX */
- mbx_calibrate_decr();
- set_rtc_time = mbx_set_rtc_time;
-
- /* First, unlock all of the registers we are going to modify.
- * To protect them from corruption during power down, registers
- * that are maintained by keep alive power are "locked". To
- * modify these registers we have to write the key value to
- * the key location associated with the register.
- */
- ((immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk = KAPWR_KEY;
- ((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck = KAPWR_KEY;
-
+ xtime.tv_sec = ppc_md.get_rtc_time();
+ xtime.tv_usec = 0;
- /* Disable the RTC one second and alarm interrupts.
- */
- ((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc &=
- ~(RTCSC_SIE | RTCSC_ALE);
-
- /* Enabling the decrementer also enables the timebase interrupts
- * (or from the other point of view, to get decrementer interrupts
- * we have to enable the timebase). The decrementer interrupt
- * is wired into the vector table, nothing to do here for that.
- */
- ((immap_t *)IMAP_ADDR)->im_sit.sit_tbscr =
- ((mk_int_int_mask(DEC_INTERRUPT) << 8) |
- (TBSCR_TBF | TBSCR_TBE));
- if (request_irq(DEC_INTERRUPT, timebase_interrupt, 0, "tbint", NULL) != 0)
- panic("Could not allocate timer IRQ!");
-
- /* Get time from the RTC.
- */
- xtime.tv_sec = ((immap_t *)IMAP_ADDR)->im_sit.sit_rtc;
- xtime.tv_usec = 0;
-
-#endif /* CONFIG_MBX */
set_dec(decrementer_count);
/* mark the rtc/on-chip timer as in sync
* so we don't update right away
@@ -291,109 +206,6 @@ __initfunc(void time_init(void))
last_rtc_update = xtime.tv_sec;
}
-#ifndef CONFIG_MBX
-/*
- * Uses the on-board timer to calibrate the on-chip decrementer register
- * for prep systems. On the pmac the OF tells us what the frequency is
- * but on prep we have to figure it out.
- * -- Cort
- */
-int calibrate_done = 0;
-volatile int *done_ptr = &calibrate_done;
-__initfunc(void prep_calibrate_decr(void))
-{
- unsigned long flags;
-
- /* the Powerstack II's have trouble with the timer so
- * we use a default value -- Cort
- */
- if ( (_prep_type == _PREP_Motorola) &&
- ((inb(0x800) & 0xF0) & 0x40) )
- {
- unsigned long freq, divisor;
- static unsigned long t2 = 0;
-
- t2 = 998700000/60;
- freq = t2 * 60; /* try to make freq/1e6 an integer */
- divisor = 60;
- printk("time_init: decrementer frequency = %lu/%lu (%luMHz)\n",
- freq, divisor,t2>>20);
- decrementer_count = freq / HZ / divisor;
- count_period_num = divisor;
- count_period_den = freq / 1000000;
- return;
- }
-
-
- save_flags(flags);
-
-#define TIMER0_COUNT 0x40
-#define TIMER_CONTROL 0x43
- /* set timer to periodic mode */
- outb_p(0x34,TIMER_CONTROL);/* binary, mode 2, LSB/MSB, ch 0 */
- /* set the clock to ~100 Hz */
- outb_p(LATCH & 0xff , TIMER0_COUNT); /* LSB */
- outb(LATCH >> 8 , TIMER0_COUNT); /* MSB */
-
- if (request_irq(0, prep_calibrate_decr_handler, 0, "timer", NULL) != 0)
- panic("Could not allocate timer IRQ!");
- __sti();
- while ( ! *done_ptr ) /* nothing */; /* wait for calibrate */
- restore_flags(flags);
- free_irq( 0, NULL);
-}
-
-__initfunc(void prep_calibrate_decr_handler(int irq, void *dev, struct pt_regs * regs))
-{
- unsigned long freq, divisor;
- static unsigned long t1 = 0, t2 = 0;
-
- if ( !t1 )
- t1 = get_dec();
- else if (!t2)
- {
- t2 = get_dec();
- t2 = t1-t2; /* decr's in 1/HZ */
- t2 = t2*HZ; /* # decrs in 1s - thus in Hz */
- freq = t2 * 60; /* try to make freq/1e6 an integer */
- divisor = 60;
- printk("time_init: decrementer frequency = %lu/%lu (%luMHz)\n",
- freq, divisor,t2>>20);
- decrementer_count = freq / HZ / divisor;
- count_period_num = divisor;
- count_period_den = freq / 1000000;
- *done_ptr = 1;
- }
-}
-
-#else /* CONFIG_MBX */
-
-/* The decrementer counts at the system (internal) clock frequency divided by
- * sixteen, or external oscillator divided by four. Currently, we only
- * support the MBX, which is system clock divided by sixteen.
- */
-__initfunc(void mbx_calibrate_decr(void))
-{
- bd_t *binfo = (bd_t *)res;
- int freq, fp, divisor;
-
- if ((((immap_t *)IMAP_ADDR)->im_clkrst.car_sccr & 0x02000000) == 0)
- printk("WARNING: Wrong decrementer source clock.\n");
-
- /* The manual says the frequency is in Hz, but it is really
- * as MHz. The value 'fp' is the number of decrementer ticks
- * per second.
- */
- fp = (binfo->bi_intfreq * 1000000) / 16;
- freq = fp*60; /* try to make freq/1e6 an integer */
- divisor = 60;
- printk("time_init: decrementer frequency = %d/%d\n", freq, divisor);
- decrementer_count = freq / HZ / divisor;
- count_period_num = divisor;
- count_period_den = freq / 1000000;
-}
-#endif /* CONFIG_MBX */
-
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
* Assumes input in normal date format, i.e. 1980-12-31 23:59:59
* => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
@@ -439,6 +251,49 @@ static int month_days[12] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
+/*
+ * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
+ */
+void GregorianDay(struct rtc_time * tm)
+{
+ int leapsToDate;
+ int lastYear;
+ int day;
+ int MonthOffset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+
+ lastYear=tm->tm_year-1;
+
+ /*
+ * Number of leap corrections to apply up to end of last year
+ */
+ leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;
+
+ /*
+ * This year is a leap year if it is divisible by 4 except when it is
+ * divisible by 100 unless it is divisible by 400
+ *
+ * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be
+ */
+ if((tm->tm_year%4==0) &&
+ ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) &&
+ (tm->tm_mon>2))
+ {
+ /*
+ * We are past Feb. 29 in a leap year
+ */
+ day=1;
+ }
+ else
+ {
+ day=0;
+ }
+
+ day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] +
+ tm->tm_mday;
+
+ tm->tm_wday=day%7;
+}
+
void to_tm(int tim, struct rtc_time * tm)
{
register int i;
@@ -467,6 +322,11 @@ void to_tm(int tim, struct rtc_time * tm)
/* Days are what is left over (+1) from all that. */
tm->tm_mday = day + 1;
+
+ /*
+ * Determine the day of week
+ */
+ GregorianDay(tm);
}
diff --git a/arch/ppc/kernel/time.h b/arch/ppc/kernel/time.h
index 64a07250c..a1c912308 100644
--- a/arch/ppc/kernel/time.h
+++ b/arch/ppc/kernel/time.h
@@ -1,5 +1,5 @@
/*
- * $Id: time.h,v 1.10 1998/04/01 07:46:03 geert Exp $
+ * $Id: time.h,v 1.11 1999/03/18 04:16:34 cort Exp $
* Common time prototypes and such for all ppc machines.
*
* Written by Cort Dougan (cort@cs.nmt.edu) to merge
@@ -9,32 +9,15 @@
#include <linux/mc146818rtc.h>
/* time.c */
-void prep_calibrate_decr_handler(int, void *,struct pt_regs *);
-void prep_calibrate_decr(void);
-void pmac_calibrate_decr(void);
-extern void apus_calibrate_decr(void);
extern unsigned decrementer_count;
extern unsigned count_period_num;
extern unsigned count_period_den;
-extern unsigned long mktime(unsigned int, unsigned int,unsigned int,
+extern unsigned long mktime(unsigned int, unsigned int, unsigned int,
unsigned int, unsigned int, unsigned int);
extern void to_tm(int tim, struct rtc_time * tm);
extern unsigned long last_rtc_update;
-/* pmac/prep/chrp_time.c */
-unsigned long prep_get_rtc_time(void);
-unsigned long pmac_get_rtc_time(void);
-unsigned long chrp_get_rtc_time(void);
-unsigned long apus_get_rtc_time(void);
-int prep_set_rtc_time(unsigned long nowtime);
-int pmac_set_rtc_time(unsigned long nowtime);
-int chrp_set_rtc_time(unsigned long nowtime);
-int apus_set_rtc_time(unsigned long nowtime);
-void pmac_read_rtc_time(void);
-void chrp_calibrate_decr(void);
-void chrp_time_init(void);
int via_calibrate_decr(void);
-void mbx_calibrate_decr(void);
/* Accessor functions for the decrementer register. */
static __inline__ unsigned int get_dec(void)
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index fa5184af2..87cc2bd68 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -191,13 +191,8 @@ AlignmentException(struct pt_regs *regs)
{
int fixed;
-#ifdef __SMP__
- if (regs->msr & MSR_FP )
- smp_giveup_fpu(current);
-#else
- if (last_task_used_math == current)
- giveup_fpu();
-#endif
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
fixed = fix_alignment(regs);
if (fixed == 1) {
regs->nip += 4; /* skip over emulated instruction */
diff --git a/arch/ppc/lib/locks.c b/arch/ppc/lib/locks.c
index 2d2a2d8c0..699c13fad 100644
--- a/arch/ppc/lib/locks.c
+++ b/arch/ppc/lib/locks.c
@@ -1,5 +1,5 @@
/*
- * $Id: locks.c,v 1.21 1998/12/28 10:28:53 paulus Exp $
+ * $Id: locks.c,v 1.23 1999/02/12 07:06:32 cort Exp $
*
* Locks for smp ppc
*
@@ -26,24 +26,18 @@ void _spin_lock(spinlock_t *lock)
#ifdef DEBUG_LOCKS
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)) {
- /* try cheap load until it's free */
- while(lock->lock) {
+ while (__spin_trylock(&lock->lock)) {
#ifdef DEBUG_LOCKS
- if(!--stuck)
- {
- printk("_spin_lock(%p) CPU#%d NIP %p"
- " holder: cpu %ld pc %08lX\n",
- lock, cpu, __builtin_return_address(0),
- lock->owner_cpu,lock->owner_pc);
- stuck = INIT_STUCK;
- /* steal the lock */
- /*xchg_u32((void *)&lock->lock,0);*/
- }
-#endif /* DEBUG_LOCKS */
- barrier();
+ if(!--stuck) {
+ printk("_spin_lock(%p) CPU#%d NIP %p"
+ " holder: cpu %ld pc %08lX\n",
+ lock, cpu, __builtin_return_address(0),
+ lock->owner_cpu,lock->owner_pc);
+ stuck = INIT_STUCK;
+ /* steal the lock */
+ /*xchg_u32((void *)&lock->lock,0);*/
}
+#endif /* DEBUG_LOCKS */
}
lock->owner_pc = (unsigned long)__builtin_return_address(0);
lock->owner_cpu = cpu;
@@ -51,15 +45,11 @@ void _spin_lock(spinlock_t *lock)
int spin_trylock(spinlock_t *lock)
{
- unsigned long result;
-
- result = (unsigned long )xchg_u32((void *)&lock->lock,0xffffffff);
- if ( !result )
- {
- lock->owner_cpu = smp_processor_id();
- lock->owner_pc = (unsigned long)__builtin_return_address(0);
- }
- return (result == 0);
+ if (__spin_trylock(&lock->lock))
+ return 0;
+ lock->owner_cpu = smp_processor_id();
+ lock->owner_pc = (unsigned long)__builtin_return_address(0);
+ return 1;
}
@@ -76,11 +66,11 @@ void _spin_unlock(spinlock_t *lp)
lp->owner_pc,lp->lock);
#endif /* DEBUG_LOCKS */
lp->owner_pc = lp->owner_cpu = 0;
- eieio(); /* actually I believe eieio only orders */
- lp->lock = 0; /* non-cacheable accesses (on 604 at least) */
- eieio(); /* - paulus. */
+ wmb();
+ lp->lock = 0;
+ wmb();
}
-
+
/*
* Just like x86, implement read-write locks as a 32-bit counter
* with the high bit (sign) being the "write" bit.
@@ -95,6 +85,7 @@ void _read_lock(rwlock_t *rw)
again:
/* get our read lock in there */
+ wmb();
atomic_inc((atomic_t *) &(rw)->lock);
if ( (signed long)((rw)->lock) < 0) /* someone has a write lock */
{
@@ -114,6 +105,7 @@ again:
/* try to get the read lock again */
goto again;
}
+ wmb();
}
void _read_unlock(rwlock_t *rw)
@@ -124,7 +116,9 @@ void _read_unlock(rwlock_t *rw)
current->comm,current->pid,current->tss.regs->nip,
rw->lock);
#endif /* DEBUG_LOCKS */
+ wmb();
atomic_dec((atomic_t *) &(rw)->lock);
+ wmb();
}
void _write_lock(rwlock_t *rw)
@@ -134,7 +128,8 @@ void _write_lock(rwlock_t *rw)
int cpu = smp_processor_id();
#endif /* DEBUG_LOCKS */
-again:
+again:
+ wmb();
if ( test_and_set_bit(31,&(rw)->lock) ) /* someone has a write lock */
{
while ( (rw)->lock & (1<<31) ) /* wait for write lock */
@@ -170,6 +165,7 @@ again:
}
goto again;
}
+ wmb();
}
void _write_unlock(rwlock_t *rw)
@@ -180,7 +176,9 @@ void _write_unlock(rwlock_t *rw)
current->comm,current->pid,current->tss.regs->nip,
rw->lock);
#endif /* DEBUG_LOCKS */
+ wmb();
clear_bit(31,&(rw)->lock);
+ wmb();
}
void __lock_kernel(struct task_struct *task)
@@ -196,24 +194,18 @@ void __lock_kernel(struct task_struct *task)
}
#endif /* DEBUG_LOCKS */
- if ( atomic_inc_return((atomic_t *) &task->lock_depth) != 1 )
+ if (atomic_inc_return((atomic_t *) &task->lock_depth) != 1)
return;
/* mine! */
- while ( xchg_u32( (void *)&klock_info.kernel_flag, KLOCK_HELD) )
- {
- /* try cheap load until it's free */
- while(klock_info.kernel_flag) {
+ while (__spin_trylock(&klock_info.kernel_flag)) {
#ifdef DEBUG_LOCKS
- if(!--stuck)
- {
- printk("_lock_kernel() CPU#%d NIP %p\n",
- smp_processor_id(),
- __builtin_return_address(0));
- stuck = INIT_STUCK;
- }
-#endif /* DEBUG_LOCKS */
- barrier();
+ if(!--stuck) {
+ printk("_lock_kernel() CPU#%d NIP %p\n",
+ smp_processor_id(),
+ __builtin_return_address(0));
+ stuck = INIT_STUCK;
}
+#endif /* DEBUG_LOCKS */
}
klock_info.akp = smp_processor_id();
@@ -223,7 +215,7 @@ void __lock_kernel(struct task_struct *task)
void __unlock_kernel(struct task_struct *task)
{
#ifdef DEBUG_LOCKS
- if ( (task->lock_depth == 0) || (klock_info.kernel_flag != KLOCK_HELD) )
+ if ((task->lock_depth == 0) || (klock_info.kernel_flag != KLOCK_HELD))
{
printk("__unlock_kernel(): %s/%d (nip %08lX) "
"lock depth %x flags %lx\n",
@@ -234,10 +226,13 @@ void __unlock_kernel(struct task_struct *task)
return;
}
#endif /* DEBUG_LOCKS */
- if ( atomic_dec_and_test((atomic_t *) &task->lock_depth) )
+ if (atomic_dec_and_test((atomic_t *) &task->lock_depth))
{
+ wmb();
klock_info.akp = NO_PROC_ID;
+ wmb();
klock_info.kernel_flag = KLOCK_CLEAR;
+ wmb();
}
}
@@ -249,5 +244,5 @@ void reacquire_kernel_lock(struct task_struct *task, int cpu,int depth)
__lock_kernel(task);
task->lock_depth = depth;
__sti();
- }
+ }
}
diff --git a/arch/ppc/lib/strcase.c b/arch/ppc/lib/strcase.c
index a9e40bce9..36b521091 100644
--- a/arch/ppc/lib/strcase.c
+++ b/arch/ppc/lib/strcase.c
@@ -10,3 +10,14 @@ int strcasecmp(const char *s1, const char *s2)
} while (c1 == c2 && c1 != 0);
return c1 - c2;
}
+
+int strncasecmp(const char *s1, const char *s2, int n)
+{
+ int c1, c2;
+
+ do {
+ c1 = tolower(*s1++);
+ c2 = tolower(*s2++);
+ } while ((--n > 0) && c1 == c2 && c1 != 0);
+ return c1 - c2;
+}
diff --git a/arch/ppc/lib/string.S b/arch/ppc/lib/string.S
index 2ff171ee3..be5504940 100644
--- a/arch/ppc/lib/string.S
+++ b/arch/ppc/lib/string.S
@@ -8,7 +8,6 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include "../kernel/ppc_asm.tmpl"
#include <asm/processor.h>
#include <asm/errno.h>
@@ -321,8 +320,6 @@ __copy_tofrom_user:
.long 75b,76b
.text
-#undef CLEAR_USE_DCBZ 1
-#undef CLEAR_NO_CACHE 1
.globl __clear_user
__clear_user:
addi r6,r3,-4
@@ -333,15 +330,6 @@ __clear_user:
/* clear a single word */
11: stwu r5,4(r6)
beqlr
-#if defined(CLEAR_NO_CACHE) && defined (CONFIG_6xx)
- /*
- * no reason to turn off the cache for a single word
- * or a few bytes -- Cort
- */
- mfspr r7,HID0
- ori r8,r7,HID0_DLOCK
- mtspr HID0,r8
-#endif /* CLEAR_NO_CACHE */
/* clear word sized chunks */
andi. r0,r6,3
add r4,r0,r4
@@ -353,10 +341,6 @@ __clear_user:
1: stwu r5,4(r6)
bdnz 1b
6: andi. r4,r4,3
-#if defined(CLEAR_NO_CACHE) && defined (CONFIG_6xx)
- /* restore the original state of HID0 in case cache was off -- Cort */
- mtspr HID0,r7
-#endif /* CLEAR_NO_CACHE */
/* clear byte sized chunks */
7: cmpwi 0,r4,0
beqlr
@@ -371,9 +355,6 @@ __clear_user:
.align 2
.long 11b,99b
.long 1b,99b
-#ifdef CLEAR_USE_DCBZ
- /*.long 66b,99b*/
-#endif
.long 8b,99b
.text
diff --git a/arch/ppc/mbx_defconfig b/arch/ppc/mbx_defconfig
index 54035b866..ddb420383 100644
--- a/arch/ppc/mbx_defconfig
+++ b/arch/ppc/mbx_defconfig
@@ -14,8 +14,8 @@ CONFIG_8xx=y
# CONFIG_ALL_PPC is not set
# CONFIG_APUS is not set
CONFIG_MBX=y
-CONFIG_SMP=n
CONFIG_MACH_SPECIFIC=y
+# CONFIG_SMP is not set
CONFIG_SERIAL_CONSOLE=y
#
@@ -58,8 +58,26 @@ CONFIG_KERNEL_ELF=y
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_IDE is not set
-# CONFIG_BLK_DEV_HD_ONLY is not set
+CONFIG_BLK_DEV_IDE=y
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_VIA82C586 is not set
+# CONFIG_BLK_DEV_CMD646 is not set
+CONFIG_BLK_DEV_SL82C105=y
+# CONFIG_IDE_CHIPSETS is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_MD is not set
@@ -75,7 +93,6 @@ CONFIG_PARIDE_PARPORT=y
# CONFIG_PACKET is not set
# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
@@ -91,7 +108,7 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_RARP is not set
CONFIG_IP_NOSR=y
-# CONFIG_SKB_LARGE is not set
+CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
@@ -103,7 +120,11 @@ CONFIG_IP_NOSR=y
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_FASTROUTE is not set
# CONFIG_NET_HW_FLOWCONTROL is not set
-# CONFIG_CPU_IS_SLOW is not set
+CONFIG_CPU_IS_SLOW=y
+
+#
+# QoS and/or fair queueing
+#
# CONFIG_NET_SCHED is not set
#
@@ -127,6 +148,7 @@ CONFIG_NET_ETHERNET=y
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_RTL8139 is not set
# CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
# CONFIG_NET_ISA is not set
# CONFIG_NET_EISA is not set
# CONFIG_NET_POCKET is not set
@@ -139,6 +161,8 @@ CONFIG_NET_ETHERNET=y
# CONFIG_TR is not set
# CONFIG_SHAPER is not set
# CONFIG_HOSTESS_SV11 is not set
+# CONFIG_COSA is not set
+# CONFIG_RCPCI is not set
#
# Amateur Radio support
@@ -162,7 +186,8 @@ CONFIG_NET_ETHERNET=y
#
# Character devices
#
-# CONFIG_VT is not set
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
CONFIG_SERIAL=y
CONFIG_SERIAL_CONSOLE=y
# CONFIG_SERIAL_EXTENDED is not set
@@ -171,9 +196,17 @@ CONFIG_SERIAL_CONSOLE=y
# CONFIG_MOUSE is not set
# CONFIG_QIC02_TAPE is not set
# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
+
+#
+# Video For Linux
+#
# CONFIG_VIDEO_DEV is not set
-# CONFIG_NVRAM is not set
+
+#
+# Joystick support
+#
# CONFIG_JOYSTICK is not set
#
@@ -185,35 +218,46 @@ CONFIG_SERIAL_CONSOLE=y
# Filesystems
#
# CONFIG_QUOTA is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_EXT2_FS is not set
-# CONFIG_ISO9660_FS is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
# CONFIG_FAT_FS is not set
# CONFIG_MSDOS_FS is not set
# CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
CONFIG_ROOT_NFS=y
# CONFIG_NFSD is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
-# CONFIG_CODA_FS is not set
# CONFIG_SMB_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_UFS_FS is not set
+# CONFIG_NCP_FS is not set
+
+#
+# Partition Types
+#
# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MAC_PARTITION 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 is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_NLS is not set
#
diff --git a/arch/ppc/mbxboot/Makefile b/arch/ppc/mbxboot/Makefile
new file mode 100644
index 000000000..235a79e7a
--- /dev/null
+++ b/arch/ppc/mbxboot/Makefile
@@ -0,0 +1,101 @@
+#
+# arch/ppc/boot/Makefile
+#
+# 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.
+#
+# Copyright (C) 1994 by Linus Torvalds
+# Adapted for PowerPC by Gary Thomas
+# modified by Cort (cort@cs.nmt.edu)
+#
+.c.s:
+ $(CC) $(CFLAGS) -S -o $*.s $<
+.s.o:
+ $(AS) -o $*.o $<
+.c.o:
+ $(CC) $(CFLAGS) -DINITRD_OFFSET=$(IOFF) -DINITRD_SIZE=$(ISZ) -DZIMAGE_OFFSET=$(ZOFF) -DZIMAGE_SIZE=$(ZSZ) -DKERNELBASE=$(KERNELBASE) -c -o $*.o $<
+.S.s:
+ $(CC) -D__ASSEMBLY__ -traditional -E -o $*.o $<
+.S.o:
+ $(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $<
+
+ZOFF = 0
+ZSZ = 0
+IOFF = 0
+ISZ = 0
+
+TFTPIMAGE=/tftpboot/zImage.mbx
+ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00100000
+GZIP_FLAGS = -v9
+
+OBJECTS := head.o misc.o ../coffboot/zlib.o mbxtty.o
+CFLAGS = -O2 -DSTDC_HEADERS -fno-builtin -I$(TOPDIR)/include -DCONFIG_MBX
+OBJCOPY = $(CROSS_COMPILE)objcopy
+OBJCOPY_ARGS = -O elf32-powerpc
+
+all: zImage
+
+zvmlinux.initrd: zvmlinux
+ $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
+ $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+ --add-section=initrd=ramdisk.image.gz \
+ --add-section=image=../coffboot/vmlinux.gz \
+ zvmlinux.initrd.tmp zvmlinux.initrd
+ $(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 \
+ --add-section=initrd=ramdisk.image.gz \
+ --add-section=image=../coffboot/vmlinux.gz \
+ zvmlinux.initrd.tmp $@
+ rm zvmlinux.initrd.tmp
+
+zImage: zvmlinux
+ ln -sf zvmlinux zImage
+
+zImage.initrd: zvmlinux.initrd
+ ln -sf zvmlinux.initrd zImage.initrd
+
+zvmlinux: $(OBJECTS) ../coffboot/vmlinux.gz
+#
+# build the boot loader image and then compute the offset into it
+# for the kernel image
+#
+ $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS)
+ $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \
+ zvmlinux.tmp $@
+#
+# 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 $(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 \
+ zvmlinux.tmp $@
+ rm zvmlinux.tmp
+
+znetboot : zImage
+ cp zImage $(TFTPIMAGE)
+
+znetboot.initrd : zImage.initrd
+ cp zImage.initrd $(TFTPIMAGE)
+
+clean:
+ rm -f vmlinux* zvmlinux* zImage*
+
+fastdep:
+ $(TOPDIR)/scripts/mkdep *.[Sch] > .depend
+
+dep:
+ $(CPP) -M *.S *.c > .depend
+
+# just here to match coffboot/Makefile
+vmlinux.coff:
+
+vmlinux.coff.initrd:
diff --git a/arch/ppc/mbxboot/head.S b/arch/ppc/mbxboot/head.S
new file mode 100644
index 000000000..a7b3f4ffc
--- /dev/null
+++ b/arch/ppc/mbxboot/head.S
@@ -0,0 +1,200 @@
+#include "../kernel/ppc_defs.h"
+#include "../kernel/ppc_asm.tmpl"
+#include <asm/processor.h>
+#include <asm/cache.h>
+
+ .text
+
+/*
+ * $Id: head.S,v 1.4 1999/04/22 06:32:09 davem 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.
+ *
+ * The MBX EPPC-Bug understands ELF, so it loads us into the location
+ * specified in the header. This is a two step process. First, EPPC-Bug
+ * loads the file into the intermediate buffer memory location specified
+ * by the environment parameters. When it discovers this is an ELF
+ * binary, it relocates to the link address for us. Unfortunately, the
+ * header does not move with the file, so we have to find the
+ * intermediate load location and read the header from there. From
+ * information provided by Motorola (thank you), we know this intermediate
+ * location can be found from the NVRAM environment.
+ * All of these addresses must be somewhat carefully chosen to make sure
+ * we don't overlap the regions. I chose to load the kernel at 0, the
+ * compressed image loads at 0x00100000, and the MBX intermediate buffer
+ * was set to 0x00200000. Provided the loaded kernel image never grows
+ * over one megabyte (which I am going to ensure never happens :-), these
+ * will work fine. When we get called from EPPC-Bug, registers are:
+ * R1 - Stack pointer at a high memory address.
+ * R3 - Pointer to Board Information Block.
+ * R4 - Pointer to argument string.
+ * Interrupts masked, cache and MMU disabled.
+ */
+
+ .globl start
+start:
+ bl start_
+start_:
+ mr r11,r3 /* Save pointer to residual/board data */
+/* Clear all of BSS */
+ lis r3,edata@h
+ ori r3,r3,edata@l
+ lis r4,end@h
+ ori r4,r4,end@l
+ subi r3,r3,4
+ subi r4,r4,4
+ li r0,0
+50: stwu r0,4(r3)
+ cmp 0,r3,r4
+ bne 50b
+90: mr r9,r1 /* Save old stack pointer (in case it matters) */
+ lis r1,.stack@h
+ ori r1,r1,.stack@l
+ addi r1,r1,4096*2
+ subi r1,r1,256
+ li r2,0x000F /* Mask pointer to 16-byte boundary */
+ andc r1,r1,r2
+/* Run loader */
+ mr r3, 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
+ lis r9,end@h
+ ori r9,r9,end@l
+ sub r7,r8,r9
+ srwi r7,r7,2
+#define ILAP_ADDRESS 0xfa000020
+ lis r8, ILAP_ADDRESS@h
+ lwz r8, ILAP_ADDRESS@l(r8)
+ addis r8, r8, 1 /* Add 64K */
+ mr r3,r8 /* Load point */
+ mr r4,r7 /* Program length */
+ mr r5,r6 /* Checksum */
+ mr r6,r11 /* Residual data */
+ bl decompress_kernel
+
+ /* changed to use r3 (as firmware does) for kernel
+ as ptr to residual -- Cort*/
+ lis r6,cmd_line@h
+ ori r6,r6,cmd_line@l
+ lwz r6, 0(r6)
+ subi r7,r6,1
+00: lbzu r2,1(r7)
+ cmpi 0,r2,0
+ bne 00b
+
+ /* r4,r5 have initrd_start, size */
+ lis r2,initrd_start@h
+ ori r2,r2,initrd_start@l
+ lwz r4,0(r2)
+ lis r2,initrd_end@h
+ ori r2,r2,initrd_end@l
+ lwz r5,0(r2)
+
+ /* tell kernel we're prep */
+ /*
+ * get start address of kernel code which is stored as a coff
+ * entry. see boot/head.S -- Cort
+ */
+ li r9,0x0
+ lwz r9,0(r9)
+ mtlr r9
+ blr
+hang:
+ b hang
+
+/*
+ * Delay for a number of microseconds
+ * -- Use the BUS timer (assumes 66MHz)
+ */
+ .globl udelay
+udelay:
+ mfspr r4,PVR
+ srwi r4,r4,16
+ cmpi 0,r4,1 /* 601 ? */
+ bne .udelay_not_601
+00: li r0,86 /* Instructions / microsecond? */
+ mtctr r0
+10: addi r0,r0,0 /* NOP */
+ bdnz 10b
+ subic. r3,r3,1
+ bne 00b
+ blr
+
+.udelay_not_601:
+ mulli r4,r3,1000 /* nanoseconds */
+ addi r4,r4,59
+ li r5,60
+ divw r4,r4,r5 /* BUS ticks */
+1: mftbu r5
+ mftb r6
+ mftbu r7
+ cmp 0,r5,r7
+ bne 1b /* Get [synced] base time */
+ addc r9,r6,r4 /* Compute end time */
+ addze r8,r5
+2: mftbu r5
+ cmp 0,r5,r8
+ blt 2b
+ bgt 3f
+ mftb r6
+ cmp 0,r6,r9
+ blt 2b
+3: blr
+
+.globl _get_HID0
+_get_HID0:
+ mfspr r3,HID0
+ blr
+
+.globl _put_HID0
+_put_HID0:
+ mtspr HID0,r3
+ blr
+
+.globl _get_MSR
+_get_MSR:
+ mfmsr r3
+ blr
+
+.globl _put_MSR
+_put_MSR:
+ mtmsr r3
+ blr
+
+/*
+ * Flush instruction cache
+ * *** I'm really paranoid here!
+ */
+_GLOBAL(flush_instruction_cache)
+ mflr r5
+ bl flush_data_cache
+ mtlr r5
+ blr
+
+#define NUM_CACHE_LINES 128*8
+#define CACHE_LINE_SIZE 32
+#define cache_flush_buffer 0x1000
+
+/*
+ * Flush data cache
+ * *** I'm really paranoid here!
+ */
+_GLOBAL(flush_data_cache)
+ lis r3,cache_flush_buffer@h
+ ori r3,r3,cache_flush_buffer@l
+ li r4,NUM_CACHE_LINES
+ mtctr r4
+00: lwz r4,0(r3)
+ addi r3,r3,CACHE_LINE_SIZE /* Next line, please */
+ bdnz 00b
+10: blr
+ .comm .stack,4096*2,4
diff --git a/arch/ppc/boot/mbxtty.c b/arch/ppc/mbxboot/mbxtty.c
index e5566dc32..e5566dc32 100644
--- a/arch/ppc/boot/mbxtty.c
+++ b/arch/ppc/mbxboot/mbxtty.c
diff --git a/arch/ppc/mbxboot/misc.c b/arch/ppc/mbxboot/misc.c
new file mode 100644
index 000000000..15bff41dd
--- /dev/null
+++ b/arch/ppc/mbxboot/misc.c
@@ -0,0 +1,637 @@
+/*
+ * misc.c
+ *
+ * $Id: misc.c,v 1.1 1999/02/17 05:00:06 cort Exp $
+ *
+ * Adapted for PowerPC by Gary Thomas
+ *
+ * Rewritten by Cort Dougan (cort@cs.nmt.edu)
+ * 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 <linux/elf.h>
+#include <linux/config.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#ifdef CONFIG_MBX
+#include <asm/mbx.h>
+#endif
+#ifdef CONFIG_FADS
+#include <asm/fads.h>
+#endif
+
+/*
+ * Please send me load/board info and such data for hardware not
+ * listed here so I can keep track since things are getting tricky
+ * with the different load addrs with different firmware. This will
+ * help to avoid breaking the load/boot process.
+ * -- Cort
+ */
+char *avail_ram;
+char *end_avail;
+
+/* 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.
+ */
+#if defined(CONFIG_SERIAL_CONSOLE)
+char cmd_preset[] = "console=ttyS0,9600n8";
+#else
+char cmd_preset[] = "";
+#endif
+char cmd_buf[256];
+char *cmd_line = cmd_buf;
+
+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);
+
+RESIDUAL hold_resid_buf;
+RESIDUAL *hold_residual = &hold_resid_buf;
+unsigned long initrd_start = 0, initrd_end = 0;
+char *zimage_start;
+int zimage_size;
+
+char *vidmem = (char *)0xC00B8000;
+int lines, cols;
+int orig_x, orig_y;
+
+void puts(const char *);
+void putc(const char c);
+void puthex(unsigned long val);
+void _bcopy(char *src, char *dst, int len);
+void * memcpy(void * __dest, __const void * __src,
+ int __n);
+void gunzip(void *, int, unsigned char *, int *);
+
+void pause()
+{
+ puts("pause\n");
+}
+
+void exit()
+{
+ puts("exit\n");
+ while(1);
+}
+
+/* The MBX is just the serial port.
+*/
+tstc(void)
+{
+ return (serial_tstc());
+}
+
+getc(void)
+{
+ while (1) {
+ if (serial_tstc()) return (serial_getc());
+ }
+}
+
+void
+putc(const char c)
+{
+ serial_putchar(c);
+}
+
+void puts(const char *s)
+{
+ char c;
+
+ while ( ( c = *s++ ) != '\0' ) {
+ serial_putchar(c);
+ if ( c == '\n' )
+ serial_putchar('\r');
+ }
+}
+
+
+void * memcpy(void * __dest, __const void * __src,
+ int __n)
+{
+ int i;
+ char *d = (char *)__dest, *s = (char *)__src;
+
+ for (i=0;i<__n;i++) d[i] = s[i];
+}
+
+int memcmp(__const void * __dest, __const void * __src,
+ int __n)
+{
+ int i;
+ char *d = (char *)__dest, *s = (char *)__src;
+
+ for (i=0;i<__n;i++, d++, s++)
+ {
+ if (*d != *s)
+ {
+ return (*s - *d);
+ }
+ }
+ return (0);
+}
+
+void error(char *x)
+{
+ puts("\n\n");
+ puts(x);
+ puts("\n\n -- System halted");
+
+ while(1); /* Halt */
+}
+
+void *zalloc(void *x, unsigned items, unsigned size)
+{
+ void *p = avail_ram;
+
+ size *= items;
+ size = (size + 7) & -8;
+ avail_ram += size;
+ if (avail_ram > end_avail) {
+ puts("oops... out of memory\n");
+ pause();
+ }
+ return p;
+}
+
+void zfree(void *x, void *addr, unsigned nb)
+{
+}
+
+#define HEAD_CRC 2
+#define EXTRA_FIELD 4
+#define ORIG_NAME 8
+#define COMMENT 0x10
+#define RESERVED 0xe0
+
+#define DEFLATED 8
+
+
+void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
+{
+ z_stream s;
+ int r, i, flags;
+
+ /* skip header */
+ i = 10;
+ flags = src[3];
+ if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+ puts("bad gzipped data\n");
+ exit();
+ }
+ if ((flags & EXTRA_FIELD) != 0)
+ i = 12 + src[10] + (src[11] << 8);
+ if ((flags & ORIG_NAME) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & COMMENT) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & HEAD_CRC) != 0)
+ i += 2;
+ if (i >= *lenp) {
+ puts("gunzip: ran out of data in header\n");
+ exit();
+ }
+
+ s.zalloc = zalloc;
+ s.zfree = zfree;
+ r = inflateInit2(&s, -MAX_WBITS);
+ if (r != Z_OK) {
+ puts("inflateInit2 returned %d\n");
+ exit();
+ }
+ s.next_in = src + i;
+ s.avail_in = *lenp - i;
+ s.next_out = dst;
+ s.avail_out = dstlen;
+ r = inflate(&s, Z_FINISH);
+ if (r != Z_OK && r != Z_STREAM_END) {
+ puts("inflate returned %d\n");
+ exit();
+ }
+ *lenp = s.next_out - (unsigned char *) dst;
+ inflateEnd(&s);
+}
+
+unsigned char sanity[0x2000];
+
+unsigned long
+decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, RESIDUAL *residual)
+{
+ int timer;
+ extern unsigned long start;
+ char *cp, ch;
+ unsigned long i, motorola_id = 0;
+ char needs_reloc = 0;
+ BATU *u;
+ BATL *l;
+ char *dp;
+
+ lines = 25;
+ cols = 80;
+ orig_x = 0;
+ orig_y = 24;
+
+ /* 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)
+ memcpy(hold_residual,residual,sizeof(bd_t));
+
+ /* 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
+ */
+ 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);
+
+ puts("loaded at: "); puthex(load_addr);
+ puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n");
+ if ( (unsigned long)load_addr != (unsigned long)&start )
+ {
+ puts("relocated to: "); puthex((unsigned long)&start);
+ puts(" ");
+ puthex((unsigned long)((unsigned long)&start + (4*num_words)));
+ puts("\n");
+ }
+
+ if ( residual )
+ {
+ puts("board data at: "); puthex((unsigned long)residual);
+ puts(" ");
+ puthex((unsigned long)((unsigned long)residual + sizeof(bd_t)));
+ puts("\n");
+ puts("relocated to: ");
+ puthex((unsigned long)hold_residual);
+ puts(" ");
+ puthex((unsigned long)((unsigned long)hold_residual + sizeof(bd_t)));
+ puts("\n");
+ }
+
+ /* we have to subtract 0x10000 here to correct for objdump including the
+ size of the elf header which we strip -- Cort */
+ zimage_start = (char *)(load_addr - 0x10000 + ZIMAGE_OFFSET);
+ zimage_size = ZIMAGE_SIZE;
+
+ if ( INITRD_OFFSET )
+ initrd_start = load_addr - 0x10000 + INITRD_OFFSET;
+ else
+ initrd_start = 0;
+ initrd_end = INITRD_SIZE + initrd_start;
+
+ /*
+ * setup avail_ram - this is the first part of ram usable
+ * by the uncompress code. -- Cort
+ */
+ avail_ram = (char *)PAGE_ALIGN((unsigned long)zimage_start+zimage_size);
+ if ( ((load_addr+(num_words*4)) > (unsigned long) avail_ram)
+ && (load_addr <= 0x01000000) )
+ avail_ram = (char *)(load_addr+(num_words*4));
+ if ( (((unsigned long)&start+(num_words*4)) > (unsigned long) avail_ram)
+ && (load_addr <= 0x01000000) )
+ avail_ram = (char *)((unsigned long)&start+(num_words*4));
+
+ /* relocate zimage */
+ puts("zimage at: "); puthex((unsigned long)zimage_start);
+ puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); puts("\n");
+ /*
+ * 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
+ */
+
+ /* Determine if we have a Motorola board */
+ needs_reloc = 0;
+ if ( (( (unsigned long)zimage_start <= 0x01000000 ) && initrd_start)
+ || needs_reloc)
+ {
+ memcpy ((void *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-zimage_size),
+ (void *)zimage_start, zimage_size );
+ zimage_start = (char *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-zimage_size);
+ end_avail = (char *)zimage_start;
+ puts("relocated to: "); puthex((unsigned long)zimage_start);
+ puts(" ");
+ puthex((unsigned long)zimage_size+(unsigned long)zimage_start);
+ puts("\n");
+ }
+
+ /* relocate initrd */
+ if ( initrd_start )
+ {
+ puts("initrd at: "); puthex(initrd_start);
+ puts(" "); puthex(initrd_end); puts("\n");
+ /*
+ * Memory is really tight on the MBX (we can assume 4M)
+ * so put the initrd at the TOP of ram, and set end_avail
+ * to right after that.
+ *
+ * I should do something like this for prep, too and keep
+ * a variable end_of_DRAM to keep track of what we think the
+ * max ram is.
+ * -- Cort
+ */
+ if (needs_reloc)
+ {
+ memcpy ((void *)PAGE_ALIGN(-PAGE_SIZE+
+ (unsigned long)end_avail-INITRD_SIZE),
+ (void *)initrd_start,
+ INITRD_SIZE );
+ initrd_start = PAGE_ALIGN(-PAGE_SIZE+
+ (unsigned long)end_avail-INITRD_SIZE);
+ initrd_end = initrd_start + INITRD_SIZE;
+ end_avail = (char *)initrd_start;
+ puts("relocated to: "); puthex(initrd_start);
+ puts(" "); puthex(initrd_end); puts("\n");
+ }
+ }
+
+ puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" ");
+ puthex((unsigned long)end_avail); puts("\n");
+
+ puts("\nLinux/PPC load: ");
+ timer = 0;
+ cp = cmd_line;
+ memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
+ while ( *cp ) putc(*cp++);
+ while (timer++ < 5*1000) {
+ if (tstc()) {
+ while ((ch = getc()) != '\n' && ch != '\r') {
+ if (ch == '\b') {
+ if (cp != cmd_line) {
+ cp--;
+ puts("\b \b");
+ }
+ } else if (ch == '?') {
+ if (!do_ipaddrs(&cp, 1)) {
+ *cp++ = ch;
+ putc(ch);
+ }
+ } else {
+ *cp++ = ch;
+ putc(ch);
+ }
+ }
+ break; /* Exit 'timer' loop */
+ }
+ udelay(1000); /* 1 msec */
+ }
+ *cp = 0;
+ /* 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;
+ }
+ puts("\n");
+
+ /* mappings on early boot can only handle 16M */
+ if ( (int)(cmd_line[0]) > (16<<20))
+ puts("cmd_line located > 16M\n");
+ if ( (int)hold_residual > (16<<20))
+ puts("hold_residual located > 16M\n");
+ if ( initrd_start > (16<<20))
+ puts("initrd_start located > 16M\n");
+
+ puts("Uncompressing Linux...");
+
+ gunzip(0, 0x400000, zimage_start, &zimage_size);
+ puts("done.\n");
+ puts("Now booting the kernel\n");
+ return (unsigned long)hold_residual;
+}
+
+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;
+}
+
+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';
+ puts(buf);
+}
+
+/*
+ * PCI/ISA I/O support
+ */
+
+volatile unsigned char *ISA_io = (unsigned char *)0x80000000;
+volatile unsigned char *ISA_mem = (unsigned char *)0xC0000000;
+
+void
+outb(int port, char val)
+{
+ /* Ensure I/O operations complete */
+ __asm__ volatile("eieio");
+ ISA_io[port] = val;
+}
+
+unsigned char
+inb(int port)
+{
+ /* Ensure I/O operations complete */
+ __asm__ volatile("eieio");
+ return (ISA_io[port]);
+}
+
+unsigned long
+local_to_PCI(unsigned long addr)
+{
+ return ((addr & 0x7FFFFFFF) | 0x80000000);
+}
+
+void
+_bcopy(char *src, char *dst, int len)
+{
+ while (len--) *dst++ = *src++;
+}
diff --git a/arch/ppc/mbxboot/offset b/arch/ppc/mbxboot/offset
new file mode 100644
index 000000000..52a1b5546
--- /dev/null
+++ b/arch/ppc/mbxboot/offset
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+OFFSET=`$1 -h $2 | grep $3 | grep -v zvmlinux| awk '{print $6}'`
+echo "0x"$OFFSET
diff --git a/arch/ppc/mbxboot/size b/arch/ppc/mbxboot/size
new file mode 100644
index 000000000..6c48f8d14
--- /dev/null
+++ b/arch/ppc/mbxboot/size
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+OFFSET=`$1 -h $2 | grep $3 | grep -v zvmlinux | awk '{print $3}'`
+echo "0x"$OFFSET
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
index 42e2918b1..92299e825 100644
--- a/arch/ppc/mm/fault.c
+++ b/arch/ppc/mm/fault.c
@@ -140,7 +140,8 @@ good_area:
if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
goto bad_area;
}
- handle_mm_fault(current, vma, address, error_code & 0x02000000);
+ if (!handle_mm_fault(current, vma, address, error_code & 0x02000000))
+ goto bad_area;
up(&mm->mmap_sem);
/*
* keep track of tlb+htab misses that are good addrs but
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index b80d4c21c..eac750568 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -1,5 +1,5 @@
/*
- * $Id: init.c,v 1.139 1998/12/29 19:53:49 cort Exp $
+ * $Id: init.c,v 1.164 1999/05/05 17:33:55 cort Exp $
*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
@@ -34,6 +34,7 @@
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/openpic.h>
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h> /* for initrd_* */
#endif
@@ -70,10 +71,12 @@ struct device_node *memory_node;
unsigned long ioremap_base;
unsigned long ioremap_bot;
unsigned long avail_start;
-struct pgtable_cache_struct quicklists;
extern int num_memory;
extern struct mem_info memory[NUM_MEMINFO];
extern boot_infos_t *boot_infos;
+#ifndef __SMP__
+struct pgtable_cache_struct quicklists;
+#endif
void MMU_init(void);
static void *MMU_get_page(void);
@@ -116,12 +119,19 @@ extern struct task_struct *current_set[NR_CPUS];
PTE *Hash, *Hash_end;
unsigned long Hash_size, Hash_mask;
#ifndef CONFIG_8xx
+#ifdef CONFIG_PPC64
+unsigned long long _SDR1;
+#else
unsigned long _SDR1;
+#endif
static void hash_init(void);
union ubat { /* BAT register values to be loaded */
BAT bat;
- P601_BAT bat_601;
+#ifdef CONFIG_PPC64
+ u64 word[2];
+#else
u32 word[2];
+#endif
} BATS[4][2]; /* 4 pairs of IBAT, DBAT */
struct batrange { /* stores address ranges mapped by BATs */
@@ -129,6 +139,8 @@ struct batrange { /* stores address ranges mapped by BATs */
unsigned long limit;
unsigned long phys;
} bat_addrs[4];
+unsigned long inline v_mapped_by_bats(unsigned long);
+unsigned long inline p_mapped_by_bats(unsigned long);
#endif /* CONFIG_8xx */
/*
@@ -329,15 +341,40 @@ __ioremap(unsigned long addr, unsigned long size, unsigned long flags)
* virt == phys; for addresses below this we use
* space going down from ioremap_base (ioremap_bot
* records where we're up to).
- *
- * We should also look out for a frame buffer and
- * map it with a free BAT register, if there is one.
*/
p = addr & PAGE_MASK;
size = PAGE_ALIGN(addr + size) - p;
+
+ /*
+ * Don't allow anybody to remap normal RAM that we're using.
+ * mem_init() sets high_memory so only do the check after that.
+ */
+ if ( mem_init_done && (p < virt_to_phys(high_memory)) )
+ {
+ printk("__ioremap(): phys addr %0lx is RAM lr %p\n", p,
+ __builtin_return_address(0));
+ return NULL;
+ }
+
if (size == 0)
return NULL;
+#ifndef CONFIG_8xx
+ /*
+ * Is it already mapped? Perhaps overlapped by a previous
+ * BAT mapping. If the whole area is mapped then we're done,
+ * otherwise remap it since we want to keep the virt addrs for
+ * each request contiguous.
+ *
+ * We make the assumption here that if the bottom and top
+ * of the range we want are mapped then it's mapped to the
+ * same virt address (and this is contiguous).
+ * -- Cort
+ */
+ if ( (v = p_mapped_by_bats(addr)) /*&& p_mapped_by_bats(addr+(size-1))*/ )
+ goto out;
+#endif /* CONFIG_8xx */
+
if (mem_init_done) {
struct vm_struct *area;
area = get_vm_area(size);
@@ -355,10 +392,17 @@ __ioremap(unsigned long addr, unsigned long size, unsigned long flags)
flags |= pgprot_val(PAGE_KERNEL);
if (flags & (_PAGE_NO_CACHE | _PAGE_WRITETHRU))
flags |= _PAGE_GUARDED;
+
+#ifndef CONFIG_8xx
+ /*
+ * Is it a candidate for a BAT mapping?
+ */
+#endif /* CONFIG_8xx */
+
for (i = 0; i < size; i += PAGE_SIZE)
map_page(&init_task, v+i, p+i, flags);
-
- return (void *) (v + (addr & ~PAGE_MASK));
+out:
+ return (void *) (v + (p & ~PAGE_MASK));
}
void iounmap(void *addr)
@@ -409,9 +453,7 @@ map_page(struct task_struct *tsk, unsigned long va,
{
pmd_t *pd;
pte_t *pg;
-#ifndef CONFIG_8xx
- int b;
-#endif
+
if (tsk->mm->pgd == NULL) {
/* Allocate upper level page map */
tsk->mm->pgd = (pgd_t *) MMU_get_page();
@@ -419,20 +461,8 @@ map_page(struct task_struct *tsk, unsigned long va,
/* Use upper 10 bits of VA to index the first level map */
pd = (pmd_t *) (tsk->mm->pgd + (va >> PGDIR_SHIFT));
if (pmd_none(*pd)) {
-#ifndef CONFIG_8xx
- /*
- * Need to allocate second-level table, but first
- * check whether this address is already mapped by
- * the BATs; if so, don't bother allocating the page.
- */
- for (b = 0; b < 4; ++b) {
- if (va >= bat_addrs[b].start
- && va <= bat_addrs[b].limit) {
- /* XXX should check the phys address matches */
- return;
- }
- }
-#endif /* CONFIG_8xx */
+ if ( v_mapped_by_bats(va) )
+ return;
pg = (pte_t *) MMU_get_page();
pmd_val(*pd) = (unsigned long) pg;
}
@@ -677,6 +707,33 @@ static void get_mem_prop(char *, struct mem_pieces *);
static void sort_mem_pieces(struct mem_pieces *);
static void coalesce_mem_pieces(struct mem_pieces *);
+/*
+ * Return 1 if this VA is mapped by BATs
+ */
+unsigned long inline v_mapped_by_bats(unsigned long va)
+{
+ int b;
+ for (b = 0; b < 4; ++b)
+ if (va >= bat_addrs[b].start
+ && va < bat_addrs[b].limit)
+ return 1;
+ return 0;
+}
+
+/*
+ * Return VA for a given PA or 0 if not mapped
+ */
+unsigned long inline p_mapped_by_bats(unsigned long pa)
+{
+ int b;
+ for (b = 0; b < 4; ++b)
+ if (pa >= bat_addrs[b].phys
+ && pa < (bat_addrs[b].limit-bat_addrs[b].start)
+ +bat_addrs[b].phys)
+ return bat_addrs[b].start+(pa-bat_addrs[b].phys);
+ return 0;
+}
+
__initfunc(static void sort_mem_pieces(struct mem_pieces *mp))
{
unsigned long a, s;
@@ -833,7 +890,7 @@ __initfunc(static void mapin_ram(void))
setbat(2, KERNELBASE, mem_base, bl, RAM_PAGE);
done = (unsigned long)bat_addrs[2].limit - KERNELBASE + 1;
- if (done < tot) {
+ if ((done < tot) && !bat_addrs[3].limit) {
/* use BAT3 to cover a bit more */
tot -= done;
for (bl = 128<<10; bl < max_size; bl <<= 1)
@@ -883,7 +940,8 @@ __initfunc(static void mapin_ram(void))
}
}
-__initfunc(static void *MMU_get_page(void))
+/* This can get called from ioremap, so don't make it an initfunc, OK? */
+static void *MMU_get_page(void)
{
void *p;
@@ -926,14 +984,16 @@ __initfunc(void free_initmem(void))
break;
case _MACH_prep:
FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
- FREESEC(__openfirmware_begin,__openfirmware_end,num_openfirmware_pages);
break;
case _MACH_mbx:
FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
- FREESEC(__openfirmware_begin,__openfirmware_end,num_openfirmware_pages);
FREESEC(__prep_begin,__prep_end,num_prep_pages);
break;
}
+
+ if ( !have_of )
+ FREESEC( __openfirmware_begin, __openfirmware_end,
+ num_openfirmware_pages );
printk ("Freeing unused kernel memory: %ldk init",
(num_freed_pages * PAGE_SIZE) >> 10);
@@ -955,7 +1015,6 @@ __initfunc(void free_initmem(void))
*/
__initfunc(void MMU_init(void))
{
-
#ifdef __SMP__
if ( first_cpu_booted ) return;
#endif /* __SMP__ */
@@ -985,10 +1044,13 @@ __initfunc(void MMU_init(void))
switch (_machine) {
case _MACH_prep:
setbat(0, 0x80000000, 0x80000000, 0x10000000, IO_PAGE);
- setbat(1, 0xd0000000, 0xc0000000, 0x10000000, IO_PAGE);
+ setbat(1, 0xf0000000, 0xc0000000, 0x08000000, IO_PAGE);
+ ioremap_base = 0xf0000000;
break;
case _MACH_chrp:
setbat(0, 0xf8000000, 0xf8000000, 0x08000000, IO_PAGE);
+ setbat(1, 0x80000000, 0x80000000, 0x10000000, IO_PAGE);
+ setbat(3, 0x90000000, 0x90000000, 0x10000000, IO_PAGE);
break;
case _MACH_Pmac:
{
@@ -1029,6 +1091,7 @@ __initfunc(void MMU_init(void))
ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE);
/* ide needs to be able to get at PCI space -- Cort */
ioremap(0x80000000, 0x4000);
+ ioremap(0x81000000, 0x4000);
#endif /* CONFIG_8xx */
}
@@ -1236,6 +1299,9 @@ __initfunc(unsigned long *pmac_find_end_of_memory(void))
unsigned long a, total;
unsigned long kstart, ksize;
int i;
+
+ /* max amount of RAM we allow -- Cort */
+#define RAM_LIMIT (768<<20)
memory_node = find_devices("memory");
if (memory_node == NULL) {
@@ -1260,7 +1326,18 @@ __initfunc(unsigned long *pmac_find_end_of_memory(void))
a = phys_mem.regions[0].address;
if (a != 0)
panic("RAM doesn't start at physical address 0");
+ /*
+ * XXX:
+ * Make sure ram mappings don't stomp on IO space
+ * This is a temporary hack to keep this from happening
+ * until we move the KERNELBASE and can allocate RAM up
+ * to our nearest IO area.
+ * -- Cort
+ */
+ if ( phys_mem.regions[0].size >= RAM_LIMIT )
+ phys_mem.regions[0].size = RAM_LIMIT;
total = phys_mem.regions[0].size;
+
if (phys_mem.n_regions > 1) {
printk("RAM starting at 0x%x is not contiguous\n",
phys_mem.regions[1].address);
@@ -1277,8 +1354,15 @@ __initfunc(unsigned long *pmac_find_end_of_memory(void))
}
prom_mem = phys_mem;
for (i = 0; i < phys_avail.n_regions; ++i)
+ {
+ if ( phys_avail.regions[i].address >= RAM_LIMIT )
+ continue;
+ if ( (phys_avail.regions[i].address+phys_avail.regions[i].size)
+ >= RAM_LIMIT )
+ phys_avail.regions[i].size = RAM_LIMIT - phys_avail.regions[i].address;
remove_mem_piece(&prom_mem, phys_avail.regions[i].address,
phys_avail.regions[i].size, 1);
+ }
/*
* phys_avail records memory we can use now.
@@ -1292,7 +1376,7 @@ __initfunc(unsigned long *pmac_find_end_of_memory(void))
remove_mem_piece(&prom_mem, kstart, ksize, 0);
remove_mem_piece(&phys_avail, 0, 0x4000, 0);
remove_mem_piece(&prom_mem, 0, 0x4000, 0);
-
+#undef RAM_LIMIT
return __va(total);
}
@@ -1421,10 +1505,18 @@ __initfunc(static void hash_init(void))
* up to a maximum of 2MB.
*/
ramsize = (ulong)end_of_DRAM - KERNELBASE;
+#ifdef CONFIG_PPC64
+ Hash_mask = 0;
+ for (h = 256<<10; h < ramsize / 256 && h < 4<<20; h *= 2, Hash_mask++)
+ ;
+ Hash_size = h;
+ Hash_mask << 10; /* so setting _SDR1 works the same -- Cort */
+#else
for (h = 64<<10; h < ramsize / 256 && h < 2<<20; h *= 2)
;
Hash_size = h;
Hash_mask = (h >> 6) - 1;
+#endif
#ifdef NO_RELOAD_HTAB
/* shrink the htab since we don't use it on 603's -- Cort */
@@ -1502,4 +1594,3 @@ __initfunc(static void hash_init(void))
}
}
#endif /* ndef CONFIG_8xx */
-
diff --git a/arch/ppc/pmac_defconfig b/arch/ppc/pmac_defconfig
index 811d599c0..274f6c679 100644
--- a/arch/ppc/pmac_defconfig
+++ b/arch/ppc/pmac_defconfig
@@ -102,7 +102,6 @@ CONFIG_NETLINK=y
# CONFIG_RTNETLINK is not set
# CONFIG_NETLINK_DEV is not set
# CONFIG_FIREWALL is not set
-CONFIG_NET_ALIAS=y
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
@@ -263,6 +262,7 @@ CONFIG_PPP=y
# CONFIG_SHAPER is not set
# CONFIG_HOSTESS_SV11 is not set
# CONFIG_COSA is not set
+# CONFIG_RCPCI is not set
#
# Amateur Radio support
diff --git a/arch/ppc/prep_defconfig b/arch/ppc/prep_defconfig
index 14b4ea4a0..01c314cb3 100644
--- a/arch/ppc/prep_defconfig
+++ b/arch/ppc/prep_defconfig
@@ -84,7 +84,6 @@ CONFIG_PARIDE_PARPORT=y
# CONFIG_PACKET is not set
# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y