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