@@ -1578,6+1578,16 @@ CONFIG_BAGET_MIPS more details about the Baget see the Linux/MIPS FAQ on
http://oss.sgi.com/mips .
+Support for Cobalt Microserver
+CONFIG_COBALT_MICRO_SERVER
+ This enables support for the Cobalt Microserver. For more information
+ see the Linux/MIPS FAQ on http://oss.sgi.com/mips .
+
+Support for 2800
+CONFIG_COBALT_28
+ This adds support for the Cobalt Microserver 2800. A kernel with this
+ option selected will only work on the 2800.
+
Support for DECstations
CONFIG_DECSTATION
This enables support for DEC's MIPS based workstations. For details
@@ -4308,12+4318,10 @@ CONFIG_DMASCC modem), in order to send and receive AX.25 packet radio network
traffic.
- Currently, this driver supports Ottawa PI/PI2
- (http://hydra.carleton.ca/info/pi2.html ) and Gracilis PackeTwin
- (http://www.paccomm.com/gracilis.html ) boards. They are detected
- automatically. If you have one of these cards, say Y here and read
- the AX25-HOWTO, available from
- http://www.linuxdoc.org/docs.html#howto .
+ Currently, this driver supports Ottawa PI/PI2, Paccomm/Gracilis
+ PackeTwin, and S5SCC/DMA boards. They are detected automatically.
+ If you have one of these cards, say Y here and read the AX25-HOWTO,
+ available from http://www.linuxdoc.org/docs.html#howto .
This driver can operate multiple boards simultaneously. If you
compile it as a module (by saying M instead of Y), it will be called
@@ -4329,7+4337,9 @@ CONFIG_DMASCC certain parameters, such as channel access timing, clock mode, and
DMA channel. This is accomplished with a small utility program,
dmascc_cfg, available at
- http://www.nt.tuwien.ac.at/~kkudielk/Linux/ .
+ http://www.nt.tuwien.ac.at/~kkudielk/Linux/ . Please be sure to get
+ at least version 1.27 of dmascc_cfg, as older versions will not
+ work with the current driver.
Z8530 SCC driver for AX.25
CONFIG_SCC
@@ -438,8+438,9 @@ S: Maintained
HIGH-SPEED SCC DRIVER FOR AX.25
P: Klaus Kudielka
-M: oe1kib@oe1kib.ampr.org
+M: klaus.kudielka@ieee.org
L: linux-hams@vger.rutgers.edu
+W: http://www.nt.tuwien.ac.at/~kkudielk/Linux/
S: Maintained
LOGICAL VOLUME MANAGER
@@ -85,11+85,6 @@ CPPFLAGS := -D__KERNEL__ -I$(HPATH) CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -Werror
AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS)
-# use '-fno-strict-aliasing', but only if the compiler can take it
-CFLAGS += $(shell if $(CC) -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-strict-aliasing"; fi)
-
-export CPPFLAGS CFLAGS AFLAGS
-
#
# ROOT_DEV specifies the default root-device when making the image.
# This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case
@@ -179,6+174,11 @@ DRIVERS += $(DRIVERS-y)
include arch/$(ARCH)/Makefile
+# use '-fno-strict-aliasing', but only if the compiler can take it
+CFLAGS += $(shell if $(CC) -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-strict-aliasing"; fi)
+
+export CPPFLAGS CFLAGS AFLAGS
+
export NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS
.S.s:
@@ -77,8+77,8 @@ sigpending = 8 addr_limit = 12
exec_domain = 16
need_resched = 20
-processor = 56
-tsk_ptrace = 60
+processor = 48
+tsk_ptrace = 56
ENOSYS = 38
@@ -88,12+88,38 @@ static void default_idle(void) }
/*
+ * On SMP it's slightly faster (but much more power-consuming!)
+ * to poll the ->need_resched flag instead of waiting for the
+ * cross-CPU IPI to arrive. Use this option with caution.
+ */
+static void poll_idle (void)
+{
+ int oldval;
+
+ __sti();
+
+ /*
+ * Deal with another CPU just having chosen a thread to
+ * run here:
+ */
+ oldval = xchg(¤t->need_resched, -1);
+
+ if (!oldval)
+ asm volatile(
+ "2:"
+ "cmpl $-1, %0;"
+ "rep; nop;"
+ "je 2b;"
+ : :"m" (current->need_resched));
+}
+
+/*
* The idle thread. There's no useful work to be
* done, so just try to conserve power and have a
* low exit latency (ie sit in a loop waiting for
* somebody to say that they'd like to reschedule)
*/
-void cpu_idle(void)
+void cpu_idle (void)
{
/* endless idle loop with no priority at all */
init_idle();
@@ -111,6+137,18 @@ void cpu_idle(void) }
}
+static int __init idle_setup (char *str)
+{
+ if (!strncmp(str, "poll", 4)) {
+ printk("using polling idle threads.\n");
+ pm_idle = poll_idle;
+ }
+
+ return 1;
+}
+
+__setup("idle=", idle_setup);
+
static long no_idt[2] = {0, 0};
static int reboot_mode = 0;
static int reboot_thru_bios = 0;
-# $Id: Makefile,v 1.22 2000/01/26 00:07:44 ralf Exp $
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
@@ -101,6+100,12 @@ LIBS += arch/mips/arc/arclib.a LOADADDR += 0x80080000
endif
+ifdef CONFIG_COBALT_MICRO_SERVER
+ARCHIVES += arch/mips/cobalt/cobalt.o
+SUBDIRS += arch/mips/cobalt
+LOADADDR += 0x80000000
+endif
+
ifdef CONFIG_SNI_RM200_PCI
CORE_FILES += arch/mips/sni/sni.o
SUBDIRS += arch/mips/sni arch/mips/arc
@@ -193,6+198,11 @@ archclean: $(MAKE) -C arch/mips/baget clean
archmrproper:
+ @$(MAKEBOOT) mrproper
+ $(MAKE) -C arch/$(ARCH)/tools mrproper
archdep:
+ if [ ! -f $(TOPDIR)/include/asm-$(ARCH)/offset.h ]; then \
+ touch $(TOPDIR)/include/asm-$(ARCH)/offset.h; \
+ fi;
@$(MAKEBOOT) dep
@@ -144,7+144,7 @@ static inline struct prom_pmemblock *find_largest_memblock(void) void __init prom_meminit(void)
{
struct prom_pmemblock *largest;
- unsigned long bootmap_size, kbegin, kend;
+ unsigned long bootmap_size;
struct linux_mdesc *p;
int totram;
int i = 0;
clean:
rm -f vmlinux.ecoff
+ rm -f zImage zImage.tmp mkboot
+
+mrproper:
+ rm -f vmlinux.ecoff
rm -f addinitrd
rm -f elf2ecoff
+zImage: $(CONFIGURE) mkboot $(TOPDIR)/vmlinux
+ $(OBJCOPY) $(strip-flags) $(TOPDIR)/vmlinux zImage.tmp
+ ./mkboot zImage.tmp zImage
+ rm -f zImage.tmp
+
+mkboot: mkboot.c
+ $(HOSTCC) -o $@ $^
+
+zdisk: zImage
+ cp $(TOPDIR)/vmlinux $(TOPDIR)/vm
+ $(STRIP) $(TOPDIR)/vm
+ gzip -9f $(TOPDIR)/vm
+
dummy:
include $(TOPDIR)/Rules.make
--- /dev/null
+#
+# Makefile for the Cobalt micro systems family specific parts of the kernel
+#
+# 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).
+#
+# $Id: Makefile,v 1.1 1997/10/23 22:25:41 ralf Exp $
+#
+
+.S.s:
+ $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+ $(CC) $(CFLAGS) -c $< -o $*.o
+
+all: cobalt.o
+O_TARGET := cobalt.o
+O_OBJS := cobaltscc.o hw-access.o int-handler.o pci.o reset.o setup.o via.o
+
+int-handler.o: int-handler.S
+
+clean:
+
+include $(TOPDIR)/Rules.make
--- /dev/null
+/*
+ * Filename: cobaltscc.c
+ *
+ * Description: Functions for supporting and testing serial I/O
+ *
+ * Author(s): Timothy Stonis
+ *
+ * Copyright 1997, Cobalt Microserver, Inc.
+ */
+#include "z8530.h"
+#include "diagdefs.h"
+#include "serial.h"
+#include "asm/io.h"
+
+/*
+ * Function prototypes
+ */
+void InitSerialPort(unsigned char *);
+void RegisterDelay(void);
+void InitScc(void);
+
+/*
+ * Function: RegisterDelay
+ *
+ * Description: A little delay since the SCC can't handle quick consecutive
+ * accesses
+ * In: none
+ * Out: none
+ */
+void RegisterDelay(void)
+{
+ register int ctr;
+
+ for(ctr=0;ctr<0x40;ctr++);
+}
+
+/*
+ * Function: SccInit
+ *
+ * Description: Initialize all the SCC registers for 19200 baud, asynchronous,
+ * 8 bit, 1 stop bit, no parity communication (Channel A)
+ *
+ * In: none
+ *
+ * Out: none
+ */
+void InitScc(void)
+{
+ /* Force hardware reset */
+ Write8530(kSCC_ChanA | kSCC_Command, R9 | NULLCODE);
+ RegisterDelay();
+ Write8530(kSCC_ChanA, FHWRES);
+ RegisterDelay();
+
+ /* x32 clock, 1 stop bit, no parity */
+ Write8530(kSCC_ChanA | kSCC_Command, R4 | NULLCODE);
+ RegisterDelay();
+ Write8530(kSCC_ChanA, X16CLK | SB1);
+ RegisterDelay();
+
+ /* Rx 8 bits, Rx disabled */
+ Write8530(kSCC_ChanA | kSCC_Command, R3 | NULLCODE);
+ RegisterDelay();
+ Write8530(kSCC_ChanA, Rx8);
+ RegisterDelay();
+
+ /* Tx 8 bits, DTR, RTS, Tx off */
+ Write8530(kSCC_ChanA | kSCC_Command, R5 | NULLCODE);
+ RegisterDelay();
+ Write8530(kSCC_ChanA, Tx8 | DTR | RTS);
+ RegisterDelay();
+
+ /* Int. Disabled */
+ Write8530(kSCC_ChanA | kSCC_Command, R9 | NULLCODE);
+ RegisterDelay();
+ Write8530(kSCC_ChanA, 0x0);
+ RegisterDelay();
+
+ /* NRZ */
+ Write8530(kSCC_ChanA | kSCC_Command, R10 | NULLCODE);
+ RegisterDelay();
+ Write8530(kSCC_ChanA, NRZ);
+ RegisterDelay();
+
+ /* Tx & Rx = BRG out, TRxC = BRG out */
+ Write8530(kSCC_ChanA | kSCC_Command, R11 | NULLCODE);
+ RegisterDelay();
+ Write8530(kSCC_ChanA, TCBR | RCBR | TRxCBR | TRxCOI);
+ RegisterDelay();
+
+ /* Time constant = 0x01 */
+ Write8530(kSCC_ChanA | kSCC_Command, R12 | NULLCODE);
+ RegisterDelay();
+ Write8530(kSCC_ChanA, kSCC_115200 );
+ RegisterDelay();
+
+ /* Time constant high = 0x00 */
+ Write8530(kSCC_ChanA | kSCC_Command, R13 | NULLCODE);
+ RegisterDelay();
+ Write8530(kSCC_ChanA, 0x00);
+ RegisterDelay();
+
+ /* BRG in = ~RTxC, BRG off, loopback */
+ Write8530(kSCC_ChanA | kSCC_Command, R14 | NULLCODE);
+ RegisterDelay();
+ Write8530(kSCC_ChanA, LOOPBAK | BRSRC);
+ RegisterDelay();
+}
+
+/*
+ * Function: EnableScc
+ *
+ * Description: Enable transmit and receive on SCC Channel A
+ * In: none
+ * Out: none
+ */
+void EnableScc(void)
+{
+ /* Enable BRG */
+ Write8530(kSCC_ChanA | kSCC_Command, R14 | NULLCODE);
+ RegisterDelay();
+ Write8530(kSCC_ChanA, BRENABL | BRSRC);
+ RegisterDelay();
+
+ /* Rx enable (Rx 8 bits) */
+ Write8530(kSCC_ChanA | kSCC_Command, R3 | NULLCODE);
+ RegisterDelay();
+ Write8530(kSCC_ChanA, RxENABLE | Rx8);
+ RegisterDelay();
+
+ /* Tx enable (Tx8, DTR, RTS) */
+ Write8530(kSCC_ChanA | kSCC_Command, R5 | NULLCODE);
+ RegisterDelay();
+ Write8530(kSCC_ChanA, TxENAB | Tx8 | DTR | RTS);
+ RegisterDelay();
+}
+
+/*
+ * Function: SccOutb
+ *
+ * Description: Write a byte to the SCC (Channel A) and blink LED
+ * In: Byte to send
+ * Out: none
+ */
+void SccOutb(unsigned char byte)
+{
+ /* LED on.. */
+ Write8530(kSCC_ChanB | kSCC_Command, R5);
+ RegisterDelay();
+ Write8530(kSCC_ChanB | kSCC_Command, RTS);
+ RegisterDelay();
+
+ while ((Read8530(kSCC_ChanA) & Tx_BUF_EMP) == 0)
+ RegisterDelay();
+
+ Write8530(kSCC_ChanA | kSCC_Direct, byte);
+ RegisterDelay();
+
+ /* LED off.. */
+ Write8530(kSCC_ChanB | kSCC_Command, R9);
+ RegisterDelay();
+ Write8530(kSCC_ChanB | kSCC_Command, CHRB);
+ RegisterDelay();
+}
+
+/*
+ * Function: SccInb
+ *
+ * Description: Read a byte from the SCC (Channel A)
+ * In: Byte to send
+ * Out: none
+ */
+void SccInb(unsigned char *byte)
+{
+ while ((Read8530(kSCC_ChanA) & Rx_CH_AV) == 0)
+ RegisterDelay();
+
+ *byte = Read8530(kSCC_ChanA | kSCC_Direct);
+ RegisterDelay();
+}
+
+/*
+ * Function: SccWrite
+ *
+ * Description: Write a null terminated string to the SCC
+ * In: C string
+ * Out: none
+ */
+void SccWrite(const unsigned char *string)
+{
+ while((*string) != 0) {
+ if (*string == 10)
+ SccOutb((unsigned char) 13);
+ SccOutb(*(string++));
+ }
+}
+
+/*
+ * Function: InitSerialPort
+ *
+ * Description: Initialize the SCC and spit out the header message
+ * In: Header message
+ * Out: none
+ */
+void InitSerialPort(unsigned char *msg)
+{
+ InitScc();
+ EnableScc();
+ SccWrite(msg);
+}
+
+/*
+ * Function: SccInbTimeout
+ *
+ * Description: Read a byte from the SCC (Channel A) with timeout
+ * In: Byte to send
+ * Out: Timeout status
+ */
+unsigned char SccInbTimeout(unsigned char *byte, unsigned long timeout)
+{
+ unsigned long ctr = 0;
+
+ while ((Read8530(kSCC_ChanA) & Rx_CH_AV) == 0) {
+ RegisterDelay();
+ if ((ctr++) > timeout)
+ return 0xFF;
+ }
+
+ *byte = Read8530(kSCC_ChanA | kSCC_Direct);
+ RegisterDelay();
+
+ return 0;
+}
+
+#include <linux/serial_reg.h>
+
+extern int serial_echo_init (int base);
+extern int serial_echo_print (const char *s);
+
+/*
+ * this defines the address for the port to which printk echoing is done
+ * when CONFIG_SERIAL_ECHO is defined
+ */
+#define SERIAL_ECHO_PORT 0x1C800000
+
+static int serial_echo_port = 0;
+
+#define serial_echo_outb(v,a) outb((v),(a)+serial_echo_port)
+#define serial_echo_inb(a) inb((a)+serial_echo_port)
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+/* Wait for transmitter & holding register to empty */
+#define WAIT_FOR_XMITR \
+ do { \
+ lsr = serial_echo_inb(UART_LSR); \
+ } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY)
+
+/*
+ * These two functions abstract the actual communications with the
+ * debug port. This is so we can change the underlying communications
+ * mechanism without modifying the rest of the code.
+ */
+int
+serial_echo_print(const char *s)
+{
+ int lsr, ier;
+ int i;
+
+ if (!serial_echo_port)
+ return 0;
+
+ /*
+ * First save the IER then disable the interrupts
+ */
+ ier = serial_echo_inb(UART_IER);
+ serial_echo_outb(0x00, UART_IER);
+
+ /*
+ * Now, do each character
+ */
+ for (i = 0; *s; i++, s++) {
+ WAIT_FOR_XMITR;
+
+ /* Send the character out. */
+ serial_echo_outb(*s, UART_TX);
+
+ /* if a LF, also do CR... */
+ if (*s == 10) {
+ WAIT_FOR_XMITR;
+ serial_echo_outb(13, UART_TX);
+ }
+ }
+
+ /*
+ * Finally, Wait for transmitter & holding register to empty
+ * and restore the IER
+ */
+ do {
+ lsr = serial_echo_inb(UART_LSR);
+ } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY);
+ serial_echo_outb(ier, UART_IER);
+
+ return 0;
+}
+
+
+int
+serial_echo_init(int base)
+{
+ int comstat, hi, lo;
+
+ serial_echo_port = base;
+
+ /*
+ * read the Divisor Latch
+ */
+ comstat = serial_echo_inb(UART_LCR);
+ serial_echo_outb(comstat | UART_LCR_DLAB, UART_LCR);
+ hi = serial_echo_inb(UART_DLM);
+ lo = serial_echo_inb(UART_DLL);
+ serial_echo_outb(comstat, UART_LCR);
+
+ /*
+ * now do hardwired init
+ */
+ serial_echo_outb(0x03, UART_LCR); /* No parity, 8 data bits, 1 stop */
+ serial_echo_outb(0x83, UART_LCR); /* Access divisor latch */
+
+ /* This is computed using:
+ *
+ * const BASE_BAUD = (18432000 / 16);
+ * UART_DLM = (BASE_BAUD / baud_I_want) >> 8;
+ * UART_DLL = (BASE_BAUD / baud_I_want) & 0xff;
+ */
+ serial_echo_outb(0x00, UART_DLM); /* 115200 baud */
+ serial_echo_outb(0x0A, UART_DLL);
+
+ serial_echo_outb(0x03, UART_LCR); /* Done with divisor */
+
+ /*
+ * Prior to disabling interrupts, read the LSR and RBR
+ * registers
+ */
+ comstat = serial_echo_inb(UART_LSR); /* COM? LSR */
+ comstat = serial_echo_inb(UART_RX); /* COM? RBR */
+ serial_echo_outb(0x00, UART_IER); /* Disable all interrupts */
+
+ return 0;
+}
--- /dev/null
+/*
+ * Filename: diagdefs.h
+ *
+ * Description: Some general definitions used by the diagnostics
+ *
+ * Author(s): Timothy Stonis
+ *
+ * Copyright 1997, Cobalt Microserver, Inc.
+ */
+
+#define KSEG0_Base 0x80000000
+#define KSEG1_Base 0xA0000000
+
+// Some useful Galileo registers/base addresses (boot time kseg1 mapping)
+#define kGal_InternalBase ( 0x14000000 | KSEG1_Base )
+#define kGal_DevBank0Base ( 0x1C000000 | KSEG1_Base )
+#define kGal_DevBank1Base ( 0x1C800000 | KSEG1_Base )
+
+#define kGal_RAS10Lo 0x008
+#define kGal_RAS10Hi 0x010
+#define kGal_RAS32Lo 0x018
+#define kGal_RAS32Hi 0x020
+
+#define kGal_PCIIOLo 0x048
+#define kGal_PCIIOHi 0x050
+
+#define kGal_RAS10LoCfg 0x000
+#define kGal_RAS10HiCfg 0x03
+#define kGal_RAS32LoCfg 0x004
+#define kGal_RAS32HiCfg 0x07
+
+#define kGal_PCIIOLoCfg 0x000
+#define kGal_PCIIOHiCfg 0x0F
+
+
+#define kGal_DevBank0PReg 0x45C
+#define kGal_DevBank1PReg 0x460
+#define kGal_DevBank2PReg 0x464
+#define kGal_DevBank3PReg 0x468
+#define kGal_DevBankBPReg 0x46C
+
+#define kGal_DRAMCReg 0x448
+#define kGal_DRAM0PReg 0x44C
+#define kGal_DRAM1PReg 0x450
+#define kGal_DRAM2PReg 0x454
+#define kGal_DRAM3PReg 0x458
+
+#define kGal_ConfigAddr 0xCF8
+#define kGal_ConfigData 0xCFC
+#define kGal_PCICfgEn 0x1F // Generate config cycle
+#define kGal_DevNum 0x00 // Technically 0x06, but 0 works too
+#define kGal_MasMemEn 0x06
+#define kGal_Latency 0x700
+
+#define kGal_RAS01StartReg 0x10
+#define kGal_RAS23StartReg 0x14
+#define kGal_RAS01SizeReg 0x0C08
+#define kGal_RAS23SizeReg 0x0C0C
+
+
+#define kGal_RAS01Start 0x000
+#define kGal_RAS23Start 0x00800000
+#define kGal_RAS01Size 0x007FFFFF
+#define kGal_RAS23Size 0x007FFFFF
+
+
+// Paramter information for devices, DRAM, etc
+#define kGal_DevBank0Cfg 0x1446DB33
+#define kGal_DevBank1Cfg 0x144FE667
+#define kGal_DevBankBCfg 0x1446DC43
+#define kGal_DRAMConfig 0x00000300
+#define kGal_DRAM0Config 0x00000010
+#define kGal_DRAM1Config 0x00000010
+#define kGal_DRAM2Config 0x00000010
+#define kGal_DRAM3Config 0x00000010
+
+#define kGal_DRAM0Hi 0x00000003
+#define kGal_DRAM0Lo 0x00000000
+#define kGal_DRAM1Hi 0x00000007
+#define kGal_DRAM1Lo 0x00000004
+#define kGal_DRAM2Hi 0x0000000B
+#define kGal_DRAM2Lo 0x00000008
+#define kGal_DRAM3Hi 0x0000000F
+#define kGal_DRAM3Lo 0x0000000C
+
+#define kGal_RAS0Lo 0x400
+#define kGal_RAS0Hi 0x404
+#define kGal_RAS1Lo 0x408
+#define kGal_RAS1Hi 0x40C
+#define kGal_RAS2Lo 0x410
+#define kGal_RAS2Hi 0x414
+#define kGal_RAS3Lo 0x418
+#define kGal_RAS3Hi 0x41C
+
+// Feedback LED indicators during setup code (reset.S, main.c)
+#define kLED_AllOn 0x0F
+#define kLED_FlashTest 0x01
+#define kLED_MemTest 0x02
+#define kLED_SCCTest 0x03
+#define kLED_GalPCI 0x04
+#define kLED_EnetTest 0x05
+#define kLED_SCSITest 0x06
+#define kLED_IOCTest 0x07
+#define kLED_Quickdone 0x0A
+#define kLED_Exception 0x0B
+#define kLED_ProcInit 0x0E
+#define kLED_AllOff 0x00
+
+#define kLEDBase kGal_DevBank0Base
+
+// Some memory related constants
+#define kRAM_Start (0x00000000 | KSEG0_Base)
+
+#define kTestPat1 0xA5A5A5A5
+#define kTestPat2 0x5A5A5A5A
+
+#define k1Meg_kseg1 (0x00100000 | KSEG0_Base)
+#define k2Meg_kseg1 (0x00200000 | KSEG0_Base)
+#define k4Meg_kseg1 (0x00400000 | KSEG0_Base)
+#define k8Meg_kseg1 (0x00800000 | KSEG0_Base)
+#define k16Meg_kseg1 (0x01000000 | KSEG0_Base)
+
+#define kInit_SP k4Meg_kseg1 - 0x100
+#define kVectorBase 0x200
+#define kDebugVectors 0x400
+#define kMallocCheese 0x80E00000
+#define kDecompAddr 0x80700000
+#define kCompAddr 0x80500000
+
+
+// Ethernet definitions
+#define kEnet_VIOBase ( 0x12100000 | KSEG1_Base )
+#define kEnet_PIOBase 0x12100000
+#define kEnet_CSCfg 0x46
+#define kEnet_DevNum 0x07
+#define kEnet_CSR3 0x18
+#define kEnet_CSR15 0x78
+
+
+#define kEnet_GEPOut 0x080f0000
+#define kEnet_GEPOn 0x000f0000
+
+
+// SCSI definitions
+#define kSCSI_VIOBase ( 0x12200000 | KSEG1_Base )
+#define kSCSI_PIOBase 0x12200000
+#define kSCSI_CSCfg 0x46
+#define kSCSI_DevNum 0x08
+#define kSCSI_GPCNTL 0x47
+#define kSCSI_GPREG 0x07
+#define kSCSI_SCRTCHA 0x34
+
+#define kSCSI_GPIOOut 0x0C
+#define kSCSI_LEDsOn 0x00
+
+// I/O Controller definitions
+#define kIOC_VIOBase ( 0x10000000 | KSEG1_Base )
+#define kIOC_RIOBase 0x10000000
+#define kIOC_DevNum 0x09
+#define kIOC_ISAFunc 0x00
+#define kIOC_IDEFunc 0x01
+#define kIOC_USBFunc 0x02
+#define kIOC_MiscC0 0x44
+#define kIOC_IDEEnable 0x40
+
+#define kIOC_PCIIDEOn 0x02800085
+#define kIOC_PriIDEOn 0x0A
+
+// Some PCI Definitions
+#define kPCI_StatCmd 0x04
+#define kPCI_LatCache 0x0C
+#define kPCI_CBIO 0x10
+#define kPCI_CBMEM 0x14
+
+// Random constants
+#define kBogoSec 0x0003F940
+#define kSCCDelay 0x00000001
--- /dev/null
+/*
+ * Low-level hardware access stuff for Cobalt Microserver 27 board.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
+ */
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <asm/cachectl.h>
+#include <asm/cobalt.h>
+#include <asm/segment.h>
+#include <asm/vector.h>
+
+void
+dummy(void)
+{
+ panic("What the hell is this called for?");
+}
+
+static unsigned char cobalt_read_cmos(unsigned long reg)
+{
+ unsigned char retval;
+
+ VIA_PORT_WRITE(0x70, reg);
+ retval = VIA_PORT_READ(0x71);
+ VIA_DELAY();
+
+ return retval;
+}
+
+static void cobalt_write_cmos(unsigned char val, unsigned long reg)
+{
+ VIA_PORT_WRITE(0x70, reg);
+ VIA_PORT_WRITE(0x71, val);
+}
+
+struct feature cobalt_feature = {
+ /*
+ * How to access the floppy controller's ports
+ */
+ (void *)dummy, (void *)dummy,
+ /*
+ * How to access the floppy DMA functions.
+ */
+ (void *)dummy, (void *)dummy, (void *)dummy, (void *)dummy,
+ (void *)dummy, (void *)dummy, (void *)dummy, (void *)dummy,
+ (void *)dummy, (void *)dummy, (void *)dummy,
+ /*
+ * How to access the RTC functions.
+ */
+ cobalt_read_cmos,
+ cobalt_write_cmos
+};
--- /dev/null
+/*
+ * arch/mips/cobalt/int-handler.S
+ */
+#include <asm/asm.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/cobalt.h>
+#include <asm/irq.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/*
+ * cobalt_handle_int: Interrupt handler for the twenty-seven board.
+ */
+ .align 5
+ .set noreorder
+ NESTED(cobalt_handle_int, PT_SIZE, ra)
+ .set noat
+ SAVE_ALL
+ REG_S sp,PT_OR2(sp)
+ CLI
+ .set at
+ mfc0 t0,CP0_CAUSE
+ mfc0 t1,CP0_STATUS
+ and t0,t1
+ xor t1,t0
+ mtc0 t1,CP0_STATUS # mask all active ints
+ /* Such a kind of cascade is optimal for R5000 */
+
+ andi t1,t0,STATUSF_IP2
+ bnez t1,ll_galileo_irq
+ andi t1,t0,STATUSF_IP3
+ bnez t1,ll_ethernet0_irq
+/*
+ * This should be conditional, and not used for the cube-1, but
+ * there is not a config flag that is useful.
+ */
+
+ andi t1,t0,STATUSF_IP4
+ bnez t1,ll_ethernet1_irq
+/* #endif */
+ andi t1,t0,STATUSF_IP6
+ bnez t1,ll_via_irq
+ andi t1,t0,STATUSF_IP5
+ bnez t1,ll_serial_irq
+ andi t1,t0,STATUSF_IP7
+ bnez t1,ll_pci_irq
+ nop
+ /* wrong alarm ... */
+ j spurious_interrupt
+ nop
+ END(cobalt_handle_int)
+
+
+ .align 5
+ .set reorder
+ll_galileo_irq: move a0,sp
+ INC_INTR_COUNT(s1,s2)
+ jal galileo_irq
+ nop
+ DEC_INTR_COUNT(s1,s2)
+ j ret_from_irq
+ nop
+
+ .align 5
+ .set reorder
+ll_via_irq: move a0,sp
+ INC_INTR_COUNT(s1,s2)
+ jal via_irq
+ nop
+ DEC_INTR_COUNT(s1,s2)
+ j ret_from_irq
+ nop
+
+ .align 5
+ .set reorder
+ll_ethernet0_irq:
+ INC_INTR_COUNT(s1,s2)
+ mfc0 s0,CP0_STATUS # mask interrupt
+ ori t0,s0,(STATUSF_IP3 | STATUSF_IP4)
+ xori t0,(STATUSF_IP3 | STATUSF_IP4)
+ mtc0 t0,CP0_STATUS
+ li a0,4
+ move a1,sp
+ jal do_IRQ
+ nop
+ mtc0 s0,CP0_STATUS
+ DEC_INTR_COUNT(s1,s2)
+ j ret_from_irq
+ nop
+
+ .align 5
+ .set reorder
+ll_serial_irq: li a0,7
+ INC_INTR_COUNT(s1,s2)
+ move a1,sp
+ jal do_IRQ
+ nop
+ DEC_INTR_COUNT(s1,s2)
+ j ret_from_irq
+ nop
+
+
+ .align 5
+ .set reorder
+ll_ethernet1_irq:
+ INC_INTR_COUNT(s1,s2)
+ mfc0 s0,CP0_STATUS # mask interrupt
+
+ ori t0,s0, (STATUSF_IP3 | STATUSF_IP4)
+ xori t0,(STATUSF_IP3 | STATUSF_IP4)
+
+ mtc0 t0,CP0_STATUS
+ li a0,13
+ move a1,sp
+ jal do_IRQ
+ nop
+ mtc0 s0,CP0_STATUS
+ DEC_INTR_COUNT(s1,s2)
+ j ret_from_irq
+ nop
+
+ #
+ # This is pretty weird. The "pci" interrupt on the hardware
+ # skematic is from the PCI side of the galileo, so we would
+ # only get interrupts here if WE write the control register
+ # that normally enables the cpu to send interrupts to the PCI.
+ #
+ # If you want to interrupt a PCI card, look elsewhere.
+ #
+ .align 5
+ .set reorder
+ll_pci_irq: li a0,7
+ INC_INTR_COUNT(s1,s2)
+ move a1,sp
+ jal do_IRQ
+ nop
+ DEC_INTR_COUNT(s1,s2)
+ j ret_from_irq
+ nop
--- /dev/null
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Cobalt Qube specific PCI support.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/bios32.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <asm/cobalt.h>
+#include <asm/pci.h>
+#include <asm/io.h>
+
+#undef PCI_DEBUG
+
+#ifdef CONFIG_PCI
+
+static void qube_expansion_slot_bist(void)
+{
+ unsigned char ctrl;
+ int timeout = 100000;
+
+ pcibios_read_config_byte(0, (0x0a<<3), PCI_BIST, &ctrl);
+ if(!(ctrl & PCI_BIST_CAPABLE))
+ return;
+
+ pcibios_write_config_byte(0, (0x0a<<3), PCI_BIST, ctrl|PCI_BIST_START);
+ do {
+ pcibios_read_config_byte(0, (0x0a<<3), PCI_BIST, &ctrl);
+ if(!(ctrl & PCI_BIST_START))
+ break;
+ } while(--timeout > 0);
+ if((timeout <= 0) || (ctrl & PCI_BIST_CODE_MASK))
+ printk("PCI: Expansion slot card failed BIST with code %x\n",
+ (ctrl & PCI_BIST_CODE_MASK));
+}
+
+static void qube_expansion_slot_fixup(void)
+{
+ unsigned short pci_cmd;
+ unsigned long ioaddr_base = 0x10108000; /* It's magic, ask Doug. */
+ unsigned long memaddr_base = 0x12000000;
+ int i;
+
+ /* Enable bits in COMMAND so driver can talk to it. */
+ pcibios_read_config_word(0, (0x0a<<3), PCI_COMMAND, &pci_cmd);
+ pci_cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+ pcibios_write_config_word(0, (0x0a<<3), PCI_COMMAND, pci_cmd);
+
+ /* Give it a working IRQ. */
+ pcibios_write_config_byte(0, (0x0a<<3), PCI_INTERRUPT_LINE, 9);
+
+ /* Fixup base addresses, we only support I/O at the moment. */
+ for(i = 0; i <= 5; i++) {
+ unsigned int regaddr = (PCI_BASE_ADDRESS_0 + (i * 4));
+ unsigned int rval, mask, size, alignme, aspace;
+ unsigned long *basep = &ioaddr_base;
+
+ /* Check type first, punt if non-IO. */
+ pcibios_read_config_dword(0, (0x0a<<3), regaddr, &rval);
+ aspace = (rval & PCI_BASE_ADDRESS_SPACE);
+ if(aspace != PCI_BASE_ADDRESS_SPACE_IO)
+ basep = &memaddr_base;
+
+ /* Figure out how much it wants, if anything. */
+ pcibios_write_config_dword(0, (0x0a<<3), regaddr, 0xffffffff);
+ pcibios_read_config_dword(0, (0x0a<<3), regaddr, &rval);
+
+ /* Unused? */
+ if(rval == 0)
+ continue;
+
+ rval &= PCI_BASE_ADDRESS_IO_MASK;
+ mask = (~rval << 1) | 0x1;
+ size = (mask & rval) & 0xffffffff;
+ alignme = size;
+ if(alignme < 0x400)
+ alignme = 0x400;
+ rval = ((*basep + (alignme - 1)) & ~(alignme - 1));
+ *basep = (rval + size);
+ pcibios_write_config_dword(0, (0x0a<<3), regaddr, rval | aspace);
+ }
+ qube_expansion_slot_bist();
+}
+
+static void qube_raq_tulip_fixup(void)
+{
+ unsigned short pci_cmd;
+
+ /* Enable the device. */
+ pcibios_read_config_word(0, (0x0c<<3), PCI_COMMAND, &pci_cmd);
+ pci_cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MASTER);
+ pcibios_write_config_word(0, (0x0c<<3), PCI_COMMAND, pci_cmd);
+
+ /* Give it it's IRQ. */
+ /* NOTE: RaQ board #1 has a bunch of green wires which swapped the
+ * IRQ line values of Tulip 0 and Tulip 1. All other
+ * boards have eth0=4,eth1=13. -DaveM
+ */
+#ifndef RAQ_BOARD_1_WITH_HWHACKS
+ pcibios_write_config_byte(0, (0x0c<<3), PCI_INTERRUPT_LINE, 13);
+#else
+ pcibios_write_config_byte(0, (0x0c<<3), PCI_INTERRUPT_LINE, 4);
+#endif
+
+ /* And finally, a usable I/O space allocation, right after what
+ * the first Tulip uses.
+ */
+ pcibios_write_config_dword(0, (0x0c<<3), PCI_BASE_ADDRESS_0, 0x10101001);
+}
+
+static void qube_raq_scsi_fixup(void)
+{
+ unsigned short pci_cmd;
+
+ /* Enable the device. */
+ pcibios_read_config_word(0, (0x08<<3), PCI_COMMAND, &pci_cmd);
+
+ pci_cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY
+ | PCI_COMMAND_INVALIDATE);
+ pcibios_write_config_word(0, (0x08<<3), PCI_COMMAND, pci_cmd);
+
+ /* Give it it's IRQ. */
+ pcibios_write_config_byte(0, (0x08<<3), PCI_INTERRUPT_LINE, 4);
+
+ /* And finally, a usable I/O space allocation, right after what
+ * the second Tulip uses.
+ */
+ pcibios_write_config_dword(0, (0x08<<3), PCI_BASE_ADDRESS_0, 0x10102001);
+ pcibios_write_config_dword(0, (0x08<<3), PCI_BASE_ADDRESS_1, 0x00002000);
+ pcibios_write_config_dword(0, (0x08<<3), PCI_BASE_ADDRESS_2, 0x00100000);
+}
+
+static unsigned long
+qube_pcibios_fixup(unsigned long mem_start, unsigned long mem_end)
+{
+ extern int cobalt_is_raq;
+ int raq_p = cobalt_is_raq;
+ unsigned int tmp;
+
+ /* Fixup I/O and Memory space decoding on Galileo. */
+ isa_slot_offset = COBALT_LOCAL_IO_SPACE;
+
+ /* Fix PCI latency-timer and cache-line-size values in Galileo
+ * host bridge.
+ */
+ pcibios_write_config_byte(0, 0, PCI_LATENCY_TIMER, 64);
+ pcibios_write_config_byte(0, 0, PCI_CACHE_LINE_SIZE, 7);
+
+ /*
+ * Now tell the SCSI device that we expect an interrupt at
+ * IRQ 7 and not the default 0.
+ */
+ pcibios_write_config_byte(0, 0x08<<3, PCI_INTERRUPT_LINE,
+ COBALT_SCSI_IRQ);
+
+ /*
+ * Now tell the Ethernet device that we expect an interrupt at
+ * IRQ 13 and not the default 189.
+ *
+ * The IRQ of the first Tulip is different on Qube and RaQ
+ * hardware except for the weird first RaQ bringup board,
+ * see above for details. -DaveM
+ */
+ if (! raq_p) {
+ /* All Qube's route this the same way. */
+ pcibios_write_config_byte(0, 0x07<<3, PCI_INTERRUPT_LINE,
+ COBALT_ETHERNET_IRQ);
+ } else {
+#ifndef RAQ_BOARD_1_WITH_HWHACKS
+ pcibios_write_config_byte(0, (0x07<<3), PCI_INTERRUPT_LINE, 4);
+#else
+ pcibios_write_config_byte(0, (0x07<<3), PCI_INTERRUPT_LINE, 13);
+#endif
+ }
+
+ if (! raq_p) {
+ /* See if there is a device in the expansion slot, if so
+ * fixup IRQ, fix base addresses, and enable master +
+ * I/O + memory accesses in config space.
+ */
+ pcibios_read_config_dword(0, 0x0a<<3, PCI_VENDOR_ID, &tmp);
+ if(tmp != 0xffffffff && tmp != 0x00000000)
+ qube_expansion_slot_fixup();
+ } else {
+ /* If this is a RAQ, we may need to setup the second Tulip
+ * and SCSI as well. Due to the different configurations
+ * a RaQ can have, we need to explicitly check for the
+ * presence of each of these (optional) devices. -DaveM
+ */
+ pcibios_read_config_dword(0, 0x0c<<3, PCI_VENDOR_ID, &tmp);
+ if(tmp != 0xffffffff && tmp != 0x00000000)
+ qube_raq_tulip_fixup();
+
+ pcibios_read_config_dword(0, 0x08<<3, PCI_VENDOR_ID, &tmp);
+ if(tmp != 0xffffffff && tmp != 0x00000000)
+ qube_raq_scsi_fixup();
+
+ /* And if we are a 2800 we have to setup the expansion slot
+ * too.
+ */
+ pcibios_read_config_dword(0, 0x0a<<3, PCI_VENDOR_ID, &tmp);
+ if(tmp != 0xffffffff && tmp != 0x00000000)
+ qube_expansion_slot_fixup();
+ }
+
+ return mem_start;
+}
+
+static __inline__ int pci_range_ck(unsigned char bus, unsigned char dev)
+{
+ if ((bus == 0) && ( (dev==0) || ((dev>6) && (dev <= 12))) )
+ return 0; /* OK device number */
+
+ return -1; /* NOT ok device number */
+}
+
+#define PCI_CFG_DATA ((volatile unsigned long *)0xb4000cfc)
+#define PCI_CFG_CTRL ((volatile unsigned long *)0xb4000cf8)
+
+#define PCI_CFG_SET(dev,fun,off) \
+ ((*PCI_CFG_CTRL) = (0x80000000 | ((dev)<<11) | \
+ ((fun)<<8) | (off)))
+
+static int qube_pcibios_read_config_dword (unsigned char bus,
+ unsigned char dev,
+ unsigned char offset,
+ unsigned int *val)
+{
+ unsigned char fun = dev & 0x07;
+
+ dev >>= 3;
+ if (offset & 0x3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (pci_range_ck(bus, dev)) {
+ *val = 0xFFFFFFFF;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ PCI_CFG_SET(dev, fun, offset);
+ *val = *PCI_CFG_DATA;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int qube_pcibios_read_config_word (unsigned char bus,
+ unsigned char dev,
+ unsigned char offset,
+ unsigned short *val)
+{
+ unsigned char fun = dev & 0x07;
+
+ dev >>= 3;
+ if (offset & 0x1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (pci_range_ck(bus, dev)) {
+ *val = 0xffff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ PCI_CFG_SET(dev, fun, (offset & ~0x3));
+ *val = *PCI_CFG_DATA >> ((offset & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int qube_pcibios_read_config_byte (unsigned char bus,
+ unsigned char dev,
+ unsigned char offset,
+ unsigned char *val)
+{
+ unsigned char fun = dev & 0x07;
+
+ dev >>= 3;
+ if (pci_range_ck(bus, dev)) {
+ *val = 0xff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ PCI_CFG_SET(dev, fun, (offset & ~0x3));
+ *val = *PCI_CFG_DATA >> ((offset & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int qube_pcibios_write_config_dword (unsigned char bus,
+ unsigned char dev,
+ unsigned char offset,
+ unsigned int val)
+{
+ unsigned char fun = dev & 0x07;
+
+ dev >>= 3;
+ if(offset & 0x3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (pci_range_ck(bus, dev))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ PCI_CFG_SET(dev, fun, offset);
+ *PCI_CFG_DATA = val;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+qube_pcibios_write_config_word (unsigned char bus, unsigned char dev,
+ unsigned char offset, unsigned short val)
+{
+ unsigned char fun = dev & 0x07;
+ unsigned long tmp;
+
+ dev >>= 3;
+ if (offset & 0x1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (pci_range_ck(bus, dev))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ PCI_CFG_SET(dev, fun, (offset & ~0x3));
+ tmp = *PCI_CFG_DATA;
+ tmp &= ~(0xffff << ((offset & 0x3) * 8));
+ tmp |= (val << ((offset & 0x3) * 8));
+ *PCI_CFG_DATA = tmp;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+qube_pcibios_write_config_byte (unsigned char bus, unsigned char dev,
+ unsigned char offset, unsigned char val)
+{
+ unsigned char fun = dev & 0x07;
+ unsigned long tmp;
+
+ dev >>= 3;
+ if (pci_range_ck(bus, dev))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ PCI_CFG_SET(dev, fun, (offset & ~0x3));
+ tmp = *PCI_CFG_DATA;
+ tmp &= ~(0xff << ((offset & 0x3) * 8));
+ tmp |= (val << ((offset & 0x3) * 8));
+ *PCI_CFG_DATA = tmp;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops qube_pci_ops = {
+ qube_pcibios_fixup,
+ qube_pcibios_read_config_byte,
+ qube_pcibios_read_config_word,
+ qube_pcibios_read_config_dword,
+ qube_pcibios_write_config_byte,
+ qube_pcibios_write_config_word,
+ qube_pcibios_write_config_dword
+};
+
+#endif /* CONFIG_PCI */
--- /dev/null
+/*
+ * Reset a Cobalt Qube.
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+
+void cobalt_machine_restart(char *command)
+{
+ *(volatile char *)0xbc000000 = 0x0f;
+
+ /*
+ * Ouch, we're still alive ... This time we take the silver bullet ...
+ * ... and find that we leave the hardware in a state in which the
+ * kernel in the flush locks up somewhen during of after the PCI
+ * detection stuff.
+ */
+ set_cp0_status((ST0_BEV | ST0_ERL), (ST0_BEV | ST0_ERL));
+ set_cp0_config(CONFIG_CM_CMASK, CONFIG_CM_UNCACHED);
+ flush_cache_all();
+ write_32bit_cp0_register(CP0_WIRED, 0);
+ __asm__ __volatile__(
+ "jr\t%0"
+ :
+ : "r" (0xbfc00000));
+}
+
+extern int led_state;
+#define kLED 0xBC000000
+#define LEDSet(x) (*(volatile unsigned char *) kLED) = (( unsigned char)x)
+
+void cobalt_machine_halt(void)
+{
+ int mark;
+
+ // Blink our cute little LED (number 3)...
+ while (1) {
+ led_state = led_state | ( 1 << 3 );
+ LEDSet(led_state);
+ mark = jiffies;
+ while (jiffies<(mark+HZ));
+ led_state = led_state & ~( 1 << 3 );
+ LEDSet(led_state);
+ mark = jiffies;
+ while (jiffies<(mark+HZ));
+ }
+}
+
+/*
+ * This triggers the luser mode device driver for the power switch ;-)
+ */
+void cobalt_machine_power_off(void)
+{
+ printk("You can switch the machine off now.\n");
+ cobalt_machine_halt();
+}
--- /dev/null
+/*
+ *
+ * Filename: serial.h
+ *
+ * Description: Some general definitions used for serial code
+ *
+ * Author(s): Timothy Stonis
+ *
+ * Copyright 1997, Cobalt Microserver, Inc.
+ */
+
+/*
+ * Serial port definitions
+ */
+#define kSCC_Base kGal_DevBank1Base
+#define kHelloWorldMsg "Cobalt Networks Diagnostics - 'We serve it, you surf it'\n\r"
+#define kSCC_ChanA 0x01
+#define kSCC_ChanB 0x00
+#define kSCC_Direct 0x02
+#define kSCC_Command 0x00
+
+#define kSCC_TestVal 0xA5
+#define kSCC_19200 0x07 /* x32 clock mode, 19200 baud */
+#define kSCC_115200 0x01 /* x16 clock mode, 115200 baud */
+
+#define Read8530(n) (*((unsigned char *) (kSCC_Base | (n))))
+
+#define Write8530(x,y) (*((unsigned char *) (kSCC_Base | (x))) = (y))
--- /dev/null
+/*
+ * Setup pointers to hardware dependand routines.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996, 1997 by Ralf Baechle
+ */
+#include <linux/bios32.h>
+#include <linux/config.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/timex.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/cobalt.h>
+#include <asm/pci.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/reboot.h>
+#include <asm/vector.h>
+
+extern void cobalt_machine_restart(char *command);
+extern void cobalt_machine_halt(void);
+extern void cobalt_machine_power_off(void);
+
+extern int serial_console;
+
+/*
+ * Initial irq handlers.
+ */
+static void no_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+}
+
+/*
+ * IRQ2 is cascade interrupt to second interrupt controller
+ */
+static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL};
+
+extern struct feature cobalt_feature;
+extern asmlinkage void cobalt_handle_int(void);
+
+static void cobalt_irq_setup(void)
+{
+ /*
+ * Clear all of the interrupts while we change the able around a bit.
+ */
+ set_cp0_status(ST0_IM, 0);
+
+ /* Sets the exception_handler array. */
+ set_except_vector(0, cobalt_handle_int);
+
+ request_region(0xb0000020, 0x20, "pic1");
+ request_region(0xb00000A0, 0x20, "pic2");
+ setup_x86_irq(2, &irq2);
+
+ cli();
+
+ set_cp0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1 | IE_IRQ0);
+
+ /* Setup VIA irq mask */
+ VIA_PORT_WRITE(0x20, 0x10);
+ VIA_PORT_WRITE(0x21, 0x00);
+ VIA_PORT_WRITE(0x21, 0x00);
+
+ VIA_PORT_WRITE(0xa0, 0x10);
+ VIA_PORT_WRITE(0xa1, 0x00);
+ VIA_PORT_WRITE(0xa1, 0x00);
+}
+
+void (*board_time_init)(struct irqaction *irq);
+
+static void cobalt_calibrate_timer(void)
+{
+ volatile unsigned long *timer_reg = (volatile unsigned long *)0xb4000850;
+
+ /* Default to 150MHZ, since this is what we are shipping. */
+ *timer_reg = 500000;
+}
+
+static void cobalt_time_init(struct irqaction *irq)
+{
+ /* Load timer value for 100 Hz */
+ cobalt_calibrate_timer();
+ /* *((volatile unsigned long *) 0xb4000850) = (unsigned long) 440000; */
+
+ setup_x86_irq(0, irq);
+
+ /* Enable timer ints */
+ *((volatile unsigned long *) 0xb4000864) = (unsigned long) 0x00000003;
+ /* Unmask timer int */
+ *((volatile unsigned long *) 0xb4000c1c) = (unsigned long) 0x00000100;
+}
+
+extern struct pci_ops qube_pci_ops;
+int cobalt_serial_present;
+int cobalt_serial_type;
+int cobalt_is_raq;
+
+void cobalt_setup(void)
+{
+ tag *atag;
+
+ /*
+ * We just check if a tag_screen_info can be gathered
+ * in setup_arch(), if yes we don't proceed futher...
+ */
+ atag = bi_TagFind(tag_screen_info);
+ if (!atag) {
+ /*
+ * If no, we try to find the tag_arc_displayinfo which is
+ * always created by Milo for an ARC box (for now Milo only
+ * works on ARC boxes :) -Stoned.
+ */
+ atag = bi_TagFind(tag_arcdisplayinfo);
+ if (atag) {
+
+ screen_info.orig_x =
+ ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_x;
+ screen_info.orig_y =
+ ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_y;
+ screen_info.orig_video_cols =
+ ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->columns;
+ screen_info.orig_video_lines =
+ ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->lines;
+ }
+ }
+
+ _machine_restart = cobalt_machine_restart;
+ _machine_halt = cobalt_machine_halt;
+ _machine_power_off = cobalt_machine_power_off;
+
+ irq_setup = cobalt_irq_setup;
+ board_time_init = cobalt_time_init;
+ feature = &cobalt_feature;
+ mips_io_port_base = COBALT_LOCAL_IO_SPACE;
+
+ pci_ops = &qube_pci_ops;
+
+#ifdef CONFIG_COBALT_SERIAL
+ serial_console = 1;
+#endif /* CONFIG_COBALT_SERIAL */
+
+ /* We have to do this early, here, before the value could
+ * possibly be overwritten by the bootup sequence.
+ */
+ cobalt_serial_present = *((unsigned long *) 0xa020001c);
+ cobalt_serial_type = *((unsigned long *) 0xa0200020);
+ cobalt_is_raq = (cobalt_serial_present != 0x0
+ && cobalt_serial_type == 0x1);
+}
+
+void AddTagsEndSymbol(void);
+int bi_TagAdd (enum bi_tag type, unsigned long size, void *data);
+unsigned long next_tag = (unsigned long) NULL;
+unsigned long memory_upper = (unsigned long) NULL;
+
+int bi_TagAdd (enum bi_tag type, unsigned long size, void *data)
+{
+ tag t;
+ unsigned long addr;
+
+ t.tag = type;
+ t.size = size;
+
+ /*
+ * If next_tag equals NULL it means it's the first tag we're asked
+ * to create.
+ */
+ if (next_tag == (unsigned long) NULL) {
+ /*
+ * If memory_upper not equals NULL it means that identify()
+ * was able to figure out how much memory is present in the
+ * box so we initialize next_tag from it.
+ */
+ if (memory_upper != (unsigned long) NULL)
+ next_tag = memory_upper;
+
+ /* Else we rely on the fact that the first tag we create for
+ * a box for which we don't know how RAM it gots is a tag of
+ * type tag_memupper. This is ensured by the first entry in
+ * the defaults tag list for such a box (see identify.c).
+ * First we check this.
+ */
+ else {
+ /* Ok it's a memupper tag: we put it's value in
+ * memory_upper so launch() can pass it to the
+ * kernel in register a0 and we initialize next_tag.
+ */
+ next_tag = *(unsigned long *) data;
+ memory_upper = *((unsigned long *) data);
+ }
+ }
+
+ /* We put the tag structure. */
+ addr = next_tag - (sizeof (tag));
+
+ memcpy ((void *) addr, (void *) &t, (size_t) (sizeof (tag)));
+
+ /* We put the tag's data if any. */
+ if (size != 0) {
+ addr = addr - size;
+ memcpy ((void *) addr, data, (size_t) (t.size));
+ }
+
+ /*
+ * Set next_tag ready for the next tag creation.
+ */
+ next_tag = addr;
+ AddTagsEndSymbol();
+
+ return 0;
+}
+
+void SetUpBootInfo(void)
+{
+ unsigned long LongVar;
+ int atag;
+
+ /*
+ * This is hard coded here but will change when we have a
+ * Size mem routine.
+ */
+
+ /*
+ * 64mb of memory.
+ */
+
+ //mips_memory_upper = 0x84000000;
+
+
+#ifndef BOOTLOADER
+
+#if 0 /* You break'a the kernel I break'a ya face. -DaveM */
+
+ /* Eight meg of memory. */
+ mips_memory_upper = 0x80800000; /* XXX this appears to be unused -
+ this assignment is not present in the normal
+ $cvstree/linux/arch/mips/cobalt/setup.c */
+#endif
+#else
+#include "../../../../include/diagdefs.h"
+ mips_memory_upper = (unsigned long) kBootloaderMipsMemoryUpper;
+#endif
+
+ LongVar = mips_memory_upper;
+ atag = bi_TagAdd(tag_memupper, ULONGSIZE, &LongVar);
+
+ /* Here is the machine type.
+ */
+ LongVar = MACH_COBALT_27;
+ atag = bi_TagAdd(tag_machtype, ULONGSIZE, &LongVar);
+
+ LongVar = 0x80000000;
+ atag = bi_TagAdd(tag_memlower, ULONGSIZE, &LongVar);
+
+ LongVar = CPU_R4300;
+ atag = bi_TagAdd(tag_cputype, ULONGSIZE, &LongVar);
+
+ LongVar = MACH_GROUP_COBALT;
+ atag = bi_TagAdd(tag_machgroup, ULONGSIZE, &LongVar);
+
+ LongVar = 0;
+ atag = bi_TagAdd(tag_scache_size, ULONGSIZE, &LongVar);
+
+ LongVar = 48;
+ atag = bi_TagAdd(tag_tlb_entries, ULONGSIZE, &LongVar);
+
+ LongVar = 0;
+ atag = bi_TagAdd(tag_drive_info, ULONGSIZE, &LongVar);
+
+ LongVar = 0xe0800000;
+ atag = bi_TagAdd(tag_vram_base, ULONGSIZE, &LongVar);
+
+ LongVar = 0;
+ atag = bi_TagAdd(tag_dummy, 0, &LongVar);
+}
+
+void AddTagsEndSymbol(void)
+{
+ short X;
+ X = 1;
+}
+
+/*
+ * Oh shit, this is so crappy ...
+ */
+#include <linux/mm.h>
+#include <asm/pgtable.h>
+int my_cacheflush(unsigned long start, unsigned long size, unsigned int what)
+{
+ flush_cache_range(current->mm, start, start + size);
+ return 0;
+}
+
+
+/*
+ * The ROM set the flag to 0x1 to turn off output. This is interpreted
+ * as "valid", "no kernel output", and index '0' into the following
+ * tables. We overload entry '0' to specify a sensible default rate.
+ */
+static int cons_baud_int[] = { 9600, 0, 9600, 0, 0, 115200, 0, 0 };
+static int cons_baud_baud[] = { B9600, 0, B9600, 0, 0, B115200, 0, 0 };
+
+static union cobalt_cons_info
+cobalt_get_console_info(void)
+{
+ char board_id = 0;
+ static union cobalt_cons_info cons_info;
+ static int read_info = 0;
+ extern void add_init_env(char *);
+
+ if (read_info)
+ return cons_info;
+
+ VIA_PORT_WRITE(VIA_CMOS_ADDR, VIA_CMOS_CONSOLE_FLG);
+ cons_info.ccons_char = VIA_PORT_READ(VIA_CMOS_DATA);
+
+#if 0
+ printk("cobalt_get_console_info: read 0x%x from console flag\n",
+ cons_info.ccons_char);
+#endif
+
+ /*
+ * CMOS hasn't been initialized or baud rate isn't known.
+ * - read the board id and provide backwards compat.
+ */
+ if (cons_info.ccons_bits.valid != VIA_CMOS_CONS_VALID
+ || ! cons_baud_int[cons_info.ccons_bits.baud]
+ || ! cons_baud_baud[cons_info.ccons_bits.baud]) {
+ pcibios_read_config_byte(0, PCI_DEVSHFT(COBALT_PCICONF_VIA),
+ VIA_COBALT_BRD_ID_REG, &board_id);
+
+#if 0
+ printk("cobalt_get_console_info: read 0x%x from board config\n",
+ board_id);
+#endif
+
+ switch (VIA_COBALT_BRD_REG_to_ID(board_id)) {
+ case COBALT_BRD_ID_QUBE1:
+ cons_info.ccons_bits.baud = VIA_CMOS_CONS_115K;
+ cons_info.ccons_bits.kout = 1;
+ break;
+ case COBALT_BRD_ID_RAQ1:
+ cons_info.ccons_bits.baud = VIA_CMOS_CONS_9600;
+ cons_info.ccons_bits.kout = 1;
+ break;
+ case COBALT_BRD_ID_QUBE2:
+ cons_info.ccons_bits.baud = VIA_CMOS_CONS_9600;
+ cons_info.ccons_bits.kout = 0;
+ break;
+ case COBALT_BRD_ID_RAQ2:
+ cons_info.ccons_bits.baud = VIA_CMOS_CONS_9600;
+ cons_info.ccons_bits.kout = 1;
+ break;
+ }
+ cons_info.ccons_bits.valid = VIA_CMOS_CONS_VALID;
+ }
+
+ read_info = 1;
+
+#if defined(DEBUG_LOADER)
+ cons_info.ccons_bits.kout = 1;
+#endif
+
+ if (!cons_info.ccons_bits.kout) {
+ add_init_env("CONSOLE=/dev/null");
+ }
+
+#if 0
+ printk("cobalt_get_console_info: returning 0x%x\n",
+ cons_info.ccons_char);
+#endif
+
+ return cons_info;
+}
+
+int
+cobalt_cons_koutok(void)
+{
+ union cobalt_cons_info cons;
+
+ cons = cobalt_get_console_info();
+
+ return cons.ccons_bits.kout;
+}
+
+int
+cobalt_cons_baudbaud(void)
+{
+ union cobalt_cons_info cons;
+
+ cons = cobalt_get_console_info();
+
+ return cons_baud_baud[cons.ccons_bits.baud];
+}
+
+int
+cobalt_cons_baudint(void)
+{
+ union cobalt_cons_info cons;
+
+ cons = cobalt_get_console_info();
+
+ return cons_baud_int[cons.ccons_bits.baud];
+}
--- /dev/null
+/*
+ * Interrupt handling for the VIA ISA bridge.
+ *
+ * Everything the same ... just different ...
+ */
+#include <linux/kernel.h>
+#include <asm/cobalt.h>
+#include <asm/ptrace.h>
+#include <asm/io.h>
+
+extern asmlinkage void do_IRQ(int irq, struct pt_regs * regs);
+
+extern unsigned char cache_21;
+extern unsigned char cache_A1;
+
+/*
+ * (un)mask_irq, disable_irq() and enable_irq() only handle (E)ISA and
+ * PCI devices. Other onboard hardware needs specific routines.
+ */
+void mask_irq(unsigned int irq_nr)
+{
+ unsigned char mask;
+
+ mask = 1 << (irq_nr & 7);
+ if (irq_nr < 8) {
+ cache_21 |= mask;
+ outb(cache_21, 0x10000021);
+ } else {
+ cache_A1 |= mask;
+ outb(cache_A1, 0x100000a1);
+ }
+}
+
+void unmask_irq(unsigned int irq_nr)
+{
+ unsigned char mask;
+
+ mask = ~(1 << (irq_nr & 7));
+ if (irq_nr < 8) {
+ cache_21 &= mask;
+ outb(cache_21, 0x10000021);
+ } else {
+ cache_A1 &= mask;
+ outb(cache_A1, 0x100000a1);
+ }
+}
+
+asmlinkage void via_irq(struct pt_regs *regs)
+{
+ char mstat, sstat;
+
+ /* Read Master Status */
+ VIA_PORT_WRITE(0x20, 0x0C);
+ mstat = VIA_PORT_READ(0x20);
+
+ if (mstat < 0) {
+ mstat &= 0x7f;
+ if (mstat != 2) {
+ do_IRQ(mstat, regs);
+ VIA_PORT_WRITE(0x20, mstat | 0x20);
+ } else {
+ sstat = VIA_PORT_READ(0xA0);
+
+ /* Slave interrupt */
+ VIA_PORT_WRITE(0xA0, 0x0C);
+ sstat = VIA_PORT_READ(0xA0);
+
+ if (sstat < 0) {
+ do_IRQ((sstat + 8) & 0x7f, regs);
+ VIA_PORT_WRITE(0x20, 0x22);
+ VIA_PORT_WRITE(0xA0, (sstat & 0x7f) | 0x20);
+ } else {
+ printk("Spurious slave interrupt...\n");
+ }
+ }
+ } else
+ printk("Spurious master interrupt...");
+}
+
+asmlinkage void galileo_irq(struct pt_regs *regs)
+{
+ unsigned long irq_src = *((unsigned long *) 0xb4000c18);
+
+ /* Check for timer irq ... */
+ if (irq_src & 0x00000100) {
+ *((volatile unsigned long *) 0xb4000c18) = 0;
+ do_IRQ(0, regs);
+ } else
+ printk("Spurious Galileo interrupt...\n");
+}
--- /dev/null
+/* 8530 Serial Communications Controller Register definitions */
+#define FLAG 0x7e
+
+/* Write Register 0 */
+#define R0 0 /* Register selects */
+#define R1 1
+#define R2 2
+#define R3 3
+#define R4 4
+#define R5 5
+#define R6 6
+#define R7 7
+#define R8 8
+#define R9 9
+#define R10 10
+#define R11 11
+#define R12 12
+#define R13 13
+#define R14 14
+#define R15 15
+
+#define NULLCODE 0 /* Null Code */
+#define POINT_HIGH 0x8 /* Select upper half of registers */
+#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */
+#define SEND_ABORT 0x18 /* HDLC Abort */
+#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */
+#define RES_Tx_P 0x28 /* Reset TxINT Pending */
+#define ERR_RES 0x30 /* Error Reset */
+#define RES_H_IUS 0x38 /* Reset highest IUS */
+
+#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */
+#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */
+#define RES_EOM_L 0xC0 /* Reset EOM latch */
+
+/* Write Register 1 */
+
+#define EXT_INT_ENAB 0x1 /* Ext Int Enable */
+#define TxINT_ENAB 0x2 /* Tx Int Enable */
+#define PAR_SPEC 0x4 /* Parity is special condition */
+
+#define RxINT_DISAB 0 /* Rx Int Disable */
+#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */
+#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */
+#define INT_ERR_Rx 0x18 /* Int on error only */
+
+#define WT_RDY_RT 0x20 /* Wait/Ready on R/T */
+#define WT_FN_RDYFN 0x40 /* Wait/FN/Ready FN */
+#define WT_RDY_ENAB 0x80 /* Wait/Ready Enable */
+
+/* Write Register #2 (Interrupt Vector) */
+
+/* Write Register 3 */
+
+#define RxENABLE 0x1 /* Rx Enable */
+#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */
+#define ADD_SM 0x4 /* Address Search Mode (SDLC) */
+#define RxCRC_ENAB 0x8 /* Rx CRC Enable */
+#define ENT_HM 0x10 /* Enter Hunt Mode */
+#define AUTO_ENAB 0x20 /* Auto Enables */
+#define Rx5 0x0 /* Rx 5 Bits/Character */
+#define Rx7 0x40 /* Rx 7 Bits/Character */
+#define Rx6 0x80 /* Rx 6 Bits/Character */
+#define Rx8 0xc0 /* Rx 8 Bits/Character */
+
+/* Write Register 4 */
+
+#define PAR_ENA 0x1 /* Parity Enable */
+#define PAR_EVEN 0x2 /* Parity Even/Odd* */
+
+#define SYNC_ENAB 0 /* Sync Modes Enable */
+#define SB1 0x4 /* 1 stop bit/char */
+#define SB15 0x8 /* 1.5 stop bits/char */
+#define SB2 0xc /* 2 stop bits/char */
+
+#define MONSYNC 0 /* 8 Bit Sync character */
+#define BISYNC 0x10 /* 16 bit sync character */
+#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */
+#define EXTSYNC 0x30 /* External Sync Mode */
+
+#define X1CLK 0x0 /* x1 clock mode */
+#define X16CLK 0x40 /* x16 clock mode */
+#define X32CLK 0x80 /* x32 clock mode */
+#define X64CLK 0xC0 /* x64 clock mode */
+
+/* Write Register 5 */
+
+#define TxCRC_ENAB 0x1 /* Tx CRC Enable */
+#define RTS 0x2 /* RTS */
+#define SDLC_CRC 0x4 /* SDLC/CRC-16 */
+#define TxENAB 0x8 /* Tx Enable */
+#define SND_BRK 0x10 /* Send Break */
+#define Tx5 0x0 /* Tx 5 bits (or less)/character */
+#define Tx7 0x20 /* Tx 7 bits/character */
+#define Tx6 0x40 /* Tx 6 bits/character */
+#define Tx8 0x60 /* Tx 8 bits/character */
+#define DTR 0x80 /* DTR */
+
+/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
+
+/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
+
+/* Write Register 8 (transmit buffer) */
+
+/* Write Register 9 (Master interrupt control) */
+#define VIS 1 /* Vector Includes Status */
+#define NV 2 /* No Vector */
+#define DLC 4 /* Disable Lower Chain */
+#define MIE 8 /* Master Interrupt Enable */
+#define STATHI 0x10 /* Status high */
+#define NORESET 0 /* No reset on write to R9 */
+#define CHRB 0x40 /* Reset channel B */
+#define CHRA 0x80 /* Reset channel A */
+#define FHWRES 0xc0 /* Force hardware reset */
+
+/* Write Register 10 (misc control bits) */
+#define BIT6 1 /* 6 bit/8bit sync */
+#define LOOPMODE 2 /* SDLC Loop mode */
+#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */
+#define MARKIDLE 8 /* Mark/flag on idle */
+#define GAOP 0x10 /* Go active on poll */
+#define NRZ 0 /* NRZ mode */
+#define NRZI 0x20 /* NRZI mode */
+#define FM1 0x40 /* FM1 (transition = 1) */
+#define FM0 0x60 /* FM0 (transition = 0) */
+#define CRCPS 0x80 /* CRC Preset I/O */
+
+/* Write Register 11 (Clock Mode control) */
+#define TRxCXT 0 /* TRxC = Xtal output */
+#define TRxCTC 1 /* TRxC = Transmit clock */
+#define TRxCBR 2 /* TRxC = BR Generator Output */
+#define TRxCDP 3 /* TRxC = DPLL output */
+#define TRxCOI 4 /* TRxC O/I */
+#define TCRTxCP 0 /* Transmit clock = RTxC pin */
+#define TCTRxCP 8 /* Transmit clock = TRxC pin */
+#define TCBR 0x10 /* Transmit clock = BR Generator output */
+#define TCDPLL 0x18 /* Transmit clock = DPLL output */
+#define RCRTxCP 0 /* Receive clock = RTxC pin */
+#define RCTRxCP 0x20 /* Receive clock = TRxC pin */
+#define RCBR 0x40 /* Receive clock = BR Generator output */
+#define RCDPLL 0x60 /* Receive clock = DPLL output */
+#define RTxCX 0x80 /* RTxC Xtal/No Xtal */
+
+/* Write Register 12 (lower byte of baud rate generator time constant) */
+
+/* Write Register 13 (upper byte of baud rate generator time constant) */
+
+/* Write Register 14 (Misc control bits) */
+#define BRENABL 1 /* Baud rate generator enable */
+#define BRSRC 2 /* Baud rate generator source */
+#define DTRREQ 4 /* DTR/Request function */
+#define AUTOECHO 8 /* Auto Echo */
+#define LOOPBAK 0x10 /* Local loopback */
+#define SEARCH 0x20 /* Enter search mode */
+#define RMC 0x40 /* Reset missing clock */
+#define DISDPLL 0x60 /* Disable DPLL */
+#define SSBR 0x80 /* Set DPLL source = BR generator */
+#define SSRTxC 0xa0 /* Set DPLL source = RTxC */
+#define SFMM 0xc0 /* Set FM mode */
+#define SNRZI 0xe0 /* Set NRZI mode */
+
+/* Write Register 15 (external/status interrupt control) */
+#define ZCIE 2 /* Zero count IE */
+#define DCDIE 8 /* DCD IE */
+#define SYNCIE 0x10 /* Sync/hunt IE */
+#define CTSIE 0x20 /* CTS IE */
+#define TxUIE 0x40 /* Tx Underrun/EOM IE */
+#define BRKIE 0x80 /* Break/Abort IE */
+
+
+/* Read Register 0 */
+#define Rx_CH_AV 0x1 /* Rx Character Available */
+#define ZCOUNT 0x2 /* Zero count */
+#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */
+#define DCD 0x8 /* DCD */
+#define SYNC_HUNT 0x10 /* Sync/hunt */
+#define CTS 0x20 /* CTS */
+#define TxEOM 0x40 /* Tx underrun */
+#define BRK_ABRT 0x80 /* Break/Abort */
+
+/* Read Register 1 */
+#define ALL_SNT 0x1 /* All sent */
+/* Residue Data for 8 Rx bits/char programmed */
+#define RES3 0x8 /* 0/3 */
+#define RES4 0x4 /* 0/4 */
+#define RES5 0xc /* 0/5 */
+#define RES6 0x2 /* 0/6 */
+#define RES7 0xa /* 0/7 */
+#define RES8 0x6 /* 0/8 */
+#define RES18 0xe /* 1/8 */
+#define RES28 0x0 /* 2/8 */
+/* Special Rx Condition Interrupts */
+#define PAR_ERR 0x10 /* Parity error */
+#define Rx_OVR 0x20 /* Rx Overrun Error */
+#define CRC_ERR 0x40 /* CRC/Framing Error */
+#define END_FR 0x80 /* End of Frame (SDLC) */
+
+/* Read Register 2 (channel b only) - Interrupt vector */
+
+/* Read Register 3 (interrupt pending register) ch a only */
+#define CHBEXT 0x1 /* Channel B Ext/Stat IP */
+#define CHBTxIP 0x2 /* Channel B Tx IP */
+#define CHBRxIP 0x4 /* Channel B Rx IP */
+#define CHAEXT 0x8 /* Channel A Ext/Stat IP */
+#define CHATxIP 0x10 /* Channel A Tx IP */
+#define CHARxIP 0x20 /* Channel A Rx IP */
+
+/* Read Register 8 (receive data register) */
+
+/* Read Register 10 (misc status bits) */
+#define ONLOOP 2 /* On loop */
+#define LOOPSEND 0x10 /* Loop sending */
+#define CLK2MIS 0x40 /* Two clocks missing */
+#define CLK1MIS 0x80 /* One clock missing */
+
+/* Read Register 12 (lower byte of baud rate generator constant) */
+
+/* Read Register 13 (upper byte of baud rate generator constant) */
+
+/* Read Register 15 (value of WR 15) */
-# $Id: config.in,v 1.46 2000/03/26 22:59:01 ralf Exp $
+#
# For a description of the syntax of this configuration file,
# see Documentation/kbuild/config-language.txt.
#
@@ -11,10+11,14 @@ endmenu
mainmenu_option next_comment
comment 'Machine selection'
-bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61
bool 'Support for Algorithmics P4032 (EXPERIMENTAL)' CONFIG_ALGOR_P4032
bool 'Support for BAGET MIPS series (EXPERIMENTAL)' CONFIG_BAGET_MIPS
+ bool 'Support for Cobalt Server' CONFIG_COBALT_MICRO_SERVER
+ if [ "$CONFIG_COBALT_MICRO_SERVER" = "y" ]; then
+ bool ' Support for 2800' CONFIG_COBALT_28
+ fi
bool 'Support for DECstations (EXPERIMENTAL)' CONFIG_DECSTATION
bool 'Support for NEC DDB Vrc-5074 (EXPERIMENTAL)' CONFIG_DDB5074
fi
@@ -27,10+31,11 @@ bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI # Select some configuration options automatically for certain systems.
#
unset CONFIG_ARC32
-unset CONFIG_PCI
unset CONFIG_ISA
+unset CONFIG_PCI
unset CONFIG_MIPS_JAZZ
unset CONFIG_VIDEO_G364
+unset CONFIG_PC_KEYB
define_bool CONFIG_SBUS n
if [ "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \
"$CONFIG_OLIVETTI_M700" = "y" ]; then
define_bool CONFIG_ARC32 y
- define_bool CONFIG_HAVE_IO_PORTS y
+ define_bool CONFIG_ISA y
define_bool CONFIG_FB y
define_bool CONFIG_FB_G364 y
define_bool CONFIG_MIPS_JAZZ y
+ define_bool CONFIG_PC_KEYB y
fi
if [ "$CONFIG_ACER_PICA_61" = "y" ]; then
define_bool CONFIG_ARC32 y
- define_bool CONFIG_HAVE_IO_PORTS y
+ define_bool CONFIG_ISA y
define_bool CONFIG_MIPS_JAZZ y
+ define_bool CONFIG_PC_KEYB y
+fi
+if [ "$CONFIG_COBALT_MICRO_SERVER" = "y" ]; then
+ define_bool CONFIG_ISA n
+ define_bool CONFIG_COBALT_27 y
+ define_bool CONFIG_COBALT_LCD y
+ define_bool CONFIG_COBALT_SERIAL y
+ define_bool CONFIG_PCI y
fi
if [ "$CONFIG_SGI_IP22" = "y" ]; then
define_bool CONFIG_ARC32 y
+ define_bool CONFIG_PC_KEYB y
+ define_bool CONFIG_SGI y
fi
if [ "$CONFIG_SNI_RM200_PCI" = "y" ]; then
define_bool CONFIG_ARC32 y
- define_bool CONFIG_HAVE_IO_PORTS y
+ define_bool CONFIG_PCI y
+ define_bool CONFIG_ISA y
+ define_bool CONFIG_PC_KEYB y
fi
if [ "$CONFIG_DDB5074" = "y" ]; then
- define_bool CONFIG_HAVE_IO_PORTS y
define_bool CONFIG_ISA y
define_bool CONFIG_PCI y
fi
@@ -85,7+102,7 @@ mainmenu_option next_comment R8000 CONFIG_CPU_R8000 \
R10000 CONFIG_CPU_R10000" R4x00
- bool 'Advanced CPU Config' CONFIG_CPU_ADVANCED
+ bool 'Override CPU Options' CONFIG_CPU_ADVANCED
if [ "$CONFIG_CPU_ADVANCED" = "y" ]; then
bool ' ll/sc Instructions available' CONFIG_CPU_HAS_LLSC
@@ -149,6+166,9 @@ comment 'General setup'
if [ "$CONFIG_DECSTATION" = "y" ]; then
bool 'TURBOchannel support' CONFIG_TC
+# if [ "$CONFIG_TC" = "y" ]; then
+# bool ' Access.Bus support' CONFIG_ACCESSBUS
+# fi
fi
endmenu
@@ -170,13+190,13 @@ if [ "$CONFIG_NET" = "y" ]; then source net/Config.in
fi
-if [ "$CONFIG_DECSTATION" != "n" -a \
- "$CONFIG_SGI_IP22" != "n" ]; then
+if [ "$CONFIG_DECSTATION" != "y" -a \
+ "$CONFIG_SGI_IP22" != "y" ]; then
source drivers/telephony/Config.in
fi
-if [ "$CONFIG_SGI_IP22" != "n" -a \
- "$CONFIG_DECSTATION" != "n" ]; then
+if [ "$CONFIG_SGI_IP22" != "y" -a \
+ "$CONFIG_DECSTATION" != "y" ]; then
mainmenu_option next_comment
comment 'ATA/IDE/MFM/RLL support'
@@ -202,8+222,8 @@ if [ "$CONFIG_SCSI" != "n" ]; then fi
endmenu
-if [ "$CONFIG_DECSTATION" != "n" -a \
- "$CONFIG_SGI_IP22" != "n" ]; then
+if [ "$CONFIG_DECSTATION" != "y" -a \
+ "$CONFIG_SGI_IP22" != "y" ]; then
source drivers/i2o/Config.in
fi
@@ -270,8+290,8 @@ if [ "$CONFIG_ISA" = "y" -o "$CONFIG_PCI" = "y" ]; then endmenu
fi
-if [ "$CONFIG_DECSTATION" != "n" -a \
- "$CONFIG_SGI_IP22" != "n" ]; then
+if [ "$CONFIG_DECSTATION" != "y" -a \
+ "$CONFIG_SGI_IP22" != "y" ]; then
source drivers/char/Config.in
fi
@@ -295,8+315,9 @@ if [ "$CONFIG_DECSTATION" = "y" ]; then if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
fi
- bool 'Keyboard Support' CONFIG_KEYBOARD
- bool 'Mouse Support' CONFIG_MOUSE
+# if [ "$CONFIG_ACCESSBUS" = "y" ]; then
+# bool 'MAXINE Access.Bus mouse (VSXXX-BB/GB) support' CONFIG_DTOP_MOUSE
+# fi
bool 'Enhanced Real Time Clock Support' CONFIG_RTC
endmenu
fi
@@ -320,6+320,13 @@ int pcibios_enable_resources(struct pci_dev *dev) int idx;
struct resource *r;
+ /*
+ * Don't touch the Nile 4
+ */
+ if (dev->vendor == PCI_VENDOR_ID_NEC &&
+ dev->device == PCI_DEVICE_ID_NEC_NILE4)
+ return 0;
+
pci_read_config_word(dev, PCI_COMMAND, &cmd);
old_cmd = cmd;
for(idx=0; idx<6; idx++) {
#include <linux/mc146818rtc.h>
#include <linux/pc_keyb.h>
#include <linux/pci.h>
+#include <linux/ide.h>
#include <asm/addrspace.h>
#include <asm/bcache.h>
@@ -38,6+39,7 @@ extern void breakpoint(void); extern void console_setup(char *);
#endif
+extern struct ide_ops std_ide_ops;
extern struct rtc_ops ddb_rtc_ops;
static void (*back_to_prom)(void) = (void (*)(void))0xbfc00000;
@@ -107,6+109,9 @@ void __init ddb_setup(void) _machine_halt = ddb_machine_halt;
_machine_power_off = ddb_machine_power_off;
+#ifdef CONFIG_BLK_DEV_IDE
+ ide_ops = &std_ide_ops;
+#endif
rtc_ops = &ddb_rtc_ops;
/* Reboot on panic */
@@ -155,6+155,6 @@ void prom_free_prom_memory (void) addr += PAGE_SIZE;
}
- printk("Freeing unused PROM memory: %dk freed\n",
+ printk("Freeing unused PROM memory: %ldk freed\n",
(end - PAGE_SIZE) >> 10);
}
@@ -13,6+13,7 @@ CONFIG_EXPERIMENTAL=y # CONFIG_ACER_PICA_61 is not set
# CONFIG_ALGOR_P4032 is not set
# CONFIG_BAGET_MIPS is not set
+# CONFIG_COBALT_MICRO_SERVER is not set
# CONFIG_DECSTATION is not set
# CONFIG_DDB5074 is not set
# CONFIG_MIPS_MAGNUM_4000 is not set
@@ -21,6+22,8 @@ CONFIG_SGI_IP22=y # CONFIG_SNI_RM200_PCI is not set
# CONFIG_SBUS is not set
CONFIG_ARC32=y
+CONFIG_PC_KEYB=y
+CONFIG_SGI=y
# CONFIG_ISA is not set
# CONFIG_PCI is not set
@@ -65,6+68,11 @@ CONFIG_KMOD=y # CONFIG_PCMCIA is not set
#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
@@ -72,17+80,14 @@ CONFIG_KMOD=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 is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_LVM is not set
# CONFIG_BLK_DEV_MD is not set
# CONFIG_MD_LINEAR is not set
# CONFIG_MD_RAID0 is not set
-# CONFIG_RAID15_DANGEROUS is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_INITRD is not set
@@ -121,9+126,9 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
# CONFIG_LLC is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -232,6+237,7 @@ CONFIG_AUTOFS4_FS=y # CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_RAMFS is not set
CONFIG_ISO9660_FS=y
#
# Code maturity level options
#
-# CONFIG_EXPERIMENTAL is not set
+CONFIG_EXPERIMENTAL=y
#
# Machine selection
#
+# CONFIG_ACER_PICA_61 is not set
+# CONFIG_ALGOR_P4032 is not set
+# CONFIG_BAGET_MIPS is not set
+CONFIG_COBALT_MICRO_SERVER=y
+CONFIG_COBALT_28=y
+# CONFIG_DECSTATION is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_MIPS_MAGNUM_4000 is not set
+# CONFIG_OLIVETTI_M700 is not set
# CONFIG_SGI_IP22 is not set
-CONFIG_SGI_IP27=y
-# CONFIG_SGI_SN0_N_MODE is not set
-# CONFIG_DISCONTIGMEM is not set
-# CONFIG_SMP is not set
-CONFIG_BOOT_ELF64=y
-CONFIG_ARC64=y
-CONFIG_COHERENT_IO=y
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SBUS is not set
+# CONFIG_ISA is not set
+CONFIG_COBALT_27=y
+CONFIG_COBALT_LCD=y
+CONFIG_COBALT_SERIAL=y
CONFIG_PCI=y
-CONFIG_QL_ISP_A64=y
# CONFIG_ISA is not set
-# CONFIG_SBUS is not set
#
# CPU selection
#
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_R6000 is not set
# CONFIG_CPU_R4300 is not set
# CONFIG_CPU_R4X00 is not set
# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_NEVADA is not set
+CONFIG_CPU_NEVADA=y
# CONFIG_CPU_R8000 is not set
-CONFIG_CPU_R10000=y
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_WB is not set
#
# General setup
#
-# CONFIG_MIPS_INSANE_LARGE is not set
-# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_KCORE_ELF=y
+CONFIG_ELF_KERNEL=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
CONFIG_NET=y
CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
-CONFIG_BINFMT_ELF=y
-CONFIG_MIPS32_COMPAT=y
-CONFIG_BINFMT_ELF32=y
-# CONFIG_BINFMT_MISC is not set
#
-# Loadable module support
+# Parallel port support
#
+# CONFIG_PARPORT is not set
CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
+CONFIG_MODVERSIONS=y
CONFIG_KMOD=y
-CONFIG_PCI_NAMES=y
+# CONFIG_PCMCIA is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
#
# Block devices
@@ -66,17+81,18 @@ CONFIG_PCI_NAMES=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 is not set
+CONFIG_BLK_DEV_LOOP=m
# 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_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
# CONFIG_MD_RAID0 is not set
-# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_BOOT is not set
+# CONFIG_AUTODETECT_RAID is not set
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_INITRD is not set
#
@@ -86,30+102,49 @@ CONFIG_PCI_NAMES=y # CONFIG_NETLINK is not set
# CONFIG_NETFILTER is not set
# CONFIG_FILTER is not set
-CONFIG_UNIX=y
+# CONFIG_UNIX is not set
CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP 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 is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_PIMSM_V1 is not set
+# CONFIG_IP_PIMSM_V2 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 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+# CONFIG_SPX is not set
+CONFIG_ATALK=m
# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_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
#
# Telephony Support
@@ -134,16+169,18 @@ CONFIG_SCSI=y #
CONFIG_BLK_DEV_SD=y
CONFIG_SD_EXTRA_DEVS=40
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_BLK_DEV_SR is not set
-# CONFIG_CHR_DEV_SG is not set
+CONFIG_CHR_DEV_ST=m
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_SR_EXTRA_DEVS=2
+CONFIG_CHR_DEV_SG=m
#
# 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 is not set
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
#
@@ -155,7+192,11 @@ CONFIG_SD_EXTRA_DEVS=40 # CONFIG_SCSI_AHA152X is not set
# CONFIG_SCSI_AHA1542 is not set
# CONFIG_SCSI_AHA1740 is not set
-# CONFIG_SCSI_AIC7XXX is not set
+CONFIG_SCSI_AIC7XXX=y
+# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
+# CONFIG_AIC7XXX_PROC_STATS is not set
+CONFIG_AIC7XXX_RESET_DELAY=5
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
# CONFIG_SCSI_AM53C974 is not set
@@ -171,25+212,30 @@ CONFIG_SD_EXTRA_DEVS=40 # CONFIG_SCSI_GENERIC_NCR5380 is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM is not set
# CONFIG_SCSI_NCR53C406A is not set
# CONFIG_SCSI_SYM53C416 is not set
# CONFIG_SCSI_SIM710 is not set
# CONFIG_SCSI_NCR53C7xx is not set
-# CONFIG_SCSI_NCR53C8XX is not set
+CONFIG_SCSI_NCR53C8XX=y
# CONFIG_SCSI_SYM53C8XX is not set
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4
+CONFIG_SCSI_NCR53C8XX_SYNC=5
+# CONFIG_SCSI_NCR53C8XX_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=y
+# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_T128 is not set
# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_DEBUG is not set
#
# I2O device support
@@ -210,7+256,12 @@ CONFIG_NETDEVICES=y # ARCnet devices
#
# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_APPLETALK is not set
+CONFIG_DUMMY=m
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_NET_SB1000 is not set
@@ -219,11+270,11 @@ CONFIG_NETDEVICES=y # Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
-CONFIG_SGI_IOC3_ETH=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_AT1700 is not set
# CONFIG_DEPCA is not set
# CONFIG_NET_ISA is not set
# CONFIG_NET_PCI is not set
@@ -232,12+283,22 @@ CONFIG_SGI_IOC3_ETH=y #
# Ethernet (1000 Mbit)
#
+# CONFIG_YELLOWFIN is not set
# CONFIG_ACENIC is not set
# CONFIG_SK98LIN is not set
# CONFIG_FDDI is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# 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
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
#
# Wireless LAN (non-hamradio)
@@ -249,6+310,8 @@ CONFIG_SGI_IOC3_ETH=y #
# CONFIG_TR is not set
# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
#
# Wan interfaces
@@ -256,19+319,81 @@ CONFIG_SGI_IOC3_ETH=y # CONFIG_WAN is not set
#
-# Amateur Radio support
+# ISDN subsystem
#
-# CONFIG_HAMRADIO is not set
+CONFIG_ISDN=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_ISDN_AUDIO=y
+# CONFIG_ISDN_TTY_FAX is not set
#
-# IrDA (infrared) support
+# ISDN feature submodules
#
-# CONFIG_IRDA is not set
+# CONFIG_ISDN_DRV_LOOP is not set
+# CONFIG_ISDN_DIVERSION is not set
#
-# ISDN subsystem
+# low-level hardware drivers
+#
+
+#
+# Passive ISDN cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+# CONFIG_HISAX_NO_SENDCOMPLETE is not set
+# CONFIG_HISAX_NO_LLC is not set
+# CONFIG_HISAX_NO_KEYPAD is not set
+CONFIG_HISAX_1TR6=y
+
+#
+# HiSax supported cards
#
-# CONFIG_ISDN is not set
+# CONFIG_HISAX_16_0 is not set
+# CONFIG_HISAX_16_3 is not set
+# CONFIG_HISAX_TELESPCI is not set
+# CONFIG_HISAX_S0BOX is not set
+# CONFIG_HISAX_AVM_A1 is not set
+# CONFIG_HISAX_FRITZPCI is not set
+# CONFIG_HISAX_AVM_A1_PCMCIA is not set
+CONFIG_HISAX_ELSA=y
+# CONFIG_HISAX_IX1MICROR2 is not set
+# CONFIG_HISAX_DIEHLDIVA is not set
+# CONFIG_HISAX_ASUSCOM is not set
+# CONFIG_HISAX_TELEINT is not set
+# CONFIG_HISAX_HFCS is not set
+# CONFIG_HISAX_SEDLBAUER is not set
+# CONFIG_HISAX_SPORTSTER is not set
+# CONFIG_HISAX_MIC is not set
+# CONFIG_HISAX_NETJET is not set
+# CONFIG_HISAX_NICCY is not set
+# CONFIG_HISAX_ISURF is not set
+# CONFIG_HISAX_HSTSAPHIR is not set
+# CONFIG_HISAX_BKM_A4T is not set
+# CONFIG_HISAX_SCT_QUADRO is not set
+# CONFIG_HISAX_GAZEL is not set
+# CONFIG_HISAX_HFC_PCI is not set
+# CONFIG_HISAX_W6692 is not set
+# CONFIG_HISAX_HFC_SX is not set
+
+#
+# Active ISDN cards
+#
+# CONFIG_ISDN_DRV_ICN is not set
+# CONFIG_ISDN_DRV_PCBIT is not set
+# CONFIG_ISDN_DRV_SC is not set
+# CONFIG_ISDN_DRV_ACT2000 is not set
+# CONFIG_ISDN_DRV_EICON is not set
+# CONFIG_ISDN_CAPI is not set
+# CONFIG_ISDN_CAPI_MIDDLEWARE is not set
+# CONFIG_HYSDN is not set
#
# Old CD-ROM drivers (not SCSI, not IDE)
@@ -279,13+404,10 @@ CONFIG_SGI_IOC3_ETH=y # Character devices
#
# CONFIG_VT is not set
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL is not set
# CONFIG_SERIAL_EXTENDED is not set
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_UNIX98_PTYS is not set
-# CONFIG_PRINTER is not set
-# CONFIG_PPDEV is not set
#
# I2C support
@@ -308,8+430,9 @@ CONFIG_SERIAL_CONSOLE=y # Watchdog Cards
#
# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
+CONFIG_RTC=y
#
# Video For Linux
@@ -325,11+448,12 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_FTAPE is not set
# CONFIG_DRM is not set
# CONFIG_DRM_TDFX is not set
+# CONFIG_AGP is not set
#
# File systems
#
-# CONFIG_QUOTA is not set
+CONFIG_QUOTA=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_ADFS_FS is not set
@@ -337,14+461,15 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_BFS_FS is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_VFAT_FS=m
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_RAMFS is not set
-# CONFIG_ISO9660_FS is not set
+CONFIG_ISO9660_FS=m
# CONFIG_JOLIET is not set
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
@@ -372,12+497,12 @@ CONFIG_EXT2_FS=y # CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
-CONFIG_ROOT_NFS=y
+# CONFIG_ROOT_NFS is not set
# CONFIG_NFSD is not set
# CONFIG_NFSD_V3 is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
-# CONFIG_SMB_FS is not set
+CONFIG_SMB_FS=m
# CONFIG_NCP_FS is not set
# CONFIG_NCPFS_PACKET_SIGNING is not set
# CONFIG_NCPFS_IOCTL_LOCKING is not set
@@ -393,18+518,41 @@ CONFIG_LOCKD=y #
# Partition Types
#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-# CONFIG_MSDOS_PARTITION is not set
-CONFIG_SGI_PARTITION=y
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_NLS is not set
-CONFIG_KCORE_ELF=y
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_ISO8859_9=m
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+CONFIG_NLS_KOI8_R=m
#
# Sound
@@ -419,7+567,6 @@ CONFIG_KCORE_ELF=y #
# Kernel hacking
#
-CONFIG_CROSSCOMPILE=y
+# CONFIG_CROSSCOMPILE is not set
# CONFIG_MIPS_FPE_MODULE is not set
-# CONFIG_REMOTE_DEBUG is not set
# CONFIG_MAGIC_SYSRQ is not set
@@ -13,6+13,7 @@ CONFIG_EXPERIMENTAL=y # CONFIG_ACER_PICA_61 is not set
# CONFIG_ALGOR_P4032 is not set
# CONFIG_BAGET_MIPS is not set
+# CONFIG_COBALT_MICRO_SERVER is not set
CONFIG_DECSTATION=y
# CONFIG_DDB5074 is not set
# CONFIG_MIPS_MAGNUM_4000 is not set
@@ -63,6+64,11 @@ CONFIG_TC=y # CONFIG_PCMCIA is not set
#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
@@ -70,17+76,14 @@ CONFIG_TC=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 is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_LVM is not set
# CONFIG_BLK_DEV_MD is not set
# CONFIG_MD_LINEAR is not set
# CONFIG_MD_RAID0 is not set
-# CONFIG_RAID15_DANGEROUS is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_INITRD is not set
@@ -119,9+122,9 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
# CONFIG_LLC is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -212,8+215,6 @@ CONFIG_SERIAL=y CONFIG_ZS=y
CONFIG_SERIAL_CONSOLE=y
# CONFIG_UNIX98_PTYS is not set
-# CONFIG_KEYBOARD is not set
-# CONFIG_MOUSE is not set
# CONFIG_RTC is not set
#
@@ -232,6+233,7 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_RAMFS is not set
# CONFIG_ISO9660_FS is not set
@@ -13,6+13,7 @@ CONFIG_EXPERIMENTAL=y # CONFIG_ACER_PICA_61 is not set
# CONFIG_ALGOR_P4032 is not set
# CONFIG_BAGET_MIPS is not set
+# CONFIG_COBALT_MICRO_SERVER is not set
# CONFIG_DECSTATION is not set
# CONFIG_DDB5074 is not set
# CONFIG_MIPS_MAGNUM_4000 is not set
@@ -21,6+22,8 @@ CONFIG_SGI_IP22=y # CONFIG_SNI_RM200_PCI is not set
# CONFIG_SBUS is not set
CONFIG_ARC32=y
+CONFIG_PC_KEYB=y
+CONFIG_SGI=y
# CONFIG_ISA is not set
# CONFIG_PCI is not set
@@ -65,6+68,11 @@ CONFIG_KMOD=y # CONFIG_PCMCIA is not set
#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
@@ -72,17+80,14 @@ CONFIG_KMOD=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 is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_LVM is not set
# CONFIG_BLK_DEV_MD is not set
# CONFIG_MD_LINEAR is not set
# CONFIG_MD_RAID0 is not set
-# CONFIG_RAID15_DANGEROUS is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_INITRD is not set
@@ -121,9+126,9 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
# CONFIG_LLC is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -232,6+237,7 @@ CONFIG_AUTOFS4_FS=y # CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_RAMFS is not set
CONFIG_ISO9660_FS=y
#
# Code maturity level options
#
-# CONFIG_EXPERIMENTAL is not set
+CONFIG_EXPERIMENTAL=y
#
# Machine selection
#
-CONFIG_SGI_IP22=y
-# CONFIG_SGI_IP27 is not set
-CONFIG_BOOT_ELF32=y
-CONFIG_ARC32=y
-CONFIG_BOARD_SCACHE=y
-CONFIG_ARC_MEMORY=y
-# CONFIG_ISA is not set
-# CONFIG_PCI is not set
+# CONFIG_ACER_PICA_61 is not set
+# CONFIG_ALGOR_P4032 is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_COBALT_MICRO_SERVER is not set
+# CONFIG_DECSTATION is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_MIPS_MAGNUM_4000 is not set
+# CONFIG_OLIVETTI_M700 is not set
+# CONFIG_SGI_IP22 is not set
+CONFIG_SNI_RM200_PCI=y
# CONFIG_SBUS is not set
+CONFIG_ARC32=y
+CONFIG_PCI=y
+CONFIG_ISA=y
+CONFIG_PC_KEYB=y
#
# CPU selection
#
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_R6000 is not set
# CONFIG_CPU_R4300 is not set
# CONFIG_CPU_R4X00 is not set
CONFIG_CPU_R5000=y
# CONFIG_CPU_NEVADA is not set
# CONFIG_CPU_R8000 is not set
# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_WB is not set
#
# General setup
#
-# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_KCORE_ELF=y
+CONFIG_ELF_KERNEL=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
CONFIG_NET=y
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
-CONFIG_SYSVIPC=y
+# CONFIG_PCI_NAMES is not set
+# CONFIG_SYSVIPC is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_MIPS32_COMPAT is not set
-# CONFIG_BINFMT_MISC is not set
#
-# Loadable module support
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Plug and Play configuration
#
-# CONFIG_MODULES is not set
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
#
# Block devices
#
-# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_FD=y
# 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 is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_LVM is not set
# CONFIG_BLK_DEV_MD is not set
# CONFIG_MD_LINEAR is not set
# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_INITRD is not set
#
# Networking options
#
-# CONFIG_PACKET is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
# CONFIG_NETLINK is not set
# CONFIG_NETFILTER is not set
# CONFIG_FILTER is not set
@@ -81,9+107,7 @@ CONFIG_UNIX=y CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP 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
@@ -93,7+117,10 @@ CONFIG_IP_PNP_BOOTP=y #
# (it is safe to leave these untouched)
#
-CONFIG_SKB_LARGE=y
+# CONFIG_SKB_LARGE is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
#
#
@@ -101,6+128,19 @@ CONFIG_SKB_LARGE=y # CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_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
#
# Telephony Support
@@ -124,6+164,7 @@ CONFIG_SKB_LARGE=y # I2O device support
#
# CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
# CONFIG_I2O_BLOCK is not set
# CONFIG_I2O_LAN is not set
# CONFIG_I2O_SCSI is not set
@@ -132,58+173,7 @@ CONFIG_SKB_LARGE=y #
# Network device support
#
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_NET_SB1000 is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_FDDI is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-CONFIG_SGISEEQ=y
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
+# CONFIG_NETDEVICES is not set
#
# ISDN subsystem
@@ -204,8+194,6 @@ CONFIG_VT_CONSOLE=y # CONFIG_SERIAL_EXTENDED is not set
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_UNIX98_PTYS is not set
-# CONFIG_PRINTER is not set
-# CONFIG_PPDEV is not set
#
# I2C support
@@ -228,6+216,7 @@ CONFIG_VT_CONSOLE=y # Watchdog Cards
#
# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
@@ -245,6+234,7 @@ CONFIG_VT_CONSOLE=y # CONFIG_FTAPE is not set
# CONFIG_DRM is not set
# CONFIG_DRM_TDFX is not set
+# CONFIG_AGP is not set
#
# File systems
@@ -262,6+252,7 @@ CONFIG_VT_CONSOLE=y # CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_RAMFS is not set
# CONFIG_ISO9660_FS is not set
@@ -290,13+281,13 @@ CONFIG_EXT2_FS=y # Network File Systems
#
# CONFIG_CODA_FS is not set
-CONFIG_NFS_FS=y
+# CONFIG_NFS_FS is not set
# CONFIG_NFS_V3 is not set
-CONFIG_ROOT_NFS=y
+# CONFIG_ROOT_NFS is not set
# CONFIG_NFSD is not set
# CONFIG_NFSD_V3 is not set
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
+# CONFIG_SUNRPC is not set
+# CONFIG_LOCKD is not set
# CONFIG_SMB_FS is not set
# CONFIG_NCP_FS is not set
# CONFIG_NCPFS_PACKET_SIGNING is not set
@@ -313,27+304,36 @@ CONFIG_LOCKD=y #
# Partition Types
#
-# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+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=y
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
# CONFIG_NLS is not set
#
# Console drivers
#
-CONFIG_SGI_NEWPORT_CONSOLE=y
-CONFIG_FONT_8x16=y
-CONFIG_KCORE_ELF=y
+CONFIG_VGA_CONSOLE=y
+# CONFIG_FB is not set
#
-# Sound
+# Frame-buffer support
#
-# CONFIG_SOUND is not set
+# CONFIG_FB is not set
#
-# SGI devices
+# Sound
#
-# CONFIG_SGI_SERIAL is not set
-CONFIG_SGI_DS1286=y
+# CONFIG_SOUND is not set
#
# USB support
@@ -344,5+344,5 @@ CONFIG_SGI_DS1286=y # Kernel hacking
#
CONFIG_CROSSCOMPILE=y
-# CONFIG_REMOTE_DEBUG is not set
+# CONFIG_MIPS_FPE_MODULE is not set
# CONFIG_MAGIC_SYSRQ is not set
-# $Id: Makefile,v 1.14 1999/10/09 00:00:58 ralf Exp $
#
# Makefile for the Linux/MIPS kernel.
#
#
# SGIs have very different interrupt/timer hardware.
#
-ifndef CONFIG_SGI_IP22
- ifndef CONFIG_DECSTATION
- ifndef CONFIG_BAGET_MIPS
- O_OBJS += time.o
+ifndef CONFIG_DECSTATION
+ ifndef CONFIG_BAGET_MIPS
+ O_OBJS += time.o
+ ifndef CONFIG_SGI_IP22
OX_OBJS += irq.o
endif
endif
* in the kernel space a lot easier. So far this handler in the released
* kernel source is just a dummy.
*
- * Copyright (C) 1997 Ralf Baechle
- *
- * $Id: fpe.c,v 1.3 1998/04/05 11:23:50 ralf Exp $
+ * Copyright (C) 1997, 2000 Ralf Baechle
*/
#include <linux/kernel.h>
#include <linux/module.h>
@@ -24,7+22,6 @@ MODULE_SUPPORTED_DEVICE("MIPS FPU");
static void do_fpe(struct pt_regs *regs, unsigned int fcr31)
{
- lock_kernel();
#ifdef CONF_DEBUG_EXCEPTIONS
show_regs(regs);
#endif
@@ -34,7+31,6 @@ static void do_fpe(struct pt_regs *regs, unsigned int fcr31) goto out;
force_sig(SIGFPE, current);
out:
- unlock_kernel();
}
/*
END(except_vec0_r4600)
/* TLB refill, EXL == 0, R52x0 "Nevada" version */
+ /*
+ * This version has a bug workaround for the Nevada. It seems
+ * as if under certain circumstances the move from cp0_context
+ * might produce a bogus result when the mfc0 instruction and
+ * it's consumer are in a different cacheline or a load instruction,
+ * probably any memory reference, is between them. This is
+ * potencially slower than the R4000 version, so we use this
+ * special version.
+ */
.set noreorder
.set noat
LEAF(except_vec0_nevada)
-/* $Id: irixelf.c,v 1.28 2000/03/23 02:25:42 ralf Exp $
- *
+/*
* irixelf.c: Code to load IRIX ELF executables which conform to
* the MIPS ABI.
*
@@ -467,7+466,6 @@ static inline int look_for_irix_interpreter(char **name, return 0;
dput_and_out:
- allow_write_access(file);
fput(file);
out:
kfree(*name);
@@ -771,7+769,7 @@ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs) #endif
start_thread(regs, elf_entry, bprm->p);
- if (current->flags & PF_PTRACED)
+ if (current->ptrace & PT_PTRACED)
send_sig(SIGTRAP, current, 0);
return 0;
out:
@@ -1284,7+1282,7 @@ static int __init init_irix_binfmt(void) return register_binfmt(&irix_format);
}
-static void __exit cleanup_module(void)
+static void __exit exit_irix_binfmt(void)
{
/* Remove the IRIX ELF loaders. */
unregister_binfmt(&irix_format);
-/* $Id: irixioctl.c,v 1.6 1999/02/06 05:12:56 adevries Exp $
+/*
* irixioctl.c: A fucking mess...
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
@@ -48,7+48,7 @@ static struct tty_struct *get_tty(int fd)
static struct tty_struct *get_real_tty(struct tty_struct *tp)
{
- if(tp->driver.type == TTY_DRIVER_TYPE_PTY &&
+ if (tp->driver.type == TTY_DRIVER_TYPE_PTY &&
tp->driver.subtype == PTY_TYPE_MASTER)
return tp->link;
else
@@ -61,7+61,6 @@ asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg) mm_segment_t old_fs;
int error = 0;
- lock_kernel();
#ifdef DEBUG_IOCTLS
printk("[%s:%d] irix_ioctl(%d, ", current->comm, current->pid, fd);
#endif
@@ -87,7+86,7 @@ asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg) old_fs = get_fs(); set_fs(get_ds());
error = sys_ioctl(fd, TCGETS, (unsigned long) &kt);
set_fs(old_fs);
- if(error)
+ if (error)
break;
__put_user(kt.c_iflag, &it->c_iflag);
__put_user(kt.c_oflag, &it->c_oflag);
@@ -106,7+105,7 @@ asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg) #ifdef DEBUG_IOCTLS
printk("TCSETS, %08lx) ", arg);
#endif
- if(!access_ok(VERIFY_READ, it, sizeof(*it))) {
+ if (!access_ok(VERIFY_READ, it, sizeof(*it))) {
error = -EFAULT;
break;
}
@@ -259,6+258,5 @@ asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg) #ifdef DEBUG_IOCTLS
printk("error=%d\n", error);
#endif
- unlock_kernel();
return error;
}
* irixsig.c: WHEEE, IRIX signals! YOW, am I compatable or what?!?!
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: irixsig.c,v 1.13 1999/10/09 00:00:58 ralf Exp $
+ * Copyright (C) 1997 - 2000 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 2000 Silicon Graphics, Inc.
*/
-
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
int options, unsigned long *ru);
+extern asmlinkage void syscall_trace(void);
#undef DEBUG_SIG
@@ -131,10+131,8 @@ static void inline setup_irix_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
int signr, sigset_t *oldmask, siginfo_t *info)
{
- lock_kernel();
printk("Aiee: setup_tr_frame wants to be written");
do_exit(SIGSEGV);
- unlock_kernel();
}
static inline void handle_signal(unsigned long sig, struct k_sigaction *ka,
@@ -193,7+191,7 @@ asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs) if (!signr)
break;
- if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+ if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
current->state = TASK_STOPPED;
@@ -266,8+264,8 @@ asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs) /* FALLTHRU */
default:
- lock_kernel();
sigaddset(¤t->signal, signr);
+ recalc_sigpending(current);
current->flags |= PF_SIGNALED;
do_exit(exit_code);
/* NOTREACHED */
@@ -354,6+352,8 @@ irix_sigreturn(struct pt_regs *regs) /*
* Don't let your children do this ...
*/
+ if (current->ptrace & PT_TRACESYS)
+ syscall_trace();
__asm__ __volatile__(
"move\t$29,%0\n\t"
"j\tret_from_sys_call"
@@ -429,23+429,24 @@ irix_sigaction(int sig, const struct sigaction *act,
asmlinkage int irix_sigpending(irix_sigset_t *set)
{
- lock_kernel();
+ int err;
+
if (verify_area(VERIFY_WRITE, set, sizeof(*set)) < 0)
return -EFAULT;
/* fill in "set" with signals pending but blocked. */
spin_lock_irq(¤t->sigmask_lock);
- __put_user(current->blocked.sig[0] & current->signal.sig[0],
- &set->sig[0]);
- __put_user(current->blocked.sig[1] & current->signal.sig[1],
- &set->sig[1]);
- __put_user(current->blocked.sig[2] & current->signal.sig[2],
- &set->sig[2]);
- __put_user(current->blocked.sig[3] & current->signal.sig[3],
- &set->sig[3]);
+ err = __put_user(current->blocked.sig[0] & current->signal.sig[0],
+ &set->sig[0]);
+ err |= __put_user(current->blocked.sig[1] & current->signal.sig[1],
+ &set->sig[1]);
+ err |= __put_user(current->blocked.sig[2] & current->signal.sig[2],
+ &set->sig[2]);
+ err |= __put_user(current->blocked.sig[3] & current->signal.sig[3],
+ &set->sig[3]);
spin_unlock_irq(¤t->sigmask_lock);
- return 0;
+ return err;
}
asmlinkage int irix_sigprocmask(int how, irix_sigset_t *new, irix_sigset_t *old)
@@ -453,10+454,9 @@ asmlinkage int irix_sigprocmask(int how, irix_sigset_t *new, irix_sigset_t *old) sigset_t oldbits, newbits;
int error;
-
- if(new) {
+ if (new) {
error = verify_area(VERIFY_READ, new, sizeof(*new));
- if(error)
+ if (error)
return error;
__copy_from_user(&newbits, new, sizeof(unsigned long)*4);
sigdelsetmask(&newbits, ~_BLOCKABLE);
@@ -565,7+565,6 @@ asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info, sigset_t kset;
int i, sig, error, timeo = 0;
- lock_kernel();
#ifdef DEBUG_SIG
printk("[%s:%d] irix_sigpoll_sys(%p,%p,%p)\n",
current->comm, current->pid, set, info, tp);
@@ -636,7+635,6 @@ asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info, error = -EINTR;
out:
- unlock_kernel();
return error;
}
@@ -662,44+660,45 @@ asmlinkage int irix_waitsys(int type, int pid, struct irix5_siginfo *info, DECLARE_WAITQUEUE(wait, current);
struct task_struct *p;
- lock_kernel();
- if(!info) {
+ if (!info) {
retval = -EINVAL;
goto out;
}
retval = verify_area(VERIFY_WRITE, info, sizeof(*info));
if(retval)
goto out;
- if(ru) {
+ if (ru) {
retval = verify_area(VERIFY_WRITE, ru, sizeof(*ru));
if(retval)
goto out;
}
- if(options & ~(W_MASK)) {
+ if (options & ~(W_MASK)) {
retval = -EINVAL;
goto out;
}
- if(type != P_PID && type != P_PGID && type != P_ALL) {
+ if (type != P_PID && type != P_PGID && type != P_ALL) {
retval = -EINVAL;
goto out;
}
add_wait_queue(¤t->wait_chldexit, &wait);
repeat:
flag = 0;
- for(p = current->p_cptr; p; p = p->p_osptr) {
- if((type == P_PID) && p->pid != pid)
+ current->state = TASK_INTERRUPTIBLE;
+ read_lock(&tasklist_lock);
+ for (p = current->p_cptr; p; p = p->p_osptr) {
+ if ((type == P_PID) && p->pid != pid)
continue;
- if((type == P_PGID) && p->pgrp != pid)
+ if ((type == P_PGID) && p->pgrp != pid)
continue;
- if((p->exit_signal != SIGCHLD))
+ if ((p->exit_signal != SIGCHLD))
continue;
flag = 1;
- switch(p->state) {
+ switch (p->state) {
case TASK_STOPPED:
if (!p->exit_code)
continue;
if (!(options & (W_TRAPPED|W_STOPPED)) &&
- !(p->flags & PF_PTRACED))
+ !(p->ptrace & PT_PTRACED))
continue;
if (ru != NULL)
getrusage(p, RUSAGE_BOTH, ru);
@@ -740,12+739,13 @@ repeat: continue;
}
}
- if(flag) {
+ read_unlock(&tasklist_lock);
+ if (flag) {
retval = 0;
- if(options & W_NOHANG)
+ if (options & W_NOHANG)
goto end_waitsys;
retval = -ERESTARTSYS;
- if(signal_pending(current))
+ if (signal_pending(current))
goto end_waitsys;
current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -753,10+753,10 @@ repeat: }
retval = -ECHILD;
end_waitsys:
+ current->state = TASK_RUNNING;
remove_wait_queue(¤t->wait_chldexit, &wait);
out:
- unlock_kernel();
return retval;
}
@@ -779,8+779,7 @@ asmlinkage int irix_getcontext(struct pt_regs *regs) struct irix5_context *ctx;
unsigned long flags;
- lock_kernel();
- if(regs->regs[2] == 1000)
+ if (regs->regs[2] == 1000)
base = 1;
ctx = (struct irix5_context *) regs->regs[base + 4];
@@ -803,7+802,7 @@ asmlinkage int irix_getcontext(struct pt_regs *regs)
__put_user(0, &ctx->weird_graphics_thing);
__put_user(0, &ctx->regs[0]);
- for(i = 1; i < 32; i++)
+ for (i = 1; i < 32; i++)
__put_user(regs->regs[i], &ctx->regs[i]);
__put_user(regs->lo, &ctx->regs[32]);
__put_user(regs->hi, &ctx->regs[33]);
@@ -821,7+820,6 @@ asmlinkage int irix_getcontext(struct pt_regs *regs) error = 0;
out:
- unlock_kernel();
return error;
}
@@ -830,7+828,6 @@ asmlinkage unsigned long irix_setcontext(struct pt_regs *regs) int error, base = 0;
struct irix5_context *ctx;
- lock_kernel();
if(regs->regs[2] == 1000)
base = 1;
ctx = (struct irix5_context *) regs->regs[base + 4];
@@ -841,15+838,15 @@ asmlinkage unsigned long irix_setcontext(struct pt_regs *regs) #endif
error = verify_area(VERIFY_READ, ctx, sizeof(*ctx));
- if(error)
+ if (error)
goto out;
- if(ctx->flags & 0x02) {
+ if (ctx->flags & 0x02) {
/* XXX sigstack garbage, todo... */
printk("Wheee, cannot do sigstack stuff in setcontext\n");
}
- if(ctx->flags & 0x04) {
+ if (ctx->flags & 0x04) {
int i;
/* XXX extra control block stuff... todo... */
@@ -860,7+857,7 @@ asmlinkage unsigned long irix_setcontext(struct pt_regs *regs) regs->cp0_epc = ctx->regs[35];
}
- if(ctx->flags & 0x08) {
+ if (ctx->flags & 0x08) {
/* XXX fpu context, blah... */
printk("Wheee, cannot restore FPU context yet...\n");
}
@@ -868,7+865,6 @@ asmlinkage unsigned long irix_setcontext(struct pt_regs *regs) error = regs->regs[2];
out:
- unlock_kernel();
return error;
}
@@ -878,7+874,6 @@ asmlinkage int irix_sigstack(struct irix_sigstack *new, struct irix_sigstack *ol {
int error;
- lock_kernel();
#ifdef DEBUG_SIG
printk("[%s:%d] irix_sigstack(%p,%p)\n",
current->comm, current->pid, new, old);
@@ -895,8+890,8 @@ asmlinkage int irix_sigstack(struct irix_sigstack *new, struct irix_sigstack *ol goto out;
}
error = 0;
+
out:
- unlock_kernel();
return error;
}
@@ -907,18+902,17 @@ asmlinkage int irix_sigaltstack(struct irix_sigaltstack *new, {
int error;
- lock_kernel();
#ifdef DEBUG_SIG
printk("[%s:%d] irix_sigaltstack(%p,%p)\n",
current->comm, current->pid, new, old);
#endif
- if(new) {
+ if (new) {
error = verify_area(VERIFY_READ, new, sizeof(*new));
if(error)
goto out;
}
- if(old) {
+ if (old) {
error = verify_area(VERIFY_WRITE, old, sizeof(*old));
if(error)
goto out;
@@ -927,7+921,6 @@ asmlinkage int irix_sigaltstack(struct irix_sigaltstack *new,
out:
error = 0;
- unlock_kernel();
return error;
}
@@ -940,7+933,6 @@ asmlinkage int irix_sigsendset(struct irix_procset *pset, int sig) {
int error;
- lock_kernel();
error = verify_area(VERIFY_READ, pset, sizeof(*pset));
if(error)
goto out;
@@ -950,10+942,8 @@ asmlinkage int irix_sigsendset(struct irix_procset *pset, int sig) pset->cmd, pset->ltype, pset->lid, pset->rtype, pset->rid,
sig);
#endif
-
error = -EINVAL;
out:
- unlock_kernel();
return error;
}
-/* $Id: irq.c,v 1.20 2000/02/23 00:41:00 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
* Code to handle x86 style IRQs plus some generic interrupt stuff.
*
* Copyright (C) 1992 Linus Torvalds
- * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle
+ * Copyright (C) 1994 - 2000 Ralf Baechle
*/
#include <linux/errno.h>
#include <linux/init.h>
@@ -267,8+266,10 @@ int i8259_setup_irq(int irq, struct irqaction * new) if (!shared) {
if (is_i8259_irq(irq))
unmask_irq(irq);
+#if CONFIG_DDB5074 /* This has no business here */
else
nile4_enable_irq(irq_to_nile4(irq));
+#endif
}
restore_flags(flags);
return 0;
@@ -343,7+344,7 @@ unsigned long probe_irq_on (void) /* first, enable any unassigned (E)ISA irqs */
for (i = 15; i > 0; i--) {
if (!irq_action[i]) {
- enable_irq(i);
+ i8259_enable_irq(i);
irqs |= (1 << i);
}
}
-/* $Id: mips_ksyms.c,v 1.25 2000/02/24 00:12:40 ralf Exp $
- *
+/*
* Export MIPS-specific functions needed for loadable modules.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1996, 1997, 1998 by Ralf Baechle
+ * Copyright (C) 1996, 1997, 1998, 2000 by Ralf Baechle
*/
#include <linux/config.h>
#include <linux/module.h>
#include <asm/irq.h>
#include <linux/in6.h>
#include <linux/pci.h>
+#include <linux/ide.h>
#include <asm/checksum.h>
#include <asm/dma.h>
-#include <asm/floppy.h>
#include <asm/io.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/sgi/sgihpc.h>
#include <asm/softirq.h>
#include <asm/uaccess.h>
+#ifdef CONFIG_BLK_DEV_FD
+#include <asm/floppy.h>
+#endif
extern void *__bzero(void *__s, size_t __count);
extern long __strncpy_from_user_nocheck_asm(char *__to,
@@ -50,11+52,12 @@ EXPORT_SYMBOL_NOVERS(memmove); EXPORT_SYMBOL_NOVERS(strcat);
EXPORT_SYMBOL_NOVERS(strchr);
EXPORT_SYMBOL_NOVERS(strlen);
+EXPORT_SYMBOL_NOVERS(strpbrk);
EXPORT_SYMBOL_NOVERS(strncat);
EXPORT_SYMBOL_NOVERS(strnlen);
EXPORT_SYMBOL_NOVERS(strrchr);
+EXPORT_SYMBOL_NOVERS(strstr);
EXPORT_SYMBOL_NOVERS(strtok);
-EXPORT_SYMBOL_NOVERS(strpbrk);
EXPORT_SYMBOL(_clear_page);
EXPORT_SYMBOL(enable_irq);
@@ -131,4+134,9 @@ EXPORT_SYMBOL(unregister_fpe); EXPORT_SYMBOL(screen_info);
#endif
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+EXPORT_SYMBOL(ide_ops);
+#endif
+
EXPORT_SYMBOL(get_wchan);
+EXPORT_SYMBOL(irq_stat);
@@ -39,12+39,12 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) #endif
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
- if (current->flags & PF_PTRACED) {
+ if (current->ptrace & PT_PTRACED) {
res = -EPERM;
goto out;
}
/* set the ptrace bit in the process flags. */
- current->flags |= PF_PTRACED;
+ current->ptrace |= PT_PTRACED;
res = 0;
goto out;
}
@@ -76,9+76,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
goto out_tsk;
/* the same process cannot be attached many times */
- if (child->flags & PF_PTRACED)
+ if (child->ptrace & PT_PTRACED)
goto out_tsk;
- child->flags |= PF_PTRACED;
+ child->ptrace |= PT_PTRACED;
write_lock_irq(&tasklist_lock);
if (child->p_pptr != current) {
@@ -93,7+93,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) goto out_tsk;
}
res = -ESRCH;
- if (!(child->flags & PF_PTRACED))
+ if (!(child->ptrace & PT_PTRACED))
goto out_tsk;
if (child->state != TASK_STOPPED) {
if (request != PTRACE_KILL)
@@ -243,9+243,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) if ((unsigned long) data > _NSIG)
break;
if (request == PTRACE_SYSCALL)
- child->flags |= PF_TRACESYS;
+ child->ptrace |= PT_TRACESYS;
else
- child->flags &= ~PF_TRACESYS;
+ child->ptrace &= ~PT_TRACESYS;
child->exit_code = data;
wake_up_process(child);
res = 0;
@@ -269,7+269,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) res = -EIO;
if ((unsigned long) data > _NSIG)
break;
- child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+ child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
child->exit_code = data;
write_lock_irq(&tasklist_lock);
REMOVE_LINKS(child);
asmlinkage void syscall_trace(void)
{
- if ((current->flags & (PF_PTRACED|PF_TRACESYS))
- != (PF_PTRACED|PF_TRACESYS))
+ if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
+ != (PT_PTRACED|PT_TRACESYS))
return;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
@@ -171,6+171,7 @@ stackargs:
/*
* The stackpointer for a call with more than 4 arguments is bad.
+ * We probably should handle this case a bit more drastic.
*/
bad_stack:
negu v0 # error
@@ -76,7+76,7 @@ extern struct fd_ops no_fd_ops; struct fd_ops *fd_ops;
#endif
-#ifdef CONFIG_BLK_DEV_IDE
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
extern struct ide_ops no_ide_ops;
struct ide_ops *ide_ops;
#endif
@@ -84,8+84,10 @@ struct ide_ops *ide_ops; extern struct rtc_ops no_rtc_ops;
struct rtc_ops *rtc_ops;
+#ifdef CONFIG_PC_KEYB
extern struct kbd_ops no_kbd_ops;
struct kbd_ops *kbd_ops;
+#endif
/*
* Setup information
@@ -272,8+274,11 @@ void __init setup_arch(char **cmdline_p) ide_ops = &no_ide_ops;
#endif
- rtc_ops = &no_rtc_ops;
+#ifdef CONFIG_PC_KEYB
kbd_ops = &no_kbd_ops;
+#endif
+
+ rtc_ops = &no_rtc_ops;
switch(mips_machgroup)
{
-/* $Id: signal.c,v 1.24 2000/02/04 07:40:23 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
@@ -37,6+36,8 @@ extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); extern asmlinkage int save_fp_context(struct sigcontext *sc);
extern asmlinkage int restore_fp_context(struct sigcontext *sc);
+extern asmlinkage void syscall_trace(void);
+
int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
{
if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
@@ -265,6+266,8 @@ sys_sigreturn(struct pt_regs regs) /*
* Don't let your children do this ...
*/
+ if (current->ptrace & PT_TRACESYS)
+ syscall_trace();
__asm__ __volatile__(
"move\t$29, %0\n\t"
"j\tret_from_sys_call"
@@ -585,7+588,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) if (!signr)
break;
- if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+ if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
current->state = TASK_STOPPED;
@@ -659,7+662,6 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) /* FALLTHRU */
default:
- lock_kernel();
sigaddset(¤t->signal, signr);
recalc_sigpending(current);
current->flags |= PF_SIGNALED;
-/* $Id: softfp.S,v 1.1 1998/07/16 19:10:02 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1998 by Ralf Baechle
+ * Copyright (C) 1998, 2000 by Ralf Baechle
*
* For now it's just a crude hack good enough to run certain fp programs like
* Mozilla.
@@ -190,15+189,15 @@ LEAF(simfp) #define FMT_switch(insn,opc,temp0,temp1) \
insn: srl temp0, opc, 19; \
andi temp0, 0x1c; \
- la temp1, insn ## .tab; \
+ la temp1, insn##.tab; \
addu temp0, temp1; \
lw temp0, (temp0); \
jr temp0; \
\
.data; \
-insn ## .tab: \
- .word insn ## .s, insn ## .d, unimp, unimp; \
- .word insn ## .w, insn ## .l, unimp, unimp; \
+insn##.tab: \
+ .word insn##.s, insn##.d, unimp, unimp; \
+ .word insn##.w, insn##.l, unimp, unimp; \
.previous
BITCH(add)
-/* $Id: syscall.c,v 1.13 2000/02/04 07:40:23 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1995 - 1999 by Ralf Baechle
+ * Copyright (C) 1995 - 2000 by Ralf Baechle
+ * Copyright (C) 2000 Silicon Graphics, Inc.
*
* TODO: Implement the compatibility syscalls.
* Don't waste that much memory for empty entries in the syscall
#include <linux/mman.h>
#include <linux/sched.h>
#include <linux/file.h>
+#include <linux/slab.h>
#include <linux/utsname.h>
#include <linux/unistd.h>
#include <asm/branch.h>
-/* $Id: sysirix.c,v 1.26 2000/03/12 23:15:33 ralf Exp $
- *
+/*
* sysirix.c: IRIX system call emulation.
*
* Copyright (C) 1996 David S. Miller
* Copyright (C) 1997 Miguel de Icaza
* Copyright (C) 1997, 1998 Ralf Baechle
*/
-
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/pagemap.h>
#include <asm/sgialib.h>
#include <asm/inventory.h>
-/* 2,526 lines of complete and utter shit coming up... */
+/* 2,191 lines of complete and utter shit coming up... */
extern int max_threads;
@@ -59,7+57,7 @@ asmlinkage int irix_sysmp(struct pt_regs *regs) error = smp_num_cpus;
break;
default:
- printk("SYSMP[%s:%ld]: Unsupported opcode %d\n",
+ printk("SYSMP[%s:%d]: Unsupported opcode %d\n",
current->comm, current->pid, (int)cmd);
error = -EINVAL;
break;
@@ -91,13+89,12 @@ asmlinkage int irix_prctl(struct pt_regs *regs) unsigned long cmd;
int error = 0, base = 0;
- lock_kernel();
- if(regs->regs[2] == 1000)
+ if (regs->regs[2] == 1000)
base = 1;
cmd = regs->regs[base + 4];
- switch(cmd) {
+ switch (cmd) {
case PR_MAXPROCS:
- printk("irix_prctl[%s:%ld]: Wants PR_MAXPROCS\n",
+ printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n",
current->comm, current->pid);
error = max_threads;
break;
@@ -105,14+102,14 @@ asmlinkage int irix_prctl(struct pt_regs *regs) case PR_ISBLOCKED: {
struct task_struct *task;
- printk("irix_prctl[%s:%ld]: Wants PR_ISBLOCKED\n",
+ printk("irix_prctl[%s:%d]: Wants PR_ISBLOCKED\n",
current->comm, current->pid);
+ read_lock(&tasklist_lock);
task = find_task_by_pid(regs->regs[base + 5]);
- if(!task) {
- error = -ESRCH;
- break;
- }
- error = (task->run_list.next != NULL);
+ error = -ESRCH;
+ if (error)
+ error = (task->run_list.next != NULL);
+ read_unlock(&tasklist_lock);
/* Can _your_ OS find this out that fast? */
break;
}
@@ -120,17+117,17 @@ asmlinkage int irix_prctl(struct pt_regs *regs) case PR_SETSTACKSIZE: {
long value = regs->regs[base + 5];
- printk("irix_prctl[%s:%ld]: Wants PR_SETSTACKSIZE<%08lx>\n",
+ printk("irix_prctl[%s:%d]: Wants PR_SETSTACKSIZE<%08lx>\n",
current->comm, current->pid, (unsigned long) value);
- if(value > RLIM_INFINITY)
+ if (value > RLIM_INFINITY)
value = RLIM_INFINITY;
- if(capable(CAP_SYS_ADMIN)) {
+ if (capable(CAP_SYS_ADMIN)) {
current->rlim[RLIMIT_STACK].rlim_max =
current->rlim[RLIMIT_STACK].rlim_cur = value;
error = value;
break;
}
- if(value > current->rlim[RLIMIT_STACK].rlim_max) {
+ if (value > current->rlim[RLIMIT_STACK].rlim_max) {
error = -EINVAL;
break;
}
@@ -140,25+137,25 @@ asmlinkage int irix_prctl(struct pt_regs *regs) }
case PR_GETSTACKSIZE:
- printk("irix_prctl[%s:%ld]: Wants PR_GETSTACKSIZE\n",
+ printk("irix_prctl[%s:%d]: Wants PR_GETSTACKSIZE\n",
current->comm, current->pid);
error = current->rlim[RLIMIT_STACK].rlim_cur;
break;
case PR_MAXPPROCS:
- printk("irix_prctl[%s:%ld]: Wants PR_MAXPROCS\n",
+ printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n",
current->comm, current->pid);
error = 1;
break;
case PR_UNBLKONEXEC:
- printk("irix_prctl[%s:%ld]: Wants PR_UNBLKONEXEC\n",
+ printk("irix_prctl[%s:%d]: Wants PR_UNBLKONEXEC\n",
current->comm, current->pid);
error = -EINVAL;
break;
case PR_SETEXITSIG:
- printk("irix_prctl[%s:%ld]: Wants PR_SETEXITSIG\n",
+ printk("irix_prctl[%s:%d]: Wants PR_SETEXITSIG\n",
current->comm, current->pid);
/* We can probably play some game where we set the task
@@ -169,31+166,31 @@ asmlinkage int irix_prctl(struct pt_regs *regs) break;
case PR_RESIDENT:
- printk("irix_prctl[%s:%ld]: Wants PR_RESIDENT\n",
+ printk("irix_prctl[%s:%d]: Wants PR_RESIDENT\n",
current->comm, current->pid);
error = 0; /* Compatibility indeed. */
break;
case PR_ATTACHADDR:
- printk("irix_prctl[%s:%ld]: Wants PR_ATTACHADDR\n",
+ printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDR\n",
current->comm, current->pid);
error = -EINVAL;
break;
case PR_DETACHADDR:
- printk("irix_prctl[%s:%ld]: Wants PR_DETACHADDR\n",
+ printk("irix_prctl[%s:%d]: Wants PR_DETACHADDR\n",
current->comm, current->pid);
error = -EINVAL;
break;
case PR_TERMCHILD:
- printk("irix_prctl[%s:%ld]: Wants PR_TERMCHILD\n",
+ printk("irix_prctl[%s:%d]: Wants PR_TERMCHILD\n",
current->comm, current->pid);
error = -EINVAL;
break;
case PR_GETSHMASK:
- printk("irix_prctl[%s:%ld]: Wants PR_GETSHMASK\n",
+ printk("irix_prctl[%s:%d]: Wants PR_GETSHMASK\n",
current->comm, current->pid);
error = -EINVAL; /* Until I have the sproc() stuff in. */
break;
@@ -203,30+200,29 @@ asmlinkage int irix_prctl(struct pt_regs *regs) break;
case PR_COREPID:
- printk("irix_prctl[%s:%ld]: Wants PR_COREPID\n",
+ printk("irix_prctl[%s:%d]: Wants PR_COREPID\n",
current->comm, current->pid);
error = -EINVAL;
break;
case PR_ATTACHADDRPERM:
- printk("irix_prctl[%s:%ld]: Wants PR_ATTACHADDRPERM\n",
+ printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDRPERM\n",
current->comm, current->pid);
error = -EINVAL;
break;
case PR_PTHREADEXIT:
- printk("irix_prctl[%s:%ld]: Wants PR_PTHREADEXIT\n",
+ printk("irix_prctl[%s:%d]: Wants PR_PTHREADEXIT\n",
current->comm, current->pid);
do_exit(regs->regs[base + 5]);
default:
- printk("irix_prctl[%s:%ld]: Non-existant opcode %d\n",
+ printk("irix_prctl[%s:%d]: Non-existant opcode %d\n",
current->comm, current->pid, (int)cmd);
error = -EINVAL;
break;
}
- unlock_kernel();
return error;
}
@@ -267,81+263,83 @@ extern long prom_setenv(char *name, char *value);
asmlinkage int irix_syssgi(struct pt_regs *regs)
{
- unsigned long cmd;
- int retval, base = 0;
+ unsigned long cmd;
+ int retval, base = 0;
- lock_kernel();
- if(regs->regs[2] == 1000)
- base = 1;
+ if (regs->regs[2] == 1000)
+ base = 1;
- cmd = regs->regs[base + 4];
- switch(cmd) {
- case SGI_SYSID: {
- char *buf = (char *) regs->regs[base + 5];
+ cmd = regs->regs[base + 4];
+ switch(cmd) {
+ case SGI_SYSID: {
+ char *buf = (char *) regs->regs[base + 5];
- /* XXX Use ethernet addr.... */
- retval = clear_user(buf, 64);
- break;
- }
+ /* XXX Use ethernet addr.... */
+ retval = clear_user(buf, 64);
+ break;
+ }
#if 0
- case SGI_RDNAME: {
- int pid = (int) regs->regs[base + 5];
- char *buf = (char *) regs->regs[base + 6];
- struct task_struct *p;
-
- retval = verify_area(VERIFY_WRITE, buf, 16);
- if(retval)
- break;
- for_each_task(p) {
- if(p->pid == pid)
- goto found0;
- }
- retval = -ESRCH;
-
- found0:
- /* XXX Need to check sizes. */
- copy_to_user(buf, p->comm, 16);
- retval = 0;
- break;
- }
-
- case SGI_GETNVRAM: {
- char *name = (char *) regs->regs[base+5];
- char *buf = (char *) regs->regs[base+6];
- char *value;
+ case SGI_RDNAME: {
+ int pid = (int) regs->regs[base + 5];
+ char *buf = (char *) regs->regs[base + 6];
+ struct task_struct *p;
+ char comm[16];
+
+ retval = verify_area(VERIFY_WRITE, buf, 16);
+ if (retval)
+ break;
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid(pid);
+ if (!p) {
+ read_unlock(&tasklist_lock);
+ retval = -ESRCH;
+ break;
+ }
+ memcpy(comm, p->comm, 16);
+ read_unlock(&tasklist_lock);
+
+ /* XXX Need to check sizes. */
+ copy_to_user(buf, p->comm, 16);
+ retval = 0;
+ break;
+ }
+
+ case SGI_GETNVRAM: {
+ char *name = (char *) regs->regs[base+5];
+ char *buf = (char *) regs->regs[base+6];
+ char *value;
return -EINVAL; /* til I fix it */
- retval = verify_area(VERIFY_WRITE, buf, 128);
- if (retval)
- break;
- value = prom_getenv(name);
- if (!value) {
- retval = -EINVAL;
- break;
- }
- /* Do I strlen() for the length? */
- copy_to_user(buf, value, 128);
- retval = 0;
- break;
- }
-
- case SGI_SETNVRAM: {
- char *name = (char *) regs->regs[base+5];
- char *value = (char *) regs->regs[base+6];
+ retval = verify_area(VERIFY_WRITE, buf, 128);
+ if (retval)
+ break;
+ value = prom_getenv(name); /* PROM lock? */
+ if (!value) {
+ retval = -EINVAL;
+ break;
+ }
+ /* Do I strlen() for the length? */
+ copy_to_user(buf, value, 128);
+ retval = 0;
+ break;
+ }
+
+ case SGI_SETNVRAM: {
+ char *name = (char *) regs->regs[base+5];
+ char *value = (char *) regs->regs[base+6];
return -EINVAL; /* til I fix it */
- retval = prom_setenv(name, value);
+ retval = prom_setenv(name, value);
/* XXX make sure retval conforms to syssgi(2) */
printk("[%s:%d] setnvram(\"%s\", \"%s\"): retval %d",
- current->comm, current->pid,
- name, value, retval);
+ current->comm, current->pid, name, value, retval);
/* if (retval == PROM_ENOENT)
retval = -ENOENT; */
break;
}
#endif
-
+
case SGI_SETPGID: {
#ifdef DEBUG_PROCGRPS
- printk("[%s:%ld] setpgid(%d, %d) ",
+ printk("[%s:%d] setpgid(%d, %d) ",
current->comm, current->pid,
(int) regs->regs[base + 5], (int)regs->regs[base + 6]);
#endif
@@ -438,7+436,7 @@ asmlinkage int irix_syssgi(struct pt_regs *regs)
case SGI_GETSID:
#ifdef DEBUG_PROCGRPS
- printk("[%s:%ld] getsid(%d) ", current->comm, current->pid,
+ printk("[%s:%d] getsid(%d) ", current->comm, current->pid,
(int) regs->regs[base + 5]);
#endif
retval = sys_getsid(regs->regs[base + 5]);
@@ -463,25+461,31 @@ asmlinkage int irix_syssgi(struct pt_regs *regs) break;
case SGI_PHYSP: {
+ unsigned long addr = regs->regs[base + 5];
+ int *pageno = (int *) (regs->regs[base + 6]);
+ struct mm_struct *mm = current->mm;
pgd_t *pgdp;
pmd_t *pmdp;
pte_t *ptep;
- unsigned long addr = regs->regs[base + 5];
- int *pageno = (int *) (regs->regs[base + 6]);
retval = verify_area(VERIFY_WRITE, pageno, sizeof(int));
- if(retval)
+ if (retval)
return retval;
- pgdp = pgd_offset(current->mm, addr);
+
+ down(&mm->mmap_sem);
+ pgdp = pgd_offset(mm, addr);
pmdp = pmd_offset(pgdp, addr);
ptep = pte_offset(pmdp, addr);
- if(ptep) {
- if(pte_val(*ptep) & (_PAGE_VALID | _PAGE_PRESENT)) {
- return put_user((pte_val(*ptep) & PAGE_MASK)>>PAGE_SHIFT, pageno);
- return 0;
+ retval = -EINVAL;
+ if (ptep) {
+ pte_t pte = *ptep;
+
+ if (pte_val(pte) & (_PAGE_VALID | _PAGE_PRESENT)) {
+ retval = put_user((pte_val(pte) & PAGE_MASK) >>
+ PAGE_SHIFT, pageno);
}
}
- retval = -EINVAL;
+ up(&mm->mmap_sem);
break;
}
@@ -490,7+494,7 @@ asmlinkage int irix_syssgi(struct pt_regs *regs) void *buffer = (void *) regs->regs [base + 6];
int count = (int) regs->regs [base + 7];
- switch (arg1){
+ switch (arg1) {
case SGI_INV_SIZEOF:
retval = sizeof (inventory_t);
break;
@@ -510,7+514,6 @@ asmlinkage int irix_syssgi(struct pt_regs *regs) };
out:
- unlock_kernel();
return retval;
}
@@ -532,7+535,7 @@ asmlinkage int irix_brk(unsigned long brk) struct mm_struct *mm = current->mm;
int ret;
- lock_kernel();
+ down(&mm->mmap_sem);
if (brk < mm->end_code) {
ret = -ENOMEM;
goto out;
@@ -590,7+593,7 @@ asmlinkage int irix_brk(unsigned long brk) ret = 0;
out:
- unlock_kernel();
+ up(&mm->mmap_sem);
return ret;
}
@@ -612,26+615,21 @@ asmlinkage int irix_getgid(struct pt_regs *regs) return current->gid;
}
+extern rwlock_t xtime_lock;
+
asmlinkage int irix_stime(int value)
{
- int ret;
+ if (!capable(CAP_SYS_TIME))
+ return -EPERM;
- lock_kernel();
- if(!capable(CAP_SYS_TIME)) {
- ret = -EPERM;
- goto out;
- }
- cli();
+ write_lock_irq(&xtime_lock);
xtime.tv_sec = value;
xtime.tv_usec = 0;
time_maxerror = MAXPHASE;
time_esterror = MAXPHASE;
- sti();
- ret = 0;
+ write_unlock_irq(&xtime_lock);
-out:
- unlock_kernel();
- return ret;
+ return 0;
}
extern int do_setitimer(int which, struct itimerval *value,
@@ -641,7+639,6 @@ static inline void jiffiestotv(unsigned long jiffies, struct timeval *value) {
value->tv_usec = (jiffies % HZ) * (1000000 / HZ);
value->tv_sec = jiffies / HZ;
- return;
}
static inline void getitimer_real(struct itimerval *value)
@@ -668,8+665,7 @@ asmlinkage unsigned int irix_alarm(unsigned int seconds) struct itimerval it_new, it_old;
unsigned int oldalarm;
- lock_kernel();
- if(!seconds) {
+ if (!seconds) {
getitimer_real(&it_old);
del_timer(¤t->real_timer);
} else {
@@ -679,11+675,13 @@ asmlinkage unsigned int irix_alarm(unsigned int seconds) do_setitimer(ITIMER_REAL, &it_new, &it_old);
}
oldalarm = it_old.it_value.tv_sec;
- /* ehhh.. We can't return 0 if we have an alarm pending.. */
- /* And we'd better return too much than too little anyway */
+ /*
+ * ehhh.. We can't return 0 if we have an alarm pending ...
+ * And we'd better return too much than too little anyway
+ */
if (it_old.it_value.tv_usec)
oldalarm++;
- unlock_kernel();
+
return oldalarm;
}
@@ -691,6+689,7 @@ asmlinkage int irix_pause(void) {
current->state = TASK_INTERRUPTIBLE;
schedule();
+
return -EINTR;
}
@@ -701,14+700,11 @@ extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type, asmlinkage int irix_mount(char *dev_name, char *dir_name, unsigned long flags,
char *type, void *data, int datalen)
{
- int ret;
-
- printk("[%s:%ld] irix_mount(%p,%p,%08lx,%p,%p,%d)\n",
+ printk("[%s:%d] irix_mount(%p,%p,%08lx,%p,%p,%d)\n",
current->comm, current->pid,
dev_name, dir_name, flags, type, data, datalen);
- ret = sys_mount(dev_name, dir_name, type, flags, data);
- return ret;
+ return sys_mount(dev_name, dir_name, type, flags, data);
}
struct irix_statfs {
@@ -725,7+721,7 @@ asmlinkage int irix_statfs(const char *path, struct irix_statfs *buf, int error, i;
/* We don't support this feature yet. */
- if(fs_type) {
+ if (fs_type) {
error = -EINVAL;
goto out;
}
@@ -747,7+743,7 @@ asmlinkage int irix_statfs(const char *path, struct irix_statfs *buf, __put_user(kbuf.f_bfree, &buf->f_bfree);
__put_user(kbuf.f_files, &buf->f_files);
__put_user(kbuf.f_ffree, &buf->f_ffree);
- for(i = 0; i < 6; i++) {
+ for (i = 0; i < 6; i++) {
__put_user(0, &buf->f_fname[i]);
__put_user(0, &buf->f_fpack[i]);
}
@@ -803,7+799,7 @@ asmlinkage int irix_setpgrp(int flags) int error;
#ifdef DEBUG_PROCGRPS
- printk("[%s:%ld] setpgrp(%d) ", current->comm, current->pid, flags);
+ printk("[%s:%d] setpgrp(%d) ", current->comm, current->pid, flags);
#endif
if(!flags)
error = current->pgrp;
@@ -818,23+814,19 @@ asmlinkage int irix_setpgrp(int flags)
asmlinkage int irix_times(struct tms * tbuf)
{
- int error;
+ int err = 0;
- lock_kernel();
if (tbuf) {
- error = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf);
- if (error)
- goto out;
- __put_user(current->times.tms_utime,&tbuf->tms_utime);
- __put_user(current->times.tms_stime,&tbuf->tms_stime);
- __put_user(current->times.tms_cutime,&tbuf->tms_cutime);
- __put_user(current->times.tms_cstime,&tbuf->tms_cstime);
+ err = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf);
+ if (err)
+ return err;
+ err |= __put_user(current->times.tms_utime,&tbuf->tms_utime);
+ err |= __put_user(current->times.tms_stime,&tbuf->tms_stime);
+ err |= __put_user(current->times.tms_cutime,&tbuf->tms_cutime);
+ err |= __put_user(current->times.tms_cstime,&tbuf->tms_cstime);
}
- error = 0;
-out:
- unlock_kernel();
- return error;
+ return err;
}
asmlinkage int irix_exec(struct pt_regs *regs)
@@ -847,12+839,12 @@ asmlinkage int irix_exec(struct pt_regs *regs) filename = getname((char *) (long)regs->regs[base + 4]);
error = PTR_ERR(filename);
if (IS_ERR(filename))
- goto out;
+ return error;
+
error = do_execve(filename, (char **) (long)regs->regs[base + 5],
(char **) 0, regs);
putname(filename);
-out:
return error;
}
@@ -861,31+853,32 @@ asmlinkage int irix_exece(struct pt_regs *regs) int error, base = 0;
char *filename;
- if(regs->regs[2] == 1000)
+ if (regs->regs[2] == 1000)
base = 1;
filename = getname((char *) (long)regs->regs[base + 4]);
error = PTR_ERR(filename);
if (IS_ERR(filename))
- goto out;
+ return error;
error = do_execve(filename, (char **) (long)regs->regs[base + 5],
(char **) (long)regs->regs[base + 6], regs);
putname(filename);
-out:
return error;
}
asmlinkage unsigned long irix_gethostid(void)
{
- printk("[%s:%ld]: irix_gethostid() called...\n",
+ printk("[%s:%d]: irix_gethostid() called...\n",
current->comm, current->pid);
+
return -EINVAL;
}
asmlinkage unsigned long irix_sethostid(unsigned long val)
{
- printk("[%s:%ld]: irix_sethostid(%08lx) called...\n",
+ printk("[%s:%d]: irix_sethostid(%08lx) called...\n",
current->comm, current->pid, val);
+
return -EINVAL;
}
@@ -929,20+922,18 @@ asmlinkage int irix_getdomainname(char *name, int len) {
int error;
- lock_kernel();
+ error = verify_area(VERIFY_WRITE, name, len);
+ if (error)
+ return error;
+
+ down_read(&uts_sem);
if(len > (__NEW_UTS_LEN - 1))
len = __NEW_UTS_LEN - 1;
- error = verify_area(VERIFY_WRITE, name, len);
- if(error)
- goto out;
- if(copy_to_user(name, system_utsname.domainname, len)) {
- error = -EFAULT;
- goto out;
- }
error = 0;
+ if (copy_to_user(name, system_utsname.domainname, len))
+ error = -EFAULT;
+ up_read(&uts_sem);
-out:
- unlock_kernel();
return error;
}
@@ -955,7+946,7 @@ asmlinkage int irix_msgsys(int opcode, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3,
unsigned long arg4)
{
- switch(opcode) {
+ switch (opcode) {
case 0:
return sys_msgget((key_t) arg0, (int) arg1);
case 1:
@@ -974,7+965,7 @@ asmlinkage int irix_msgsys(int opcode, unsigned long arg0, unsigned long arg1, asmlinkage int irix_shmsys(int opcode, unsigned long arg0, unsigned long arg1,
unsigned long arg2, unsigned long arg3)
{
- switch(opcode) {
+ switch (opcode) {
case 0:
return sys_shmat((int) arg0, (char *)arg1, (int) arg2,
(unsigned long *) arg3);
@@ -992,7+983,7 @@ asmlinkage int irix_shmsys(int opcode, unsigned long arg0, unsigned long arg1, asmlinkage int irix_semsys(int opcode, unsigned long arg0, unsigned long arg1,
unsigned long arg2, int arg3)
{
- switch(opcode) {
+ switch (opcode) {
case 0:
return sys_semctl((int) arg0, (int) arg1, (int) arg2,
(union semun) arg3);
@@ -1006,25+997,42 @@ asmlinkage int irix_semsys(int opcode, unsigned long arg0, unsigned long arg1, }
}
-extern asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high,
- unsigned long offset_low, loff_t * result,
- unsigned int origin);
+static inline loff_t llseek(struct file *file, loff_t offset, int origin)
+{
+ loff_t (*fn)(struct file *, loff_t, int);
+ loff_t retval;
-asmlinkage int irix_lseek64(int fd, int _unused, int offhi, int offlow, int base)
+ fn = default_llseek;
+ if (file->f_op && file->f_op->llseek)
+ fn = file->f_op->llseek;
+ lock_kernel();
+ retval = fn(file, offset, origin);
+ unlock_kernel();
+ return retval;
+}
+
+asmlinkage int irix_lseek64(int fd, int _unused, int offhi, int offlow,
+ int origin)
{
- mm_segment_t old_fs;
- loff_t junk;
- int error;
+ int retval;
+ struct file * file;
+ loff_t offset;
- old_fs = get_fs(); set_fs(get_ds());
- error = sys_llseek(fd, offhi, offlow, &junk, base);
- set_fs(old_fs);
+ retval = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto bad;
+ retval = -EINVAL;
+ if (origin > 2)
+ goto out_putf;
- if(error)
- goto out;
- error = (int) junk;
-out:
- return error;
+ offset = llseek(file, ((loff_t) offhi << 32) | offlow, origin);
+ retval = (int) offset;
+
+out_putf:
+ fput(file);
+bad:
+ return retval;
}
asmlinkage int irix_sginap(int ticks)
@@ -1056,10+1064,8 @@ asmlinkage unsigned long irix_mmap32(unsigned long addr, size_t len, int prot, unsigned long retval;
if (!(flags & MAP_ANONYMOUS)) {
- if (!(file = fget(fd))) {
- retval = -EBADF;
- goto out;
- }
+ if (!(file = fget(fd)))
+ return -EBADF;
/* Ok, bad taste hack follows, try to think in something else
* when reading this. */
@@ -1083,28+1089,30 @@ asmlinkage unsigned long irix_mmap32(unsigned long addr, size_t len, int prot, if (file)
fput(file);
-out:
return retval;
}
asmlinkage int irix_madvise(unsigned long addr, int len, int behavior)
{
- printk("[%s:%ld] Wheee.. irix_madvise(%08lx,%d,%d)\n",
+ printk("[%s:%d] Wheee.. irix_madvise(%08lx,%d,%d)\n",
current->comm, current->pid, addr, len, behavior);
+
return -EINVAL;
}
asmlinkage int irix_pagelock(char *addr, int len, int op)
{
- printk("[%s:%ld] Wheee.. irix_pagelock(%p,%d,%d)\n",
+ printk("[%s:%d] Wheee.. irix_pagelock(%p,%d,%d)\n",
current->comm, current->pid, addr, len, op);
+
return -EINVAL;
}
asmlinkage int irix_quotactl(struct pt_regs *regs)
{
- printk("[%s:%ld] Wheee.. irix_quotactl()\n",
+ printk("[%s:%d] Wheee.. irix_quotactl()\n",
current->comm, current->pid);
+
return -EINVAL;
}
@@ -1113,14+1121,14 @@ asmlinkage int irix_BSDsetpgrp(int pid, int pgrp) int error;
#ifdef DEBUG_PROCGRPS
- printk("[%s:%ld] BSDsetpgrp(%d, %d) ", current->comm, current->pid,
+ printk("[%s:%d] BSDsetpgrp(%d, %d) ", current->comm, current->pid,
pid, pgrp);
#endif
if(!pid)
pid = current->pid;
/* Wheee, weird sysv thing... */
- if((pgrp == 0) && (pid == current->pid))
+ if ((pgrp == 0) && (pid == current->pid))
error = sys_setsid();
else
error = sys_setpgid(pid, pgrp);
@@ -1134,8+1142,9 @@ asmlinkage int irix_BSDsetpgrp(int pid, int pgrp)
asmlinkage int irix_systeminfo(int cmd, char *buf, int cnt)
{
- printk("[%s:%ld] Wheee.. irix_systeminfo(%d,%p,%d)\n",
+ printk("[%s:%d] Wheee.. irix_systeminfo(%d,%p,%d)\n",
current->comm, current->pid, cmd, buf, cnt);
+
return -EINVAL;
}
@@ -1149,22+1158,17 @@ struct iuname {
asmlinkage int irix_uname(struct iuname *buf)
{
- int retval;
-
- lock_kernel();
- if(copy_to_user(system_utsname.sysname, buf->sysname, 65)
- || copy_to_user(system_utsname.nodename, buf->nodename, 65)
- || copy_to_user(system_utsname.release, buf->release, 65)
- || copy_to_user(system_utsname.version, buf->version, 65)
- || copy_to_user(system_utsname.machine, buf->machine, 65)) {
- retval = -EFAULT;
- goto out;
+ down_read(&uts_sem);
+ if (copy_to_user(system_utsname.sysname, buf->sysname, 65)
+ || copy_to_user(system_utsname.nodename, buf->nodename, 65)
+ || copy_to_user(system_utsname.release, buf->release, 65)
+ || copy_to_user(system_utsname.version, buf->version, 65)
+ || copy_to_user(system_utsname.machine, buf->machine, 65)) {
+ return -EFAULT;
}
- retval = 1;
+ up_read(&uts_sem);
-out:
- unlock_kernel();
- return retval;
+ return 1;
}
#undef DEBUG_XSTAT
@@ -1260,7+1264,7 @@ asmlinkage int irix_xstat(int version, char *filename, struct stat *statbuf) int retval;
#ifdef DEBUG_XSTAT
- printk("[%s:%ld] Wheee.. irix_xstat(%d,%s,%p) ",
+ printk("[%s:%d] Wheee.. irix_xstat(%d,%s,%p) ",
current->comm, current->pid, version, filename, statbuf);
#endif
switch(version) {
@@ -1309,7+1313,7 @@ asmlinkage int irix_lxstat(int version, char *filename, struct stat *statbuf) int error;
#ifdef DEBUG_XSTAT
- printk("[%s:%ld] Wheee.. irix_lxstat(%d,%s,%p) ",
+ printk("[%s:%d] Wheee.. irix_lxstat(%d,%s,%p) ",
current->comm, current->pid, version, filename, statbuf);
#endif
switch(version) {
@@ -1358,7+1362,7 @@ asmlinkage int irix_fxstat(int version, int fd, struct stat *statbuf) int error;
#ifdef DEBUG_XSTAT
- printk("[%s:%ld] Wheee.. irix_fxstat(%d,%d,%p) ",
+ printk("[%s:%d] Wheee.. irix_fxstat(%d,%d,%p) ",
current->comm, current->pid, version, fd, statbuf);
#endif
switch(version) {
@@ -1406,26+1410,27 @@ asmlinkage int irix_xmknod(int ver, char *filename, int mode, dev_t dev) {
int retval;
- printk("[%s:%ld] Wheee.. irix_xmknod(%d,%s,%x,%x)\n",
+ printk("[%s:%d] Wheee.. irix_xmknod(%d,%s,%x,%x)\n",
current->comm, current->pid, ver, filename, mode, (int) dev);
+
switch(ver) {
case 2:
retval = sys_mknod(filename, mode, dev);
- goto out;
+ break;
default:
retval = -EINVAL;
- goto out;
+ break;
};
-out:
return retval;
}
asmlinkage int irix_swapctl(int cmd, char *arg)
{
- printk("[%s:%ld] Wheee.. irix_swapctl(%d,%p)\n",
+ printk("[%s:%d] Wheee.. irix_swapctl(%d,%p)\n",
current->comm, current->pid, cmd, arg);
+
return -EINVAL;
}
@@ -1443,7+1448,7 @@ asmlinkage int irix_statvfs(char *fname, struct irix_statvfs *buf) struct statfs kbuf;
int error, i;
- printk("[%s:%ld] Wheee.. irix_statvfs(%s,%p)\n",
+ printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n",
current->comm, current->pid, fname, buf);
error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
if (error)
@@ -1468,11+1473,11 @@ asmlinkage int irix_statvfs(char *fname, struct irix_statvfs *buf) #else
__put_user(kbuf.f_fsid.val[0], &buf->f_fsid);
#endif
- for(i = 0; i < 16; i++)
+ for (i = 0; i < 16; i++)
__put_user(0, &buf->f_basetype[i]);
__put_user(0, &buf->f_flag);
__put_user(kbuf.f_namelen, &buf->f_namemax);
- for(i = 0; i < 32; i++)
+ for (i = 0; i < 32; i++)
__put_user(0, &buf->f_fstr[i]);
error = 0;
@@ -1489,7+1494,7 @@ asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf) struct file *file;
int error, i;
- printk("[%s:%ld] Wheee.. irix_fstatvfs(%d,%p)\n",
+ printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n",
current->comm, current->pid, fd, buf);
error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
asmlinkage int irix_priocntl(struct pt_regs *regs)
{
- printk("[%s:%ld] Wheee.. irix_priocntl()\n",
+ printk("[%s:%d] Wheee.. irix_priocntl()\n",
current->comm, current->pid);
+
return -EINVAL;
}
asmlinkage int irix_sigqueue(int pid, int sig, int code, int val)
{
- printk("[%s:%ld] Wheee.. irix_sigqueue(%d,%d,%d,%d)\n",
+ printk("[%s:%d] Wheee.. irix_sigqueue(%d,%d,%d,%d)\n",
current->comm, current->pid, pid, sig, code, val);
+
return -EINVAL;
}
@@ -1549,7+1556,7 @@ asmlinkage int irix_truncate64(char *name, int pad, int size1, int size2) {
int retval;
- if(size1) {
+ if (size1) {
retval = -EINVAL;
goto out;
}
@@ -1563,7+1570,7 @@ asmlinkage int irix_ftruncate64(int fd, int pad, int size1, int size2) {
int retval;
- if(size1) {
+ if (size1) {
retval = -EINVAL;
goto out;
}
asmlinkage int irix_dmi(struct pt_regs *regs)
{
- printk("[%s:%ld] Wheee.. irix_dmi()\n",
+ printk("[%s:%d] Wheee.. irix_dmi()\n",
current->comm, current->pid);
return -EINVAL;
@@ -1658,7+1665,7 @@ asmlinkage int irix_dmi(struct pt_regs *regs) asmlinkage int irix_pread(int fd, char *buf, int cnt, int off64,
int off1, int off2)
{
- printk("[%s:%ld] Wheee.. irix_pread(%d,%p,%d,%d,%d,%d)\n",
+ printk("[%s:%d] Wheee.. irix_pread(%d,%p,%d,%d,%d,%d)\n",
current->comm, current->pid, fd, buf, cnt, off64, off1, off2);
return -EINVAL;
@@ -1667,7+1674,7 @@ asmlinkage int irix_pread(int fd, char *buf, int cnt, int off64, asmlinkage int irix_pwrite(int fd, char *buf, int cnt, int off64,
int off1, int off2)
{
- printk("[%s:%ld] Wheee.. irix_pwrite(%d,%p,%d,%d,%d,%d)\n",
+ printk("[%s:%d] Wheee.. irix_pwrite(%d,%p,%d,%d,%d,%d)\n",
current->comm, current->pid, fd, buf, cnt, off64, off1, off2);
return -EINVAL;
@@ -1677,7+1684,7 @@ asmlinkage int irix_sgifastpath(int cmd, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)
{
- printk("[%s:%ld] Wheee.. irix_fastpath(%d,%08lx,%08lx,%08lx,%08lx,"
+ printk("[%s:%d] Wheee.. irix_fastpath(%d,%08lx,%08lx,%08lx,%08lx,"
"%08lx,%08lx)\n",
current->comm, current->pid, cmd, arg0, arg1, arg2,
arg3, arg4, arg5);
@@ -1702,7+1709,7 @@ asmlinkage int irix_statvfs64(char *fname, struct irix_statvfs64 *buf) struct statfs kbuf;
int error, i;
- printk("[%s:%ld] Wheee.. irix_statvfs(%s,%p)\n",
+ printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n",
current->comm, current->pid, fname, buf);
error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
if(error)
@@ -1748,7+1755,7 @@ asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf) struct file *file;
int error, i;
- printk("[%s:%ld] Wheee.. irix_fstatvfs(%d,%p)\n",
+ printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n",
current->comm, current->pid, fd, buf);
error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
asmlinkage int irix_getmountid(char *fname, unsigned long *midbuf)
{
- int error;
+ int err;
- printk("[%s:%ld] irix_getmountid(%s, %p)\n",
+ printk("[%s:%d] irix_getmountid(%s, %p)\n",
current->comm, current->pid, fname, midbuf);
- error = verify_area(VERIFY_WRITE, midbuf, (sizeof(unsigned long) * 4));
- if(error)
- goto out;
+ err = verify_area(VERIFY_WRITE, midbuf, (sizeof(unsigned long) * 4));
+ if (err)
+ return err;
/*
* The idea with this system call is that when trying to determine
@@ -1803,21+1810,20 @@ asmlinkage int irix_getmountid(char *fname, unsigned long *midbuf) * fsid of the filesystem to try and make the right decision, but
* we don't have this so for now. XXX
*/
- __put_user(0, &midbuf[0]);
- __put_user(0, &midbuf[1]);
- __put_user(0, &midbuf[2]);
- __put_user(0, &midbuf[3]);
- error = 0;
+ err |= __put_user(0, &midbuf[0]);
+ err |= __put_user(0, &midbuf[1]);
+ err |= __put_user(0, &midbuf[2]);
+ err |= __put_user(0, &midbuf[3]);
-out:
- return error;
+ return err;
}
asmlinkage int irix_nsproc(unsigned long entry, unsigned long mask,
unsigned long arg, unsigned long sp, int slen)
{
- printk("[%s:%ld] Wheee.. irix_nsproc(%08lx,%08lx,%08lx,%08lx,%d)\n",
+ printk("[%s:%d] Wheee.. irix_nsproc(%08lx,%08lx,%08lx,%08lx,%d)\n",
current->comm, current->pid, entry, mask, arg, sp, slen);
+
return -EINVAL;
}
@@ -1879,7+1885,7 @@ asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count int error;
#ifdef DEBUG_GETDENTS
- printk("[%s:%ld] ngetdents(%d, %p, %d, %p) ", current->comm,
+ printk("[%s:%d] ngetdents(%d, %p, %d, %p) ", current->comm,
current->pid, fd, dirent, count, eob);
#endif
error = -EBADF;
@@ -1979,11+1985,11 @@ asmlinkage int irix_getdents64(int fd, void *dirent, int cnt) goto out;
error = -EFAULT;
- if(!access_ok(VERIFY_WRITE, dirent, cnt))
+ if (!access_ok(VERIFY_WRITE, dirent, cnt))
goto out_f;
error = -EINVAL;
- if(cnt < (sizeof(struct irix_dirent64) + 255))
+ if (cnt < (sizeof(struct irix_dirent64) + 255))
goto out_f;
buf.curr = (struct irix_dirent64 *) dirent;
@@ -2026,12+2032,12 @@ asmlinkage int irix_ngetdents64(int fd, void *dirent, int cnt, int *eob) goto out;
error = -EFAULT;
- if(!access_ok(VERIFY_WRITE, dirent, cnt) ||
- !access_ok(VERIFY_WRITE, eob, sizeof(*eob)))
+ if (!access_ok(VERIFY_WRITE, dirent, cnt) ||
+ !access_ok(VERIFY_WRITE, eob, sizeof(*eob)))
goto out_f;
error = -EINVAL;
- if(cnt < (sizeof(struct irix_dirent64) + 255))
+ if (cnt < (sizeof(struct irix_dirent64) + 255))
goto out_f;
*eob = 0;
@@ -2063,44+2069,44 @@ asmlinkage int irix_uadmin(unsigned long op, unsigned long func, unsigned long a {
int retval;
- switch(op) {
+ switch (op) {
case 1:
/* Reboot */
- printk("[%s:%ld] irix_uadmin: Wants to reboot...\n",
+ printk("[%s:%d] irix_uadmin: Wants to reboot...\n",
current->comm, current->pid);
retval = -EINVAL;
goto out;
case 2:
/* Shutdown */
- printk("[%s:%ld] irix_uadmin: Wants to shutdown...\n",
+ printk("[%s:%d] irix_uadmin: Wants to shutdown...\n",
current->comm, current->pid);
retval = -EINVAL;
goto out;
case 4:
/* Remount-root */
- printk("[%s:%ld] irix_uadmin: Wants to remount root...\n",
+ printk("[%s:%d] irix_uadmin: Wants to remount root...\n",
current->comm, current->pid);
retval = -EINVAL;
goto out;
case 8:
/* Kill all tasks. */
- printk("[%s:%ld] irix_uadmin: Wants to kill all tasks...\n",
+ printk("[%s:%d] irix_uadmin: Wants to kill all tasks...\n",
current->comm, current->pid);
retval = -EINVAL;
goto out;
case 256:
/* Set magic mushrooms... */
- printk("[%s:%ld] irix_uadmin: Wants to set magic mushroom[%d]...\n",
+ printk("[%s:%d] irix_uadmin: Wants to set magic mushroom[%d]...\n",
current->comm, current->pid, (int) func);
retval = -EINVAL;
goto out;
default:
- printk("[%s:%ld] irix_uadmin: Unknown operation [%d]...\n",
+ printk("[%s:%d] irix_uadmin: Unknown operation [%d]...\n",
current->comm, current->pid, (int) op);
retval = -EINVAL;
goto out;
@@ -2122,20+2128,20 @@ asmlinkage int irix_utssys(char *inbuf, int arg, int type, char *outbuf)
case 2:
/* ustat() */
- printk("[%s:%ld] irix_utssys: Wants to do ustat()\n",
+ printk("[%s:%d] irix_utssys: Wants to do ustat()\n",
current->comm, current->pid);
retval = -EINVAL;
goto out;
case 3:
/* fusers() */
- printk("[%s:%ld] irix_utssys: Wants to do fusers()\n",
+ printk("[%s:%d] irix_utssys: Wants to do fusers()\n",
current->comm, current->pid);
retval = -EINVAL;
goto out;
default:
- printk("[%s:%ld] irix_utssys: Wants to do unknown type[%d]\n",
+ printk("[%s:%d] irix_utssys: Wants to do unknown type[%d]\n",
current->comm, current->pid, (int) type);
retval = -EINVAL;
goto out;
@@ -2157,7+2163,7 @@ asmlinkage int irix_fcntl(int fd, int cmd, int arg) int retval;
#ifdef DEBUG_FCNTL
- printk("[%s:%ld] irix_fcntl(%d, %d, %d) ", current->comm,
+ printk("[%s:%d] irix_fcntl(%d, %d, %d) ", current->comm,
current->pid, fd, cmd, arg);
#endif
if (cmd == IRIX_F_ALLOCSP){
@@ -2176,26+2182,26 @@ asmlinkage int irix_ulimit(int cmd, int arg)
switch(cmd) {
case 1:
- printk("[%s:%ld] irix_ulimit: Wants to get file size limit.\n",
+ printk("[%s:%d] irix_ulimit: Wants to get file size limit.\n",
current->comm, current->pid);
retval = -EINVAL;
goto out;
case 2:
- printk("[%s:%ld] irix_ulimit: Wants to set file size limit.\n",
+ printk("[%s:%d] irix_ulimit: Wants to set file size limit.\n",
current->comm, current->pid);
retval = -EINVAL;
goto out;
case 3:
- printk("[%s:%ld] irix_ulimit: Wants to get brk limit.\n",
+ printk("[%s:%d] irix_ulimit: Wants to get brk limit.\n",
current->comm, current->pid);
retval = -EINVAL;
goto out;
case 4:
#if 0
- printk("[%s:%ld] irix_ulimit: Wants to get fd limit.\n",
+ printk("[%s:%d] irix_ulimit: Wants to get fd limit.\n",
current->comm, current->pid);
retval = -EINVAL;
goto out;
@@ -2204,13+2210,13 @@ asmlinkage int irix_ulimit(int cmd, int arg) goto out;
case 5:
- printk("[%s:%ld] irix_ulimit: Wants to get txt offset.\n",
+ printk("[%s:%d] irix_ulimit: Wants to get txt offset.\n",
current->comm, current->pid);
retval = -EINVAL;
goto out;
default:
- printk("[%s:%ld] irix_ulimit: Unknown command [%d].\n",
+ printk("[%s:%d] irix_ulimit: Unknown command [%d].\n",
current->comm, current->pid, cmd);
retval = -EINVAL;
goto out;
asmlinkage int irix_unimp(struct pt_regs *regs)
{
- printk("irix_unimp [%s:%ld] v0=%d v1=%d a0=%08lx a1=%08lx a2=%08lx "
+ printk("irix_unimp [%s:%d] v0=%d v1=%d a0=%08lx a1=%08lx a2=%08lx "
"a3=%08lx\n", current->comm, current->pid,
(int) regs->regs[2], (int) regs->regs[3],
regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]);
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
- *
- * $Id: sysmips.c,v 1.8 2000/02/05 06:47:08 ralf Exp $
+ * Copyright (C) 1995, 1996, 1997, 2000 by Ralf Baechle
*/
#include <linux/errno.h>
#include <linux/linkage.h>
@@ -51,45+49,48 @@ sys_sysmips(int cmd, int arg1, int arg2, int arg3) {
int *p;
char *name;
- int flags, tmp, len, retval;
+ int flags, tmp, len, retval, errno;
+
+ switch(cmd) {
+ case SETNAME: {
+ char nodename[__NEW_UTS_LEN + 1];
- lock_kernel();
- switch(cmd)
- {
- case SETNAME:
- retval = -EPERM;
if (!capable(CAP_SYS_ADMIN))
- goto out;
+ return -EPERM;
name = (char *) arg1;
- len = strlen_user(name);
-
- retval = len;
- if (len < 0)
- goto out;
- retval = -EINVAL;
- if (len == 0 || len > __NEW_UTS_LEN)
- goto out;
+ len = strncpy_from_user(nodename, name, sizeof(nodename));
+ if (len < 0)
+ return -EFAULT;
- /* Fiiiixmeeee... */
- copy_from_user(system_utsname.nodename, name, len);
- system_utsname.nodename[len] = '\0';
- retval = 0;
- goto out;
+ down_write(&uts_sem);
+ strncpy(system_utsname.nodename, name, len);
+ up_write(&uts_sem);
+ system_utsname.nodename[len] = '\0';
+ return 0;
+ }
- case MIPS_ATOMIC_SET:
+ case MIPS_ATOMIC_SET: {
/* This is broken in case of page faults and SMP ...
- Risc/OS fauls after maximum 20 tries with EAGAIN. */
+ Risc/OS faults after maximum 20 tries with EAGAIN. */
+ unsigned int tmp;
+
p = (int *) arg1;
- retval = verify_area(VERIFY_WRITE, p, sizeof(*p));
- if (retval)
- goto out;
+ errno = verify_area(VERIFY_WRITE, p, sizeof(*p));
+ if (errno)
+ return errno;
+ errno = 0;
save_and_cli(flags);
- retval = *p;
- *p = arg2;
+ errno |= __get_user(tmp, p);
+ errno |= __put_user(arg2, p);
restore_flags(flags);
- goto out;
+
+ if (errno)
+ return tmp;
+
+ return tmp; /* This is broken ... */
+ }
case MIPS_FIXADE:
tmp = current->thread.mflags & ~3;
@@ -112,7+113,6 @@ sys_sysmips(int cmd, int arg1, int arg2, int arg3) }
out:
- unlock_kernel();
return retval;
}
-/* $Id: time.c,v 1.14 2000/01/26 00:07:44 ralf Exp $
- *
- * Copyright (C) 1991, 1992, 1995 Linus Torvalds
- * Copyright (C) 1996, 1997, 1998 Ralf Baechle
+/*
+ * Copyright (C) 1991, 1992, 1995 Linus Torvalds
+ * Copyright (C) 1996 - 2000 Ralf Baechle
*
* This file contains the time handling details for PC-style clocks as
* found in some MIPS systems.
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
#include <asm/bootinfo.h>
#include <asm/mipsregs.h>
#include <linux/timex.h>
extern volatile unsigned long lost_ticks;
+unsigned long r4k_interval = 0;
+extern rwlock_t xtime_lock;
/*
* Change this if you have some constant time drift
@@ -219,7+221,7 @@ void do_gettimeofday(struct timeval *tv) {
unsigned long flags;
- save_and_cli(flags);
+ read_lock_irqsave (&xtime_lock, flags);
*tv = xtime;
tv->tv_usec += do_gettimeoffset();
@@ -230,7+232,7 @@ void do_gettimeofday(struct timeval *tv) if (lost_ticks)
tv->tv_usec += USECS_PER_JIFFY;
- restore_flags(flags);
+ read_unlock_irqrestore (&xtime_lock, flags);
if (tv->tv_usec >= 1000000) {
tv->tv_usec -= 1000000;
@@ -240,7+242,7 @@ void do_gettimeofday(struct timeval *tv)
void do_settimeofday(struct timeval *tv)
{
- cli();
+ write_lock_irq (&xtime_lock);
/* This is revolting. We need to set the xtime.tv_usec
* correctly. However, the value in this location is
* is value at the last tick.
@@ -259,7+261,7 @@ void do_settimeofday(struct timeval *tv) time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
- sti();
+ write_unlock_irq (&xtime_lock);
}
/*
@@ -355,7+357,6 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) dist = period / 4;
}
#endif
-#ifdef CONFIG_PROFILE
if(!user_mode(regs)) {
if (prof_buffer && current->pid) {
extern int _stext;
@@ -373,7+374,6 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) atomic_inc((atomic_t *)&prof_buffer[pc]);
}
}
-#endif
do_timer(regs);
/*
@@ -381,22+381,26 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
+ read_lock (&xtime_lock);
if ((time_status & STA_UNSYNC) == 0 &&
xtime.tv_sec > last_rtc_update + 660 &&
xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
- xtime.tv_usec <= 500000 + ((unsigned) tick) / 2)
+ xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
if (set_rtc_mmss(xtime.tv_sec) == 0)
last_rtc_update = xtime.tv_sec;
else
last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+ }
/* As we return to user mode fire off the other CPU schedulers.. this is
basically because we don't yet share IRQ's around. This message is
rigged to be safe on the 386 - basically it's a hack, so don't look
closely for now.. */
/*smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); */
+ read_unlock (&xtime_lock);
}
-static void r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static inline void
+r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
unsigned int count;
@@ -408,6+412,18 @@ static void r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) timerhi += (count < timerlo); /* Wrap around */
timerlo = count;
+#ifdef CONFIG_SGI_IP22
+ /* Since we don't get anything but r4k timer interrupts, we need to
+ * set this up so that we'll get one next time. Fortunately since we
+ * have timerhi/timerlo, we don't care so much if we miss one. So
+ * we need only ask for the next in r4k_interval counts. On other
+ * archs we have a real timer, so we don't want this.
+ */
+ write_32bit_cp0_register (CP0_COMPARE,
+ (unsigned long) (count + r4k_interval));
+ kstat.irqs[0][irq]++;
+#endif
+
timer_interrupt(irq, dev_id, regs);
if (!jiffies)
@@ -421,6+437,12 @@ static void r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) }
}
+void indy_r4k_timer_interrupt (struct pt_regs *regs)
+{
+ static const int INDY_R4K_TIMER_IRQ = 7;
+ r4k_timer_interrupt (INDY_R4K_TIMER_IRQ, NULL, regs);
+}
+
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
* Assumes input in normal date format, i.e. 1980-12-31 23:59:59
* => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
@@ -500,7+522,7 @@ void (*board_time_init)(struct irqaction *irq);
void __init time_init(void)
{
- unsigned int epoch, year, mon, day, hour, min, sec;
+ unsigned int epoch = 0, year, mon, day, hour, min, sec;
int i;
/* The Linux interpretation of the CMOS clock register contents:
@@ -543,8+565,10 @@ void __init time_init(void) }
year += epoch;
+ write_lock_irq (&xtime_lock);
xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
xtime.tv_usec = 0;
+ write_unlock_irq (&xtime_lock);
init_cycle_counter();
-/* $Id: traps.c,v 1.28 2000/03/13 10:33:02 raiko Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
@@ -209,7+208,7 @@ extern void __die(const char * str, struct pt_regs * regs, const char *where, printk(" in %s, line %ld", where, line);
printk(":\n");
show_regs(regs);
- printk("Process %s (pid: %ld, stackpage=%08lx)\n",
+ printk("Process %s (pid: %d, stackpage=%08lx)\n",
current->comm, current->pid, (unsigned long) current);
show_stack((unsigned int *) regs->regs[29]);
show_trace((unsigned int *) regs->regs[29]);
@@ -230,7+229,7 @@ void __die_if_kernel(const char * str, struct pt_regs * regs, const char *where, extern const struct exception_table_entry __start___dbe_table[];
extern const struct exception_table_entry __stop___dbe_table[];
-static void __declare_dbe_table(void)
+void __declare_dbe_table(void)
{
__asm__ __volatile__(
".section\t__dbe_table,\"a\"\n\t"
@@ -332,7+331,6 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31) return;
}
#endif
- lock_kernel();
if (fcr31 & 0x20000) {
/* Retry instruction with flush to zero ... */
if (!(fcr31 & (1<<24))) {
@@ -344,7+342,7 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31) "ctc1\t%0,$31"
: /* No outputs */
: "r" (fcr31));
- goto out;
+ return;
}
pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0);
if (get_user(insn, (unsigned int *)pc)) {
@@ -358,12+356,9 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31) }
if (compute_return_epc(regs))
- goto out;
+ return;
//force_sig(SIGFPE, current);
printk(KERN_DEBUG "Should send SIGFPE to %s\n", current->comm);
-
-out:
- unlock_kernel();
}
static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
@@ -430,17+425,15 @@ void do_ri(struct pt_regs *regs) {
unsigned int opcode;
- lock_kernel();
if (!get_insn_opcode(regs, &opcode)) {
if ((opcode & OPCODE) == LL)
simulate_ll(regs, opcode);
if ((opcode & OPCODE) == SC)
simulate_sc(regs, opcode);
} else {
- printk("[%s:%ld] Illegal instruction at %08lx ra=%08lx\n",
+ printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n",
current->comm, current->pid, regs->cp0_epc, regs->regs[31]);
}
- unlock_kernel();
if (compute_return_epc(regs))
return;
force_sig(SIGILL, current);
@@ -526,10+519,8 @@ void simulate_sc(struct pt_regs *regp, unsigned int opcode)
void do_ri(struct pt_regs *regs)
{
- lock_kernel();
- printk("[%s:%ld] Illegal instruction at %08lx ra=%08lx\n",
+ printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n",
current->comm, current->pid, regs->cp0_epc, regs->regs[31]);
- unlock_kernel();
if (compute_return_epc(regs))
return;
force_sig(SIGILL, current);
$(CC) $(CFLAGS) -c $< -o $*.o
L_TARGET = lib.a
-L_OBJS = csum_partial.o csum_partial_copy.o floppy-std.o \
- floppy-no.o ide-std.o ide-no.o kbd-std.o kbd-no.o rtc-std.o \
- rtc-no.o memcpy.o memset.o strlen_user.o strncpy_user.o \
- strnlen_user.o watch.o
+
+L_OBJS = csum_partial.o csum_partial_copy.o \
+ rtc-std.o rtc-no.o memcpy.o memset.o watch.o\
+ strlen_user.o strncpy_user.o strnlen_user.o
ifdef CONFIG_CPU_R3000
L_OBJS += r3k_dump_tlb.o
L_OBJS += dump_tlb.o
endif
+ifdef CONFIG_BLK_DEV_FD
+ L_OBJS += floppy-no.o floppy-std.o
+endif
+
+ifdef CONFIG_IDE
+ L_OBJS += ide-std.o ide-no.o
+endif
+
+ifdef CONFIG_PC_KEYB
+ L_OBJS += kbd-std.o kbd-no.o
+endif
+
include $(TOPDIR)/Rules.make
@@ -47,7+47,7 @@ dump_tlb(int first, int last) printk("Index: %2d ", i);
printk("va=%08lx asid=%08lx"
- " [pa=%06lx n=%d d=%d v=%d g=%ld]",
+ " [pa=%06lx n=%d d=%d v=%d g=%d]",
(entryhi & 0xffffe000),
entryhi & 0xfc0,
entrylo0 & PAGE_MASK,
-/* $Id: fault.c,v 1.15 2000/02/04 07:40:23 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
+ * Copyright (C) 1995 - 2000 by Ralf Baechle
*/
#include <linux/signal.h>
#include <linux/sched.h>
@@ -47,9+46,10 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, struct vm_area_struct * vma;
struct task_struct *tsk = current;
struct mm_struct *mm = tsk->mm;
- int si_code = SEGV_MAPERR;
unsigned long fixup;
+ siginfo_t info;
+ info.si_code = SEGV_MAPERR;
/*
* If we're in an interrupt or have no user
* context, we must not take the fault..
@@ -75,7+75,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, * we can handle it..
*/
good_area:
- si_code = SEGV_ACCERR;
+ info.si_code = SEGV_ACCERR;
if (write) {
if (!(vma->vm_flags & VM_WRITE))
@@ -114,7+114,6 @@ bad_area: up(&mm->mmap_sem);
if (user_mode(regs)) {
- struct siginfo si;
tsk->thread.cp0_badvaddr = address;
tsk->thread.error_code = write;
#if 0
@@ -126,10+125,11 @@ bad_area: (unsigned long) regs->cp0_epc,
(unsigned long) regs->regs[31]);
#endif
- si.si_signo = SIGSEGV;
- si.si_code = si_code;
- si.si_addr = (void *) address;
- force_sig_info(SIGSEGV, &si, tsk);
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ /* info.si_code has been set above */
+ info.si_addr = (void *) address;
+ force_sig_info(SIGSEGV, &info, tsk);
return;
}
@@ -177,7+177,11 @@ do_sigbus: * or user mode.
*/
tsk->thread.cp0_badvaddr = address;
- force_sig(SIGBUS, tsk);
+ info.si_code = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_ADRERR;
+ info.si_addr = (void *) address;
+ force_sig_info(SIGBUS, &info, tsk);
/* Kernel mode? Handle exceptions or die */
if (!user_mode(regs))
@@ -256,12+256,16 @@ void __init paging_init(void) max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
low = max_low_pfn;
+#if defined(CONFIG_PCI) || defined(CONFIG_ISA)
if (low < max_dma)
zones_size[ZONE_DMA] = low;
else {
zones_size[ZONE_DMA] = max_dma;
zones_size[ZONE_NORMAL] = low - max_dma;
}
+#else
+ zones_size[ZONE_DMA] = low;
+#endif
free_area_init(zones_size);
}
@@ -151,15+151,15 @@ unsigned long __init r3k_cache_size(unsigned long ca_flags)
static void __init probe_dcache(void)
{
- dcache_size = r3k_cache_size(ST0_DE);
+ dcache_size = r3k_cache_size(ST0_ISC);
printk("Primary data cache %dkb, linesize 4 bytes\n",
dcache_size >> 10);
}
static void __init probe_icache(void)
{
- icache_size = r3k_cache_size(ST0_DE|ST0_CE);
- printk("Primary instruction cache %dkb, linesize 8 bytes\n",
+ icache_size = r3k_cache_size(ST0_ISC|ST0_SWC);
+ printk("Primary instruction cache %dkb, linesize 4 bytes\n",
icache_size >> 10);
}
@@ -174,43+174,43 @@ static void r3k_flush_icache_range(unsigned long start, unsigned long size) save_and_cli(flags);
/* isolate cache space */
- write_32bit_cp0_register(CP0_STATUS, (ST0_DE|ST0_CE|flags)&~ST0_IEC);
+ write_32bit_cp0_register(CP0_STATUS, (ST0_ISC|ST0_SWC|flags)&~ST0_IEC);
- for (i = 0; i < size; i += 0x100) {
+ for (i = 0; i < size; i += 0x080) {
asm ( "sb\t$0,0x000(%0)\n\t"
+ "sb\t$0,0x004(%0)\n\t"
"sb\t$0,0x008(%0)\n\t"
+ "sb\t$0,0x00c(%0)\n\t"
"sb\t$0,0x010(%0)\n\t"
+ "sb\t$0,0x014(%0)\n\t"
"sb\t$0,0x018(%0)\n\t"
- "sb\t$0,0x020(%0)\n\t"
+ "sb\t$0,0x01c(%0)\n\t"
+ "sb\t$0,0x020(%0)\n\t"
+ "sb\t$0,0x024(%0)\n\t"
"sb\t$0,0x028(%0)\n\t"
+ "sb\t$0,0x02c(%0)\n\t"
"sb\t$0,0x030(%0)\n\t"
+ "sb\t$0,0x034(%0)\n\t"
"sb\t$0,0x038(%0)\n\t"
- "sb\t$0,0x040(%0)\n\t"
+ "sb\t$0,0x03c(%0)\n\t"
+ "sb\t$0,0x040(%0)\n\t"
+ "sb\t$0,0x044(%0)\n\t"
"sb\t$0,0x048(%0)\n\t"
+ "sb\t$0,0x04c(%0)\n\t"
"sb\t$0,0x050(%0)\n\t"
+ "sb\t$0,0x054(%0)\n\t"
"sb\t$0,0x058(%0)\n\t"
- "sb\t$0,0x060(%0)\n\t"
+ "sb\t$0,0x05c(%0)\n\t"
+ "sb\t$0,0x060(%0)\n\t"
+ "sb\t$0,0x064(%0)\n\t"
"sb\t$0,0x068(%0)\n\t"
+ "sb\t$0,0x06c(%0)\n\t"
"sb\t$0,0x070(%0)\n\t"
+ "sb\t$0,0x074(%0)\n\t"
"sb\t$0,0x078(%0)\n\t"
- "sb\t$0,0x080(%0)\n\t"
- "sb\t$0,0x088(%0)\n\t"
- "sb\t$0,0x090(%0)\n\t"
- "sb\t$0,0x098(%0)\n\t"
- "sb\t$0,0x0a0(%0)\n\t"
- "sb\t$0,0x0a8(%0)\n\t"
- "sb\t$0,0x0b0(%0)\n\t"
- "sb\t$0,0x0b8(%0)\n\t"
- "sb\t$0,0x0c0(%0)\n\t"
- "sb\t$0,0x0c8(%0)\n\t"
- "sb\t$0,0x0d0(%0)\n\t"
- "sb\t$0,0x0d8(%0)\n\t"
- "sb\t$0,0x0e0(%0)\n\t"
- "sb\t$0,0x0e8(%0)\n\t"
- "sb\t$0,0x0f0(%0)\n\t"
- "sb\t$0,0x0f8(%0)\n\t"
+ "sb\t$0,0x07c(%0)\n\t"
: : "r" (p) );
- p += 0x100;
+ p += 0x080;
}
restore_flags(flags);
@@ -221,13+221,13 @@ static void r3k_flush_dcache_range(unsigned long start, unsigned long size) unsigned long i, flags;
volatile unsigned char *p = (char *)start;
- if (size > icache_size)
- size = icache_size;
+ if (size > dcache_size)
+ size = dcache_size;
save_and_cli(flags);
/* isolate cache space */
- write_32bit_cp0_register(CP0_STATUS, (ST0_DE|flags)&~ST0_IEC);
+ write_32bit_cp0_register(CP0_STATUS, (ST0_ISC|flags)&~ST0_IEC);
for (i = 0; i < size; i += 0x080) {
asm ( "sb\t$0,0x000(%0)\n\t"
@@ -376,7+376,7 @@ static void r3k_flush_cache_sigtramp(unsigned long addr)
save_and_cli(flags);
- write_32bit_cp0_register(CP0_STATUS, (ST0_DE|ST0_CE|flags)&~ST0_IEC);
+ write_32bit_cp0_register(CP0_STATUS, (ST0_ISC|ST0_SWC|flags)&~ST0_IEC);
asm ( "sb\t$0,0x000(%0)\n\t"
"sb\t$0,0x008(%0)\n\t"
@@ -108,7+108,8 @@ remove_mapping (struct task_struct *task, unsigned long start, unsigned long end
void *vmalloc_uncached (unsigned long size)
{
- return vmalloc_prot (size, PAGE_KERNEL_UNCACHED);
+ return __vmalloc (size, GFP_KERNEL | __GFP_HIGHMEM,
+ PAGE_KERNEL_UNCACHED);
}
static inline void free_pte(pte_t page)
-# $Id: Makefile,v 1.7 1999/05/07 18:00:16 ulfc Exp $
+#
# Makefile for the SGI specific kernel interface routines
# under Linux.
#
$(CC) $(CFLAGS) -c $< -o $*.o
OBJS = indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o \
- system.o indy_timer.o indyIRQ.o reset.o setup.o time.o
+ system.o indyIRQ.o reset.o setup.o time.o
ifdef CONFIG_SGI_PROM_CONSOLE
OBJS += promcon.o
endif
-/* $Id: indyIRQ.S,v 1.3 1998/03/22 23:27:17 ralf Exp $
+/*
* indyIRQ.S: Interrupt exception dispatch code for FullHouse and
* Guiness.
*
/* Wheee, a timer interrupt. */
move a0, sp
- jal indy_timer_interrupt
+ jal indy_r4k_timer_interrupt
nop # delay slot
j ret_from_irq
-/* $Id: setup.c,v 1.29 2000/01/27 01:05:23 ralf Exp $
- *
+/*
* setup.c: SGI specific setup, including init of the feature struct.
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
@@ -37,6+36,8 @@ static int remote_debug = 0; extern void console_setup(char *);
#endif
+extern unsigned long r4k_interval; /* Cycle counter ticks per 1/HZ seconds */
+
extern struct rtc_ops indy_rtc_ops;
void indy_reboot_setup(void);
void sgi_volume_set(unsigned char);
@@ -136,6+137,98 @@ int __init page_is_ram(unsigned long pagenr) return 0;
}
+void (*board_time_init)(struct irqaction *irq);
+
+static unsigned long dosample(volatile unsigned char *tcwp,
+ volatile unsigned char *tc2p)
+{
+ unsigned long ct0, ct1;
+ unsigned char msb, lsb;
+
+ /* Start the counter. */
+ *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MRGEN);
+ *tc2p = (SGINT_TCSAMP_COUNTER & 0xff);
+ *tc2p = (SGINT_TCSAMP_COUNTER >> 8);
+
+ /* Get initial counter invariant */
+ ct0 = read_32bit_cp0_register(CP0_COUNT);
+
+ /* Latch and spin until top byte of counter2 is zero */
+ do {
+ *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT);
+ lsb = *tc2p;
+ msb = *tc2p;
+ ct1 = read_32bit_cp0_register(CP0_COUNT);
+ } while(msb);
+
+ /* Stop the counter. */
+ *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MSWST);
+
+ /* Return the difference, this is how far the r4k counter increments
+ * for every 1/HZ seconds. We round off the the nearest 1 MHz of
+ * master clock (= 1000000 / 100 / 2 = 5000 count).
+ */
+ return ((ct1 - ct0) / 5000) * 5000;
+}
+
+#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
+
+void sgi_time_init (struct irqaction *irq) {
+ /* Here we need to calibrate the cycle counter to at least be close.
+ * We don't need to actually register the irq handler because that's
+ * all done in indyIRQ.S.
+ */
+ struct sgi_ioc_timers *p;
+ volatile unsigned char *tcwp, *tc2p;
+ unsigned long r4k_ticks[3];
+ unsigned long r4k_next;
+
+ /* Figure out the r4k offset, the algorithm is very simple
+ * and works in _all_ cases as long as the 8254 counter
+ * register itself works ok (as an interrupt driving timer
+ * it does not because of bug, this is why we are using
+ * the onchip r4k counter/compare register to serve this
+ * purpose, but for r4k_offset calculation it will work
+ * ok for us). There are other very complicated ways
+ * of performing this calculation but this one works just
+ * fine so I am not going to futz around. ;-)
+ */
+ p = ioc_timers;
+ tcwp = &p->tcword;
+ tc2p = &p->tcnt2;
+
+ printk("Calibrating system timer... ");
+ dosample(tcwp, tc2p); /* First sample. */
+ dosample(tcwp, tc2p); /* Eat one. */
+ r4k_ticks[0] = dosample(tcwp, tc2p); /* Second sample. */
+ dosample(tcwp, tc2p); /* Eat another. */
+ r4k_ticks[1] += dosample (tcwp, tc2p); /* Third sample. */
+
+ if (r4k_ticks[0] != r4k_ticks[1]) {
+ printk ("warning: timer counts differ, retrying...");
+ dosample (tcwp, tc2p);
+ r4k_ticks[2] = dosample (tcwp, tc2p);
+ if (r4k_ticks[2] == r4k_ticks[0]
+ || r4k_ticks[2] == r4k_ticks[1])
+ r4k_interval = r4k_ticks[2];
+ else {
+ printk ("disagreement, using average...");
+ r4k_interval = (r4k_ticks[0] + r4k_ticks[1]
+ + r4k_ticks[2]) / 3;
+ }
+ } else
+ r4k_interval = r4k_ticks[0];
+
+ printk("%d [%d.%02d MHz CPU]\n", (int) r4k_interval,
+ (int) (r4k_interval / 5000), (int) (r4k_interval % 5000) / 50);
+
+ /* Set ourselves up for future interrupts */
+ r4k_next = (read_32bit_cp0_register(CP0_COUNT) + r4k_interval);
+ write_32bit_cp0_register(CP0_COMPARE, r4k_next);
+ set_cp0_status(ST0_IM, ALLINTS);
+ sti ();
+}
+
void __init sgi_setup(void)
{
#ifdef CONFIG_SERIAL_CONSOLE
@@ -147,6+240,7 @@ void __init sgi_setup(void)
irq_setup = sgi_irq_setup;
+ board_time_init = sgi_time_init;
/* Init the INDY HPC I/O controller. Need to call this before
* fucking with the memory controller because it needs to know the
@@ -229,5+323,5 @@ void __init sgi_setup(void) #ifdef CONFIG_VIDEO_VINO
init_vino();
#endif
+
}
-__initcall(rs_init);
-/* $Id: time.c,v 1.2 1998/04/05 11:24:00 ralf Exp $
- * time.c: Generic SGI time_init() code, this will dispatch to the
- * appropriate per-architecture time/counter init code.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- */
-#include <linux/init.h>
-
-extern void indy_timer_init(void);
-
-void __init time_init(void)
-{
- /* XXX assume INDY for now XXX */
- indy_timer_init();
-}
+/*
+ * time.c: Generic SGI handler for (spurious) 8254 interrupts
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <asm/sgialib.h>
+
+void indy_8254timer_irq(void)
+{
+ int cpu = smp_processor_id();
+ int irq = 4;
+
+ irq_enter(cpu);
+ kstat.irqs[0][irq]++;
+ printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n");
+ prom_getchar();
+ prom_imode();
+ irq_exit(cpu);
+}
-/* $Id: pci.c,v 1.9 1999/12/04 03:59:00 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* SNI specific PCI support for RM200/RM300.
*
- * Copyright (C) 1997, 1998, 1999 Ralf Baechle
+ * Copyright (C) 1997 - 2000 Ralf Baechle
*/
#include <linux/config.h>
#include <linux/kernel.h>
+#include <linux/init.h>
#include <linux/pci.h>
#include <linux/types.h>
#include <asm/byteorder.h>
@@ -23,10+23,11 @@ do { \ return -1; \
*(volatile u32 *)PCIMT_CONFIG_ADDRESS = \
((dev->bus->number & 0xff) << 0x10) | \
- ((dev->dev_fn & 0xff) << 0x08) | \
+ ((dev->devfn & 0xff) << 0x08) | \
(where & 0xfc); \
} while(0);
+#if 0
/* To do: Bring this uptodate ... */
static void pcimt_pcibios_fixup (void)
{
@@ -62,6+63,7 @@ static void pcimt_pcibios_fixup (void) }
}
}
+#endif
/*
* We can't address 8 and 16 bit words directly. Instead we have to
@@ -150,4+152,67 @@ struct pci_ops sni_pci_ops = { pcimt_write_config_dword
};
+void __init
+pcibios_fixup_bus(struct pci_bus *b)
+{
+}
+
+void
+pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+ struct resource *res, int resource)
+{
+ u32 new, check;
+ int reg;
+
+ new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
+ if (resource < 6) {
+ reg = PCI_BASE_ADDRESS_0 + 4*resource;
+ } else if (resource == PCI_ROM_RESOURCE) {
+ res->flags |= PCI_ROM_ADDRESS_ENABLE;
+ new |= PCI_ROM_ADDRESS_ENABLE;
+ reg = dev->rom_base_reg;
+ } else {
+ /* Somebody might have asked allocation of a non-standard resource */
+ return;
+ }
+
+ pci_write_config_dword(dev, reg, new);
+ pci_read_config_dword(dev, reg, &check);
+ if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
+ printk(KERN_ERR "PCI: Error while updating region "
+ "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+ new, check);
+ }
+}
+
+void __init pcibios_init(void)
+{
+ struct pci_ops *ops = &sni_pci_ops;
+
+ pci_scan_bus(0, ops, NULL);
+}
+
+int __init pcibios_enable_device(struct pci_dev *dev)
+{
+ /* Not needed, since we enable all devices at startup. */
+ return 0;
+}
+
+void __init
+pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+{
+}
+
+char * __init
+pcibios_setup(char *str)
+{
+ /* Nothing to do for now. */
+
+ return str;
+}
+
+struct pci_fixup pcibios_fixups[] = {
+ { 0 }
+};
+
#endif /* CONFIG_PCI */
-/* $Id: setup.c,v 1.13 1999/12/04 03:59:00 ralf Exp $
- *
+/*
* Setup pointers to hardware-dependent routines.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1996, 1997, 1998 by Ralf Baechle
+ * Copyright (C) 1996, 1997, 1998, 2000 by Ralf Baechle
*/
#include <asm/ptrace.h>
#include <linux/config.h>
#include <linux/console.h>
#include <linux/fb.h>
#include <linux/pc_keyb.h>
+#include <linux/ide.h>
#include <asm/bcache.h>
#include <asm/bootinfo.h>
#include <asm/keyboard.h>
-#include <asm/ide.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/processor.h>
@@ -78,7+77,6 @@ static void __init sni_rm200_pci_time_init(struct irqaction *irq) }
unsigned char aux_device_present;
-extern struct pci_ops sni_pci_ops;
extern unsigned char sni_map_isa_cache;
/*
@@ -110,6+108,7 @@ int __init page_is_ram(unsigned long pagenr)
void __init sni_rm200_pci_setup(void)
{
+#if 0 /* XXX Tag me deeper */
tag *atag;
/*
@@ -135,6+134,7 @@ void __init sni_rm200_pci_setup(void) ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->lines;
}
}
+#endif
sni_pcimt_detect();
sni_pcimt_sc_init();
@@ -168,7+168,6 @@ void __init sni_rm200_pci_setup(void) * the I/O port space ...
*/
request_region(0xcfc,0x04,"PCI config data");
- pci_ops = &sni_pci_ops;
#ifdef CONFIG_BLK_DEV_IDE
ide_ops = &std_ide_ops;
@@ -12,17+12,19 @@ TARGET := $(TOPDIR)/include/asm-$(ARCH)/offset.h .S.o:
$(CC) $(CFLAGS) -c $< -o $*.o
-all: $(TARGET)
-
$(TARGET): offset.h
cmp -s $^ $@ || (cp $^ $(TARGET).new && mv $(TARGET).new $(TARGET))
offset.h: offset.s
sed -n '/^@@@/s///p' $^ >$@
-offset.s: offset.c
+offset.s: offset.c $(TOPDIR)/include/linux/autoconf.h
clean:
rm -f offset.[hs] $(TARGET).new
+
+mrproper:
+ rm -f offset.[hs] $(TARGET).new
+ rm -f $(TARGET)
include $(TOPDIR)/Rules.make
@@ -86,8+86,12 @@ SUBDIRS += arch/mips64/sgi-ip27 arch/mips64/arc # must be 16kb aligned or the handling of the current variable will break.
#
#LOADADDR += 0xa80000000001c000
+ifdef CONFIG_MAPPED_KERNEL
+LOADADDR += 0xc001c000
+else
LOADADDR += 0x8001c000
endif
+endif
#
# Some machines like the Indy need 32-bit ELF binaries for booting purposes.
64bit-bfd = elf64-bigmips
endif
+ifdef CONFIG_MAPPED_KERNEL
+vmlinux.64: vmlinux
+ $(OBJCOPY) -O $(64bit-bfd) --change-addresses=0xbfffffff40000000 $< $@
+else
vmlinux.64: vmlinux
$(OBJCOPY) -O $(64bit-bfd) --change-addresses=0xa7ffffff80000000 $< $@
+endif
zImage: vmlinux
@$(MAKEBOOT) zImage
@@ -144,6+153,11 @@ archclean: rm -f vmlinux.64
archmrproper:
+ @$(MAKEBOOT) mrproper
+ $(MAKE) -C arch/$(ARCH)/tools mrproper
archdep:
+ if [ ! -f $(TOPDIR)/include/asm-$(ARCH)/offset.h ]; then \
+ touch $(TOPDIR)/include/asm-$(ARCH)/offset.h; \
+ fi;
@$(MAKEBOOT) dep
-/* $Id: identify.c,v 1.5 1999/11/19 20:35:21 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
@@ -39,7+38,7 @@ static struct smatch mach_table[] = { int prom_flags;
static struct smatch * __init
-string_to_mach(char *s)
+string_to_mach(const char *s)
{
int i;
#undef DEBUG
-extern char _end;
-
struct linux_mdesc * __init
ArcGetMemoryDescriptor(struct linux_mdesc *Current)
{
clean:
rm -f vmlinux.ecoff
+mrproper:
+ rm -f vmlinux.ecoff addinitrd elf2ecoff
+
dummy:
include $(TOPDIR)/Rules.make
@@ -17,6+17,10 @@ bool 'Support for SGI IP27' CONFIG_SGI_IP27 if [ "$CONFIG_SGI_IP27" = "y" ]; then
bool ' IP27 N-Mode' CONFIG_SGI_SN0_N_MODE
bool ' Discontiguous Memory Support' CONFIG_DISCONTIGMEM
+ bool ' NUMA support' CONFIG_NUMA
+ bool ' Mapped kernel support' CONFIG_MAPPED_KERNEL
+ bool ' Kernel text replication support' CONFIG_REPLICATE_KTEXT
+ bool ' Exception handler replication support' CONFIG_REPLICATE_EXHANDLERS
bool ' Multi-Processing support (Experimental)' CONFIG_SMP
#bool ' IP27 XXL' CONFIG_SGI_SN0_XXL
fi
@@ -40,6+44,7 @@ if [ "$CONFIG_SGI_IP22" = "y" ]; then define_bool CONFIG_ARC32 y
define_bool CONFIG_BOARD_SCACHE y
define_bool CONFIG_ARC_MEMORY y
+ define_bool CONFIG_SGI y
fi
if [ "$CONFIG_SGI_IP27" = "y" ]; then
CONFIG_SGI_IP27=y
# CONFIG_SGI_SN0_N_MODE is not set
# CONFIG_DISCONTIGMEM is not set
+# CONFIG_NUMA is not set
+# CONFIG_MAPPED_KERNEL is not set
+# CONFIG_REPLICATE_KTEXT is not set
+# CONFIG_REPLICATE_EXHANDLERS is not set
# CONFIG_SMP is not set
CONFIG_BOOT_ELF64=y
CONFIG_ARC64=y
@@ -53,12+57,15 @@ CONFIG_BINFMT_ELF32=y #
# Loadable module support
#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
+# CONFIG_MODULES is not set
CONFIG_PCI_NAMES=y
#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
@@ -66,16+73,14 @@ CONFIG_PCI_NAMES=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 is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_LVM is not set
# CONFIG_BLK_DEV_MD is not set
# CONFIG_MD_LINEAR is not set
# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_INITRD is not set
@@ -110,6+115,7 @@ CONFIG_SKB_LARGE=y # CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
#
# Telephony Support
@@ -308,6+314,7 @@ CONFIG_SERIAL_CONSOLE=y # Watchdog Cards
#
# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
@@ -342,6+349,7 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_RAMFS is not set
# CONFIG_ISO9660_FS is not set
@@ -420,6+428,5 @@ CONFIG_KCORE_ELF=y # Kernel hacking
#
CONFIG_CROSSCOMPILE=y
-# CONFIG_MIPS_FPE_MODULE is not set
# CONFIG_REMOTE_DEBUG is not set
# CONFIG_MAGIC_SYSRQ is not set
@@ -16,6+16,7 @@ CONFIG_BOOT_ELF32=y CONFIG_ARC32=y
CONFIG_BOARD_SCACHE=y
CONFIG_ARC_MEMORY=y
+CONFIG_SGI=y
# CONFIG_ISA is not set
# CONFIG_PCI is not set
# CONFIG_SBUS is not set
@@ -50,6+51,11 @@ CONFIG_BINFMT_ELF=y # CONFIG_MODULES is not set
#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
@@ -57,16+63,14 @@ CONFIG_BINFMT_ELF=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 is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_LVM is not set
# CONFIG_BLK_DEV_MD is not set
# CONFIG_MD_LINEAR is not set
# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_INITRD is not set
@@ -101,6+105,7 @@ CONFIG_SKB_LARGE=y # CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
#
# Telephony Support
@@ -228,6+233,7 @@ CONFIG_VT_CONSOLE=y # Watchdog Cards
#
# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
@@ -262,6+268,7 @@ CONFIG_VT_CONSOLE=y # CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_RAMFS is not set
# CONFIG_ISO9660_FS is not set
CONFIG_SGI_IP27=y
# CONFIG_SGI_SN0_N_MODE is not set
# CONFIG_DISCONTIGMEM is not set
+# CONFIG_NUMA is not set
+# CONFIG_MAPPED_KERNEL is not set
+# CONFIG_REPLICATE_KTEXT is not set
+# CONFIG_REPLICATE_EXHANDLERS is not set
# CONFIG_SMP is not set
CONFIG_BOOT_ELF64=y
CONFIG_ARC64=y
@@ -53,12+57,15 @@ CONFIG_BINFMT_ELF32=y #
# Loadable module support
#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
+# CONFIG_MODULES is not set
CONFIG_PCI_NAMES=y
#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
@@ -66,16+73,14 @@ CONFIG_PCI_NAMES=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 is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_LVM is not set
# CONFIG_BLK_DEV_MD is not set
# CONFIG_MD_LINEAR is not set
# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_INITRD is not set
@@ -110,6+115,7 @@ CONFIG_SKB_LARGE=y # CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
#
# Telephony Support
@@ -308,6+314,7 @@ CONFIG_SERIAL_CONSOLE=y # Watchdog Cards
#
# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
@@ -342,6+349,7 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_RAMFS is not set
# CONFIG_ISO9660_FS is not set
@@ -420,6+428,5 @@ CONFIG_KCORE_ELF=y # Kernel hacking
#
CONFIG_CROSSCOMPILE=y
-# CONFIG_MIPS_FPE_MODULE is not set
# CONFIG_REMOTE_DEBUG is not set
# CONFIG_MAGIC_SYSRQ is not set
#
.S.o:
- $(CC) $(CFLAGS) -c $< -o $*.o
+ $(CC) $(CFLAGS) $(CFLAGS_$@) -c $< -o $*.o
all: kernel.o head.o init_task.o
O_TARGET := kernel.o
O_OBJS := branch.o entry.o proc.o process.o ptrace.o r4k_cache.o r4k_fpu.o \
- r4k_genex.o r4k_switch.o r4k_tlb_debug.o r4k_tlb_glue.o scall_64.o \
- semaphore.o setup.o signal.o softfp.o syscall.o traps.o unaligned.o
+ r4k_genex.o r4k_switch.o r4k_tlb.o r4k_tlb_debug.o r4k_tlb_glue.o \
+ scall_64.o semaphore.o setup.o signal.o softfp.o syscall.o \
+ traps.o unaligned.o
OX_OBJS := mips64_ksyms.o
ifdef CONFIG_MIPS32_COMPAT
@@ -29,6+30,9 @@ ifdef CONFIG_SMP O_OBJS += smp.o
endif
+CFLAGS_r4k_genex.o := -P
+CFLAGS_r4k_tlb_glue.o := -P
+
clean:
include $(TOPDIR)/Rules.make
-/* $Id: head.S,v 1.6 2000/03/27 21:05:04 ulfc Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
#include <asm/processor.h>
#include <asm/mipsregs.h>
#include <asm/stackframe.h>
+#include <asm/pgtable.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/sn0/hubni.h>
+#include <asm/sn/klkernvars.h>
+
+ .macro ARC64_TWIDDLE_PC
+#if defined(CONFIG_ARC64) || defined(CONFIG_MAPPED_KERNEL)
+ /* We get launched at a XKPHYS address but the kernel is linked to
+ run at a KSEG0 address, so jump there. */
+ la t0, \@f
+ jr t0
+\@:
+#endif
+ .endm
-#define ARC64_TWIDDLE_PC \
-#ifdef CONFIG_ARC64 \
- /* We get launched at a XKPHYS address but the kernel is linked to \
- run at a KSEG0 address, so jump there. */ \
- la t0, 1f \
- jr t0 \
-1: \
+ /*
+ * outputs the local nasid into t1.
+ */
+ .macro GET_NASID_ASM
+ dli t1, LOCAL_HUB_ADDR(NI_STATUS_REV_ID)
+ ld t1, (t1)
+ and t1, NSRI_NODEID_MASK
+ dsrl t1, NSRI_NODEID_SHFT
+ .endm
+
+ /*
+ * inputs are the text nasid in t1, data nasid in t2.
+ */
+ .macro MAPPED_KERNEL_SETUP_TLB
+#ifdef CONFIG_MAPPED_KERNEL
+ /*
+ * This needs to read the nasid - assume 0 for now.
+ * Drop in 0xffffffffc0000000 in tlbhi, 0+VG in tlblo_0,
+ * 0+DVG in tlblo_1.
+ */
+ dli t0, 0xffffffffc0000000
+ dmtc0 t0, CP0_ENTRYHI
+ li t0, 0x1c000 # Offset of text into node memory
+ dsll t1, NASID_SHFT # Shift text nasid into place
+ dsll t2, NASID_SHFT # Same for data nasid
+ or t1, t1, t0 # Physical load address of kernel text
+ or t2, t2, t0 # Physical load address of kernel data
+ dsrl t1, 12 # 4K pfn
+ dsrl t2, 12 # 4K pfn
+ dsll t1, 6 # Get pfn into place
+ dsll t2, 6 # Get pfn into place
+ li t0, ((_PAGE_GLOBAL|_PAGE_VALID| _CACHE_CACHABLE_COW) >> 6)
+ or t0, t0, t1
+ mtc0 t0, CP0_ENTRYLO0 # physaddr, VG, cach exlwr
+ li t0, ((_PAGE_GLOBAL|_PAGE_VALID| _PAGE_DIRTY|_CACHE_CACHABLE_COW) >> 6)
+ or t0, t0, t2
+ mtc0 t0, CP0_ENTRYLO1 # physaddr, DVG, cach exlwr
+ li t0, 0x1ffe000 # MAPPED_KERN_TLBMASK, TLBPGMASK_16M
+ mtc0 t0, CP0_PAGEMASK
+ li t0, 0 # KMAP_INX
+ mtc0 t0, CP0_INDEX
+ li t0, 1
+ mtc0 t0, CP0_WIRED
+ tlbwi
+#else
+ mtc0 zero, CP0_WIRED
#endif
+ .endm
.text
@@ -38,11+91,15 @@ EXPORT(_stext)
NESTED(kernel_entry, 16, sp) # kernel entry point
- ARC64_TWIDDLE_PC
-
ori sp, 0xf # align stack on 16 byte.
xori sp, 0xf
+ GET_NASID_ASM
+ move t2, t1 # text and data are here
+ MAPPED_KERNEL_SETUP_TLB
+
+ ARC64_TWIDDLE_PC
+
/* Note that all firmware passed argument registers still
have their values. */
jal prom_init # initialize firmware
@@ -75,6+132,14 @@ NESTED(kernel_entry, 16, sp) # kernel entry point END(kernel_entry)
NESTED(bootstrap, 16, sp)
+ GET_NASID_ASM
+ li t0, KLDIR_OFFSET + (KLI_KERN_VARS * KLDIR_ENT_SIZE) + KLDIR_OFF_POINTER + K0BASE
+ dsll t1, NASID_SHFT
+ or t0, t0, t1
+ ld t0, 0(t0) # t0 points to kern_vars struct
+ lh t1, KV_RO_NASID_OFFSET(t0)
+ lh t2, KV_RW_NASID_OFFSET(t0)
+ MAPPED_KERNEL_SETUP_TLB
ARC64_TWIDDLE_PC
CLI
mfc0 t0, CP0_STATUS
@@ -89,20+154,25 @@ NESTED(bootstrap, 16, sp)
.comm kernelsp, 8, 8 # current stackpointer
+#undef PAGE_SIZE
#define PAGE_SIZE 0x1000
.macro page name, order=0
.globl \name
- .org . + (PAGE_SIZE << \order)
\name: .size \name, (PAGE_SIZE << \order)
+ .org . + (PAGE_SIZE << \order)
.type \name, @object
.endm
- .align 12
.data
+ .align 12
page swapper_pg_dir, 1
- page invalid_pte_table, 1
+ page invalid_pte_table, 0
page invalid_pmd_table, 1
- page empty_bad_page_table, 1
- page empty_bad_page
+ page empty_bad_page_table, 0
+ page empty_bad_pmd_table, 1
+ page kptbl, KPTBL_PAGE_ORDER
+ .globl ekptbl
+ page kpmdtbl, 0
+ekptbl:
-/* $Id: ioctl32.c,v 1.1 2000/04/05 00:43:25 ulfc Exp $
+/*
* ioctl32.c: Conversion between 32bit and 64bit native ioctls.
*
* Copyright (C) 2000 Silicon Graphics, Inc.
@@ -35,23+35,6 @@ struct timeval32 { #define EXT2_IOC32_GETVERSION _IOR('v', 1, int)
#define EXT2_IOC32_SETVERSION _IOW('v', 2, int)
-static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
- struct timeval32 *up = (struct timeval32 *)arg;
- struct timeval ktv;
- mm_segment_t old_fs = get_fs();
- int err;
-
- set_fs(KERNEL_DS);
- err = sys_ioctl(fd, cmd, (unsigned long)&ktv);
- set_fs(old_fs);
- if(!err) {
- err = put_user(ktv.tv_sec, &up->tv_sec);
- err |= __put_user(ktv.tv_usec, &up->tv_usec);
- }
- return err;
-}
-
struct ifmap32 {
unsigned int mem_start;
unsigned int mem_end;
-/* $Id: linux32.c,v 1.14 2000/03/23 00:30:53 ulfc Exp $
- *
+/*
* Conversion between 32-bit and 64-bit native system calls.
*
* Copyright (C) 2000 Silicon Graphics, Inc.
#include <linux/time.h>
#include <linux/poll.h>
#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/filter.h>
#include <asm/uaccess.h>
#include <asm/mman.h>
#define A(__x) ((unsigned long)(__x))
-#if 1
-static inline int
-putstat(struct stat32 *ubuf, struct stat *kbuf)
-{
- int err;
-
- err = put_user (kbuf->st_dev, &ubuf->st_dev);
- err |= __put_user (kbuf->st_ino, &ubuf->st_ino);
- err |= __put_user (kbuf->st_mode, &ubuf->st_mode);
- err |= __put_user (kbuf->st_nlink, &ubuf->st_nlink);
- err |= __put_user (kbuf->st_uid, &ubuf->st_uid);
- err |= __put_user (kbuf->st_gid, &ubuf->st_gid);
- err |= __put_user (kbuf->st_rdev, &ubuf->st_rdev);
- err |= __put_user (kbuf->st_size, &ubuf->st_size);
- err |= __put_user (kbuf->st_atime, &ubuf->st_atime);
- err |= __put_user (kbuf->st_mtime, &ubuf->st_mtime);
- err |= __put_user (kbuf->st_ctime, &ubuf->st_ctime);
- err |= __put_user (kbuf->st_blksize, &ubuf->st_blksize);
- err |= __put_user (kbuf->st_blocks, &ubuf->st_blocks);
- return err;
-}
-
-extern asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
-
-asmlinkage int
-sys32_newstat(char * filename, struct stat32 *statbuf)
-{
- int ret;
- struct stat s;
- mm_segment_t old_fs = get_fs();
-
- set_fs (KERNEL_DS);
- ret = sys_newstat(filename, &s);
- set_fs (old_fs);
- if (putstat (statbuf, &s))
- return -EFAULT;
- return ret;
-}
-
-extern asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);
-
-asmlinkage int
-sys32_newlstat(char * filename, struct stat32 *statbuf)
-{
- int ret;
- struct stat s;
- mm_segment_t old_fs = get_fs();
-
- set_fs (KERNEL_DS);
- ret = sys_newlstat(filename, &s);
- set_fs (old_fs);
- if (putstat (statbuf, &s))
- return -EFAULT;
- return ret;
-}
-
-extern asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf);
-
-asmlinkage int
-sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
-{
- int ret;
- struct stat s;
- mm_segment_t old_fs = get_fs();
-
- set_fs (KERNEL_DS);
- ret = sys_newfstat(fd, &s);
- set_fs (old_fs);
- if (putstat (statbuf, &s))
- return -EFAULT;
- return ret;
-}
-#else
/*
* Revalidate the inode. This is required for proper NFS attribute caching.
*/
@@ -105,8+33,10 @@ static __inline__ int do_revalidate(struct dentry *dentry)
{
struct inode * inode = dentry->d_inode;
+
if (inode->i_op && inode->i_op->revalidate)
return inode->i_op->revalidate(dentry);
+
return 0;
}
@@ -127,21+57,22 @@ static int cp_new_stat32(struct inode * inode, struct stat32 * statbuf) tmp.st_atime = inode->i_atime;
tmp.st_mtime = inode->i_mtime;
tmp.st_ctime = inode->i_ctime;
-/*
- * st_blocks and st_blksize are approximated with a simple algorithm if
- * they aren't supported directly by the filesystem. The minix and msdos
- * filesystems don't keep track of blocks, so they would either have to
- * be counted explicitly (by delving into the file itself), or by using
- * this simple algorithm to get a reasonable (although not 100% accurate)
- * value.
- */
-/*
- * Use minix fs values for the number of direct and indirect blocks. The
- * count is now exact for the minix fs except that it counts zero blocks.
- * Everything is in units of BLOCK_SIZE until the assignment to
- * tmp.st_blksize.
- */
+ /*
+ * st_blocks and st_blksize are approximated with a simple algorithm if
+ * they aren't supported directly by the filesystem. The minix and msdos
+ * filesystems don't keep track of blocks, so they would either have to
+ * be counted explicitly (by delving into the file itself), or by using
+ * this simple algorithm to get a reasonable (although not 100%
+ * accurate) value.
+ */
+
+ /*
+ * Use minix fs values for the number of direct and indirect blocks.
+ * The count is now exact for the minix fs except that it counts zero
+ * blocks. Everything is in units of BLOCK_SIZE until the assignment
+ * to tmp.st_blksize.
+ */
#define D_B 7
#define I_B (BLOCK_SIZE / sizeof(unsigned short))
@@ -163,53+94,49 @@ static int cp_new_stat32(struct inode * inode, struct stat32 * statbuf) tmp.st_blocks = inode->i_blocks;
tmp.st_blksize = inode->i_blksize;
}
+
return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
}
+
asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
{
- struct dentry * dentry;
+ struct nameidata nd;
int error;
- lock_kernel();
- dentry = namei(filename);
-
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = do_revalidate(dentry);
+ error = user_path_walk(filename, &nd);
+ if (!error) {
+ error = do_revalidate(nd.dentry);
if (!error)
- error = cp_new_stat32(dentry->d_inode, statbuf);
+ error = cp_new_stat32(nd.dentry->d_inode, statbuf);
- dput(dentry);
+ path_release(&nd);
}
- unlock_kernel();
+
return error;
}
-asmlinkage int sys32_newlstat(char *filename, struct stat32 * statbuf)
+
+asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
{
- struct dentry * dentry;
+ struct nameidata nd;
int error;
- lock_kernel();
- dentry = lnamei(filename);
-
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = do_revalidate(dentry);
+ error = user_path_walk_link(filename, &nd);
+ if (!error) {
+ error = do_revalidate(nd.dentry);
if (!error)
- error = cp_new_stat32(dentry->d_inode, statbuf);
+ error = cp_new_stat32(nd.dentry->d_inode, statbuf);
- dput(dentry);
+ path_release(&nd);
}
- unlock_kernel();
+
return error;
}
-asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 * statbuf)
+asmlinkage long sys32_newfstat(unsigned int fd, struct stat32 * statbuf)
{
struct file * f;
int err = -EBADF;
- lock_kernel();
f = fget(fd);
if (f) {
struct dentry * dentry = f->f_dentry;
@@ -219,10+146,10 @@ asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 * statbuf) err = cp_new_stat32(dentry->d_inode, statbuf);
fput(f);
}
- unlock_kernel();
+
return err;
}
-#endif
+
asmlinkage int sys_mmap2(void) {return 0;}
asmlinkage long sys_truncate(const char * path, unsigned long length);
@@ -232,7+159,7 @@ asmlinkage int sys_truncate64(const char *path, unsigned int high, {
if ((int)high < 0)
return -EINVAL;
- return sys_truncate(path, (high << 32) | low);
+ return sys_truncate(path, ((long) high << 32) | low);
}
asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
@@ -242,28+169,7 @@ asmlinkage int sys_ftruncate64(unsigned int fd, unsigned int high, {
if ((int)high < 0)
return -EINVAL;
- return sys_ftruncate(fd, (high << 32) | low);
-}
-
-asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
-
-asmlinkage int sys_stat64(char * filename, struct stat *statbuf)
-{
- return sys_newstat(filename, statbuf);
-}
-
-asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);
-
-asmlinkage int sys_lstat64(char * filename, struct stat *statbuf)
-{
- return sys_newlstat(filename, statbuf);
-}
-
-asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf);
-
-asmlinkage int sys_fstat64(unsigned int fd, struct stat *statbuf)
-{
- return sys_newfstat(fd, statbuf);
+ return sys_ftruncate(fd, ((long) high << 32) | low);
}
#if 0
@@ -304,7+210,8 @@ int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm) int len;
unsigned long pos;
- if (get_user(str, argv+argc) || !str || !(len = strnlen_user((char *)A(str), bprm->p)))
+ if (get_user(str, argv+argc) || !str ||
+ !(len = strnlen_user((char *)A(str), bprm->p)))
return -EFAULT;
if (bprm->p < len)
return -E2BIG;
@@ -338,9+245,11 @@ int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm) if (bytes_to_copy > len) {
bytes_to_copy = len;
if (new)
- memset(kaddr+offset+len, 0, PAGE_SIZE-offset-len);
+ memset(kaddr+offset+len, 0,
+ PAGE_SIZE-offset-len);
}
- err = copy_from_user(kaddr + offset, (char *)A(str), bytes_to_copy);
+ err = copy_from_user(kaddr + offset, (char *)A(str),
+ bytes_to_copy);
flush_page_to_ram(page);
kunmap(page);
@@ -970,7+879,7 @@ do_readv_writev32(int type, struct file *file, const struct iovec32 *vector, tot_len = 0;
i = count;
ivp = iov;
- while(i > 0) {
+ while (i > 0) {
u32 len;
u32 buf;
@@ -1038,6+947,7 @@ do_readv_writev32(int type, struct file *file, const struct iovec32 *vector, }
if (iov != iovstack)
kfree(iov);
+
return retval;
}
@@ -1045,22+955,19 @@ asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count)
{
struct file *file;
- long ret = -EBADF;
+ ssize_t ret;
- lock_kernel();
+ ret = -EBADF;
file = fget(fd);
- if(!file)
+ if (!file)
goto bad_file;
+ if (file->f_op && (file->f_mode & FMODE_READ) &&
+ (file->f_op->readv || file->f_op->read))
+ ret = do_readv_writev32(VERIFY_WRITE, file, vector, count);
- if(!(file->f_mode & 1))
- goto out;
-
- ret = do_readv_writev32(VERIFY_WRITE, file,
- vector, count);
-out:
fput(file);
+
bad_file:
- unlock_kernel();
return ret;
}
@@ -1068,22+975,18 @@ asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count)
{
struct file *file;
- int ret = -EBADF;
+ ssize_t ret;
- lock_kernel();
+ ret = -EBADF;
file = fget(fd);
if(!file)
goto bad_file;
-
- if(!(file->f_mode & 2))
- goto out;
-
- ret = do_readv_writev32(VERIFY_READ, file,
- vector, count);
-out:
+ if (file->f_op && (file->f_mode & FMODE_WRITE) &&
+ (file->f_op->writev || file->f_op->write))
+ ret = do_readv_writev32(VERIFY_READ, file, vector, count);
fput(file);
+
bad_file:
- unlock_kernel();
return ret;
}
@@ -1303,3+1206,134 @@ sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp) }
return ret;
}
+
+struct tms32 {
+ int tms_utime;
+ int tms_stime;
+ int tms_cutime;
+ int tms_cstime;
+};
+
+extern asmlinkage long sys_times(struct tms * tbuf);
+asmlinkage long sys32_times(struct tms32 *tbuf)
+{
+ struct tms t;
+ long ret;
+ mm_segment_t old_fs = get_fs();
+ int err;
+
+ set_fs(KERNEL_DS);
+ ret = sys_times(tbuf ? &t : NULL);
+ set_fs(old_fs);
+ if (tbuf) {
+ err = put_user (t.tms_utime, &tbuf->tms_utime);
+ err |= __put_user (t.tms_stime, &tbuf->tms_stime);
+ err |= __put_user (t.tms_cutime, &tbuf->tms_cutime);
+ err |= __put_user (t.tms_cstime, &tbuf->tms_cstime);
+ if (err)
+ ret = -EFAULT;
+ }
+ return ret;
+}
+
+extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
+ char *optval, int optlen);
+
+asmlinkage int sys32_setsockopt(int fd, int level, int optname,
+ char *optval, int optlen)
+{
+ if (optname == SO_ATTACH_FILTER) {
+ struct sock_fprog32 {
+ __u16 len;
+ __u32 filter;
+ } *fprog32 = (struct sock_fprog32 *)optval;
+ struct sock_fprog kfprog;
+ struct sock_filter *kfilter;
+ unsigned int fsize;
+ mm_segment_t old_fs;
+ __u32 uptr;
+ int ret;
+
+ if (get_user(kfprog.len, &fprog32->len) ||
+ __get_user(uptr, &fprog32->filter))
+ return -EFAULT;
+ kfprog.filter = (struct sock_filter *)A(uptr);
+ fsize = kfprog.len * sizeof(struct sock_filter);
+ kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
+ if (kfilter == NULL)
+ return -ENOMEM;
+ if (copy_from_user(kfilter, kfprog.filter, fsize)) {
+ kfree(kfilter);
+ return -EFAULT;
+ }
+ kfprog.filter = kfilter;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_setsockopt(fd, level, optname,
+ (char *)&kfprog, sizeof(kfprog));
+ set_fs(old_fs);
+ kfree(kfilter);
+ return ret;
+ }
+ return sys_setsockopt(fd, level, optname, optval, optlen);
+}
+
+struct flock32 {
+ short l_type;
+ short l_whence;
+ __kernel_off_t32 l_start;
+ __kernel_off_t32 l_len;
+ __kernel_pid_t32 l_pid;
+ short __unused;
+};
+
+static inline int get_flock(struct flock *kfl, struct flock32 *ufl)
+{
+ int err;
+
+ err = get_user(kfl->l_type, &ufl->l_type);
+ err |= __get_user(kfl->l_whence, &ufl->l_whence);
+ err |= __get_user(kfl->l_start, &ufl->l_start);
+ err |= __get_user(kfl->l_len, &ufl->l_len);
+ err |= __get_user(kfl->l_pid, &ufl->l_pid);
+ return err;
+}
+
+static inline int put_flock(struct flock *kfl, struct flock32 *ufl)
+{
+ int err;
+
+ err = __put_user(kfl->l_type, &ufl->l_type);
+ err |= __put_user(kfl->l_whence, &ufl->l_whence);
+ err |= __put_user(kfl->l_start, &ufl->l_start);
+ err |= __put_user(kfl->l_len, &ufl->l_len);
+ err |= __put_user(kfl->l_pid, &ufl->l_pid);
+ return err;
+}
+
+extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
+
+asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ switch (cmd) {
+ case F_GETLK:
+ case F_SETLK:
+ case F_SETLKW:
+ {
+ struct flock f;
+ mm_segment_t old_fs;
+ long ret;
+
+ if(get_flock(&f, (struct flock32 *)arg))
+ return -EFAULT;
+ old_fs = get_fs(); set_fs (KERNEL_DS);
+ ret = sys_fcntl(fd, cmd, (unsigned long)&f);
+ set_fs (old_fs);
+ if(put_flock(&f, (struct flock32 *)arg))
+ return -EFAULT;
+ return ret;
+ }
+ default:
+ return sys_fcntl(fd, cmd, (unsigned long)arg);
+ }
+}
-/* $Id: mips64_ksyms.c,v 1.8 2000/02/24 00:12:41 ralf Exp $
- *
+/*
* Export MIPS64-specific functions needed for loadable modules.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1996, 1997, 1998, 1999 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/in6.h>
#include <linux/pci.h>
-#include <asm/checksum.h>
#include <asm/dma.h>
#include <asm/floppy.h>
#include <asm/io.h>
#include <asm/semaphore.h>
#include <asm/softirq.h>
#include <asm/uaccess.h>
+#include <asm/checksum.h>
extern void *__bzero(void *__s, size_t __count);
extern long __strncpy_from_user_nocheck_asm(char *__to,
* Copyright (C) 1994 - 1999 by Ralf Baechle and others.
* Copyright (C) 1999 Silicon Graphics, Inc.
*/
+#include <linux/config.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
-/* $Id: ptrace.c,v 1.1 1999/12/04 03:59:00 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
#include <asm/system.h>
#include <asm/uaccess.h>
-/* Tracing a 32-bit process with a 64-bit strace and vice verca will not
- work. I don't know how to fix this. */
-
+/*
+ * Tracing a 32-bit process with a 64-bit strace and vice versa will not
+ * work. I don't know how to fix this.
+ */
asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
{
struct task_struct *child;
int ret;
lock_kernel();
-#if 0
- printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
- (int) request, (int) pid, (unsigned long) addr,
- (unsigned long) data);
-#endif
ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
- if (current->flags & PF_PTRACED)
+ if (current->ptrace & PT_PTRACED)
goto out;
/* set the ptrace bit in the process flags. */
- current->flags |= PF_PTRACED;
+ current->ptrace |= PT_PTRACED;
ret = 0;
goto out;
}
@@ -79,9+74,9 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
goto out_tsk;
/* the same process cannot be attached many times */
- if (child->flags & PF_PTRACED)
+ if (child->ptrace & PT_PTRACED)
goto out_tsk;
- child->flags |= PF_PTRACED;
+ child->ptrace |= PT_PTRACED;
write_lock_irq(&tasklist_lock);
if (child->p_pptr != current) {
@@ -96,7+91,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) goto out_tsk;
}
ret = -ESRCH;
- if (!(child->flags & PF_PTRACED))
+ if (!(child->ptrace & PT_PTRACED))
goto out_tsk;
if (child->state != TASK_STOPPED) {
if (request != PTRACE_KILL)
@@ -104,7+99,6 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) }
if (child->p_pptr != current)
goto out_tsk;
-
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
@@ -116,7+110,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) ret = -EIO;
if (copied != sizeof(tmp))
break;
- ret = put_user(tmp, (unsigned int *) data);
+ ret = put_user(tmp, (unsigned int *) (unsigned long) data);
break;
}
@@ -179,7+173,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) ret = -EIO;
goto out_tsk;
}
- ret = put_user(tmp, (unsigned *) data);
+ ret = put_user(tmp, (unsigned *) (unsigned long) data);
break;
}
/* when I and D space are separate, this will have to be fixed. */
@@ -248,9+242,9 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) if ((unsigned int) data > _NSIG)
break;
if (request == PTRACE_SYSCALL)
- child->flags |= PF_TRACESYS;
+ child->ptrace |= PT_TRACESYS;
else
- child->flags &= ~PF_TRACESYS;
+ child->ptrace &= ~PT_TRACESYS;
child->exit_code = data;
wake_up_process(child);
ret = 0;
@@ -274,7+268,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) ret = -EIO;
if ((unsigned long) data > _NSIG)
break;
- child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+ child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
child->exit_code = data;
write_lock_irq(&tasklist_lock);
REMOVE_LINKS(child);
@@ -312,10+306,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
- if (current->flags & PF_PTRACED)
+ if (current->ptrace & PT_PTRACED)
goto out;
/* set the ptrace bit in the process flags. */
- current->flags |= PF_PTRACED;
+ current->ptrace |= PT_PTRACED;
ret = 0;
goto out;
}
@@ -345,9+339,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
goto out_tsk;
/* the same process cannot be attached many times */
- if (child->flags & PF_PTRACED)
+ if (child->ptrace & PT_PTRACED)
goto out_tsk;
- child->flags |= PF_PTRACED;
+ child->ptrace |= PT_PTRACED;
write_lock_irq(&tasklist_lock);
if (child->p_pptr != current) {
@@ -362,7+356,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) goto out_tsk;
}
ret = -ESRCH;
- if (!(child->flags & PF_PTRACED))
+ if (!(child->ptrace & PT_PTRACED))
goto out_tsk;
if (child->state != TASK_STOPPED) {
if (request != PTRACE_KILL)
@@ -514,9+508,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) if ((unsigned long) data > _NSIG)
break;
if (request == PTRACE_SYSCALL)
- child->flags |= PF_TRACESYS;
+ child->ptrace |= PT_TRACESYS;
else
- child->flags &= ~PF_TRACESYS;
+ child->ptrace &= ~PT_TRACESYS;
child->exit_code = data;
wake_up_process(child);
ret = 0;
@@ -540,7+534,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = -EIO;
if ((unsigned long) data > _NSIG)
break;
- child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+ child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
child->exit_code = data;
write_lock_irq(&tasklist_lock);
REMOVE_LINKS(child);
asmlinkage void syscall_trace(void)
{
- if ((current->flags & (PF_PTRACED|PF_TRACESYS))
- != (PF_PTRACED|PF_TRACESYS))
+ if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
+ != (PT_PTRACED|PT_TRACESYS))
return;
+
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
--- /dev/null
+/* $Id: r4k_tlb.S,v 1.3 2000/06/30 00:48:29 kanoj Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2000 Silicon Graphics, Inc.
+ * Written by Ulf Carlsson (ulfc@engr.sgi.com)
+ */
+#include <linux/threads.h>
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/pgtable.h>
+#include <asm/stackframe.h>
+
+ .data
+ .comm pgd_current, NR_CPUS * 8, 8
+
+ /*
+ * After this macro runs we have a pointer to the pte of the address
+ * that caused the fault in in PTR.
+ */
+
+ .macro LOAD_PTE2, ptr, tmp
+#ifdef CONFIG_SMP
+ mfc0 \tmp, CP0_CONTEXT
+ dla \ptr, pgd_current
+ dsrl \tmp, 23
+ daddu \ptr, \tmp
+#else
+ dla \ptr, pgd_current
+#endif
+ dmfc0 \tmp, CP0_BADVADDR
+ ld \ptr, (\ptr)
+ bltz \tmp, kaddr
+ dsrl \tmp, (PGDIR_SHIFT-3) # get pgd offset in bytes
+ andi \tmp, ((PTRS_PER_PGD - 1)<<3)
+ daddu \ptr, \tmp # add in pgd offset
+ dmfc0 \tmp, CP0_BADVADDR
+ ld \ptr, (\ptr) # get pmd pointer
+ dsrl \tmp, (PMD_SHIFT-3) # get pmd offset in bytes
+ andi \tmp, ((PTRS_PER_PMD - 1)<<3)
+ daddu \ptr, \tmp # add in pmd offset
+ dmfc0 \tmp, CP0_XCONTEXT
+ ld \ptr, (\ptr) # get pte pointer
+ andi \tmp, 0xff0 # get pte offset
+ daddu \ptr, \tmp
+ .endm
+
+ /*
+ * This places the even/odd pte pair in the page table at the pte
+ * entry pointed to by PTE into ENTRYLO0 and ENTRYLO1.
+ */
+ .macro PTE_RELOAD, pte0, pte1
+ dsrl \pte0, 6 # convert to entrylo0
+ dmtc0 \pte0, CP0_ENTRYLO0 # load it
+ dsrl \pte1, 6 # convert to entrylo1
+ dmtc0 \pte1, CP0_ENTRYLO1 # load it
+ .endm
+
+ .text
+ .set noreorder
+ .set mips3
+
+ .align 5
+FEXPORT(except_vec0)
+ .set noat
+1: b 1b
+ nop
+
+ /* TLB refill handler for the R10000.
+ * Attention: We may only use 32 instructions.
+ */
+
+ .align 5
+FEXPORT(except_vec1_r10k)
+ .set noat
+ LOAD_PTE2 k1 k0
+ ld k0, 0(k1) # get even pte
+ ld k1, 8(k1) # get odd pte
+ PTE_RELOAD k0 k1
+ nop
+ tlbwr
+ eret
+kaddr:
+ dla k0, handle_vmalloc_address # MAPPED kernel needs this
+ jr k0
+ nop
+
+ .align 5
+FEXPORT(handle_vmalloc_address)
+ .set noat
+ /*
+ * First, determine that the address is in/above vmalloc range.
+ */
+ dmfc0 k0, CP0_BADVADDR
+ dli k1, VMALLOC_START
+ sltu k1, k0, k1
+ bne k1, zero, not_vmalloc
+ dli k1, VMALLOC_START
+
+ /*
+ * Now find offset into kptbl.
+ */
+ dsubu k0, k0, k1
+ dla k1, kptbl
+ dsrl k0, (PAGE_SHIFT+1) # get vpn2
+ dsll k0, 4 # byte offset of pte
+ daddu k1, k1, k0
+
+ /*
+ * Determine that fault address is within vmalloc range.
+ */
+ dla k0, ekptbl
+ sltu k0, k1, k0
+ beq k0, zero, not_vmalloc
+
+ /*
+ * Load cp0 registers.
+ */
+ ld k0, 0(k1) # get even pte
+ ld k1, 8(k1) # get odd pte
+1:
+ PTE_RELOAD k0 k1
+ nop
+ tlbwr
+ eret
+not_vmalloc:
+ daddu k0, zero, zero
+ daddu k1, zero, zero
+ j 1b
+ nop
#include <asm/regdef.h>
#include <asm/stackframe.h>
- __INIT
-NESTED(__xtlb_refill_debug_tramp, PT_SIZE, sp)
- j __xtlb_refill_debug
- END(__xtlb_refill_debug_tramp)
-
-NESTED(__tlb_refill_debug_tramp, PT_SIZE, sp)
- j __tlb_refill_debug
- END(__tlb_refill_debug_tramp)
- __FINIT
-
.macro __BUILD_cli
CLI
.endm
@@ -31,7+21,7 @@ NESTED(__tlb_refill_debug_tramp, PT_SIZE, sp) STI
.endm
- .macro tlb_handler name interruptible
+ .macro tlb_handler name interruptible writebit
NESTED(__\name, PT_SIZE, sp)
SAVE_ALL
#if DEBUG_MIPS64
@@ -42,17+32,17 @@ ld $6, PT_R6(sp) ld $7, PT_R7(sp)
ld $2, PT_R2(sp)
#endif
- __BUILD_\interruptible
- dmfc0 t0, CP0_BADVADDR
- sd t0, PT_BVADDR(sp)
+ dmfc0 a2, CP0_BADVADDR
+ li a1, \writebit
+ sd a2, PT_BVADDR(sp)
move a0, sp
- jal \name
- j return
+ __BUILD_\interruptible
+ jal do_page_fault
END(__\name)
+ RESTORE_ALL
+ eret
.endm
- tlb_handler tlb_refill_debug cli
- tlb_handler xtlb_refill_debug cli
- tlb_handler xtlb_mod_debug sti
- tlb_handler xtlb_tlbl_debug sti
- tlb_handler xtlb_tlbs_debug sti
+ tlb_handler xtlb_mod sti 1
+ tlb_handler xtlb_tlbl sti 0
+ tlb_handler xtlb_tlbs sti 1
-/* $Id: scall_o32.S,v 1.18 2000/03/27 21:04:13 ulfc Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1995, 1996, 1997, 1998, 1999 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1995 - 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*
* Hairy, the userspace application uses a different argument passing
* convention than the kernel, so we have to translate things from o32
@@ -245,7+244,7 @@ illegal_syscall: sys sys_rmdir 1 /* 4040 */
sys sys_dup 1
sys sys_pipe 0
- sys sys_times 1
+ sys sys32_times 1
sys sys_ni_syscall 0
sys sys_brk 1 /* 4045 */
sys sys_setgid 1
@@ -257,7+256,7 @@ illegal_syscall: sys sys_umount 2
sys sys_ni_syscall 0
sys sys32_ioctl 3
- sys sys_fcntl 3 /* 4055 */
+ sys sys32_fcntl 3 /* 4055 */
sys sys_ni_syscall 2
sys sys_setpgid 2
sys sys_ni_syscall, 0
@@ -383,7+382,7 @@ illegal_syscall: sys sys_send 4
sys sys_sendmsg 3
sys sys_sendto 6 /* 4180 */
- sys sys_setsockopt 5
+ sys sys32_setsockopt 5
sys sys_shutdown 2
sys sys_socket 3
sys sys_socketpair 4
@@ -415,9+414,9 @@ illegal_syscall: sys sys_mmap2 6 /* 4210 */
sys sys_truncate64 2
sys sys_ftruncate64 2
- sys sys_stat64 3
- sys sys_lstat64 3
- sys sys_fstat64 3 /* 4210 */
+ sys sys_newstat 3
+ sys sys_newlstat 3
+ sys sys_newfstat 3 /* 4210 */
sys sys_pivot_root 2
sys sys_mincore 3
sys sys_madvise 3
#include <asm/io.h>
#include <asm/stackframe.h>
#include <asm/system.h>
+#include <asm/pgalloc.h>
#ifdef CONFIG_SGI_IP27
/* XXX Origin garbage has no business in this file */
@@ -153,6+154,9 @@ void __init setup_arch(char **cmdline_p) unsigned long tmp;
unsigned long *initrd_header;
#endif
+ int i;
+ pmd_t *pmd = kpmdtbl;
+ pte_t *pte = kptbl;
cpu_probe();
load_mmu();
@@ -191,4+195,10 @@ void __init setup_arch(char **cmdline_p) #endif
paging_init();
+
+ memset((void *)kptbl, 0, PAGE_SIZE << KPTBL_PAGE_ORDER);
+ memset((void *)kpmdtbl, 0, PAGE_SIZE);
+ pgd_set(swapper_pg_dir, kpmdtbl);
+ for (i = 0; i < (1 << KPTBL_PAGE_ORDER); pmd++,i++,pte+=PTRS_PER_PTE)
+ pmd_val(*pmd) = (unsigned long)pte;
}
-/* $Id: signal.c,v 1.4 2000/01/17 23:32:46 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1991, 1992 Linus Torvalds
- * Copyright (C) 1994 - 1999 Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1994 - 2000 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#include <linux/config.h>
#include <linux/sched.h>
@@ -38,6+37,8 @@ extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); extern asmlinkage int save_fp_context(struct sigcontext *sc);
extern asmlinkage int restore_fp_context(struct sigcontext *sc);
+extern asmlinkage void syscall_trace(void);
+
int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
{
if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
@@ -197,8+198,6 @@ sys_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) err |= __put_user(old_ka.sa.sa_handler, &oact->sa_handler);
err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
err |= __put_user(0, &oact->sa_mask.sig[1]);
- err |= __put_user(0, &oact->sa_mask.sig[2]);
- err |= __put_user(0, &oact->sa_mask.sig[3]);
err |= __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer);
if (err)
return -EFAULT;
@@ -294,6+293,8 @@ sys_sigreturn(abi64_no_regargs, struct pt_regs regs) /*
* Don't let your children do this ...
*/
+ if (current->ptrace & PT_TRACESYS)
+ syscall_trace();
__asm__ __volatile__(
"move\t$29, %0\n\t"
"j\tret_from_sys_call"
@@ -354,7+355,7 @@ setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
err |= __put_user(regs->cp0_epc, &sc->sc_pc);
-#define save_gp_reg(i) { \
+#define save_gp_reg(i) do { \
err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \
} while(0)
__put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
@@ -620,7+621,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) if (!signr)
break;
- if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+ if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
current->state = TASK_STOPPED;
@@ -694,7+695,6 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) /* FALLTHRU */
default:
- lock_kernel();
sigaddset(¤t->signal, signr);
recalc_sigpending(current);
current->flags |= PF_SIGNALED;
-/* $Id: signal32.c,v 1.4 2000/03/15 22:46:55 kanoj Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
* Copyright (C) 1994 - 1999 Ralf Baechle
* Copyright (C) 1999 Silicon Graphics, Inc.
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
@@ -37,6+37,8 @@ extern asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs *regs); extern asmlinkage int save_fp_context(struct sigcontext *sc);
extern asmlinkage int restore_fp_context(struct sigcontext *sc);
+extern asmlinkage void syscall_trace(void);
+
/* 32-bit compatibility types */
#define _NSIG32_BPW 32
@@ -60,7+62,7 @@ struct sigaction32 { /* IRIX compatible stack_t */
typedef struct sigaltstack32 {
void *ss_sp;
- size_t ss_size;
+ __kernel_size_t32 ss_size;
int ss_flags;
} stack32_t;
@@ -94,18+96,72 @@ static inline int refill_fp_context(struct sigcontext *sc) return err;
}
+extern void __put_sigset_unknown_nsig(void);
+extern void __get_sigset_unknown_nsig(void);
+
+static inline int
+put_sigset(const sigset_t *kbuf, sigset32_t *ubuf)
+{
+ int err = 0;
+
+ if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
+ return -EFAULT;
+
+ switch (_NSIG_WORDS) {
+ default:
+ __put_sigset_unknown_nsig();
+ case 2:
+ err |= __put_user (kbuf->sig[1] >> 32, &ubuf->sig[3]);
+ err |= __put_user (kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]);
+ case 1:
+ err |= __put_user (kbuf->sig[0] >> 32, &ubuf->sig[1]);
+ err |= __put_user (kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]);
+ }
+
+ return err;
+}
+
+static inline int
+get_sigset(sigset_t *kbuf, const sigset32_t *ubuf)
+{
+ int err = 0;
+ unsigned long sig[4];
+
+ if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
+ return -EFAULT;
+
+ switch (_NSIG_WORDS) {
+ default:
+ __get_sigset_unknown_nsig();
+ case 2:
+ err |= __get_user (sig[3], &ubuf->sig[3]);
+ err |= __get_user (sig[2], &ubuf->sig[2]);
+ kbuf->sig[1] = sig[2] | (sig[3] << 32);
+ case 1:
+ err |= __get_user (sig[1], &ubuf->sig[1]);
+ err |= __get_user (sig[0], &ubuf->sig[0]);
+ kbuf->sig[0] = sig[0] | (sig[1] << 32);
+ }
+
+ return err;
+}
+
/*
* Atomically swap in the new signal mask, and wait for a signal.
*/
asmlinkage inline int
sys32_sigsuspend(abi64_no_regargs, struct pt_regs regs)
{
- sigset_t *uset, saveset, newset;
+ sigset32_t *uset;
+ sigset_t newset, saveset;
- save_static(®s);
+#if DEBUG_MIPS64
printk("%s called.\n", __FUNCTION__);
- uset = (sigset_t *) regs.regs[4];
- if (copy_from_user(&newset, uset, sizeof(sigset_t)))
+#endif
+
+ save_static(®s);
+ uset = (sigset32_t *) regs.regs[4];
+ if (get_sigset(&newset, uset))
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
@@ -128,19+184,22 @@ printk("%s called.\n", __FUNCTION__); asmlinkage int
sys32_rt_sigsuspend(abi64_no_regargs, struct pt_regs regs)
{
- sigset_t *unewset, saveset, newset;
+ sigset32_t *uset;
+ sigset_t newset, saveset;
size_t sigsetsize;
- save_static(®s);
+#if DEBUG_MIPS64
printk("%s called.\n", __FUNCTION__);
+#endif
+ save_static(®s);
/* XXX Don't preclude handling different sized sigset_t's. */
sigsetsize = regs.regs[5];
- if (sigsetsize != sizeof(sigset_t))
+ if (sigsetsize != sizeof(sigset32_t))
return -EINVAL;
- unewset = (sigset_t *) regs.regs[4];
- if (copy_from_user(&newset, unewset, sizeof(newset)))
+ uset = (sigset32_t *) regs.regs[4];
+ if (get_sigset(&newset, uset))
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
@@ -172,10+231,12 @@ asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act,
if (!access_ok(VERIFY_READ, act, sizeof(*act)))
return -EFAULT;
- err |= __get_user(new_ka.sa.sa_handler, &act->sa_handler);
+ err |= __get_user((u32)(u64)new_ka.sa.sa_handler,
+ &act->sa_handler);
err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
err |= __get_user(mask, &act->sa_mask.sig[0]);
- err |= __get_user(new_ka.sa.sa_restorer, &act->sa_restorer);
+ err |= __get_user((u32)(u64)new_ka.sa.sa_restorer,
+ &act->sa_restorer);
if (err)
return -EFAULT;
@@ -188,12+249,14 @@ asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act, if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
return -EFAULT;
err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
- err |= __put_user(old_ka.sa.sa_handler, &oact->sa_handler);
+ err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
+ &oact->sa_handler);
err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
err |= __put_user(0, &oact->sa_mask.sig[1]);
err |= __put_user(0, &oact->sa_mask.sig[2]);
err |= __put_user(0, &oact->sa_mask.sig[3]);
- err |= __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer);
+ err |= __put_user((u32)(u64)old_ka.sa.sa_restorer,
+ &oact->sa_restorer);
if (err)
return -EFAULT;
}
@@ -204,12+267,37 @@ asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act, asmlinkage int
sys32_sigaltstack(abi64_no_regargs, struct pt_regs regs)
{
- const stack_t *uss = (const stack_t *) regs.regs[4];
- stack_t *uoss = (stack_t *) regs.regs[5];
+ const stack32_t *uss = (const stack32_t *) regs.regs[4];
+ stack32_t *uoss = (stack32_t *) regs.regs[5];
unsigned long usp = regs.regs[29];
-printk("%s called.\n", __FUNCTION__);
+ stack_t kss, koss;
+ int ret, err = 0;
+ mm_segment_t old_fs = get_fs();
- return do_sigaltstack(uss, uoss, usp);
+ if (uss) {
+ if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
+ return -EFAULT;
+ err |= __get_user(kss.ss_sp, &uss->ss_sp);
+ err |= __get_user(kss.ss_size, &uss->ss_size);
+ err |= __get_user(kss.ss_flags, &uss->ss_flags);
+ if (err)
+ return -EFAULT;
+ }
+
+ set_fs (KERNEL_DS);
+ ret = do_sigaltstack(uss ? &kss : NULL , uoss ? &koss : NULL, usp);
+ set_fs (old_fs);
+
+ if (!ret && uoss) {
+ if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
+ return -EFAULT;
+ err |= __put_user(koss.ss_sp, &uoss->ss_sp);
+ err |= __put_user(koss.ss_size, &uoss->ss_size);
+ err |= __put_user(koss.ss_flags, &uoss->ss_flags);
+ if (err)
+ return -EFAULT;
+ }
+ return ret;
}
static asmlinkage int
@@ -293,6+381,8 @@ printk("%s called.\n", __FUNCTION__); /*
* Don't let your children do this ...
*/
+ if (current->ptrace & PT_TRACESYS)
+ syscall_trace();
__asm__ __volatile__(
"move\t$29, %0\n\t"
"j\tret_from_sys_call"
@@ -610,7+700,7 @@ printk("%s: delivering signal.\n", current->comm); if (!signr)
break;
- if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+ if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
current->state = TASK_STOPPED;
@@ -684,7+774,6 @@ printk("%s: delivering signal.\n", current->comm); /* FALLTHRU */
default:
- lock_kernel();
sigaddset(¤t->signal, signr);
recalc_sigpending(current);
current->flags |= PF_SIGNALED;
@@ -723,26+812,128 @@ extern asmlinkage int sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset);
asmlinkage int sys32_sigprocmask(int how, old_sigset_t32 *set,
- old_sigset_t32 *oset)
+ old_sigset_t32 *oset)
{
old_sigset_t s;
int ret;
mm_segment_t old_fs = get_fs();
- if (set && get_user (s, set)) return -EFAULT;
+ if (set && get_user (s, set))
+ return -EFAULT;
set_fs (KERNEL_DS);
ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL);
set_fs (old_fs);
- if (ret) return ret;
- if (oset && put_user (s, oset)) return -EFAULT;
- return 0;
+ if (!ret && oset && put_user (s, oset))
+ return -EFAULT;
+ return ret;
}
-/* Dummies ... */
+asmlinkage long sys_sigpending(old_sigset_t *set);
+
+asmlinkage int sys32_sigpending(old_sigset_t32 *set)
+{
+ old_sigset_t pending;
+ int ret;
+ mm_segment_t old_fs = get_fs();
+
+ set_fs (KERNEL_DS);
+ ret = sys_sigpending(&pending);
+ set_fs (old_fs);
+
+ if (put_user(pending, set))
+ return -EFAULT;
+
+ return ret;
+}
+
+asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act,
+ struct sigaction32 *oact,
+ unsigned int sigsetsize)
+{
+ struct k_sigaction new_sa, old_sa;
+ int ret = -EINVAL;
+
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t))
+ goto out;
+
+ if (act) {
+ int err = 0;
+
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)))
+ return -EFAULT;
+ err |= __get_user((u32)(u64)new_sa.sa.sa_handler,
+ &act->sa_handler);
+ err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags);
+ err |= __get_user((u32)(u64)new_sa.sa.sa_restorer,
+ &act->sa_restorer);
+ err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask);
+ if (err)
+ return -EFAULT;
+ }
+
+ ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
+
+ if (!ret && oact) {
+ int err = 0;
+
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
+ return -EFAULT;
+
+ err |= __put_user((u32)(u64)new_sa.sa.sa_handler,
+ &oact->sa_handler);
+ err |= __put_user(new_sa.sa.sa_flags, &oact->sa_flags);
+ err |= __put_user((u32)(u64)new_sa.sa.sa_restorer,
+ &oact->sa_restorer);
+ err |= put_sigset(&new_sa.sa.sa_mask, &oact->sa_mask);
+ if (err)
+ return -EFAULT;
+ }
+out:
+ return ret;
+}
+
+asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset,
+ size_t sigsetsize);
+
+asmlinkage int sys32_rt_sigprocmask(int how, sigset32_t *set, sigset32_t *oset,
+ unsigned int sigsetsize)
+{
+ sigset_t old_set, new_set;
+ int ret;
+ mm_segment_t old_fs = get_fs();
+
+ if (set && get_sigset(&new_set, set))
+ return -EFAULT;
+
+ set_fs (KERNEL_DS);
+ ret = sys_rt_sigprocmask(how, set ? &new_set : NULL,
+ oset ? &old_set : NULL, sigsetsize);
+ set_fs (old_fs);
+
+ if (!ret && oset && put_sigset(&old_set, oset))
+ return -EFAULT;
+
+ return ret;
+}
+
+asmlinkage long sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
+
+asmlinkage int sys32_rt_sigpending(sigset32_t *uset, unsigned int sigsetsize)
+{
+ int ret;
+ sigset_t set;
+ mm_segment_t old_fs = get_fs();
+
+ set_fs (KERNEL_DS);
+ ret = sys_rt_sigpending(&set, sigsetsize);
+ set_fs (old_fs);
+
+ if (!ret && put_sigset(&set, uset))
+ return -EFAULT;
+
+ return ret;
+}
-asmlinkage void sys32_sigpending(void) { panic(__FUNCTION__ " called."); }
-asmlinkage void sys32_rt_sigaction(void) { panic(__FUNCTION__ " called."); }
-asmlinkage void sys32_rt_sigprocmask(void) { panic(__FUNCTION__ " called."); }
-asmlinkage void sys32_rt_sigpending(void) { panic(__FUNCTION__ " called."); }
asmlinkage void sys32_rt_sigtimedwait(void) { panic(__FUNCTION__ " called."); }
asmlinkage void sys32_rt_sigqueueinfo(void) { panic(__FUNCTION__ " called."); }
@@ -69,14+69,12 @@ static void smp_tune_scheduling (void) void __init smp_boot_cpus(void)
{
extern void allowboot(void);
- extern int maxcpus;
init_new_context(current, &init_mm);
global_irq_holder = 0;
current->processor = 0;
init_idle();
smp_tune_scheduling();
- smp_num_cpus = maxcpus;
allowboot();
}
-/* $Id: softfp.S,v 1.2 2000/03/21 23:50:42 ulfc Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1998, 1999 by Ralf Baechle
- * Copyright (C) 1999 by Silicon Graphics, Inc.
+ * Copyright (C) 1998, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 by Silicon Graphics, Inc.
*
* For now it's just a crude hack good enough to run certain fp programs like
* Mozilla.
@@ -192,15+191,15 @@ LEAF(simfp) #define FMT_switch(insn,opc,temp0,temp1) \
insn: srl temp0, opc, 18; \
andi temp0, 0x1c; \
- la temp1, insn ## .tab; \
+ la temp1, insn##.tab; \
daddu temp0, temp1; \
ld temp0, (temp0); \
jr temp0; \
\
.data; \
-insn ## .tab: \
- .dword insn ## .s, insn ## .d, unimp, unimp; \
- .dword insn ## .w, insn ## .l, unimp, unimp; \
+insn##.tab: \
+ .dword insn##.s, insn##.d, unimp, unimp; \
+ .dword insn##.w, insn##.l, unimp, unimp; \
.previous
BITCH(add)
-/* $Id: syscall.c,v 1.3 2000/02/04 07:40:24 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1995 - 1999 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1995 - 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#include <linux/errno.h>
#include <linux/linkage.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
+#include <linux/slab.h>
#include <asm/ipc.h>
#include <asm/cachectl.h>
#include <asm/offset.h>
@@ -170,39+170,46 @@ sys_sysmips(int cmd, long arg1, int arg2, int arg3) char *name;
int flags, tmp, len, errno;
- switch(cmd)
- {
- case SETNAME:
+ switch(cmd) {
+ case SETNAME: {
+ char nodename[__NEW_UTS_LEN + 1];
+
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
name = (char *) arg1;
- len = strlen_user(name);
- if (len == 0 || len > __NEW_UTS_LEN)
- return -EINVAL;
- down(&uts_sem);
- errno = -EFAULT;
- if (!copy_from_user(system_utsname.nodename, name, len)) {
- system_utsname.nodename[len] = '\0';
- errno = 0;
- }
- up(&uts_sem);
- return errno;
+ len = strncpy_from_user(nodename, name, sizeof(nodename));
+ if (len < 0)
+ return -EFAULT;
- case MIPS_ATOMIC_SET:
+ down_write(&uts_sem);
+ strncpy(system_utsname.nodename, name, len);
+ up_write(&uts_sem);
+ system_utsname.nodename[len] = '\0';
+ return 0;
+ }
+
+ case MIPS_ATOMIC_SET: {
/* This is broken in case of page faults and SMP ...
- Risc/OS fauls after maximum 20 tries with EAGAIN. */
+ Risc/OS faults after maximum 20 tries with EAGAIN. */
+ unsigned int tmp;
+
p = (int *) arg1;
errno = verify_area(VERIFY_WRITE, p, sizeof(*p));
if (errno)
return errno;
+ errno = 0;
save_and_cli(flags);
- errno = *p;
- *p = arg2;
+ errno |= __get_user(tmp, p);
+ errno |= __put_user(arg2, p);
restore_flags(flags);
- return errno; /* This is broken ... */
+ if (errno)
+ return tmp;
+
+ return tmp; /* This is broken ... */
+ }
case MIPS_FIXADE:
tmp = current->thread.mflags & ~3;
@@ -226,7+233,7 @@ sys_sysmips(int cmd, long arg1, int arg2, int arg3) * This is really horribly ugly.
*/
asmlinkage int sys_ipc (uint call, int first, int second,
- int third, void *ptr, long fifth)
+ unsigned long third, void *ptr, long fifth)
{
int version, ret;
-/* $Id: traps.c,v 1.4 2000/01/20 23:50:27 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
@@ -41,9+40,9 @@ static inline void console_verbose(void) console_loglevel = 15;
}
-extern asmlinkage void __xtlb_mod_debug(void);
-extern asmlinkage void __xtlb_tlbl_debug(void);
-extern asmlinkage void __xtlb_tlbs_debug(void);
+extern asmlinkage void __xtlb_mod(void);
+extern asmlinkage void __xtlb_tlbl(void);
+extern asmlinkage void __xtlb_tlbs(void);
extern asmlinkage void handle_adel(void);
extern asmlinkage void handle_ades(void);
extern asmlinkage void handle_ibe(void);
@@ -77,10+76,10 @@ int kstack_depth_to_print = 24; * This routine abuses get_user()/put_user() to reference pointers
* with at least a bit of error checking ...
*/
-void show_stack(unsigned int *sp)
+void show_stack(unsigned long *sp)
{
int i;
- unsigned int *stack;
+ unsigned long *stack;
stack = sp;
i = 0;
@@ -94,22+93,22 @@ void show_stack(unsigned int *sp) break;
}
- printk(" %08lx", stackdata);
+ printk(" %016lx", stackdata);
if (++i > 40) {
printk(" ...");
break;
}
- if (i % 8 == 0)
+ if (i % 4 == 0)
printk("\n ");
}
}
-void show_trace(unsigned int *sp)
+void show_trace(unsigned long *sp)
{
int i;
- unsigned int *stack;
+ unsigned long *stack;
unsigned long kernel_start, kernel_end;
unsigned long module_start, module_end;
extern char _stext, _etext;
@@ -144,7+143,11 @@ void show_trace(unsigned int *sp) if ((addr >= kernel_start && addr < kernel_end) ||
(addr >= module_start && addr < module_end)) {
- printk(" [<%08lx>]", addr);
+ /* Since our kernel is still at KSEG0,
+ * truncate the address so that ksymoops
+ * understands it.
+ */
+ printk(" [<%08x>]", (unsigned int) addr);
if (++i > 40) {
printk(" ...");
break;
@@ -160,12+163,12 @@ void show_code(unsigned int *pc) printk("\nCode:");
for(i = -3 ; i < 6 ; i++) {
- unsigned long insn;
+ unsigned int insn;
if (__get_user(insn, pc + i)) {
printk(" (Bad address in epc)\n");
break;
}
- printk("%c%08lx%c",(i?' ':'<'),insn,(i?' ':'>'));
+ printk("%c%08x%c",(i?' ':'<'),insn,(i?' ':'>'));
}
}
@@ -180,10+183,10 @@ void die(const char * str, struct pt_regs * regs, unsigned long err) spin_lock_irq(&die_lock);
printk("%s: %04lx\n", str, err & 0xffff);
show_regs(regs);
- printk("Process %s (pid: %ld, stackpage=%08lx)\n",
+ printk("Process %s (pid: %d, stackpage=%08lx)\n",
current->comm, current->pid, (unsigned long) current);
- show_stack((unsigned int *) regs->regs[29]);
- show_trace((unsigned int *) regs->regs[29]);
+ show_stack((unsigned long *) regs->regs[29]);
+ show_trace((unsigned long *) regs->regs[29]);
show_code((unsigned int *) regs->cp0_epc);
printk("\n");
spin_unlock_irq(&die_lock);
@@ -230,6+233,7 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31) {
unsigned long pc;
unsigned int insn;
+ extern void simfp(unsigned int);
#ifdef CONFIG_MIPS_FPE_MODULE
if (fpe_handler != NULL) {
@@ -237,7+241,6 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31) return;
}
#endif
- lock_kernel();
if (fcr31 & 0x20000) {
/* Retry instruction with flush to zero ... */
if (!(fcr31 & (1<<24))) {
@@ -249,7+252,7 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31) "ctc1\t%0,$31"
: /* No outputs */
: "r" (fcr31));
- goto out;
+ return;
}
pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0);
if (get_user(insn, (unsigned int *)pc)) {
@@ -263,12+266,9 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31) }
if (compute_return_epc(regs))
- goto out;
+ return;
//force_sig(SIGFPE, current);
printk(KERN_DEBUG "Should send SIGFPE to %s\n", current->comm);
-
-out:
- unlock_kernel();
}
static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
@@ -327,11+327,9 @@ void do_tr(struct pt_regs *regs)
void do_ri(struct pt_regs *regs)
{
- lock_kernel();
- printk("Cpu%d[%s:%ld] Illegal instruction at %08lx ra=%08lx\n",
+ printk("Cpu%d[%s:%d] Illegal instruction at %08lx ra=%08lx\n",
smp_processor_id(), current->comm, current->pid, regs->cp0_epc,
regs->regs[31]);
- unlock_kernel();
if (compute_return_epc(regs))
return;
force_sig(SIGILL, current);
@@ -390,7+388,7 @@ void do_reserved(struct pt_regs *regs) * caused by a new unknown cpu type or after another deadly
* hard/software error.
*/
- panic("Caught reserved exception %d - should not happen.",
+ panic("Caught reserved exception %ld - should not happen.",
(regs->cp0_cause & 0x1f) >> 2);
}
@@ -471,8+469,8 @@ static inline void go_64(void)
void __init trap_init(void)
{
- extern char __tlb_refill_debug_tramp;
- extern char __xtlb_refill_debug_tramp;
+ extern char except_vec0;
+ extern char except_vec1_r10k;
extern char except_vec2_generic;
extern char except_vec3_generic, except_vec3_r4000;
extern void bus_error_init(void);
@@ -528,8+526,8 @@ void __init trap_init(void) case CPU_NEVADA:
r4k:
/* Debug TLB refill handler. */
- memcpy((void *)KSEG0, &__tlb_refill_debug_tramp, 0x80);
- memcpy((void *)KSEG0 + 0x080, &__xtlb_refill_debug_tramp, 0x80);
+ memcpy((void *)KSEG0, &except_vec0, 0x80);
+ memcpy((void *)KSEG0 + 0x080, &except_vec1_r10k, 0x80);
/* Cache error vector */
memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80);
0x100);
}
- set_except_vector(1, __xtlb_mod_debug);
- set_except_vector(2, __xtlb_tlbl_debug);
- set_except_vector(3, __xtlb_tlbs_debug);
+ set_except_vector(1, __xtlb_mod);
+ set_except_vector(2, __xtlb_tlbl);
+ set_except_vector(3, __xtlb_tlbs);
set_except_vector(4, handle_adel);
set_except_vector(5, handle_ades);
@@ -3,11+3,9 @@ ENTRY(kernel_entry) SECTIONS
{
/* Read-only sections, merged into text segment: */
- . = 0x80000000;
.init : { *(.init) } =0
.text :
{
- _ftext = . ;
*(.text)
*(.rodata)
*(.rodata1)
@@ -15,9+13,9 @@ SECTIONS *(.gnu.warning)
} =0
_etext = .;
- PROVIDE (etext = .);
. = ALIGN(16384);
+ /* This for CONFIG_MAPPED_KERNEL . = . + 16777216; */
.data.init_task : { *(.data.init_task) }
/* Startup code */
@@ -65,7+63,6 @@ SECTIONS CONSTRUCTORS
}
.data1 : { *(.data1) }
- _gp = . + 0x8000;
.lit8 : { *(.lit8) }
.lit4 : { *(.lit4) }
.ctors : { *(.ctors) }
@@ -77,10+74,7 @@ SECTIONS we can shorten the on-disk segment size. */
.sdata : { *(.sdata) }
_edata = .;
- PROVIDE (edata = .);
- __bss_start = .;
- _fbss = .;
.sbss : { *(.sbss) *(.scommon) }
.bss :
{
@@ -88,7+82,6 @@ SECTIONS *(.bss)
*(COMMON)
_end = . ;
- PROVIDE (end = .);
}
/* These are needed for ELF backends which have not yet been
converted to the new style linker. */
@@ -16,7+16,6 @@ SECTIONS /* . = 0xa800000000300000; */
. = 0xffffffff80300000;
.text : {
- _ftext = . ;
*(.text)
*(.rodata)
*(.rodata1)
@@ -24,7+23,6 @@ SECTIONS *(.gnu.warning)
} = 0
_etext = .;
- PROVIDE (etext = .);
. = ALIGN(16384);
.data.init_task : { *(.data.init_task) }
@@ -74,7+72,6 @@ SECTIONS CONSTRUCTORS
}
.data1 : { *(.data1) }
- _gp = . + 0x8000;
.lit8 : { *(.lit8) }
.lit4 : { *(.lit4) }
.ctors : { *(.ctors) }
@@ -86,10+83,7 @@ SECTIONS we can shorten the on-disk segment size. */
.sdata : { *(.sdata) }
_edata = .;
- PROVIDE (edata = .);
- __bss_start = .;
- _fbss = .;
.sbss : { *(.sbss) *(.scommon) }
.bss :
{
@@ -97,7+91,6 @@ SECTIONS *(.bss)
*(COMMON)
_end = . ;
- PROVIDE (end = .);
}
/* These are needed for ELF backends which have not yet been
converted to the new style linker. */
@@ -133,28+133,28 @@ dump_list_process(struct task_struct *t, void *address) pgd_t *page_dir, *pgd;
pmd_t *pmd;
pte_t *pte, page;
- unsigned int addr;
+ unsigned long addr;
unsigned long val;
- addr = (unsigned int) address;
+ addr = (unsigned long) address;
- printk("Addr == %08x\n", addr);
- printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd);
+ printk("Addr == %08lx\n", addr);
+ printk("tasks->mm.pgd == %08lx\n", (unsigned long) t->mm->pgd);
page_dir = pgd_offset(t->mm, 0);
- printk("page_dir == %08x\n", (unsigned int) page_dir);
+ printk("page_dir == %08lx\n", (unsigned long) page_dir);
pgd = pgd_offset(t->mm, addr);
- printk("pgd == %08x, ", (unsigned int) pgd);
+ printk("pgd == %08lx, ", (unsigned long) pgd);
pmd = pmd_offset(pgd, addr);
- printk("pmd == %08x, ", (unsigned int) pmd);
+ printk("pmd == %08lx, ", (unsigned long) pmd);
pte = pte_offset(pmd, addr);
- printk("pte == %08x, ", (unsigned int) pte);
+ printk("pte == %08lx, ", (unsigned long) pte);
page = *pte;
- printk("page == %08x\n", (unsigned int) pte_val(page));
+ printk("page == %08lx\n", (unsigned long) pte_val(page));
val = pte_val(page);
if (val & _PAGE_PRESENT) printk("present ");
-/* $Id: floppy-std.c,v 1.1 1999/08/21 21:43:00 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
#include <asm/keyboard.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/mc146818rtc.h>
#include <asm/pgtable.h>
/*
@@ -458,7+458,6 @@ void __init ld_mmu_andes(void) _user_mode = andes_user_mode;
flush_cache_all();
- write_32bit_cp0_register(CP0_WIRED, 0);
/*
* You should never change this register:
-/* $Id: fault.c,v 1.7 2000/03/13 22:43:25 kanoj Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1995, 1996, 1997, 1998, 1999 by Ralf Baechle
- * Copyright (C) 1999 by Silicon Graphics
+ * Copyright (C) 1995 - 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 by Silicon Graphics, Inc.
*/
#include <linux/signal.h>
#include <linux/sched.h>
@@ -41,7+40,8 @@ extern void die(char *, struct pt_regs *, unsigned long write); asmlinkage void
dodebug(abi64_no_regargs, struct pt_regs regs)
{
- printk("Got syscall %d, cpu %d proc %s:%d epc 0x%lx\n", regs.regs[2], smp_processor_id(), current->comm, current->pid, regs.cp0_epc);
+ printk("Got syscall %ld, cpu %d proc %s:%d epc 0x%lx\n", regs.regs[2],
+ smp_processor_id(), current->comm, current->pid, regs.cp0_epc);
}
asmlinkage void
@@ -68,9+68,10 @@ do_page_fault(struct pt_regs *regs, unsigned long write, unsigned long address) struct vm_area_struct * vma;
struct task_struct *tsk = current;
struct mm_struct *mm = tsk->mm;
- int si_code = SEGV_MAPERR;
unsigned long fixup;
+ siginfo_t info;
+ info.si_code = SEGV_MAPERR;
/*
* If we're in an interrupt or have no user
* context, we must not take the fault..
@@ -96,7+97,7 @@ do_page_fault(struct pt_regs *regs, unsigned long write, unsigned long address) * we can handle it..
*/
good_area:
- si_code = SEGV_ACCERR;
+ info.si_code = SEGV_ACCERR;
if (write) {
if (!(vma->vm_flags & VM_WRITE))
@@ -134,8+135,14 @@ good_area: bad_area:
up(&mm->mmap_sem);
+ /*
+ * Quickly check for vmalloc range faults.
+ */
+ if ((!vma) && (address >= VMALLOC_START) && (address < VMALLOC_END)) {
+ printk("Fix vmalloc invalidate fault\n");
+ while(1);
+ }
if (user_mode(regs)) {
- struct siginfo si;
tsk->thread.cp0_badvaddr = address;
tsk->thread.error_code = write;
#if 0
@@ -147,10+154,11 @@ bad_area: (unsigned long) regs->cp0_epc,
(unsigned long) regs->regs[31]);
#endif
- si.si_signo = SIGSEGV;
- si.si_code = si_code;
- si.si_addr = (void *) address;
- force_sig_info(SIGSEGV, &si, tsk);
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ /* info.si_code has been set above */
+ info.si_addr = (void *) address;
+ force_sig_info(SIGSEGV, &info, tsk);
return;
}
@@ -174,8+182,9 @@ no_context: * terminate things with extreme prejudice.
*/
printk(KERN_ALERT "Cpu %d Unable to handle kernel paging request at "
- "address %08lx, epc == %08lx, ra == %08lx\n",
- smp_processor_id(), address, regs->cp0_epc, regs->regs[31]);
+ "address %08lx, epc == %08x, ra == %08x\n",
+ smp_processor_id(), address, (unsigned int) regs->cp0_epc,
+ (unsigned int) regs->regs[31]);
die("Oops", regs, write);
do_exit(SIGKILL);
@@ -198,7+207,11 @@ do_sigbus: * or user mode.
*/
tsk->thread.cp0_badvaddr = address;
- force_sig(SIGBUS, tsk);
+ info.si_code = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_ADRERR;
+ info.si_addr = (void *) address;
+ force_sig_info(SIGBUS, &info, tsk);
/* Kernel mode? Handle exceptions or die */
if (!user_mode(regs))
@@ -56,7+56,7 @@ void __bad_pte(pmd_t *pmd) void __bad_pmd(pgd_t *pgd)
{
printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd));
- pgd_set(pgd, (pmd_t *) BAD_PAGETABLE);
+ pgd_set(pgd, empty_bad_pmd_table);
}
void pgd_init(unsigned long page)
@@ -93,7+93,7 @@ pgd_t *get_pgd_slow(void) return ret;
}
-void pmd_init(unsigned long addr)
+void pmd_init(unsigned long addr, unsigned long pagetable)
{
unsigned long *p, *end;
@@ -101,14+101,14 @@ void pmd_init(unsigned long addr) end = p + PTRS_PER_PMD;
while (p < end) {
- p[0] = (unsigned long) invalid_pte_table;
- p[1] = (unsigned long) invalid_pte_table;
- p[2] = (unsigned long) invalid_pte_table;
- p[3] = (unsigned long) invalid_pte_table;
- p[4] = (unsigned long) invalid_pte_table;
- p[5] = (unsigned long) invalid_pte_table;
- p[6] = (unsigned long) invalid_pte_table;
- p[7] = (unsigned long) invalid_pte_table;
+ p[0] = (unsigned long)pagetable;
+ p[1] = (unsigned long)pagetable;
+ p[2] = (unsigned long)pagetable;
+ p[3] = (unsigned long)pagetable;
+ p[4] = (unsigned long)pagetable;
+ p[5] = (unsigned long)pagetable;
+ p[6] = (unsigned long)pagetable;
+ p[7] = (unsigned long)pagetable;
p += 8;
}
}
@@ -120,7+120,7 @@ pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset) pmd = (pmd_t *) __get_free_pages(GFP_KERNEL, 1);
if (pgd_none(*pgd)) {
if (pmd) {
- pmd_init((unsigned long)pmd);
+ pmd_init((unsigned long)pmd, (unsigned long)invalid_pte_table);
pgd_set(pgd, pmd);
return pmd + offset;
}
@@ -161,7+161,7 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) {
pte_t *page;
- page = (pte_t *) __get_free_pages(GFP_KERNEL, 1);
+ page = (pte_t *) __get_free_pages(GFP_KERNEL, 0);
if (pmd_none(*pmd)) {
if (page) {
clear_page(page);
@@ -171,7+171,7 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) pmd_set(pmd, BAD_PAGETABLE);
return NULL;
}
- free_pages((unsigned long)page, 1);
+ free_pages((unsigned long)page, 0);
if (pmd_bad(*pmd)) {
__bad_pte(pmd);
return NULL;
@@ -246,21+246,6 @@ unsigned long setup_zero_pages(void) return 1UL << order;
}
-extern inline void pte_init(unsigned long page)
-{
- unsigned long *p, *end, bp;
-
- bp = pte_val(BAD_PAGE);
- p = (unsigned long *) page;
- end = p + (2 * PTRS_PER_PTE);
-
- while (p < end) {
- p[0] = p[1] = p[2] = p[3] =
- p[4] = p[5] = p[6] = p[7] = bp;
- p += 8;
- }
-}
-
/*
* BAD_PAGE is the page that is used for page faults when linux
* is out-of-memory. Older versions of linux just did a
@@ -276,33+261,17 @@ extern inline void pte_init(unsigned long page) */
pmd_t * __bad_pmd_table(void)
{
- extern pmd_t invalid_pmd_table[PTRS_PER_PMD];
- unsigned long page;
-
- page = (unsigned long) invalid_pmd_table;
- pmd_init(page);
-
- return (pmd_t *) page;
+ return empty_bad_pmd_table;
}
pte_t * __bad_pagetable(void)
{
- extern char empty_bad_page_table[PAGE_SIZE];
- unsigned long page;
-
- page = (unsigned long) empty_bad_page_table;
- pte_init(page);
-
- return (pte_t *) page;
+ return empty_bad_page_table;
}
pte_t __bad_page(void)
{
- extern char empty_bad_page[PAGE_SIZE];
- unsigned long page = (unsigned long) empty_bad_page;
-
- clear_page((void *)page);
- return pte_mkdirty(mk_pte_phys(__pa(page), PAGE_SHARED));
+ return __pte(0);
}
void show_mem(void)
@@ -337,7+306,7 @@ void show_mem(void) #ifndef CONFIG_DISCONTIGMEM
/* References to section boundaries */
-extern char _ftext, _etext, _fdata, _edata;
+extern char _stext, _etext, _fdata, _edata;
extern char __init_begin, __init_end;
void __init paging_init(void)
@@ -347,8+316,10 @@ void __init paging_init(void)
/* Initialize the entire pgd. */
pgd_init((unsigned long)swapper_pg_dir);
- pmd_init((unsigned long)invalid_pmd_table);
- memset((void *)invalid_pte_table, 0, sizeof(pte_t) * 2 * PTRS_PER_PTE);
+ pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table);
+ memset((void *)invalid_pte_table, 0, sizeof(pte_t) * PTRS_PER_PTE);
+ pmd_init((unsigned long)empty_bad_pmd_table, (unsigned long)empty_bad_page_table);
+ memset((void *)empty_bad_page_table, 0, sizeof(pte_t) * PTRS_PER_PTE);
max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
low = max_low_pfn;
@@ -384,7+355,7 @@ void __init mem_init(void) reservedpages++;
}
- codesize = (unsigned long) &_etext - (unsigned long) &_ftext;
+ codesize = (unsigned long) &_etext - (unsigned long) &_stext;
datasize = (unsigned long) &_edata - (unsigned long) &_fdata;
initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
@@ -2545,7+2545,6 @@ void __init ld_mmu_r4xx0(void) _user_mode = r4k_user_mode;
flush_cache_all();
- write_32bit_cp0_register(CP0_WIRED, 0);
/*
* You should never change this register:
#include <linux/tty.h>
#include <asm/addrspace.h>
+#include <asm/mmu_context.h>
#include <asm/bcache.h>
#include <asm/keyboard.h>
#include <asm/irq.h>
@@ -125,6+126,7 @@ void __init ip22_setup(void) #ifdef CONFIG_SERIAL_CONSOLE
char *ctype;
#endif
+ TLBMISS_HANDLER_SETUP();
/* Init the INDY HPC I/O controller. Need to call this before
* fucking with the memory controller because it needs to know the
L_TARGET = ip27.a
L_OBJS = ip27-berr.o ip27-irq.o ip27-irq-glue.o ip27-klconfig.o \
ip27-memory.o ip27-pci.o ip27-pci-dma.o ip27-reset.o ip27-setup.o \
- ip27-timer.o ip27-init.o ip27-nmi.o
+ ip27-timer.o ip27-init.o ip27-nmi.o ip27-klnuma.o
include $(TOPDIR)/Rules.make
-/* $Id: ip27-berr.c,v 1.1 2000/01/20 22:50:29 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
#include <asm/sn/sn0/hub.h>
#include <asm/uaccess.h>
+extern void dump_tlb_addr(unsigned long addr);
+extern void dump_tlb_all(void);
+
extern asmlinkage void handle_ibe(void);
extern asmlinkage void handle_dbe(void);
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <asm/sn/launch.h>
#include <asm/sn/sn_private.h>
#include <asm/sn/sn0/ip27.h>
+#include <asm/sn/mapped_kernel.h>
#define CPU_NONE (cpuid_t)-1
#define CNODEMASK_SETB(p, bit) ((p) |= 1ULL << (bit))
cpumask_t boot_cpumask;
-static volatile cpumask_t boot_barrier;
hubreg_t region_mask = 0;
static int fine_mode = 0;
int maxcpus;
static spinlock_t hub_mask_lock = SPIN_LOCK_UNLOCKED;
static cnodemask_t hub_init_mask;
+static atomic_t numstarted = ATOMIC_INIT(1);
+nasid_t master_nasid = INVALID_NASID;
cnodeid_t nasid_to_compact_node[MAX_NASIDS];
nasid_t compact_to_nasid_node[MAX_COMPACT_NODES];
@@ -160,19+161,6 @@ cpuid_t cpu_node_probe(cpumask_t *boot_cpumask, int *numnodes) return(highest + 1);
}
-void alloc_cpupda(int i)
-{
- cnodeid_t node;
- nasid_t nasid;
-
- node = get_cpu_cnode(i);
- nasid = COMPACT_TO_NASID_NODEID(node);
-
- cputonasid(i) = nasid;
- cputocnode(i) = node;
- cputoslice(i) = get_cpu_slice(i);
-}
-
int cpu_enabled(cpuid_t cpu)
{
if (cpu == CPU_NONE)
@@ -180,19+168,11 @@ int cpu_enabled(cpuid_t cpu) return (CPUMASK_TSTB(boot_cpumask, cpu) != 0);
}
-void initpdas(void)
-{
- cpuid_t i;
-
- for (i = 0; i < maxcpus; i++)
- if (cpu_enabled(i))
- alloc_cpupda(i);
-}
-
void mlreset (void)
{
int i;
+ master_nasid = get_nasid();
fine_mode = is_fine_dirmode();
/*
@@ -202,11+182,12 @@ void mlreset (void) CPUMASK_CLRALL(boot_cpumask);
maxcpus = cpu_node_probe(&boot_cpumask, &numnodes);
printk("Discovered %d cpus on %d nodes\n", maxcpus, numnodes);
- initpdas();
gen_region_mask(®ion_mask, numnodes);
CNODEMASK_CLRALL(hub_init_mask);
+ setup_replication_mask(numnodes);
+
/*
* Set all nodes' calias sizes to 8k
*/
@@ -221,7+202,11 @@ void mlreset (void) * thinks it is a node 0 address.
*/
REMOTE_HUB_S(nasid, PI_REGION_PRESENT, (region_mask | 1));
+#ifdef CONFIG_REPLICATE_EXHANDLERS
+ REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_8K);
+#else
REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_0);
+#endif
#ifdef LATER
/*
@@ -283,6+268,7 @@ void sn_mp_setup(void)
void per_hub_init(cnodeid_t cnode)
{
+ extern void pcibr_setup(cnodeid_t);
cnodemask_t done;
spin_lock(&hub_mask_lock);
@@ -290,16+276,35 @@ void per_hub_init(cnodeid_t cnode) if (!(done = CNODEMASK_TSTB(hub_init_mask, cnode))) {
/* Turn our bit on in the mask. */
CNODEMASK_SETB(hub_init_mask, cnode);
- }
- spin_unlock(&hub_mask_lock);
-
- /*
- * Do the actual initialization if it hasn't been done yet.
- * We don't need to hold a lock for this work.
- */
- if (!done) {
+ /*
+ * Do the actual initialization if it hasn't been done yet.
+ * We don't need to hold a lock for this work.
+ */
hub_rtc_init(cnode);
+ pcibr_setup(cnode);
+#ifdef CONFIG_REPLICATE_EXHANDLERS
+ /*
+ * If this is not a headless node initialization,
+ * copy over the caliased exception handlers.
+ */
+ if (get_compact_nodeid() == cnode) {
+ extern char except_vec0, except_vec1_r10k;
+ extern char except_vec2_generic, except_vec3_generic;
+
+ memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic,
+ 0x80);
+ memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
+ 0x80);
+ memcpy((void *)KSEG0, &except_vec0, 0x80);
+ memcpy((void *)KSEG0 + 0x080, &except_vec1_r10k, 0x80);
+ memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80);
+ memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
+ 0x100);
+ flush_cache_all();
+ }
+#endif
}
+ spin_unlock(&hub_mask_lock);
}
/*
@@ -318,10+323,11 @@ void per_cpu_init(void) extern void install_cpu_nmi_handler(int slice);
extern void load_mmu(void);
static int is_slave = 0;
- cpuid_t cpu = getcpuid();
+ int cpu = smp_processor_id();
cnodeid_t cnode = get_compact_nodeid();
current_cpu_data.asid_cache = ASID_FIRST_VERSION;
+ TLBMISS_HANDLER_SETUP();
#if 0
intr_init();
#endif
@@ -331,7+337,7 @@ void per_cpu_init(void) if (smp_processor_id()) /* master can't do this early, no kmalloc */
install_cpuintr(cpu);
/* Install our NMI handler if symmon hasn't installed one. */
- install_cpu_nmi_handler(cputoslice(smp_processor_id()));
+ install_cpu_nmi_handler(cputoslice(cpu));
#if 0
install_tlbintr(cpu);
#endif
@@ -343,9+349,10 @@ void per_cpu_init(void) set_cp0_status(ST0_KX|ST0_SX|ST0_UX, ST0_KX|ST0_SX|ST0_UX);
sti();
load_mmu();
- }
- if (is_slave == 0)
+ atomic_inc(&numstarted);
+ } else {
is_slave = 1;
+ }
}
cnodeid_t get_compact_nodeid(void)
@@ -362,6+369,24 @@ cnodeid_t get_compact_nodeid(void)
#ifdef CONFIG_SMP
+/*
+ * Takes as first input the PROM assigned cpu id, and the kernel
+ * assigned cpu id as the second.
+ */
+static void alloc_cpupda(cpuid_t cpu, int cpunum)
+{
+ cnodeid_t node;
+ nasid_t nasid;
+
+ node = get_cpu_cnode(cpu);
+ nasid = COMPACT_TO_NASID_NODEID(node);
+
+ cputonasid(cpunum) = nasid;
+ cputocnode(cpunum) = node;
+ cputoslice(cpunum) = get_cpu_slice(cpu);
+ cpu_data[cpunum].p_cpuid = cpu;
+}
+
void __init smp_callin(void)
{
#if 0
@@ -380,10+405,10 @@ int __init start_secondary(void) return cpu_idle();
}
-static atomic_t numstarted = ATOMIC_INIT(0);
+static volatile cpumask_t boot_barrier;
+
void cboot(void)
{
- atomic_inc(&numstarted);
CPUMASK_CLRB(boot_barrier, getcpuid()); /* needs atomicity */
per_cpu_init();
#if 0
@@ -399,22+424,24 @@ void cboot(void) void allowboot(void)
{
int num_cpus = 0;
- cpuid_t cpu;
+ cpuid_t cpu, mycpuid = getcpuid();
cnodeid_t cnode;
extern void bootstrap(void);
sn_mp_setup();
/* Master has already done per_cpu_init() */
- install_cpuintr(getcpuid());
+ install_cpuintr(smp_processor_id());
#if 0
bte_lateinit();
ecc_init();
#endif
+ replicate_kernel_text(numnodes);
boot_barrier = boot_cpumask;
/* Launch slaves. */
for (cpu = 0; cpu < maxcpus; cpu++) {
- if (cpu == smp_processor_id()) {
+ if (cpu == mycpuid) {
+ alloc_cpupda(cpu, num_cpus);
num_cpus++;
/* We're already started, clear our bit */
CPUMASK_CLRB(boot_barrier, cpu);
@@ -433,6+460,7 @@ void allowboot(void) p = init_task.prev_task;
sprintf(p->comm, "%s%d", "Idle", num_cpus);
init_tasks[num_cpus] = p;
+ alloc_cpupda(cpu, num_cpus);
p->processor = num_cpus;
p->has_cpu = 1; /* we schedule the first task manually */
del_from_runqueue(p);
@@ -448,10+476,10 @@ void allowboot(void) * created idle process, gp to the proc struct
* (so that current-> works).
*/
- LAUNCH_SLAVE(cputonasid(cpu), cputoslice(cpu),
- (launch_proc_t)bootstrap, 0,
- (void *)((unsigned long)p+KERNEL_STACK_SIZE - 32),
- (void *)p);
+ LAUNCH_SLAVE(cputonasid(num_cpus),cputoslice(num_cpus),
+ (launch_proc_t)MAPPED_KERN_RW_TO_K0(bootstrap),
+ 0, (void *)((unsigned long)p +
+ KERNEL_STACK_SIZE - 32), (void *)p);
/*
* Now optimistically set the mapping arrays. We
@@ -461,13+489,18 @@ void allowboot(void) __cpu_number_map[cpu] = num_cpus;
__cpu_logical_map[num_cpus] = cpu;
num_cpus++;
- /* smp_num_cpus++; Do after smp_send_reschedule works */
+ /*
+ * Wait this cpu to start up and initialize its hub,
+ * and discover the io devices it will control.
+ *
+ * XXX: We really want to fire up launch all the CPUs
+ * at once. We have to preserve the order of the
+ * devices on the bridges first though.
+ */
+ while(atomic_read(&numstarted) != num_cpus);
}
}
- /* while(atomic_read(&numstarted) != (maxcpus - num_cpus)) */
- if (maxcpus > 1) while(atomic_read(&numstarted) == 0);
- printk("Holding %d cpus slave\n", atomic_read(&numstarted));
#ifdef LATER
Wait logic goes here.
@@ -484,6+517,7 @@ void allowboot(void) cpu_io_setup();
init_mfhi_war();
#endif
+ smp_num_cpus = num_cpus;
}
#else /* CONFIG_SMP */
-/* $Id: ip27-irq.c,v 1.9 2000/03/14 01:39:27 ralf Exp $
- *
+/*
* ip27-irq.c: Highlevel interrupt handling for IP27 architecture.
*
- * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/smp_lock.h>
#include <linux/kernel_stat.h>
#include <linux/delay.h>
+#include <linux/irq.h>
#include <asm/bitops.h>
#include <asm/bootinfo.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/mipsregs.h>
#include <asm/system.h>
irq_cpustat_t irq_stat [NR_CPUS];
extern asmlinkage void ip27_irq(void);
+extern int irq_to_bus[], irq_to_slot[], bus_to_cpu[];
int (*irq_cannonicalize)(int irq);
-int intr_connect_level(cpuid_t cpu, int bit);
-int intr_disconnect_level(cpuid_t cpu, int bit);
+int intr_connect_level(int cpu, int bit);
+int intr_disconnect_level(int cpu, int bit);
unsigned int local_bh_count[NR_CPUS];
unsigned int local_irq_count[NR_CPUS];
@@ -76,15+75,17 @@ unsigned long spurious_count = 0; * we need to map irq's up to at least bit 7 of the INT_MASK0_A register
* since bits 0-6 are pre-allocated for other purposes.
*/
-#define IRQ_TO_SWLEVEL(i) i + 7
-#define SWLEVEL_TO_IRQ(s) s - 7
+#define IRQ_TO_SWLEVEL(cpu, i) i + 7
+#define SWLEVEL_TO_IRQ(cpu, s) s - 7
/*
- * use these macros to get the encoded nasid, widget id, and real irq
+ * use these macros to get the encoded nasid and widget id
* from the irq value
*/
-#define NASID_FROM_IRQ(i) ((i >> 16)&(0xff))
-#define WID_FROM_IRQ(i) ((i >> 8)&(0xff))
-#define IRQ_FROM_IRQ(i) ((i)&(0xff))
+#define IRQ_TO_BUS(i) irq_to_bus[(i)]
+#define IRQ_TO_CPU(i) bus_to_cpu[IRQ_TO_BUS(i)]
+#define NASID_FROM_PCI_IRQ(i) bus_to_nid[IRQ_TO_BUS(i)]
+#define WID_FROM_PCI_IRQ(i) bus_to_wid[IRQ_TO_BUS(i)]
+#define SLOT_FROM_PCI_IRQ(i) irq_to_slot[i]
void disable_irq(unsigned int irq_nr)
{
@@ -104,7+105,7 @@ int get_irq_list(char *buf) int i, len = 0;
struct irqaction * action;
- for (i = 0 ; i < 32 ; i++) {
+ for (i = 0 ; i < NR_IRQS ; i++) {
action = irq_action[i];
if (!action)
continue;
@@ -126,20+127,18 @@ int get_irq_list(char *buf) * do_IRQ handles all normal device IRQ's (the special SMP cross-CPU interrupts
* have their own specific handlers).
*/
-asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
+static void do_IRQ(cpuid_t thiscpu, int irq, struct pt_regs * regs)
{
struct irqaction *action;
- int do_random, cpu;
+ int do_random;
- cpu = smp_processor_id();
- irq_enter(cpu, irq);
- kstat.irqs[cpu][irq]++;
+ irq_enter(thiscpu, irq);
+ kstat.irqs[thiscpu][irq]++;
action = *(irq + irq_action);
if (action) {
if (!(action->flags & SA_INTERRUPT))
__sti();
- action = *(irq + irq_action);
do_random = 0;
do {
do_random |= action->flags;
@@ -150,7+149,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) add_interrupt_randomness(irq);
__cli();
}
- irq_exit(cpu, irq);
+ irq_exit(thiscpu, irq);
/* unmasking and bottom half handling is done magically for us. */
}
@@ -171,31+170,46 @@ static int ms1bit(unsigned long x)
return b + (int) (x >> 1);
}
-
-/* For now ... */
+
+/*
+ * This code is unnecessarily complex, because we do SA_INTERRUPT
+ * intr enabling. Basically, once we grab the set of intrs we need
+ * to service, we must mask _all_ these interrupts; firstly, to make
+ * sure the same intr does not intr again, causing recursion that
+ * can lead to stack overflow. Secondly, we can not just mask the
+ * one intr we are do_IRQing, because the non-masked intrs in the
+ * first set might intr again, causing multiple servicings of the
+ * same intr. This effect is mostly seen for intercpu intrs.
+ * Kanoj 05.13.00
+ */
void ip27_do_irq(struct pt_regs *regs)
{
int irq, swlevel;
hubreg_t pend0, mask0;
- int pi_int_mask0 = ((cputoslice(smp_processor_id()) == 0) ?
+ cpuid_t thiscpu = smp_processor_id();
+ int pi_int_mask0 = ((cputoslice(thiscpu) == 0) ?
PI_INT_MASK0_A : PI_INT_MASK0_B);
/* copied from Irix intpend0() */
while (((pend0 = LOCAL_HUB_L(PI_INT_PEND0)) &
(mask0 = LOCAL_HUB_L(pi_int_mask0))) != 0) {
- pend0 &= mask0;
- do {
- swlevel = ms1bit(pend0);
- LOCAL_HUB_S(pi_int_mask0, mask0 & ~(1 << swlevel));
- LOCAL_HUB_CLR_INTR(swlevel);
- /* "map" swlevel to irq */
- irq = SWLEVEL_TO_IRQ(swlevel);
- do_IRQ(irq, regs);
- /* reset INT_MASK0 register */
+ pend0 &= mask0; /* Pick intrs we should look at */
+ if (pend0) {
+ /* Prevent any of the picked intrs from recursing */
+ LOCAL_HUB_S(pi_int_mask0, mask0 & ~(pend0));
+ do {
+ swlevel = ms1bit(pend0);
+ LOCAL_HUB_CLR_INTR(swlevel);
+ /* "map" swlevel to irq */
+ irq = SWLEVEL_TO_IRQ(thiscpu, swlevel);
+ do_IRQ(thiscpu, irq, regs);
+ /* clear bit in pend0 */
+ pend0 ^= 1ULL << swlevel;
+ } while(pend0);
+ /* Now allow the set of serviced intrs again */
LOCAL_HUB_S(pi_int_mask0, mask0);
- /* clear bit in pend0 */
- pend0 ^= 1ULL << swlevel;
- } while (pend0);
+ LOCAL_HUB_L(PI_INT_PEND0);
+ }
}
}
@@ -203,69+217,38 @@ void ip27_do_irq(struct pt_regs *regs) /* Startup one of the (PCI ...) IRQs routes over a bridge. */
static unsigned int bridge_startup(unsigned int irq)
{
- bridge_t *bridge;
- int pin, swlevel;
- int real_irq = IRQ_FROM_IRQ(irq);
-
- DBG("bridge_startup(): irq= 0x%x real_irq= %d\n", irq, real_irq);
- bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_IRQ(irq), WID_FROM_IRQ(irq));
-
- /* FIIIIIXME ... Temporary kludge. This knows how interrupts are
- setup in _my_ Origin. */
-
- if (irq != real_irq) /* pci device interrupt */
- switch (real_irq) {
- case IRQ_FROM_IRQ(IOC3_ETH_INT): pin = 2; break;
- default: pin = real_irq; break;
- }
- else
- switch (real_irq) {
- case CPU_RESCHED_A_IRQ:
- case CPU_RESCHED_B_IRQ:
- case CPU_CALL_A_IRQ:
- case CPU_CALL_B_IRQ:
- return 0;
- default: panic("bridge_startup: whoops? %d\n", irq);
- }
-
- /*
- * "map" irq to a swlevel greater than 6 since the first 6 bits
- * of INT_PEND0 are taken
- */
- swlevel = IRQ_TO_SWLEVEL(real_irq);
- intr_connect_level(smp_processor_id(), swlevel);
-
- bridge->b_int_addr[pin].addr = 0x20000 | swlevel;
- bridge->b_int_enable |= (1 << pin);
- /* set more stuff in int_enable reg */
+ bridgereg_t device;
+ bridge_t *bridge;
+ int pin, swlevel;
+ cpuid_t cpu;
+ nasid_t master = NASID_FROM_PCI_IRQ(irq);
+
+ bridge = (bridge_t *) NODE_SWIN_BASE(master, WID_FROM_PCI_IRQ(irq));
+ pin = SLOT_FROM_PCI_IRQ(irq);
+ cpu = IRQ_TO_CPU(irq);
+
+ DBG("bridge_startup(): irq= 0x%x pin=%d\n", irq, pin);
+ /*
+ * "map" irq to a swlevel greater than 6 since the first 6 bits
+ * of INT_PEND0 are taken
+ */
+ swlevel = IRQ_TO_SWLEVEL(cpu, irq);
+ intr_connect_level(cpu, swlevel);
+
+ bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (master << 8));
+ bridge->b_int_enable |= (1 << pin);
+ /* more stuff in int_enable reg */
bridge->b_int_enable |= 0x7ffffe00;
- if (real_irq < 2 || real_irq==4 || real_irq==5) {
- bridgereg_t device;
-#if 0
- /*
- * Allocate enough RRBs on the bridge for the DMAs.
- * Right now allocating 2 RRBs on the normal channel
- * and 2 on the virtual channel for slot 0 on the bus.
- * And same for slot 1, to get ioc3 eth working.
- */
- Not touching b_even_resp /* boot doesn't go far */
- bridge->b_even_resp = 0xdd99cc88; /* boot doesn't go far */
- bridge->b_even_resp = 0xcccc8888; /* breaks eth0 */
- bridge->b_even_resp = 0xcc88; /* breaks eth0 */
-#endif
- /* Turn on bridge swapping */
- device = bridge->b_device[real_irq].reg;
- device |= BRIDGE_DEV_SWAP_DIR;
- bridge->b_device[real_irq].reg = device;
- /*
- * Associate interrupt pin with device
- * XXX This only works if b_int_device is initialized to 0!
- */
- device = bridge->b_int_device;
- device |= (pin << (real_irq*3));
- bridge->b_int_device = device;
- }
+ /*
+ * XXX This only works if b_int_device is initialized to 0!
+ * We program the bridge to have a 1:1 mapping between devices
+ * (slots) and intr pins.
+ */
+ device = bridge->b_int_device;
+ device |= (pin << (pin*3));
+ bridge->b_int_device = device;
+
bridge->b_widget.w_tflush; /* Flush */
return 0; /* Never anything pending. */
@@ -274,70+257,25 @@ static unsigned int bridge_startup(unsigned int irq) /* Shutdown one of the (PCI ...) IRQs routes over a bridge. */
static unsigned int bridge_shutdown(unsigned int irq)
{
- bridge_t *bridge;
- int pin, swlevel;
- int real_irq = IRQ_FROM_IRQ(irq);
- struct irqaction **p;
+ bridge_t *bridge;
+ int pin, swlevel;
- bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_IRQ(irq), WID_FROM_IRQ(irq));
+ bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_PCI_IRQ(irq),
+ WID_FROM_PCI_IRQ(irq));
DBG("bridge_shutdown: irq 0x%x\n", irq);
- /* FIIIIIXME ... Temporary kludge. This knows how interrupts are
- setup in _my_ Origin. */
-
- if (irq != real_irq) /* pci device interrupt */
- switch (real_irq) {
- case IRQ_FROM_IRQ(IOC3_ETH_INT): pin = 2; break;
- default: pin = real_irq; break;
- }
- else
- switch (real_irq) {
- case CPU_RESCHED_A_IRQ:
- case CPU_RESCHED_B_IRQ:
- case CPU_CALL_A_IRQ:
- case CPU_CALL_B_IRQ:
- return 0;
- default: panic("bridge_startup: whoops?");
- }
-
- /*
- * map irq to a swlevel greater than 6 since the first 6 bits
- * of INT_PEND0 are taken
- */
- swlevel = IRQ_TO_SWLEVEL(real_irq);
- intr_disconnect_level(smp_processor_id(), swlevel);
-
- bridge->b_int_enable &= ~(1 << pin);
- bridge->b_widget.w_tflush; /* Flush */
+ pin = SLOT_FROM_PCI_IRQ(irq);
- return 0; /* Never anything pending. */
-}
+ /*
+ * map irq to a swlevel greater than 6 since the first 6 bits
+ * of INT_PEND0 are taken
+ */
+ swlevel = IRQ_TO_SWLEVEL(cpu, irq);
+ intr_disconnect_level(smp_processor_id(), swlevel);
-static void bridge_init(void)
-{
- bridge_t *bridge;
- nasid_t nasid;
- char wid;
- int bus;
-
- nasid = get_nasid();
-
- for (bus=0; bus<num_bridges; bus++) {
- bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus],bus_to_wid[bus]);
- /* Hmm... IRIX sets additional bits in the address which are
- documented as reserved in the bridge docs ... */
- bridge->b_int_mode = 0x0; /* Don't clear ints */
-#if 0
- bridge->b_wid_int_upper = 0x000a8000; /* Ints to node 0 */
- bridge->b_wid_int_lower = 0x01000090;
- bridge->b_dir_map = 0xa00000; /* DMA */
-#endif /* shouldn't lower= 0x01800090 ??? */
- bridge->b_wid_int_upper = 0x000a8000; /* Ints to widget A */
- bridge->b_wid_int_lower = 0x01800090;
- bridge->b_dir_map = 0xa00000; /* DMA */
-
- bridge->b_int_enable = 0;
- bridge->b_widget.w_tflush; /* Flush */
- }
+ bridge->b_int_enable &= ~(1 << pin);
+ bridge->b_widget.w_tflush; /* Flush */
+
+ return 0; /* Never anything pending. */
}
void irq_debug(void)
@@ -346,8+284,8 @@ void irq_debug(void)
printk("bridge->b_int_status = 0x%x\n", bridge->b_int_status);
printk("bridge->b_int_enable = 0x%x\n", bridge->b_int_enable);
- printk("PI_INT_PEND0 = 0x%x\n", LOCAL_HUB_L(PI_INT_PEND0));
- printk("PI_INT_MASK0_A = 0x%x\n", LOCAL_HUB_L(PI_INT_MASK0_A));
+ printk("PI_INT_PEND0 = 0x%lx\n", LOCAL_HUB_L(PI_INT_PEND0));
+ printk("PI_INT_MASK0_A = 0x%lx\n", LOCAL_HUB_L(PI_INT_MASK0_A));
}
int setup_irq(unsigned int irq, struct irqaction *new)
@@ -357,11+295,15 @@ int setup_irq(unsigned int irq, struct irqaction *new) unsigned long flags;
DBG("setup_irq: 0x%x\n", irq);
+ if (irq >= NR_IRQS) {
+ printk("IRQ array overflow %d\n", irq);
+ while(1);
+ }
if (new->flags & SA_SAMPLE_RANDOM)
rand_initialize_irq(irq);
save_and_cli(flags);
- p = irq_action + IRQ_FROM_IRQ(irq);
+ p = irq_action + irq;
if ((old = *p) != NULL) {
/* Can't share interrupts unless both agree to */
if (!(old->flags & new->flags & SA_SHIRQ)) {
@@ -379,7+321,7 @@ int setup_irq(unsigned int irq, struct irqaction *new)
*p = new;
- if (!shared) {
+ if ((!shared) && (irq >= BASE_PCI_IRQ)) {
bridge_startup(irq);
}
restore_flags(flags);
@@ -395,8+337,6 @@ int request_irq(unsigned int irq, struct irqaction *action;
DBG("request_irq(): irq= 0x%x\n", irq);
- if (IRQ_FROM_IRQ(irq) > 9)
- return -EINVAL;
if (!handler)
return -EINVAL;
@@ -424,18+364,18 @@ void free_irq(unsigned int irq, void *dev_id) struct irqaction * action, **p;
unsigned long flags;
- if (IRQ_FROM_IRQ(irq) > 9) {
+ if (irq >= NR_IRQS) {
printk("Trying to free IRQ%d\n", irq);
return;
}
- for (p = IRQ_FROM_IRQ(irq) + irq_action; (action = *p) != NULL; p = &action->next) {
+ for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
if (action->dev_id != dev_id)
continue;
/* Found it - now free it */
save_and_cli(flags);
*p = action->next;
- if (!irq[irq_action])
+ if (irq >= BASE_PCI_IRQ)
bridge_shutdown(irq);
restore_flags(flags);
kfree(action);
@@ -465,7+405,6 @@ void __init init_IRQ(void) {
irq_cannonicalize = indy_irq_cannonicalize;
- bridge_init();
set_except_vector(0, ip27_irq);
}
@@ -675,7+614,7 @@ static hub_intmasks_t *intr_get_ptrs(cpuid_t cpu, int bit, int *new_bit, return hub_intmasks;
}
-int intr_connect_level(cpuid_t cpu, int bit)
+int intr_connect_level(int cpu, int bit)
{
int ip;
int slice = cputoslice(cpu);
@@ -701,7+640,7 @@ int intr_connect_level(cpuid_t cpu, int bit) return(0);
}
-int intr_disconnect_level(cpuid_t cpu, int bit)
+int intr_disconnect_level(int cpu, int bit)
{
int ip;
int slice = cputoslice(cpu);
@@ -728,11+667,14 @@ void handle_resched_intr(int irq, void *dev_id, struct pt_regs *regs) /* Nothing, the return from intr will work for us */
}
-void install_cpuintr(cpuid_t cpu)
+extern void smp_call_function_interrupt(void);
+
+void install_cpuintr(int cpu)
{
- int irq;
- extern void smp_call_function_interrupt(void);
+#ifdef CONFIG_SMP
+#if (CPUS_PER_NODE == 2)
static int done = 0;
+ int irq;
/*
* This is a hack till we have a pernode irqlist. Currently,
@@ -740,15+682,13 @@ void install_cpuintr(cpuid_t cpu) * cpu irqs.
*/
-#ifdef CONFIG_SMP
-#if (CPUS_PER_NODE == 2)
irq = CPU_RESCHED_A_IRQ + cputoslice(cpu);
- intr_connect_level(cpu, IRQ_TO_SWLEVEL(irq));
+ intr_connect_level(cpu, IRQ_TO_SWLEVEL(cpu, irq));
if (done == 0)
if (request_irq(irq, handle_resched_intr, 0, "resched", 0))
panic("intercpu intr unconnectible\n");
irq = CPU_CALL_A_IRQ + cputoslice(cpu);
- intr_connect_level(cpu, IRQ_TO_SWLEVEL(irq));
+ intr_connect_level(cpu, IRQ_TO_SWLEVEL(cpu, irq));
if (done == 0)
if (request_irq(irq, smp_call_function_interrupt, 0,
"callfunc", 0))
@@ -766,12+706,12 @@ void install_cpuintr(cpuid_t cpu) done = 1;
/* HACK ENDS */
#else /* CPUS_PER_NODE */
- << Bomb! Must redefine this for more than 2 CPUS. >>
+#error Must redefine this for more than 2 CPUS.
#endif /* CPUS_PER_NODE */
#endif /* CONFIG_SMP */
}
-void install_tlbintr(cpuid_t cpu)
+void install_tlbintr(int cpu)
{
int intr_bit = N_INTPEND_BITS + TLB_INTR_A + cputoslice(cpu);
@@ -61,7+61,7 @@ lboard_t * find_lboard(lboard_t *start, unsigned char brd_type) return (lboard_t *)NULL;
}
-cnodeid_t get_cpu_cnode(int cpu)
+cnodeid_t get_cpu_cnode(cpuid_t cpu)
{
return CPUID_TO_COMPACT_NODEID(cpu);
}
--- /dev/null
+/*
+ * Ported from IRIX to Linux by Kanoj Sarcar, 06/08/00.
+ * Copyright 2000 Silicon Graphics, Inc.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mmzone.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/page.h>
+#include <asm/sn/types.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/gda.h>
+#include <asm/mmzone.h>
+#include <asm/sn/klkernvars.h>
+#include <asm/sn/mapped_kernel.h>
+#include <asm/sn/sn_private.h>
+
+#define CPUMASK_CLRALL(p) (p) = 0
+#define CPUMASK_SETB(p, bit) (p) |= 1 << (bit)
+#define CPUMASK_TSTB(p, bit) ((p) & (1ULL << (bit)))
+
+extern char _end;
+static cpumask_t ktext_repmask;
+
+/*
+ * XXX - This needs to be much smarter about where it puts copies of the
+ * kernel. For example, we should never put a copy on a headless node,
+ * and we should respect the topology of the machine.
+ */
+void __init setup_replication_mask(int maxnodes)
+{
+ static int numa_kernel_replication_ratio;
+ cnodeid_t cnode;
+
+ /* Set only the master cnode's bit. The master cnode is always 0. */
+ CPUMASK_CLRALL(ktext_repmask);
+ CPUMASK_SETB(ktext_repmask, 0);
+
+ numa_kernel_replication_ratio = 0;
+#ifdef CONFIG_REPLICATE_KTEXT
+#ifndef CONFIG_MAPPED_KERNEL
+#error Kernel replication works with mapped kernel support. No calias support.
+#endif
+ numa_kernel_replication_ratio = 1;
+#endif
+
+ for (cnode = 1; cnode < numnodes; cnode++) {
+ /* See if this node should get a copy of the kernel */
+ if (numa_kernel_replication_ratio &&
+ !(cnode % numa_kernel_replication_ratio)) {
+
+ /* Advertise that we have a copy of the kernel */
+ CPUMASK_SETB(ktext_repmask, cnode);
+ }
+ }
+
+ /* Set up a GDA pointer to the replication mask. */
+ GDA->g_ktext_repmask = &ktext_repmask;
+}
+
+
+static __init void set_ktext_source(nasid_t client_nasid, nasid_t server_nasid)
+{
+ kern_vars_t *kvp;
+ cnodeid_t client_cnode;
+
+ client_cnode = NASID_TO_COMPACT_NODEID(client_nasid);
+
+ kvp = &(PLAT_NODE_DATA(client_cnode)->kern_vars);
+
+ KERN_VARS_ADDR(client_nasid) = (unsigned long)kvp;
+
+ kvp->kv_magic = KV_MAGIC;
+
+ kvp->kv_ro_nasid = server_nasid;
+ kvp->kv_rw_nasid = master_nasid;
+ kvp->kv_ro_baseaddr = NODE_CAC_BASE(server_nasid);
+ kvp->kv_rw_baseaddr = NODE_CAC_BASE(master_nasid);
+ printk("REPLICATION: ON nasid %d, ktext from nasid %d, kdata from nasid %d\n", client_nasid, server_nasid, master_nasid);
+}
+
+/* XXX - When the BTE works, we should use it instead of this. */
+static __init void copy_kernel(nasid_t dest_nasid)
+{
+ extern char _stext, _etext;
+ unsigned long dest_kern_start, source_start, source_end, kern_size;
+
+ source_start = (unsigned long)&_stext;
+ source_end = (unsigned long)&_etext;
+ kern_size = source_end - source_start;
+
+ dest_kern_start = CHANGE_ADDR_NASID(MAPPED_KERN_RO_TO_K0(source_start),
+ dest_nasid);
+ memcpy((void *)dest_kern_start, (void *)source_start, kern_size);
+}
+
+void __init replicate_kernel_text(int maxnodes)
+{
+ cnodeid_t cnode;
+ nasid_t client_nasid;
+ nasid_t server_nasid;
+
+ server_nasid = master_nasid;
+
+ /* Record where the master node should get its kernel text */
+ set_ktext_source(master_nasid, master_nasid);
+
+ for (cnode = 1; cnode < maxnodes; cnode++) {
+ client_nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+ /* Check if this node should get a copy of the kernel */
+ if (CPUMASK_TSTB(ktext_repmask, cnode)) {
+ server_nasid = client_nasid;
+ copy_kernel(server_nasid);
+ }
+
+ /* Record where this node should get its kernel text */
+ set_ktext_source(client_nasid, server_nasid);
+ }
+}
+
+/*
+ * Return pfn of first free page of memory on a node. PROM may allocate
+ * data structures on the first couple of pages of the first slot of each
+ * node. If this is the case, getfirstfree(node) > getslotstart(node, 0).
+ */
+pfn_t node_getfirstfree(cnodeid_t cnode)
+{
+ unsigned long loadbase = CKSEG0;
+ nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
+ unsigned long offset;
+
+#ifdef CONFIG_MAPPED_KERNEL
+ loadbase = CKSSEG + 16777216;
+#endif
+ offset = PAGE_ALIGN((unsigned long)(&_end)) - loadbase;
+ if (cnode == 0)
+ return (offset >> PAGE_SHIFT);
+ else if (CPUMASK_TSTB(ktext_repmask, cnode))
+ return (TO_NODE(nasid, offset) >> PAGE_SHIFT);
+ else
+ return (KDM_TO_PHYS(PAGE_ALIGN(SYMMON_STK_ADDR(nasid, 0))) >>
+ PAGE_SHIFT);
+}
+
-/* $Id: ip27-memory.c,v 1.2 2000/01/27 01:05:24 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
#include <asm/sn/arch.h>
#include <asm/mmzone.h>
-typedef unsigned long pfn_t; /* into <asm/sn/types.h> */
-#define KDM_TO_PHYS(x) ((x) & TO_PHYS_MASK) /* into asm/addrspace.h */
-
-extern char _end;
+/* ip27-klnuma.c */
+extern pfn_t node_getfirstfree(cnodeid_t cnode);
#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
#define SLOT_IGNORED 0xffff
@@ -38,7+35,6 @@ extern char _end; short slot_lastfilled_cache[MAX_COMPACT_NODES];
unsigned short slot_psize_cache[MAX_COMPACT_NODES][MAX_MEM_SLOTS];
static pfn_t numpages;
-static pfn_t pagenr = 0;
plat_pg_data_t *plat_node_data[MAX_COMPACT_NODES];
bootmem_data_t plat_node_bdata[MAX_COMPACT_NODES];
@@ -46,26+42,11 @@ bootmem_data_t plat_node_bdata[MAX_COMPACT_NODES]; int numa_debug(void)
{
printk("NUMA debug\n");
- BUG();
+ *(int *)0 = 0;
return(0);
}
/*
- * Return pfn of first free page of memory on a node. PROM may allocate
- * data structures on the first couple of pages of the first slot of each
- * node. If this is the case, getfirstfree(node) > getslotstart(node, 0).
- */
-pfn_t node_getfirstfree(cnodeid_t cnode)
-{
- nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
-
- if (cnode == 0)
- return (KDM_TO_PHYS(PAGE_ALIGN((unsigned long)(&_end)) -
- (CKSEG0 - K0BASE)) >> PAGE_SHIFT);
- return (KDM_TO_PHYS(PAGE_ALIGN(SYMMON_STK_ADDR(nasid, 0))) >> PAGE_SHIFT);
-}
-
-/*
* Return the number of pages of memory provided by the given slot
* on the specified node.
*/
@@ -261,6+242,8 @@ prom_free_prom_memory (void)
#ifdef CONFIG_DISCONTIGMEM
+static pfn_t pagenr = 0;
+
void __init paging_init(void)
{
cnodeid_t node;
@@ -268,8+251,10 @@ void __init paging_init(void)
/* Initialize the entire pgd. */
pgd_init((unsigned long)swapper_pg_dir);
- pmd_init((unsigned long)invalid_pmd_table);
- memset((void *)invalid_pte_table, 0, sizeof(pte_t) * 2 * PTRS_PER_PTE);
+ pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table);
+ memset((void *)invalid_pte_table, 0, sizeof(pte_t) * PTRS_PER_PTE);
+ pmd_init((unsigned long)empty_bad_pmd_table, (unsigned long)empty_bad_page_table);
+ memset((void *)empty_bad_page_table, 0, sizeof(pte_t) * PTRS_PER_PTE);
for (node = 0; node < numnodes; node++) {
pfn_t start_pfn = slot_getbasepfn(node, 0);
@@ -287,7+272,7 @@ void __init paging_init(void)
void __init mem_init(void)
{
- extern char _ftext, _etext, _fdata, _edata;
+ extern char _stext, _etext, _fdata, _edata;
extern char __init_begin, __init_end;
extern unsigned long totalram_pages;
extern unsigned long setup_zero_pages(void);
@@ -367,7+352,7 @@ void __init mem_init(void) }
}
- codesize = (unsigned long) &_etext - (unsigned long) &_ftext;
+ codesize = (unsigned long) &_etext - (unsigned long) &_stext;
datasize = (unsigned long) &_edata - (unsigned long) &_fdata;
initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
@@ -145,6+145,10 @@ cont_nmi_dump(void) cpu = CNODE_TO_CPU_BASE(node);
for (n=0; n < CNODE_NUM_CPUS(node); cpu++, n++) {
CPUMASK_SETB(nmied_cpus, cpu);
+ /*
+ * cputonasid, cputoslice
+ * needs kernel cpuid
+ */
SEND_NMI((cputonasid(cpu)), (cputoslice(cpu)));
}
}
-/* $Id: ip27-pci.c,v 1.8 2000/02/16 01:07:30 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
#include <asm/sn/sn0/hub.h>
/*
+ * Max #PCI busses we can handle; ie, max #PCI bridges.
+ */
+#define MAX_PCI_BUSSES 20
+
+/*
+ * Max #PCI devices (like scsi controllers) we handle on a bus.
+ */
+#define MAX_DEVICES_PER_PCIBUS 8
+
+/*
+ * No locking needed until PCI initialization is done parallely.
+ */
+int irqstore[MAX_PCI_BUSSES][MAX_DEVICES_PER_PCIBUS];
+int lastirq = BASE_PCI_IRQ;
+
+/*
+ * Translate from irq to software PCI bus number and PCI slot.
+ */
+int irq_to_bus[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS];
+int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS];
+
+/*
* The Bridge ASIC supports both type 0 and type 1 access. Type 1 is
* not really documented, so right now I can't write code which uses it.
* Therefore we use type 0 accesses for now even though they won't work
@@ -123,13+144,12 @@ static struct pci_ops bridge_pci_ops = { void __init pcibios_init(void)
{
struct pci_ops *ops = &bridge_pci_ops;
- nasid_t nid = get_nasid();
int i;
ioport_resource.end = ~0UL;
for (i=0; i<num_bridges; i++) {
- printk("PCI: Probing PCI hardware on host bus %2d, node %d.\n", i, nid);
+ printk("PCI: Probing PCI hardware on host bus %2d.\n", i);
pci_scan_bus(i, ops, NULL);
}
}
@@ -154,15+174,36 @@ pci_swizzle(struct pci_dev *dev, u8 *pinp) return PCI_SLOT(dev->devfn);
}
-/* XXX This should include the node ID into the final interrupt number. */
+/*
+ * All observed requests have pin == 1. We could have a global here, that
+ * gets incremented and returned every time - unfortunately, pci_map_irq
+ * may be called on the same device over and over, and need to return the
+ * same value. On o2000, pin can be 0 or 1, and PCI slots can be [0..7].
+ *
+ * A given PCI device, in general, should be able to intr any of the cpus
+ * on any one of the hubs connected to its xbow.
+ */
static int __init
pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
- int rv;
- rv = (slot + (((pin-1) & 1) << 2)) & 7;
- rv |= (bus_to_wid[dev->bus->number] << 8);
- rv |= (bus_to_nid[dev->bus->number] << 16);
- return rv;
+ if ((dev->bus->number >= MAX_PCI_BUSSES) || (pin != 1) || \
+ (slot >= MAX_DEVICES_PER_PCIBUS)) {
+ printk("Increase supported PCI busses %d,%d,%d\n", \
+ dev->bus->number, slot, pin);
+ while(1);
+ }
+
+ /*
+ * Already assigned? Then return previously assigned value ...
+ */
+ if (irqstore[dev->bus->number][slot])
+ return(irqstore[dev->bus->number][slot]);
+ else {
+ lastirq++; /* IOC3_ETH_INT hack */
+ irq_to_bus[lastirq] = dev->bus->number;
+ irq_to_slot[lastirq] = slot;
+ return(irqstore[dev->bus->number][slot] = lastirq);
+ }
}
void __init
@@ -222,8+263,41 @@ pcibios_setup(char *str) }
static void __init
+pci_disable_swapping(struct pci_dev *dev)
+{
+ unsigned int bus_id = (unsigned) dev->bus->number;
+ bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id],
+ bus_to_wid[bus_id]);
+ int slot = PCI_SLOT(dev->devfn);
+ bridgereg_t devreg;
+
+ devreg = bridge->b_device[slot].reg;
+ devreg &= ~BRIDGE_DEV_SWAP_DIR; /* turn off byte swapping */
+ bridge->b_device[slot].reg = devreg;
+
+ bridge->b_widget.w_tflush; /* Flush */
+}
+
+static void __init
+pci_enable_swapping(struct pci_dev *dev)
+{
+ unsigned int bus_id = (unsigned) dev->bus->number;
+ bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id],
+ bus_to_wid[bus_id]);
+ int slot = PCI_SLOT(dev->devfn);
+ bridgereg_t devreg;
+
+ devreg = bridge->b_device[slot].reg;
+ devreg |= BRIDGE_DEV_SWAP_DIR; /* turn on byte swapping */
+ bridge->b_device[slot].reg = devreg;
+
+ bridge->b_widget.w_tflush; /* Flush */
+}
+
+static void __init
pci_fixup_ioc3(struct pci_dev *d)
{
+ unsigned int bus_id = (unsigned) d->bus->number;
int i;
/* IOC3 only decodes 0x20 bytes of the config space, so we end up
@@ -232,6+306,9 @@ pci_fixup_ioc3(struct pci_dev *d) use INTA. */
printk("PCI: Fixing base addresses for IOC3 device %s\n", d->slot_name);
+ d->resource[0].start |= NODE_OFFSET(bus_to_nid[bus_id]);
+ d->resource[0].end |= NODE_OFFSET(bus_to_nid[bus_id]);
+
for (i = 1; i <= PCI_ROM_RESOURCE; i++) {
d->resource[i].start = 0UL;
d->resource[i].end = 0UL;
@@ -240,6+317,8 @@ pci_fixup_ioc3(struct pci_dev *d) d->subsystem_vendor = 0;
d->subsystem_device = 0;
d->irq = 1;
+
+ pci_disable_swapping(d);
}
static void __init
@@ -247,24+326,25 @@ pci_fixup_isp1020(struct pci_dev *d) {
unsigned short command;
+ d->resource[0].start |= ((unsigned long)(bus_to_nid[d->bus->number])<<32);
printk("PCI: Fixing isp1020 in [bus:slot.fn] %s\n", d->slot_name);
/* Configure device to allow bus mastering, i/o and memory mapping.
* Older qlogicisp driver expects to have the IO space enable
- * bit set. Things stop working if we program the controllers as not having
- * PCI_COMMAND_MEMORY, so we have to fudge the mem_flags.
+ * bit set. Things stop working if we program the controllers as not
+ * having PCI_COMMAND_MEMORY, so we have to fudge the mem_flags.
*/
- /* only turn on scsi's on main bus */
- if (d->bus->number == 0) {
- pci_set_master(d);
- pci_read_config_word(d, PCI_COMMAND, &command);
- command |= PCI_COMMAND_MEMORY;
- command |= PCI_COMMAND_IO;
- pci_write_config_word(d, PCI_COMMAND, command);
- d->resource[1].flags |= 1;
- }
+ pci_set_master(d);
+ pci_read_config_word(d, PCI_COMMAND, &command);
+ command |= PCI_COMMAND_MEMORY;
+ command |= PCI_COMMAND_IO;
+ pci_write_config_word(d, PCI_COMMAND, command);
+ d->resource[1].flags |= 1;
+
+ pci_enable_swapping(d);
}
+
static void __init
pci_fixup_isp2x00(struct pci_dev *d)
{
@@ -280,7+360,7 @@ pci_fixup_isp2x00(struct pci_dev *d) printk("PCI: Fixing isp2x00 in [bus:slot.fn] %s\n", d->slot_name);
/* set the resource struct for this device */
- start = (u32) bridge; /* yes, we want to lose the upper 32 bits here */
+ start = (u32) (u64)bridge; /* yes, we want to lose the upper 32 bits here */
start |= BRIDGE_DEVIO(slot);
d->resource[0].start = start;
@@ -298,12+378,10 @@ pci_fixup_isp2x00(struct pci_dev *d) /* point device(x) to it appropriate small window */
devreg &= ~BRIDGE_DEV_OFF_MASK;
devreg |= (start >> 20) & BRIDGE_DEV_OFF_MASK;
-
- /* turn on byte swapping in direct map mode (how we currently run dma's) */
- devreg |= BRIDGE_DEV_SWAP_DIR; /* turn on byte swapping */
-
bridge->b_device[slot].reg = devreg;
+ pci_enable_swapping(d);
+
/* set card's base addr reg */
//pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_0, 0x500001);
//pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, 0x8b00000);
@@ -317,7+395,6 @@ pci_fixup_isp2x00(struct pci_dev *d) pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, start);
//pci_conf0_write_config_dword(d, PCI_ROM_ADDRESS, (start | 0x20000));
-
/* set cache line size */
pci_conf0_write_config_dword(d, PCI_CACHE_LINE_SIZE, 0xf080);
@@ -329,7+406,7 @@ pci_fixup_isp2x00(struct pci_dev *d) /* set host error field */
bridge->b_int_host_err = 0x44;
bridge->b_wid_tflush;
-
+
bridge->b_wid_tflush; /* wait until Bridge PIO complete */
for (i=0; i<8; i++)
printk("PCI: device(%d)= 0x%x\n",i,bridge->b_device[i].reg);
-/* $Id$
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Reset an IP27.
*
- * Copyright (C) 1997, 1998, 1999 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1997, 1998, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/sgialib.h>
-#include <asm/sgi/sgihpc.h>
-#include <asm/sgi/sgint23.h>
#include <asm/sn/addrs.h>
#include <asm/sn/arch.h>
#include <asm/sn/gda.h>
@@ -30,10+27,14 @@ void machine_restart(char *command) __attribute__((noreturn)); void machine_halt(void) __attribute__((noreturn));
void machine_power_off(void) __attribute__((noreturn));
+#define noreturn while(1); /* Silence gcc. */
+
/* XXX How to pass the reboot command to the firmware??? */
void machine_restart(char *command)
{
+#if 0
int i;
+#endif
printk("Reboot started from CPU %d\n", smp_processor_id());
#ifdef CONFIG_SMP
@@ -42,20+43,31 @@ void machine_restart(char *command) #if 0
for (i = 0; i < numnodes; i++)
REMOTE_HUB_S(COMPACT_TO_NASID_NODEID(i), PROMOP_REG,
- PROMOP_RESTART);
+ PROMOP_REBOOT);
#else
LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET);
#endif
+ noreturn;
}
void machine_halt(void)
{
- ArcEnterInteractiveMode();
+ int i;
+
+#ifdef CONFIG_SMP
+ smp_send_stop();
+#endif
+ for (i = 0; i < numnodes; i++)
+ REMOTE_HUB_S(COMPACT_TO_NASID_NODEID(i), PROMOP_REG,
+ PROMOP_RESTART);
+ LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET);
+ noreturn;
}
void machine_power_off(void)
{
/* To do ... */
+ noreturn;
}
void ip27_reboot_setup(void)
-/* $Id: ip27-setup.c,v 1.7 2000/03/07 15:45:29 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* SGI IP27 specific setup.
*
- * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
- * Copyright (C) 1999 Silcon Graphics, Inc.
+ * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 1999, 2000 Silcon Graphics, Inc.
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
#include <asm/sn/types.h>
#include <asm/sn/sn0/addrs.h>
#include <asm/sn/sn0/hubni.h>
#include <asm/pci/bridge.h>
#include <asm/paccess.h>
#include <asm/sn/sn0/ip27.h>
+#include <asm/sn/sn0/hubio.h>
/* Check against user dumbness. */
#ifdef CONFIG_VT
@@ -101,27+104,32 @@ static void __init verify_mode(void) #define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbridge */
#define BASE_XBOW_PORT 8 /* Lowest external port */
-static void __init pcibr_setup(void)
+unsigned int bus_to_cpu[256];
+
+void __init pcibr_setup(cnodeid_t nid)
{
- int i;
+ int i, start, num, masterwid;
bridge_t *bridge;
volatile u64 hubreg;
- nasid_t nasid;
+ nasid_t nasid, masternasid;
xwidget_part_num_t partnum;
widgetreg_t widget_id;
+ static spinlock_t pcibr_setup_lock = SPIN_LOCK_UNLOCKED;
- num_bridges = 0;
/*
* find what's on our local node
*/
- nasid = 0;
- hubreg = LOCAL_HUB_L(IIO_LLP_CSR);
+ spin_lock(&pcibr_setup_lock);
+ start = num_bridges; /* Remember where we start from */
+ nasid = COMPACT_TO_NASID_NODEID(nid);
+ hubreg = REMOTE_HUB_L(nasid, IIO_LLP_CSR);
if (hubreg & IIO_LLP_CSR_IS_UP) {
/* link is up */
widget_id = *(volatile widgetreg_t *)
(RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID);
partnum = XWIDGET_PART_NUM(widget_id);
- printk("pcibr_setup(): found partnum= 0x%x ", partnum);
+ printk("Cpu %d, Nasid 0x%x, pcibr_setup(): found partnum= 0x%x",
+ smp_processor_id(), nasid, partnum);
if (partnum == BRIDGE_WIDGET_PART_NUM) {
/*
* found direct connected bridge so must be Origin200
@@ -130,8+138,7 @@ static void __init pcibr_setup(void) num_bridges = 1;
bus_to_wid[0] = 0x8;
bus_to_nid[0] = 0;
- }
- if (partnum == XBOW_WIDGET_PART_NUM) {
+ } else if (partnum == XBOW_WIDGET_PART_NUM) {
lboard_t *brd;
klxbow_t *xbow_p;
/*
@@ -144,11+151,32 @@ static void __init pcibr_setup(void) KLTYPE_MIDPLANE8)) == NULL)
printk("argh\n");
else
- printk("brd= 0x%x\n", brd);
+ printk("brd = 0x%lx\n", (unsigned long) brd);
if ((xbow_p = (klxbow_t *)
find_component(brd, NULL, KLSTRUCT_XBOW)) == NULL)
printk("argh\n");
else {
+ /*
+ * Okay, here's a xbow. Lets arbitrate and find
+ * out if we should initialize it. Set hub connected
+ * at highest or lowest widget as master.
+ * This algo needs to change a little for headless
+ * nodes.
+ */
+#ifdef WIDGET_A
+ i = HUB_WIDGET_ID_MAX + 1;
+ do {
+ i--;
+ } while (!XBOW_PORT_TYPE_HUB(xbow_p, i));
+#else
+ i = HUB_WIDGET_ID_MIN - 1;
+ do {
+ i++;
+ } while (!XBOW_PORT_TYPE_HUB(xbow_p, i));
+#endif
+ masterwid = i;
+ masternasid = XBOW_PORT_NASID(xbow_p, i);
+ if (nasid == masternasid)
for (i=HUB_WIDGET_ID_MIN; i<=HUB_WIDGET_ID_MAX; i++) {
if (!XBOW_PORT_IS_ENABLED(xbow_p, i))
continue;
@@ -165,8+193,7 @@ static void __init pcibr_setup(void) }
}
}
- }
- if (partnum == XXBOW_WIDGET_PART_NUM) {
+ } else if (partnum == XXBOW_WIDGET_PART_NUM) {
/*
* found xbridge, assume ibrick for now
*/
@@ -182,13+209,17 @@ static void __init pcibr_setup(void) num_bridges = 3;
}
}
+ num = num_bridges - start;
+ spin_unlock(&pcibr_setup_lock);
/*
* set bridge registers
*/
- for (i=0; i<num_bridges; i++) {
+ for (i = start; i < (start + num); i++) {
+
DBG("pcibr_setup: bus= %d bus_to_wid[%2d]= %d bus_to_nid[%2d]= %d\n",
i, i, bus_to_wid[i], i, bus_to_nid[i]);
+ bus_to_cpu[i] = smp_processor_id();
/*
* point to this bridge
*/
@@ -207,6+238,19 @@ static void __init pcibr_setup(void) bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP;
bridge->b_wid_control |= BRIDGE_CTRL_MEM_SWAP;
+ /*
+ * Hmm... IRIX sets additional bits in the address which
+ * are documented as reserved in the bridge docs.
+ * We waste time programming b_wid_int_upper/b_wid_int_lower,
+ * since bridge_startup will set up the widget->nasid intr
+ * path anyway.
+ */
+ bridge->b_int_mode = 0x0; /* Don't clear ints */
+ bridge->b_wid_int_upper = 0x000a8000; /* Ints to widget A */
+ bridge->b_wid_int_lower = 0x01800090;
+ bridge->b_dir_map = 0xa00000; /* DMA */
+ bridge->b_int_enable = 0;
+
bridge->b_wid_tflush; /* wait until Bridge PIO complete */
}
}
@@ -216,11+260,11 @@ void __init ip27_setup(void) nasid_t nid;
hubreg_t p, e;
+ num_bridges = 0;
/*
* hub_rtc init and cpu clock intr enabled for later calibrate_delay.
*/
DBG("ip27_setup(): Entered.\n");
- per_cpu_init();
nid = get_nasid();
printk("IP27: Running on node %d.\n", nid);
@@ -239,9+283,5 @@ void __init ip27_setup(void) verify_mode();
ioc3_sio_init();
ioc3_eth_init();
-
- DBG("ip27_setup(): calling pcibr_setup\n");
- /* set some bridge registers */
- pcibr_setup();
- DBG("ip27_setup(): Exit.\n");
+ per_cpu_init();
}
-/* $Id: ip27-timer.c,v 1.3 2000/02/18 09:54:40 ulfc Exp $
- *
- * Copytight (C) 1999 Ralf Baechle (ralf@gnu.org)
- * Copytight (C) 1999 Silicon Graphics, Inc.
+/*
+ * Copytight (C) 1999, 2000 Ralf Baechle (ralf@gnu.org)
+ * Copytight (C) 1999, 2000 Silicon Graphics, Inc.
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#define CYCLES_PER_SEC (NSEC_PER_SEC/NSEC_PER_CYCLE)
#define CYCLES_PER_JIFFY (CYCLES_PER_SEC/HZ)
-static unsigned long ct_cur; /* What counter should be at next timer irq */
+static unsigned long ct_cur[NR_CPUS]; /* What counter should be at next timer irq */
static long last_rtc_update = 0; /* Last time the rtc clock got updated */
extern rwlock_t xtime_lock;
+extern volatile unsigned long lost_ticks;
static int set_rtc_mmss(unsigned long nowtime)
@@ -91,26+90,28 @@ static int set_rtc_mmss(unsigned long nowtime) void rt_timer_interrupt(struct pt_regs *regs)
{
int cpu = smp_processor_id();
- int cpuA = ((cputoslice(smp_processor_id())) == 0);
- int user = user_mode(regs);
+ int cpuA = ((cputoslice(cpu)) == 0);
int irq = 7; /* XXX Assign number */
write_lock(&xtime_lock);
again:
LOCAL_HUB_S(cpuA ? PI_RT_PEND_A : PI_RT_PEND_B, 0); /* Ack */
- ct_cur += CYCLES_PER_JIFFY;
- LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur);
+ ct_cur[cpu] += CYCLES_PER_JIFFY;
+ LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur[cpu]);
- if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur)
+ if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur[cpu])
goto again;
- kstat.irqs[cpu][irq]++; /* kstat+do_timer only for bootcpu? */
- do_timer(regs);
+ kstat.irqs[cpu][irq]++; /* kstat only for bootcpu? */
+
+ if (cpu == 0)
+ do_timer(regs);
#ifdef CONFIG_SMP
if (current->pid) {
unsigned int *inc, *inc2;
+ int user = user_mode(regs);
update_one_process(current, 1, user, !user, cpu);
if (--current->counter <= 0) {
write_unlock(&xtime_lock);
}
+unsigned long inline do_gettimeoffset(void)
+{
+ unsigned long ct_cur1;
+ ct_cur1 = REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT) + CYCLES_PER_JIFFY;
+ return (ct_cur1 - ct_cur[0]) * NSEC_PER_CYCLE / 1000;
+}
+
void do_gettimeofday(struct timeval *tv)
{
unsigned long flags;
+ unsigned long usec, sec;
read_lock_irqsave(&xtime_lock, flags);
- *tv = xtime;
+ usec = do_gettimeoffset();
+ {
+ unsigned long lost = lost_ticks;
+ if (lost)
+ usec += lost * (1000000 / HZ);
+ }
+ sec = xtime.tv_sec;
+ usec += xtime.tv_usec;
read_unlock_irqrestore(&xtime_lock, flags);
+
+ while (usec >= 1000000) {
+ usec -= 1000000;
+ sec++;
+ }
+
+ tv->tv_sec = sec;
+ tv->tv_usec = usec;
}
void do_settimeofday(struct timeval *tv)
{
write_lock_irq(&xtime_lock);
+ tv->tv_usec -= do_gettimeoffset();
+ tv->tv_usec -= lost_ticks * (1000000 / HZ);
+
+ while (tv->tv_usec < 0) {
+ tv->tv_usec += 1000000;
+ tv->tv_sec--;
+ }
+
xtime = *tv;
+ time_adjust = 0; /* stop active adjtime() */
time_state = TIME_BAD;
time_maxerror = MAXPHASE;
time_esterror = MAXPHASE;
@@ -286,15+319,16 @@ void __init hub_rtc_init(cnodeid_t cnode) * node and timeouts will not happen there.
*/
if (get_compact_nodeid() == cnode) {
+ int cpu = smp_processor_id();
LOCAL_HUB_S(PI_RT_EN_A, 1);
LOCAL_HUB_S(PI_RT_EN_B, 1);
LOCAL_HUB_S(PI_PROF_EN_A, 0);
LOCAL_HUB_S(PI_PROF_EN_B, 0);
- ct_cur = CYCLES_PER_JIFFY;
- LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur);
+ ct_cur[cpu] = CYCLES_PER_JIFFY;
+ LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur[cpu]);
LOCAL_HUB_S(PI_RT_COUNT, 0);
LOCAL_HUB_S(PI_RT_PEND_A, 0);
- LOCAL_HUB_S(PI_RT_COMPARE_B, ct_cur);
+ LOCAL_HUB_S(PI_RT_COMPARE_B, ct_cur[cpu]);
LOCAL_HUB_S(PI_RT_COUNT, 0);
LOCAL_HUB_S(PI_RT_PEND_B, 0);
}
@@ -13,17+13,19 @@ TARGET := $(TOPDIR)/include/asm-$(ARCH)/offset.h .S.o:
$(CC) $(CFLAGS) -c $< -o $*.o
-all: $(TARGET)
-
$(TARGET): offset.h
cmp -s $^ $@ || (cp $^ $(TARGET).new && mv $(TARGET).new $(TARGET))
offset.h: offset.s
sed -n '/^@@@/s///p' $^ >$@
-offset.s: offset.c
+offset.s: offset.c $(TOPDIR)/include/linux/autoconf.h
clean:
rm -f offset.[hs] $(TARGET).new
+
+mrproper:
+ rm -f offset.[hs] $(TARGET).new
+ rm -f $(TARGET)
include $(TOPDIR)/Rules.make
@@ -134,12+134,8 @@ CONFIG_INET=y # CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_IP_ALIAS is not set
+# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
-
-#
-# (it is safe to leave these untouched)
-#
-CONFIG_SKB_LARGE=y
CONFIG_IPV6=m
# CONFIG_IPV6_EUI64 is not set
# CONFIG_KHTTPD is not set
@@ -27,6+27,7 @@ define_bool CONFIG_VT_CONSOLE y bool 'Symmetric multi-processing support' CONFIG_SMP
# Global things across all Sun machines.
+define_bool CONFIG_HAVE_DEC_LOCK y
define_bool CONFIG_ISA n
define_bool CONFIG_PCMCIA n
define_bool CONFIG_SBUS y
@@ -20,6+20,7 @@ CONFIG_KMOD=y CONFIG_VT=y
CONFIG_VT_CONSOLE=y
# CONFIG_SMP is not set
+CONFIG_HAVE_DEC_LOCK=y
# CONFIG_ISA is not set
# CONFIG_PCMCIA is not set
CONFIG_SBUS=y
@@ -155,12+156,8 @@ CONFIG_INET=y # CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_IP_ALIAS is not set
+# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
-
-#
-# (it is safe to leave these untouched)
-#
-CONFIG_SKB_LARGE=y
CONFIG_IPV6=m
# CONFIG_IPV6_EUI64 is not set
# CONFIG_KHTTPD is not set
@@ -325,7+325,7 @@ beyond_if: current->thread.flags |= SPARC_FLAG_32BIT;
}
start_thread32(regs, ex.a_entry, current->mm->start_stack);
- if (current->flags & PF_PTRACED)
+ if (current->ptrace & PT_PTRACED)
send_sig(SIGTRAP, current, 0);
return 0;
}
@@ -386,6+386,46 @@ void smp_cross_call(unsigned long *func, u32 ctx, u64 data1, u64 data2) }
}
+struct call_data_struct {
+ void (*func) (void *info);
+ void *info;
+ atomic_t finished;
+ int wait;
+};
+
+extern unsigned long xcall_call_function;
+
+int smp_call_function(void (*func)(void *info), void *info,
+ int nonatomic, int wait)
+{
+ struct call_data_struct data;
+ int cpus = smp_num_cpus - 1;
+
+ if (!cpus)
+ return 0;
+
+ data.func = func;
+ data.info = info;
+ atomic_set(&data.finished, 0);
+ data.wait = wait;
+
+ smp_cross_call(&xcall_call_function,
+ 0, (u64) &data, 0);
+ if (wait) {
+ while (atomic_read(&data.finished) != cpus)
+ barrier();
+ }
+
+ return 0;
+}
+
+void smp_call_function_client(struct call_data_struct *call_data)
+{
+ call_data->func(call_data->info);
+ if (call_data->wait)
+ atomic_inc(&call_data->finished);
+}
+
extern unsigned long xcall_flush_tlb_page;
extern unsigned long xcall_flush_tlb_mm;
extern unsigned long xcall_flush_tlb_range;
@@ -279,7+279,7 @@ char * getname32(const char *filename) char *tmp, *result;
result = ERR_PTR(-ENOMEM);
- tmp = (char *)__get_free_page(GFP_KERNEL);
+ tmp = __getname();
if (tmp) {
int retval = do_getname32(filename, tmp);
# $Id: Makefile,v 1.22 2000/03/31 04:06:23 davem Exp $
-# Makefile for Sparc library files..
+# Makefile for Sparc64 library files..
#
CFLAGS := $(CFLAGS)
@@ -7,7+7,8 @@ CFLAGS := $(CFLAGS) OBJS = PeeCeeI.o blockops.o debuglocks.o strlen.o strncmp.o \
memscan.o strncpy_from_user.o strlen_user.o memcmp.o checksum.o \
VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \
- VIScsumcopyusr.o VISsave.o atomic.o rwlock.o bitops.o
+ VIScsumcopyusr.o VISsave.o atomic.o rwlock.o bitops.o \
+ dec_and_lock.o
lib.a: $(OBJS)
$(AR) rcs lib.a $(OBJS)
--- /dev/null
+/* $Id$
+ * dec_and_lock.S: Sparc64 version of "atomic_dec_and_lock()"
+ * using cas and ldstub instructions.
+ *
+ * Copyright (C) 2000 David S. Miller (davem@redhat.com)
+ */
+
+ .text
+ .align 64
+
+ /* CAS basically works like this:
+ *
+ * void CAS(MEM, REG1, REG2)
+ * {
+ * START_ATOMIC();
+ * if (*(MEM) == REG1) {
+ * TMP = *(MEM);
+ * *(MEM) = REG2;
+ * REG2 = TMP;
+ * }
+ * END_ATOMIC();
+ * }
+ *
+ * All non-contention cases are handled in 2 I-cache
+ * lines which is 1 L2 cache line.
+ */
+
+ .globl atomic_dec_and_lock
+atomic_dec_and_lock: /* %o0 = counter, %o1 = lock */
+loop1: lduw [%o0], %g5
+ subcc %g5, 1, %g7
+ be,pn %icc, to_zero
+ nop
+nzero: cas [%o0], %g5, %g7
+ cmp %g5, %g7
+ bne,pn %icc, loop1
+ mov 0, %g1
+
+out: retl
+ mov %g1, %o0
+to_zero:ldstub [%o1], %g3
+ brnz,pn %g3, spin_on_lock
+ membar #StoreLoad | #StoreStore
+loop2: cas [%o0], %g5, %g7 /* ASSERT(g7 == 0) */
+ brnz,pt %g7, out
+ mov 1, %g1
+
+ lduw [%o0], %g5
+ subcc %g5, 1, %g7
+ be,pn %icc, loop2
+ nop
+ membar #StoreStore | #LoadStore
+ stb %g0, [%o1]
+ b,pt %xcc, nzero
+ nop
+
+spin_on_lock:
+ ldub [%o1], %g3
+ brnz,pt %g3, spin_on_lock
+ membar #LoadLoad
+ b,a,pt %xcc, to_zero
@@ -432,4+432,24 @@ xcall_flush_cache_all: nop
flush %g6
retry
+
+ .globl xcall_call_function
+xcall_call_function:
+ mov TLB_TAG_ACCESS, %g5 ! wheee...
+ stxa %g1, [%g5] ASI_IMMU ! save call_data here for a bit
+ membar #Sync
+ rdpr %pstate, %g2
+ wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate
+ mov TLB_TAG_ACCESS, %g2
+ ldxa [%g2] ASI_IMMU, %g5
+ rdpr %pil, %g2
+ wrpr %g0, 15, %pil
+ sethi %hi(109f), %g7
+ b,pt %xcc, etrap_irq
+109: or %g7, %lo(109b), %g7
+ call smp_call_function_client
+ mov %l5, %o0
+ b,pt %xcc, rtrap
+ clr %l6
+
#endif /* CONFIG_SMP */
#include <linux/types.h>
#include <linux/sched.h>
+#include <linux/malloc.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/file.h>
endif
endif
-ifdef CONFIG_SGI_IP22
+ifdef CONFIG_SGI
SUB_DIRS += sgi
MOD_SUB_DIRS += sgi
endif
#include <linux/lvm.h>
-static char *lvm_snap_version = "LVM 0.8final (15/02/2000)\n";
+static char *lvm_snap_version __attribute__ ((unused)) = "LVM 0.8final (15/02/2000)\n";
extern const char *const lvm_name;
extern int lvm_blocksizes[];
@@ -75,6+75,7 @@ extern void pcwatchdog_init(void); extern int rtc_sun_init(void); /* Combines MK48T02 and MK48T08 */
extern int rtc_DP8570A_init(void);
extern int rtc_MK48T08_init(void);
+extern int ds1286_init(void);
extern int dsp56k_init(void);
extern int radio_init(void);
extern int pc110pad_init(void);
* the kernel and is not a module. Since the functions are used by some Atari
* drivers, this is the case on the Atari.
*
+ *
+ * 1.1 Cesar Barros: SMP locking fixes
+ * added changelog
*/
-#define NVRAM_VERSION "1.0"
+#define NVRAM_VERSION "1.1"
#include <linux/module.h>
#include <linux/config.h>
#endif
/* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with
- * interrupts disabled. Due to the index-port/data-port design of the RTC, we
+ * rtc_lock held. Due to the index-port/data-port design of the RTC, we
* don't want two different things trying to get to it at once. (e.g. the
* periodic 11 min sync from time.c vs. this driver.)
*/
#include <linux/nvram.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
+extern spinlock_t rtc_lock;
static int nvram_open_cnt = 0; /* #times opened */
static int nvram_open_mode; /* special open modes */
@@ -163,21+168,20 @@ unsigned char nvram_read_byte( int i ) unsigned long flags;
unsigned char c;
- save_flags(flags);
- cli();
+ spin_lock_irqsave (&rtc_lock, flags);
c = nvram_read_int( i );
- restore_flags(flags);
+ spin_unlock_irqrestore (&rtc_lock, flags);
return( c );
}
+/* This races nicely with trying to read with checksum checking (nvram_read) */
void nvram_write_byte( unsigned char c, int i )
{
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave (&rtc_lock, flags);
nvram_write_int( c, i );
- restore_flags(flags);
+ spin_unlock_irqrestore (&rtc_lock, flags);
}
int nvram_check_checksum( void )
@@ -185,10+189,9 @@ int nvram_check_checksum( void ) unsigned long flags;
int rv;
- save_flags(flags);
- cli();
+ spin_lock_irqsave (&rtc_lock, flags);
rv = nvram_check_checksum_int();
- restore_flags(flags);
+ spin_unlock_irqrestore (&rtc_lock, flags);
return( rv );
}
@@ -196,10+199,9 @@ void nvram_set_checksum( void ) {
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave (&rtc_lock, flags);
nvram_set_checksum_int();
- restore_flags(flags);
+ spin_unlock_irqrestore (&rtc_lock, flags);
}
#endif /* MACH == ATARI */
@@ -228,63+230,67 @@ static long long nvram_llseek(struct file *file,loff_t offset, int origin ) static ssize_t nvram_read(struct file * file,
char * buf, size_t count, loff_t *ppos )
{
- unsigned long flags;
+ char contents [NVRAM_BYTES];
unsigned i = *ppos;
- char *tmp = buf;
-
- if (i != *ppos)
- return -EINVAL;
+ char *tmp;
- save_flags(flags);
- cli();
+ spin_lock_irq (&rtc_lock);
- if (!nvram_check_checksum_int()) {
- restore_flags(flags);
- return( -EIO );
- }
+ if (!nvram_check_checksum_int())
+ goto checksum_err;
+
+ for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp)
+ *tmp = nvram_read_int(i);
+
+ spin_unlock_irq (&rtc_lock);
+
+ copy_to_user_ret (buf, contents, tmp - contents, -EFAULT);
- for( ; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp )
- put_user( nvram_read_int(i), tmp );
*ppos = i;
- restore_flags(flags);
- return( tmp - buf );
+ return (tmp - contents);
+
+checksum_err:
+ spin_unlock_irq (&rtc_lock);
+ return -EIO;
}
static ssize_t nvram_write(struct file * file,
const char * buf, size_t count, loff_t *ppos )
{
- unsigned long flags;
+ char contents [NVRAM_BYTES];
unsigned i = *ppos;
- const char *tmp = buf;
- char c;
-
- if (i != *ppos)
- return -EINVAL;
+ char * tmp;
- save_flags(flags);
- cli();
-
- if (!nvram_check_checksum_int()) {
- restore_flags(flags);
- return( -EIO );
- }
+ /* could comebody please help me indent this better? */
+ copy_from_user_ret (contents, buf, (NVRAM_BYTES - i) < count ?
+ (NVRAM_BYTES - i) : count,
+ -EFAULT);
+
+ spin_lock_irq (&rtc_lock);
+
+ if (!nvram_check_checksum_int())
+ goto checksum_err;
+
+ for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp)
+ nvram_write_int (*tmp, i);
- for( ; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp ) {
- get_user( c, tmp );
- nvram_write_int( c, i );
- }
nvram_set_checksum_int();
+
+ spin_unlock_irq (&rtc_lock);
+
*ppos = i;
- restore_flags(flags);
- return( tmp - buf );
+ return (tmp - contents);
+
+checksum_err:
+ spin_unlock_irq (&rtc_lock);
+ return -EIO;
}
static int nvram_ioctl( struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg )
{
- unsigned long flags;
int i;
switch( cmd ) {
@@ -293,14+299,13 @@ static int nvram_ioctl( struct inode *inode, struct file *file, if (!capable(CAP_SYS_ADMIN))
return( -EACCES );
- save_flags(flags);
- cli();
+ spin_lock_irq (&rtc_lock);
for( i = 0; i < NVRAM_BYTES; ++i )
nvram_write_int( 0, i );
nvram_set_checksum_int();
- restore_flags(flags);
+ spin_unlock_irq (&rtc_lock);
return( 0 );
case NVRAM_SETCKS: /* just set checksum, contents unchanged
@@ -309,10+314,9 @@ static int nvram_ioctl( struct inode *inode, struct file *file, if (!capable(CAP_SYS_ADMIN))
return( -EACCES );
- save_flags(flags);
- cli();
+ spin_lock_irq (&rtc_lock);
nvram_set_checksum_int();
- restore_flags(flags);
+ spin_unlock_irq (&rtc_lock);
return( 0 );
default:
@@ -355,16+359,14 @@ static int nvram_read_proc( char *buffer, char **start, off_t offset, static int nvram_read_proc( char *buffer, char **start, off_t offset,
int size, int *eof, void *data )
{
- unsigned long flags;
unsigned char contents[NVRAM_BYTES];
int i, len = 0;
off_t begin = 0;
-
- save_flags(flags);
- cli();
+
+ spin_lock_irq (&rtc_lock);
for( i = 0; i < NVRAM_BYTES; ++i )
contents[i] = nvram_read_int( i );
- restore_flags(flags);
+ spin_unlock_irq (&rtc_lock);
*eof = mach_proc_infos( contents, buffer, &len, &begin, offset, size );
@@ -475,15+477,13 @@ static char *gfx_types[] = { static int pc_proc_infos( unsigned char *nvram, char *buffer, int *len,
off_t *begin, off_t offset, int size )
{
- unsigned long flags;
int checksum;
int type;
- save_flags(flags);
- cli();
+ spin_lock_irq (&rtc_lock);
checksum = nvram_check_checksum_int();
- restore_flags(flags);
-
+ spin_unlock_irq (&rtc_lock);
+
PRINT_PROC( "Checksum status: %svalid\n", checksum ? "" : "not " );
PRINT_PROC( "# floppies : %d\n",
@@ -258,6+258,8 @@ static struct rs_multiport_struct rs_multiport[NR_IRQS]; static int IRQ_timeout[NR_IRQS];
#ifdef CONFIG_SERIAL_CONSOLE
static struct console sercons;
+#endif
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE)
static unsigned long break_pressed; /* break, really ... */
#endif
@@ -2048,7+2050,7 @@ static int set_serial_info(struct async_struct * info,
new_port = new_serial.port;
if (HIGH_BITS_OFFSET)
- new_port += new_serial.port_high << HIGH_BITS_OFFSET;
+ new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
change_irq = new_serial.irq != state->irq;
change_port = (new_port != ((int) state->port)) ||
@@ -4450,9+4452,10 @@ static struct pci_board pci_boards[] __initdata = { { PCI_VENDOR_ID_ROCKWELL, 0x1004,
0x1048, 0x1500,
SPCI_FL_BASE1, 1, 115200 },
-#if 0 /* No definition for PCI_DEVICE_ID_NEC_NILE4 */
+#ifdef CONFIG_DDB5074
/*
* NEC Vrc-5074 (Nile 4) builtin UART.
+ * Conditionally compiled in since this is a motherboard device.
*/
{ PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NILE4,
PCI_ANY_ID, PCI_ANY_ID,
@@ -5172,7+5175,7 @@ int register_serial(struct serial_struct *req)
port = req->port;
if (HIGH_BITS_OFFSET)
- port += req->port_high << HIGH_BITS_OFFSET;
+ port += (unsigned long) req->port_high << HIGH_BITS_OFFSET;
save_flags(flags); cli();
for (i = 0; i < NR_PORTS; i++) {
@@ -152,6+152,7 @@ extern void rs285_console_init(void); extern void rs285_init(void);
extern void sa1100_rs_console_init(void);
extern void sa1100_rs_init(void);
+extern void sgi_serial_console_init(void);
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
@@ -2168,9+2169,12 @@ void __init console_init(void) #ifdef CONFIG_SERIAL_CONSOLE
#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
console_8xx_init();
-#elif defined(CONFIG_SERIAL)
+#elif defined(CONFIG_SERIAL)
serial_console_init();
#endif /* CONFIG_8xx */
+#ifdef CONFIG_SGI_SERIAL
+ sgi_serial_console_init();
+#endif
#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_BVME6000_SCC) || defined(CONFIG_MVME147_SCC)
vme_scc_console_init();
#endif
@@ -1115,26+1115,26 @@ static int __init i2c_init(void) extern int i2c_dev_init(void);
#endif
#ifdef CONFIG_I2C_ALGOBIT
- extern int algo_bit_init(void);
+ extern int i2c_algo_bit_init(void);
#endif
#ifdef CONFIG_I2C_BITLP
- extern int bitlp_init(void);
+ extern int i2c_bitlp_init(void);
#endif
#ifdef CONFIG_I2C_BITELV
- extern int bitelv_init(void);
+ extern int i2c_bitelv_init(void);
#endif
#ifdef CONFIG_I2C_BITVELLE
- extern int bitvelle_init(void);
+ extern int i2c_bitvelle_init(void);
#endif
#ifdef CONFIG_I2C_BITVIA
- extern int bitvia_init(void);
+ extern int i2c_bitvia_init(void);
#endif
#ifdef CONFIG_I2C_ALGOPCF
- extern int algo_pcf_init(void);
+ extern int i2c_algo_pcf_init(void);
#endif
#ifdef CONFIG_I2C_PCFISA
- extern int pcfisa_init(void);
+ extern int i2c_pcfisa_init(void);
#endif
/* This is needed for automatic patch generation: sensors code starts here */
@@ -2858,13+2858,16 @@ int __init ide_setup (char *s) const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1);
const char max_hwif = '0' + (MAX_HWIFS - 1);
+
+ if (strncmp(s,"hd",2) == 0 && s[2] == '=') /* hd= is for hd.c */
+ return 0; /* driver and not us */
+
if (strncmp(s,"ide",3) &&
strncmp(s,"idebus",6) &&
#ifdef CONFIG_BLK_DEV_VIA82CXXX
strncmp(s,"splitfifo",9) &&
#endif /* CONFIG_BLK_DEV_VIA82CXXX */
- strncmp(s,"hdxlun",6) &&
- (strncmp(s,"hd",2) && s[2] != '='))
+ strncmp(s,"hd",2)) /* hdx= & hdxlun= */
return 0;
printk("ide_setup: %s", s);
@@ -79,7+79,6 @@ extern int ni5010_probe(struct net_device *); extern int ni52_probe(struct net_device *);
extern int ni65_probe(struct net_device *);
extern int sonic_probe(struct net_device *);
-extern int ioc3_probe(struct net_device *);
extern int SK_init(struct net_device *);
extern int seeq8005_probe(struct net_device *);
extern int smc_init( struct net_device * );
@@ -95,7+94,6 @@ extern int cs89x0_probe(struct net_device *dev); extern int ethertap_probe(struct net_device *dev);
extern int hplance_probe(struct net_device *dev);
extern int bagetlance_probe(struct net_device *);
-extern int dec_lance_probe(struct net_device *);
extern int mvme147lance_probe(struct net_device *dev);
extern int tc515_probe(struct net_device *dev);
extern int lance_probe(struct net_device *dev);
@@ -373,12+371,6 @@ struct devprobe mips_probes[] __initdata = { #ifdef CONFIG_MIPS_JAZZ_SONIC
{sonic_probe, 0},
#endif
-#ifdef CONFIG_SGI_IOC3_ETH
- {ioc3_probe, 0},
-#endif
-#ifdef CONFIG_DECLANCE /* DECstation on-board controller */
- {dec_lance_probe, 0}, /* and maybe TURBOchannel option boards */
-#endif
#ifdef CONFIG_BAGETLANCE /* Lance-based Baget ethernet boards */
{bagetlance_probe, 0},
#endif
/*
- * $Id: dmascc.c,v 1.3 1998/09/07 04:41:56 kudielka Exp $
+ * $Id: dmascc.c,v 1.27 2000/06/01 14:46:23 oe1kib Exp $
*
* Driver for high-speed SCC boards (those with DMA support)
- * Copyright (C) 1997 Klaus Kudielka
+ * Copyright (C) 1997-2000 Klaus Kudielka
+ *
+ * S5SCC/DMA support by Janko Koleznik S52HI
*
* 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
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
*/
#include <linux/module.h>
#include <linux/delay.h>
-#include <linux/dmascc.h>
#include <linux/errno.h>
#include <linux/if_arp.h>
#include <linux/in.h>
+#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
#include <linux/sockios.h>
#include <linux/tqueue.h>
#include <linux/version.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/segment.h>
+#include <asm/uaccess.h>
#include <net/ax25.h>
#include "z8530.h"
-/* Linux 2.0 compatibility */
-
-#if LINUX_VERSION_CODE < 0x20100
-
-
-#define __init
-#define __initdata
-#define __initfunc(x) x
-
-#define MODULE_AUTHOR(x)
-#define MODULE_DESCRIPTION(x)
-#define MODULE_PARM(x,y)
-
-#define copy_to_user(x,y,z) memcpy_tofs(x,y,z)
-#define copy_from_user(x,y,z) memcpy_fromfs(x,y,z)
-#define test_and_set_bit(x,y) set_bit(x,y)
-#define register_netdevice(x) register_netdev(x)
-#define unregister_netdevice(x) unregister_netdev(x)
-#define dev_kfree_skb(x) dev_kfree_skb(x,FREE_WRITE)
-#define SET_DEV_INIT(x) (x=dmascc_dev_init)
-
-#define SHDLCE 0x01 /* WR15 */
-
-#define AUTOEOM 0x02 /* WR7' */
-#define RXFIFOH 0x08
-#define TXFIFOE 0x20
-
-static int dmascc_dev_init(struct net_device *dev)
-{
- return 0;
-}
-
-static void dev_init_buffers(struct net_device *dev)
-{
- int i;
-
- for (i = 0; i < DEV_NUMBUFFS; i++)
- skb_queue_head_init(&dev->buffs[i]);
-}
-
-
-#else
-
-
-#include <linux/init.h>
-#include <asm/uaccess.h>
-
-#define SET_DEV_INIT(x)
-
+/* Linux 2.2 and 2.3 compatibility */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,14)
+#define net_device device
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43)
+#define netif_start_queue(dev) { dev->tbusy = 0; }
+#define netif_stop_queue(dev) { dev->tbusy = 1; }
+#define netif_wake_queue(dev) { dev->tbusy = 0; mark_bh(NET_BH); }
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,47)
+#define netif_running(dev) (dev->flags & IFF_UP)
#endif
/* Number of buffers per channel */
-#define NUM_TX_BUF 2 /* NUM_TX_BUF >= 1 (2 recommended) */
-#define NUM_RX_BUF 2 /* NUM_RX_BUF >= 1 (2 recommended) */
-#define BUF_SIZE 2016
+#define NUM_TX_BUF 2 /* NUM_TX_BUF >= 1 (min. 2 recommended) */
+#define NUM_RX_BUF 6 /* NUM_RX_BUF >= 1 (min. 2 recommended) */
+#define BUF_SIZE 1576 /* BUF_SIZE >= mtu + hard_header_len */
/* Cards supported */
@@ -112,13+79,18 @@ static void dev_init_buffers(struct net_device *dev) 0, 8, 3686400, 7372800 }
#define HW_TWIN { "Gracilis PackeTwin", 0x200, 0x10, 0x10, 32, \
0, 4, 6144000, 6144000 }
+#define HW_S5 { "S5SCC/DMA", 0x200, 0x10, 0x10, 32, \
+ 0, 8, 4915200, 9830400 }
+
+#define HARDWARE { HW_PI, HW_PI2, HW_TWIN, HW_S5 }
-#define HARDWARE { HW_PI, HW_PI2, HW_TWIN }
+#define TMR_0_HZ 25600 /* Frequency of timer 0 */
#define TYPE_PI 0
#define TYPE_PI2 1
#define TYPE_TWIN 2
-#define NUM_TYPES 3
+#define TYPE_S5 3
+#define NUM_TYPES 4
#define MAX_NUM_DEVS 32
@@ -188,16+160,44 @@ static void dev_init_buffers(struct net_device *dev)
/* Status values */
-/* tx_state */
-#define TX_IDLE 0
-#define TX_OFF 1
-#define TX_TXDELAY 2
-#define TX_ACTIVE 3
-#define TX_SQDELAY 4
+#define IDLE 0
+#define TX_HEAD 1
+#define TX_DATA 2
+#define TX_PAUSE 3
+#define TX_TAIL 4
+#define RTS_OFF 5
+#define WAIT 6
+#define DCD_ON 7
+#define RX_ON 8
+#define DCD_OFF 9
+
+
+/* Ioctls */
+
+#define SIOCGSCCPARAM SIOCDEVPRIVATE
+#define SIOCSSCCPARAM (SIOCDEVPRIVATE+1)
/* Data types */
+struct scc_param {
+ int pclk_hz; /* frequency of BRG input (don't change) */
+ int brg_tc; /* BRG terminal count; BRG disabled if < 0 */
+ int nrzi; /* 0 (nrz), 1 (nrzi) */
+ int clocks; /* see dmascc_cfg documentation */
+ int txdelay; /* [1/TMR_0_HZ] */
+ int txtimeout; /* [1/HZ] */
+ int txtail; /* [1/TMR_0_HZ] */
+ int waittime; /* [1/TMR_0_HZ] */
+ int slottime; /* [1/TMR_0_HZ] */
+ int persist; /* 1 ... 256 */
+ int dma; /* -1 (disable), 0, 1, 3 */
+ int txpause; /* [1/TMR_0_HZ] */
+ int rtsoff; /* [1/TMR_0_HZ] */
+ int dcdon; /* [1/TMR_0_HZ] */
+ int dcdoff; /* [1/TMR_0_HZ] */
+};
+
struct scc_hardware {
char *name;
int io_region;
@@ -211,10+211,17 @@ struct scc_hardware { };
struct scc_priv {
- struct enet_statistics stats;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+ char name[IFNAMSIZ];
+#endif
+ int type;
+ int chip;
+ struct net_device *dev;
struct scc_info *info;
+ struct net_device_stats stats;
int channel;
- int cmd, data, tmr;
+ int card_base, scc_cmd, scc_data;
+ int tmr_cnt, tmr_ctrl, tmr_mode;
struct scc_param param;
char rx_buf[NUM_RX_BUF][BUF_SIZE];
int rx_len[NUM_RX_BUF];
@@ -226,17+233,13 @@ struct scc_priv { int tx_len[NUM_TX_BUF];
int tx_ptr;
int tx_head, tx_tail, tx_count;
- int tx_sem, tx_state;
+ int state;
unsigned long tx_start;
- int status;
+ int rr0;
};
struct scc_info {
- int type;
- int chip;
- int open;
- int scc_base;
- int tmr_base;
+ int irq_used;
int twin_serial_cfg;
struct net_device dev[2];
struct scc_priv priv[2];
@@ -247,25+250,33 @@ struct scc_info { /* Function declarations */
int dmascc_init(void) __init;
-static int setup_adapter(int io, int h, int n) __init;
+static int setup_adapter(int card_base, int type, int n) __init;
+
+static void write_scc(struct scc_priv *priv, int reg, int val);
+static void write_scc_data(struct scc_priv *priv, int val, int fast);
+static int read_scc(struct scc_priv *priv, int reg);
+static int read_scc_data(struct scc_priv *priv);
-static inline void write_scc(int ctl, int reg, int val);
-static inline int read_scc(int ctl, int reg);
static int scc_open(struct net_device *dev);
static int scc_close(struct net_device *dev);
static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
static int scc_send_packet(struct sk_buff *skb, struct net_device *dev);
-static struct enet_statistics *scc_get_stats(struct net_device *dev);
+static struct net_device_stats *scc_get_stats(struct net_device *dev);
static int scc_set_mac_address(struct net_device *dev, void *sa);
+
static void scc_isr(int irq, void *dev_id, struct pt_regs * regs);
static inline void z8530_isr(struct scc_info *info);
-static void rx_isr(struct net_device *dev);
-static void special_condition(struct net_device *dev, int rc);
+static void rx_isr(struct scc_priv *priv);
+static void special_condition(struct scc_priv *priv, int rc);
static void rx_bh(void *arg);
-static void tx_isr(struct net_device *dev);
-static void es_isr(struct net_device *dev);
-static void tm_isr(struct net_device *dev);
-static inline void delay(struct net_device *dev, int t);
+static void tx_isr(struct scc_priv *priv);
+static void es_isr(struct scc_priv *priv);
+static void tm_isr(struct scc_priv *priv);
+
+static inline void tx_on(struct scc_priv *priv);
+static inline void rx_on(struct scc_priv *priv);
+static inline void rx_off(struct scc_priv *priv);
+static void start_timer(struct scc_priv *priv, int t, int r15);
static inline unsigned char random(void);
@@ -287,7+298,6 @@ static struct scc_info *first = NULL; static unsigned long rand;
-
/* Module functions */
#ifdef MODULE
@@ -298,14+308,12 @@ MODULE_DESCRIPTION("Driver for high-speed SCC boards"); MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NUM_DEVS) "i");
-int init_module(void)
-{
+int init_module(void) {
return dmascc_init();
}
-void cleanup_module(void)
-{
+void cleanup_module(void) {
int i;
struct scc_info *info;
@@ -315,15+323,17 @@ void cleanup_module(void) /* Unregister devices */
for (i = 0; i < 2; i++) {
if (info->dev[i].name)
+ rtnl_lock();
unregister_netdevice(&info->dev[i]);
+ rtnl_unlock();
}
/* Reset board */
- if (info->type == TYPE_TWIN)
- outb_p(0, info->dev[0].base_addr + TWIN_SERIAL_CFG);
- write_scc(info->priv[0].cmd, R9, FHWRES);
+ if (info->priv[0].type == TYPE_TWIN)
+ outb(0, info->dev[0].base_addr + TWIN_SERIAL_CFG);
+ write_scc(&info->priv[0], R9, FHWRES);
release_region(info->dev[0].base_addr,
- hw[info->type].io_size);
+ hw[info->priv[0].type].io_size);
/* Free memory */
first = info->next;
@@ -335,8+345,7 @@ void cleanup_module(void) #else
-void __init dmascc_setup(char *str, int *ints)
-{
+void __init dmascc_setup(char *str, int *ints) {
int i;
for (i = 0; i < MAX_NUM_DEVS && i < ints[0]; i++)
@@ -349,8+358,7 @@ void __init dmascc_setup(char *str, int *ints)
/* Initialization functions */
-int __init dmascc_init(void)
-{
+int __init dmascc_init(void) {
int h, i, j, n;
int base[MAX_NUM_DEVS], tcmd[MAX_NUM_DEVS], t0[MAX_NUM_DEVS],
t1[MAX_NUM_DEVS];
@@ -402,18+410,18 @@ int __init dmascc_init(void) for (i = 0; i < hw[h].num_devs; i++)
if (base[i]) {
/* Timer 0: LSB+MSB, Mode 3, TMR_0_HZ */
- outb_p(0x36, tcmd[i]);
- outb_p((hw[h].tmr_hz/TMR_0_HZ) & 0xFF, t0[i]);
- outb_p((hw[h].tmr_hz/TMR_0_HZ) >> 8, t0[i]);
+ outb(0x36, tcmd[i]);
+ outb((hw[h].tmr_hz/TMR_0_HZ) & 0xFF, t0[i]);
+ outb((hw[h].tmr_hz/TMR_0_HZ) >> 8, t0[i]);
/* Timer 1: LSB+MSB, Mode 0, HZ/10 */
- outb_p(0x70, tcmd[i]);
- outb_p((TMR_0_HZ/HZ*10) & 0xFF, t1[i]);
- outb_p((TMR_0_HZ/HZ*10) >> 8, t1[i]);
+ outb(0x70, tcmd[i]);
+ outb((TMR_0_HZ/HZ*10) & 0xFF, t1[i]);
+ outb((TMR_0_HZ/HZ*10) >> 8, t1[i]);
start[i] = jiffies;
delay[i] = 0;
counting[i] = 1;
/* Timer 2: LSB+MSB, Mode 0 */
- outb_p(0xb0, tcmd[i]);
+ outb(0xb0, tcmd[i]);
}
time = jiffies;
/* Wait until counter registers are loaded */
@@ -424,8+432,8 @@ int __init dmascc_init(void) for (i = 0; i < hw[h].num_devs; i++)
if (base[i] && counting[i]) {
/* Read back Timer 1: latch; read LSB; read MSB */
- outb_p(0x40, tcmd[i]);
- t_val = inb_p(t1[i]) + (inb_p(t1[i]) << 8);
+ outb(0x40, tcmd[i]);
+ t_val = inb(t1[i]) + (inb(t1[i]) << 8);
/* Also check whether counter did wrap */
if (t_val == 0 || t_val > TMR_0_HZ/HZ*10) counting[i] = 0;
delay[i] = jiffies - start[i];
@@ -452,31+460,46 @@ int __init dmascc_init(void) return -EIO;
}
-int __init setup_adapter(int io, int h, int n)
-{
+
+int __init setup_adapter(int card_base, int type, int n) {
int i, irq, chip;
struct scc_info *info;
struct net_device *dev;
struct scc_priv *priv;
unsigned long time;
unsigned int irqs;
- int tmr = io + hw[h].tmr_offset;
- int scc = io + hw[h].scc_offset;
- int cmd = scc + SCCA_CMD;
+ int tmr_base = card_base + hw[type].tmr_offset;
+ int scc_base = card_base + hw[type].scc_offset;
char *chipnames[] = CHIPNAMES;
- /* Reset 8530 */
- write_scc(cmd, R9, FHWRES | MIE | NV);
+ /* Allocate memory */
+ info = kmalloc(sizeof(struct scc_info), GFP_KERNEL | GFP_DMA);
+ if (!info) {
+ printk("dmascc: could not allocate memory for %s at %#3x\n",
+ hw[type].name, card_base);
+ return -1;
+ }
+
+ /* Initialize what is necessary for write_scc and write_scc_data */
+ memset(info, 0, sizeof(struct scc_info));
+ priv = &info->priv[0];
+ priv->type = type;
+ priv->card_base = card_base;
+ priv->scc_cmd = scc_base + SCCA_CMD;
+ priv->scc_data = scc_base + SCCA_DATA;
+
+ /* Reset SCC */
+ write_scc(priv, R9, FHWRES | MIE | NV);
/* Determine type of chip by enabling SDLC/HDLC enhancements */
- write_scc(cmd, R15, SHDLCE);
- if (!read_scc(cmd, R15)) {
+ write_scc(priv, R15, SHDLCE);
+ if (!read_scc(priv, R15)) {
/* WR7' not present. This is an ordinary Z8530 SCC. */
chip = Z8530;
} else {
/* Put one character in TX FIFO */
- write_scc(cmd, R8, 0);
- if (read_scc(cmd, R0) & Tx_BUF_EMP) {
+ write_scc_data(priv, 0, 0);
+ if (read_scc(priv, R0) & Tx_BUF_EMP) {
/* TX FIFO not full. This is a Z85230 ESCC with a 4-byte FIFO. */
chip = Z85230;
} else {
@@ -484,93+507,76 @@ int __init setup_adapter(int io, int h, int n) chip = Z85C30;
}
}
- write_scc(cmd, R15, 0);
+ write_scc(priv, R15, 0);
/* Start IRQ auto-detection */
sti();
irqs = probe_irq_on();
/* Enable interrupts */
- switch (h) {
- case TYPE_PI:
- case TYPE_PI2:
- outb_p(0, io + PI_DREQ_MASK);
- write_scc(cmd, R15, CTSIE);
- write_scc(cmd, R0, RES_EXT_INT);
- write_scc(cmd, R1, EXT_INT_ENAB);
- break;
- case TYPE_TWIN:
- outb_p(0, io + TWIN_DMA_CFG);
- inb_p(io + TWIN_CLR_TMR1);
- inb_p(io + TWIN_CLR_TMR2);
- outb_p(TWIN_EI, io + TWIN_SERIAL_CFG);
- break;
+ if (type == TYPE_TWIN) {
+ outb(0, card_base + TWIN_DMA_CFG);
+ inb(card_base + TWIN_CLR_TMR1);
+ inb(card_base + TWIN_CLR_TMR2);
+ outb((info->twin_serial_cfg = TWIN_EI), card_base + TWIN_SERIAL_CFG);
+ } else {
+ write_scc(priv, R15, CTSIE);
+ write_scc(priv, R0, RES_EXT_INT);
+ write_scc(priv, R1, EXT_INT_ENAB);
}
/* Start timer */
- outb_p(1, tmr + TMR_CNT1);
- outb_p(0, tmr + TMR_CNT1);
+ outb(1, tmr_base + TMR_CNT1);
+ outb(0, tmr_base + TMR_CNT1);
+
/* Wait and detect IRQ */
time = jiffies; while (jiffies - time < 2 + HZ / TMR_0_HZ);
irq = probe_irq_off(irqs);
/* Clear pending interrupt, disable interrupts */
- switch (h) {
- case TYPE_PI:
- case TYPE_PI2:
- write_scc(cmd, R1, 0);
- write_scc(cmd, R15, 0);
- write_scc(cmd, R0, RES_EXT_INT);
- break;
- case TYPE_TWIN:
- inb_p(io + TWIN_CLR_TMR1);
- outb_p(0, io + TWIN_SERIAL_CFG);
- break;
+ if (type == TYPE_TWIN) {
+ inb(card_base + TWIN_CLR_TMR1);
+ } else {
+ write_scc(priv, R1, 0);
+ write_scc(priv, R15, 0);
+ write_scc(priv, R0, RES_EXT_INT);
}
if (irq <= 0) {
printk("dmascc: could not find irq of %s at %#3x (irq=%d)\n",
- hw[h].name, io, irq);
- return -1;
- }
-
- /* Allocate memory */
- info = kmalloc(sizeof(struct scc_info), GFP_KERNEL | GFP_DMA);
- if (!info) {
- printk("dmascc: could not allocate memory for %s at %#3x\n",
- hw[h].name, io);
+ hw[type].name, card_base, irq);
+ kfree_s(info, sizeof(struct scc_info));
return -1;
}
/* Set up data structures */
- memset(info, 0, sizeof(struct scc_info));
- info->type = h;
- info->chip = chip;
- info->scc_base = io + hw[h].scc_offset;
- info->tmr_base = io + hw[h].tmr_offset;
- info->twin_serial_cfg = 0;
for (i = 0; i < 2; i++) {
dev = &info->dev[i];
priv = &info->priv[i];
+ priv->type = type;
+ priv->chip = chip;
+ priv->dev = dev;
priv->info = info;
priv->channel = i;
- priv->cmd = info->scc_base + (i ? SCCB_CMD : SCCA_CMD);
- priv->data = info->scc_base + (i ? SCCB_DATA : SCCA_DATA);
- priv->tmr = info->tmr_base + (i ? TMR_CNT2 : TMR_CNT1);
- priv->param.pclk_hz = hw[h].pclk_hz;
+ priv->card_base = card_base;
+ priv->scc_cmd = scc_base + (i ? SCCB_CMD : SCCA_CMD);
+ priv->scc_data = scc_base + (i ? SCCB_DATA : SCCA_DATA);
+ priv->tmr_cnt = tmr_base + (i ? TMR_CNT2 : TMR_CNT1);
+ priv->tmr_ctrl = tmr_base + TMR_CTRL;
+ priv->tmr_mode = i ? 0xb0 : 0x70;
+ priv->param.pclk_hz = hw[type].pclk_hz;
priv->param.brg_tc = -1;
priv->param.clocks = TCTRxCP | RCRTxCP;
- priv->param.txdelay = TMR_0_HZ * 10 / 1000;
- priv->param.txtime = HZ * 3;
- priv->param.sqdelay = TMR_0_HZ * 1 / 1000;
- priv->param.slottime = TMR_0_HZ * 10 / 1000;
- priv->param.waittime = TMR_0_HZ * 100 / 1000;
- priv->param.persist = 32;
+ priv->param.persist = 256;
+ priv->param.dma = -1;
priv->rx_task.routine = rx_bh;
- priv->rx_task.data = dev;
+ priv->rx_task.data = priv;
dev->priv = priv;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+ if (sizeof(dev->name) == sizeof(char *)) dev->name = priv->name;
+#endif
sprintf(dev->name, "dmascc%i", 2*n+i);
- dev->base_addr = io;
+ dev->base_addr = card_base;
dev->irq = irq;
dev->open = scc_open;
dev->stop = scc_close;
@@ -580,7+586,6 @@ int __init setup_adapter(int io, int h, int n) dev->hard_header = ax25_encapsulate;
dev->rebuild_header = ax25_rebuild_header;
dev->set_mac_address = scc_set_mac_address;
- SET_DEV_INIT(dev->init);
dev->type = ARPHRD_AX25;
dev->hard_header_len = 73;
dev->mtu = 1500;
@@ -589,203+594,298 @@ int __init setup_adapter(int io, int h, int n) memcpy(dev->broadcast, ax25_broadcast, 7);
memcpy(dev->dev_addr, ax25_test, 7);
dev_init_buffers(dev);
+ rtnl_lock();
if (register_netdevice(dev)) {
printk("dmascc: could not register %s\n", dev->name);
}
+ rtnl_unlock();
}
- request_region(io, hw[h].io_size, "dmascc");
+ request_region(card_base, hw[type].io_size, "dmascc");
info->next = first;
first = info;
- printk("dmascc: found %s (%s) at %#3x, irq %d\n", hw[h].name,
- chipnames[chip], io, irq);
+ printk("dmascc: found %s (%s) at %#3x, irq %d\n", hw[type].name,
+ chipnames[chip], card_base, irq);
return 0;
}
/* Driver functions */
-static inline void write_scc(int ctl, int reg, int val)
-{
- outb_p(reg, ctl);
- outb_p(val, ctl);
+static void write_scc(struct scc_priv *priv, int reg, int val) {
+ unsigned long flags;
+ switch (priv->type) {
+ case TYPE_S5:
+ if (reg) outb(reg, priv->scc_cmd);
+ outb(val, priv->scc_cmd);
+ return;
+ case TYPE_TWIN:
+ if (reg) outb_p(reg, priv->scc_cmd);
+ outb_p(val, priv->scc_cmd);
+ return;
+ default:
+ save_flags(flags);
+ cli();
+ outb_p(0, priv->card_base + PI_DREQ_MASK);
+ if (reg) outb_p(reg, priv->scc_cmd);
+ outb_p(val, priv->scc_cmd);
+ outb(1, priv->card_base + PI_DREQ_MASK);
+ restore_flags(flags);
+ return;
+ }
}
-static inline int read_scc(int ctl, int reg)
-{
- outb_p(reg, ctl);
- return inb_p(ctl);
+static void write_scc_data(struct scc_priv *priv, int val, int fast) {
+ unsigned long flags;
+ switch (priv->type) {
+ case TYPE_S5:
+ outb(val, priv->scc_data);
+ return;
+ case TYPE_TWIN:
+ outb_p(val, priv->scc_data);
+ return;
+ default:
+ if (fast) outb_p(val, priv->scc_data);
+ else {
+ save_flags(flags);
+ cli();
+ outb_p(0, priv->card_base + PI_DREQ_MASK);
+ outb_p(val, priv->scc_data);
+ outb(1, priv->card_base + PI_DREQ_MASK);
+ restore_flags(flags);
+ }
+ return;
+ }
}
-static int scc_open(struct net_device *dev)
-{
+static int read_scc(struct scc_priv *priv, int reg) {
+ int rc;
+ unsigned long flags;
+ switch (priv->type) {
+ case TYPE_S5:
+ if (reg) outb(reg, priv->scc_cmd);
+ return inb(priv->scc_cmd);
+ case TYPE_TWIN:
+ if (reg) outb_p(reg, priv->scc_cmd);
+ return inb_p(priv->scc_cmd);
+ default:
+ save_flags(flags);
+ cli();
+ outb_p(0, priv->card_base + PI_DREQ_MASK);
+ if (reg) outb_p(reg, priv->scc_cmd);
+ rc = inb_p(priv->scc_cmd);
+ outb(1, priv->card_base + PI_DREQ_MASK);
+ restore_flags(flags);
+ return rc;
+ }
+}
+
+
+static int read_scc_data(struct scc_priv *priv) {
+ int rc;
+ unsigned long flags;
+ switch (priv->type) {
+ case TYPE_S5:
+ return inb(priv->scc_data);
+ case TYPE_TWIN:
+ return inb_p(priv->scc_data);
+ default:
+ save_flags(flags);
+ cli();
+ outb_p(0, priv->card_base + PI_DREQ_MASK);
+ rc = inb_p(priv->scc_data);
+ outb(1, priv->card_base + PI_DREQ_MASK);
+ restore_flags(flags);
+ return rc;
+ }
+}
+
+
+static int scc_open(struct net_device *dev) {
struct scc_priv *priv = dev->priv;
struct scc_info *info = priv->info;
- int io = dev->base_addr;
- int cmd = priv->cmd;
+ int card_base = priv->card_base;
+
+ MOD_INC_USE_COUNT;
/* Request IRQ if not already used by other channel */
- if (!info->open) {
- if (request_irq(dev->irq, scc_isr, SA_INTERRUPT, "dmascc", info))
+ if (!info->irq_used) {
+ if (request_irq(dev->irq, scc_isr, 0, "dmascc", info)) {
+ MOD_DEC_USE_COUNT;
return -EAGAIN;
+ }
}
+ info->irq_used++;
/* Request DMA if required */
- if (dev->dma && request_dma(dev->dma, "dmascc")) {
- if (!info->open) free_irq(dev->irq, info);
- return -EAGAIN;
+ if (priv->param.dma >= 0) {
+ if (request_dma(priv->param.dma, "dmascc")) {
+ if (--info->irq_used == 0) free_irq(dev->irq, info);
+ MOD_DEC_USE_COUNT;
+ return -EAGAIN;
+ } else {
+ unsigned long flags = claim_dma_lock();
+ clear_dma_ff(priv->param.dma);
+ release_dma_lock(flags);
+ }
}
/* Initialize local variables */
priv->rx_ptr = 0;
priv->rx_over = 0;
priv->rx_head = priv->rx_tail = priv->rx_count = 0;
- priv->tx_state = TX_IDLE;
+ priv->state = IDLE;
priv->tx_head = priv->tx_tail = priv->tx_count = 0;
priv->tx_ptr = 0;
- priv->tx_sem = 0;
/* Reset channel */
- write_scc(cmd, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
+ write_scc(priv, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
/* X1 clock, SDLC mode */
- write_scc(cmd, R4, SDLC | X1CLK);
+ write_scc(priv, R4, SDLC | X1CLK);
/* DMA */
- write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN);
+ write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
/* 8 bit RX char, RX disable */
- write_scc(cmd, R3, Rx8);
+ write_scc(priv, R3, Rx8);
/* 8 bit TX char, TX disable */
- write_scc(cmd, R5, Tx8);
+ write_scc(priv, R5, Tx8);
/* SDLC address field */
- write_scc(cmd, R6, 0);
+ write_scc(priv, R6, 0);
/* SDLC flag */
- write_scc(cmd, R7, FLAG);
- switch (info->chip) {
+ write_scc(priv, R7, FLAG);
+ switch (priv->chip) {
case Z85C30:
/* Select WR7' */
- write_scc(cmd, R15, SHDLCE);
+ write_scc(priv, R15, SHDLCE);
/* Auto EOM reset */
- write_scc(cmd, R7, AUTOEOM);
- write_scc(cmd, R15, 0);
+ write_scc(priv, R7, AUTOEOM);
+ write_scc(priv, R15, 0);
break;
case Z85230:
/* Select WR7' */
- write_scc(cmd, R15, SHDLCE);
- /* RX FIFO half full (interrupt only), Auto EOM reset,
- TX FIFO empty (DMA only) */
- write_scc(cmd, R7, AUTOEOM | (dev->dma ? TXFIFOE : RXFIFOH));
- write_scc(cmd, R15, 0);
+ write_scc(priv, R15, SHDLCE);
+ /* The following bits are set (see 2.5.2.1):
+ - Automatic EOM reset
+ - Interrupt request if RX FIFO is half full
+ This bit should be ignored in DMA mode (according to the
+ documentation), but actually isn't. The receiver doesn't work if
+ it is set. Thus, we have to clear it in DMA mode.
+ - Interrupt/DMA request if TX FIFO is completely empty
+ a) If set, the ESCC behaves as if it had no TX FIFO (Z85C30
+ compatibility).
+ b) If cleared, DMA requests may follow each other very quickly,
+ filling up the TX FIFO.
+ Advantage: TX works even in case of high bus latency.
+ Disadvantage: Edge-triggered DMA request circuitry may miss
+ a request. No more data is delivered, resulting
+ in a TX FIFO underrun.
+ Both PI2 and S5SCC/DMA seem to work fine with TXFIFOE cleared.
+ The PackeTwin doesn't. I don't know about the PI, but let's
+ assume it behaves like the PI2.
+ */
+ if (priv->param.dma >= 0) {
+ if (priv->type == TYPE_TWIN) write_scc(priv, R7, AUTOEOM | TXFIFOE);
+ else write_scc(priv, R7, AUTOEOM);
+ } else {
+ write_scc(priv, R7, AUTOEOM | RXFIFOH);
+ }
+ write_scc(priv, R15, 0);
break;
}
/* Preset CRC, NRZ(I) encoding */
- write_scc(cmd, R10, CRCPS | (priv->param.nrzi ? NRZI : NRZ));
+ write_scc(priv, R10, CRCPS | (priv->param.nrzi ? NRZI : NRZ));
/* Configure baud rate generator */
if (priv->param.brg_tc >= 0) {
/* Program BR generator */
- write_scc(cmd, R12, priv->param.brg_tc & 0xFF);
- write_scc(cmd, R13, (priv->param.brg_tc>>8) & 0xFF);
+ write_scc(priv, R12, priv->param.brg_tc & 0xFF);
+ write_scc(priv, R13, (priv->param.brg_tc>>8) & 0xFF);
/* BRG source = SYS CLK; enable BRG; DTR REQ function (required by
PackeTwin, not connected on the PI2); set DPLL source to BRG */
- write_scc(cmd, R14, SSBR | DTRREQ | BRSRC | BRENABL);
+ write_scc(priv, R14, SSBR | DTRREQ | BRSRC | BRENABL);
/* Enable DPLL */
- write_scc(cmd, R14, SEARCH | DTRREQ | BRSRC | BRENABL);
+ write_scc(priv, R14, SEARCH | DTRREQ | BRSRC | BRENABL);
} else {
/* Disable BR generator */
- write_scc(cmd, R14, DTRREQ | BRSRC);
+ write_scc(priv, R14, DTRREQ | BRSRC);
}
/* Configure clocks */
- if (info->type == TYPE_TWIN) {
+ if (priv->type == TYPE_TWIN) {
/* Disable external TX clock receiver */
- outb_p((info->twin_serial_cfg &=
+ outb((info->twin_serial_cfg &=
~(priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)),
- io + TWIN_SERIAL_CFG);
+ card_base + TWIN_SERIAL_CFG);
}
- write_scc(cmd, R11, priv->param.clocks);
- if ((info->type == TYPE_TWIN) && !(priv->param.clocks & TRxCOI)) {
+ write_scc(priv, R11, priv->param.clocks);
+ if ((priv->type == TYPE_TWIN) && !(priv->param.clocks & TRxCOI)) {
/* Enable external TX clock receiver */
- outb_p((info->twin_serial_cfg |=
+ outb((info->twin_serial_cfg |=
(priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)),
- io + TWIN_SERIAL_CFG);
+ card_base + TWIN_SERIAL_CFG);
}
/* Configure PackeTwin */
- if (info->type == TYPE_TWIN) {
+ if (priv->type == TYPE_TWIN) {
/* Assert DTR, enable interrupts */
- outb_p((info->twin_serial_cfg |= TWIN_EI |
+ outb((info->twin_serial_cfg |= TWIN_EI |
(priv->channel ? TWIN_DTRB_ON : TWIN_DTRA_ON)),
- io + TWIN_SERIAL_CFG);
+ card_base + TWIN_SERIAL_CFG);
}
/* Read current status */
- priv->status = read_scc(cmd, R0);
- /* Enable SYNC, DCD, and CTS interrupts */
- write_scc(cmd, R15, DCDIE | CTSIE | SYNCIE);
-
- /* Configure PI2 DMA */
- if (info->type <= TYPE_PI2) outb_p(1, io + PI_DREQ_MASK);
+ priv->rr0 = read_scc(priv, R0);
+ /* Enable DCD interrupt */
+ write_scc(priv, R15, DCDIE);
netif_start_queue(dev);
- info->open++;
- MOD_INC_USE_COUNT;
return 0;
}
-static int scc_close(struct net_device *dev)
-{
+static int scc_close(struct net_device *dev) {
struct scc_priv *priv = dev->priv;
struct scc_info *info = priv->info;
- int io = dev->base_addr;
- int cmd = priv->cmd;
+ int card_base = priv->card_base;
netif_stop_queue(dev);
- info->open--;
- if (info->type == TYPE_TWIN)
+ if (priv->type == TYPE_TWIN) {
/* Drop DTR */
- outb_p((info->twin_serial_cfg &=
+ outb((info->twin_serial_cfg &=
(priv->channel ? ~TWIN_DTRB_ON : ~TWIN_DTRA_ON)),
- io + TWIN_SERIAL_CFG);
-
- /* Reset channel, free DMA */
- write_scc(cmd, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
- if (dev->dma) {
- if (info->type == TYPE_TWIN) outb_p(0, io + TWIN_DMA_CFG);
- free_dma(dev->dma);
+ card_base + TWIN_SERIAL_CFG);
}
- if (!info->open) {
- if (info->type <= TYPE_PI2) outb_p(0, io + PI_DREQ_MASK);
- free_irq(dev->irq, info);
+ /* Reset channel, free DMA and IRQ */
+ write_scc(priv, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
+ if (priv->param.dma >= 0) {
+ if (priv->type == TYPE_TWIN) outb(0, card_base + TWIN_DMA_CFG);
+ free_dma(priv->param.dma);
}
+ if (--info->irq_used == 0) free_irq(dev->irq, info);
+
MOD_DEC_USE_COUNT;
return 0;
}
-static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
- int rc;
+static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) {
struct scc_priv *priv = dev->priv;
switch (cmd) {
case SIOCGSCCPARAM:
- if(copy_to_user(ifr->ifr_data, &priv->param, sizeof(struct scc_param)))
- return -EFAULT;
+ if (copy_to_user(ifr->ifr_data, &priv->param, sizeof(struct scc_param)))
+ return -EFAULT;
return 0;
case SIOCSSCCPARAM:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- if (netif_running(dev))
- return -EAGAIN;
- if(copy_from_user(&priv->param, ifr->ifr_data, sizeof(struct scc_param)))
- return -EFAULT;
- dev->dma = priv->param.dma;
+ if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ if (netif_running(dev)) return -EAGAIN;
+ if (copy_from_user(&priv->param, ifr->ifr_data, sizeof(struct scc_param)))
+ return -EFAULT;
return 0;
default:
return -EINVAL;
@@ -793,165+893,150 @@ static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) }
-static int scc_send_packet(struct sk_buff *skb, struct net_device *dev)
-{
+static int scc_send_packet(struct sk_buff *skb, struct net_device *dev) {
struct scc_priv *priv = dev->priv;
- struct scc_info *info = priv->info;
- int cmd = priv->cmd;
unsigned long flags;
int i;
- /* Block a timer-based transmit from overlapping */
+ /* Temporarily stop the scheduler feeding us packets */
netif_stop_queue(dev);
-
+
/* Transfer data to DMA buffer */
i = priv->tx_head;
memcpy(priv->tx_buf[i], skb->data+1, skb->len-1);
priv->tx_len[i] = skb->len-1;
+ /* Clear interrupts while we touch our circular buffers */
save_flags(flags);
cli();
- /* Set the busy flag if we just filled up the last buffer */
+ /* Move the ring buffer's head */
priv->tx_head = (i + 1) % NUM_TX_BUF;
priv->tx_count++;
- if (priv->tx_count != NUM_TX_BUF)
- netif_wake_queue(dev);
+
+ /* If we just filled up the last buffer, leave queue stopped.
+ The higher layers must wait until we have a DMA buffer
+ to accept the data. */
+ if (priv->tx_count < NUM_TX_BUF) netif_wake_queue(dev);
/* Set new TX state */
- if (priv->tx_state == TX_IDLE) {
+ if (priv->state == IDLE) {
/* Assert RTS, start timer */
- priv->tx_state = TX_TXDELAY;
- if (info->type <= TYPE_PI2) outb_p(0, dev->base_addr + PI_DREQ_MASK);
- write_scc(cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
- if (info->type <= TYPE_PI2) outb_p(1, dev->base_addr + PI_DREQ_MASK);
+ priv->state = TX_HEAD;
priv->tx_start = jiffies;
- delay(dev, priv->param.txdelay);
+ write_scc(priv, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
+ write_scc(priv, R15, 0);
+ start_timer(priv, priv->param.txdelay, 0);
}
+ /* Turn interrupts back on and free buffer */
restore_flags(flags);
-
dev_kfree_skb(skb);
- priv->tx_sem = 0;
return 0;
}
-static struct enet_statistics *scc_get_stats(struct net_device *dev)
-{
+static struct net_device_stats *scc_get_stats(struct net_device *dev) {
struct scc_priv *priv = dev->priv;
return &priv->stats;
}
-static int scc_set_mac_address(struct net_device *dev, void *sa)
-{
+static int scc_set_mac_address(struct net_device *dev, void *sa) {
memcpy(dev->dev_addr, ((struct sockaddr *)sa)->sa_data, dev->addr_len);
return 0;
}
-static void scc_isr(int irq, void *dev_id, struct pt_regs * regs)
-{
+static void scc_isr(int irq, void *dev_id, struct pt_regs * regs) {
struct scc_info *info = dev_id;
- int is, io = info->dev[0].base_addr;
- /* We're a fast IRQ handler and are called with interrupts disabled */
+ /* At this point interrupts are enabled, and the interrupt under service
+ is already acknowledged, but masked off.
- /* IRQ sharing doesn't make sense due to ISA's edge-triggered
- interrupts, hence it is safe to return if we have found and
- processed a single device. */
-
- /* Interrupt processing: We loop until we know that the IRQ line is
+ Interrupt processing: We loop until we know that the IRQ line is
low. If another positive edge occurs afterwards during the ISR,
another interrupt will be triggered by the interrupt controller
- as soon as the IRQ level is enabled again (see asm/irq.h). */
-
- switch (info->type) {
- case TYPE_PI:
- case TYPE_PI2:
- outb_p(0, io + PI_DREQ_MASK);
- z8530_isr(info);
- outb_p(1, io + PI_DREQ_MASK);
- return;
- case TYPE_TWIN:
- while ((is = ~inb_p(io + TWIN_INT_REG)) &
+ as soon as the IRQ level is enabled again (see asm/irq.h).
+
+ Bottom-half handlers will be processed after scc_isr(). This is
+ important, since we only have small ringbuffers and want new data
+ to be fetched/delivered immediately. */
+
+ if (info->priv[0].type == TYPE_TWIN) {
+ int is, card_base = info->priv[0].card_base;
+ while ((is = ~inb(card_base + TWIN_INT_REG)) &
TWIN_INT_MSK) {
if (is & TWIN_SCC_MSK) {
z8530_isr(info);
} else if (is & TWIN_TMR1_MSK) {
- inb_p(io + TWIN_CLR_TMR1);
- tm_isr(&info->dev[0]);
+ inb(card_base + TWIN_CLR_TMR1);
+ tm_isr(&info->priv[0]);
} else {
- inb_p(io + TWIN_CLR_TMR2);
- tm_isr(&info->dev[1]);
+ inb(card_base + TWIN_CLR_TMR2);
+ tm_isr(&info->priv[1]);
}
}
- /* No interrupts pending from the PackeTwin */
- return;
- }
+ } else z8530_isr(info);
}
-static inline void z8530_isr(struct scc_info *info)
-{
- int is, a_cmd;
-
- a_cmd = info->scc_base + SCCA_CMD;
+static inline void z8530_isr(struct scc_info *info) {
+ int is, i = 100;
- while ((is = read_scc(a_cmd, R3))) {
+ while ((is = read_scc(&info->priv[0], R3)) && i--) {
if (is & CHARxIP) {
- rx_isr(&info->dev[0]);
+ rx_isr(&info->priv[0]);
} else if (is & CHATxIP) {
- tx_isr(&info->dev[0]);
+ tx_isr(&info->priv[0]);
} else if (is & CHAEXT) {
- es_isr(&info->dev[0]);
+ es_isr(&info->priv[0]);
} else if (is & CHBRxIP) {
- rx_isr(&info->dev[1]);
+ rx_isr(&info->priv[1]);
} else if (is & CHBTxIP) {
- tx_isr(&info->dev[1]);
+ tx_isr(&info->priv[1]);
} else {
- es_isr(&info->dev[1]);
+ es_isr(&info->priv[1]);
}
+ write_scc(&info->priv[0], R0, RES_H_IUS);
+ i++;
+ }
+ if (i < 0) {
+ printk("dmascc: stuck in ISR with RR3=0x%02x.\n", is);
}
/* Ok, no interrupts pending from this 8530. The INT line should
be inactive now. */
}
-static void rx_isr(struct net_device *dev)
-{
- struct scc_priv *priv = dev->priv;
- int cmd = priv->cmd;
-
- if (dev->dma) {
+static void rx_isr(struct scc_priv *priv) {
+ if (priv->param.dma >= 0) {
/* Check special condition and perform error reset. See 2.4.7.5. */
- special_condition(dev, read_scc(cmd, R1));
- write_scc(cmd, R0, ERR_RES);
+ special_condition(priv, read_scc(priv, R1));
+ write_scc(priv, R0, ERR_RES);
} else {
/* Check special condition for each character. Error reset not necessary.
Same algorithm for SCC and ESCC. See 2.4.7.1 and 2.4.7.4. */
int rc;
- while (read_scc(cmd, R0) & Rx_CH_AV) {
- rc = read_scc(cmd, R1);
+ while (read_scc(priv, R0) & Rx_CH_AV) {
+ rc = read_scc(priv, R1);
if (priv->rx_ptr < BUF_SIZE)
- priv->rx_buf[priv->rx_head][priv->rx_ptr++] = read_scc(cmd, R8);
+ priv->rx_buf[priv->rx_head][priv->rx_ptr++] =
+ read_scc_data(priv);
else {
priv->rx_over = 2;
- read_scc(cmd, R8);
+ read_scc_data(priv);
}
- special_condition(dev, rc);
+ special_condition(priv, rc);
}
}
}
-static void special_condition(struct net_device *dev, int rc)
-{
- struct scc_priv *priv = dev->priv;
- int cb, cmd = priv->cmd;
+static void special_condition(struct scc_priv *priv, int rc) {
+ int cb;
unsigned long flags;
/* See Figure 2-15. Only overrun and EOF need to be checked. */
@@ -959,18+1044,15 @@ static void special_condition(struct net_device *dev, int rc) if (rc & Rx_OVR) {
/* Receiver overrun */
priv->rx_over = 1;
- if (!dev->dma) write_scc(cmd, R0, ERR_RES);
+ if (priv->param.dma < 0) write_scc(priv, R0, ERR_RES);
} else if (rc & END_FR) {
/* End of frame. Get byte count */
- if (dev->dma) {
- flags=claim_dma_lock();
- disable_dma(dev->dma);
- clear_dma_ff(dev->dma);
- cb = BUF_SIZE - get_dma_residue(dev->dma) - 2;
- release_dma_lock(flags);
-
+ if (priv->param.dma >= 0) {
+ flags = claim_dma_lock();
+ cb = BUF_SIZE - get_dma_residue(priv->param.dma) - 2;
+ release_dma_lock(flags);
} else {
- cb = priv->rx_ptr - 2;
+ cb = priv->rx_ptr - 2;
}
if (priv->rx_over) {
/* We had an overrun */
@@ -980,36+1062,32 @@ static void special_condition(struct net_device *dev, int rc) priv->rx_over = 0;
} else if (rc & CRC_ERR) {
/* Count invalid CRC only if packet length >= minimum */
- if (cb >= 8) {
+ if (cb >= 15) {
priv->stats.rx_errors++;
priv->stats.rx_crc_errors++;
}
} else {
- if (cb >= 8) {
- /* Put good frame in FIFO */
- priv->rx_len[priv->rx_head] = cb;
- priv->rx_head = (priv->rx_head + 1) % NUM_RX_BUF;
- priv->rx_count++;
- if (priv->rx_count == NUM_RX_BUF) {
- /* Disable receiver if FIFO full */
- write_scc(cmd, R3, Rx8);
+ if (cb >= 15) {
+ if (priv->rx_count < NUM_RX_BUF - 1) {
+ /* Put good frame in FIFO */
+ priv->rx_len[priv->rx_head] = cb;
+ priv->rx_head = (priv->rx_head + 1) % NUM_RX_BUF;
+ priv->rx_count++;
+ /* Mark bottom half handler */
+ queue_task(&priv->rx_task, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+ } else {
priv->stats.rx_errors++;
priv->stats.rx_over_errors++;
}
- /* Mark bottom half handler */
- queue_task(&priv->rx_task, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
}
}
/* Get ready for new frame */
- if (dev->dma) {
-
- flags=claim_dma_lock();
- set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]);
- set_dma_count(dev->dma, BUF_SIZE);
- enable_dma(dev->dma);
+ if (priv->param.dma >= 0) {
+ flags = claim_dma_lock();
+ set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]);
+ set_dma_count(priv->param.dma, BUF_SIZE);
release_dma_lock(flags);
-
} else {
priv->rx_ptr = 0;
}
@@ -1017,12+1095,8 @@ static void special_condition(struct net_device *dev, int rc) }
-static void rx_bh(void *arg)
-{
- struct net_device *dev = arg;
- struct scc_priv *priv = dev->priv;
- struct scc_info *info = priv->info;
- int cmd = priv->cmd;
+static void rx_bh(void *arg) {
+ struct scc_priv *priv = arg;
int i = priv->rx_tail;
int cb;
unsigned long flags;
@@ -1045,20+1119,15 @@ static void rx_bh(void *arg) data = skb_put(skb, cb+1);
data[0] = 0;
memcpy(&data[1], priv->rx_buf[i], cb);
- skb->dev = dev;
+ skb->dev = priv->dev;
skb->protocol = ntohs(ETH_P_AX25);
skb->mac.raw = skb->data;
netif_rx(skb);
priv->stats.rx_packets++;
+ priv->stats.rx_bytes += cb;
}
save_flags(flags);
cli();
- /* Enable receiver if RX buffers have been unavailable */
- if ((priv->rx_count == NUM_RX_BUF) && (priv->status & DCD)) {
- if (info->type <= TYPE_PI2) outb_p(0, dev->base_addr + PI_DREQ_MASK);
- write_scc(cmd, R3, RxENABLE | Rx8 | RxCRC_ENAB);
- if (info->type <= TYPE_PI2) outb_p(1, dev->base_addr + PI_DREQ_MASK);
- }
/* Move tail */
priv->rx_tail = i = (i + 1) % NUM_RX_BUF;
priv->rx_count--;
@@ -1068,265+1137,277 @@ static void rx_bh(void *arg) }
-static void tx_isr(struct net_device *dev)
-{
- struct scc_priv *priv = dev->priv;
- int cmd = priv->cmd;
+static void tx_isr(struct scc_priv *priv) {
int i = priv->tx_tail, p = priv->tx_ptr;
/* Suspend TX interrupts if we don't want to send anything.
See Figure 2-22. */
if (p == priv->tx_len[i]) {
- write_scc(cmd, R0, RES_Tx_P);
+ write_scc(priv, R0, RES_Tx_P);
return;
}
/* Write characters */
- while ((read_scc(cmd, R0) & Tx_BUF_EMP) && p < priv->tx_len[i]) {
- write_scc(cmd, R8, priv->tx_buf[i][p++]);
+ while ((read_scc(priv, R0) & Tx_BUF_EMP) && p < priv->tx_len[i]) {
+ write_scc_data(priv, priv->tx_buf[i][p++], 0);
}
- priv->tx_ptr = p;
+ /* Reset EOM latch of Z8530 */
+ if (!priv->tx_ptr && p && priv->chip == Z8530)
+ write_scc(priv, R0, RES_EOM_L);
+
+ priv->tx_ptr = p;
}
-static void es_isr(struct net_device *dev)
-{
- struct scc_priv *priv = dev->priv;
- struct scc_info *info = priv->info;
- int i, cmd = priv->cmd;
- int st, dst, res;
+static void es_isr(struct scc_priv *priv) {
+ int i, rr0, drr0, res;
unsigned long flags;
- /* Read status and reset interrupt bit */
- st = read_scc(cmd, R0);
- write_scc(cmd, R0, RES_EXT_INT);
- dst = priv->status ^ st;
- priv->status = st;
-
- /* Since the EOM latch is reset automatically, we assume that
- it has been zero if and only if we are in the TX_ACTIVE state.
- Otherwise we follow 2.4.9.6. */
+ /* Read status, reset interrupt bit (open latches) */
+ rr0 = read_scc(priv, R0);
+ write_scc(priv, R0, RES_EXT_INT);
+ drr0 = priv->rr0 ^ rr0;
+ priv->rr0 = rr0;
- /* Transmit underrun */
- if ((priv->tx_state == TX_ACTIVE) && (st & TxEOM)) {
+ /* Transmit underrun (2.4.9.6). We can't check the TxEOM flag, since
+ it might have already been cleared again by AUTOEOM. */
+ if (priv->state == TX_DATA) {
/* Get remaining bytes */
i = priv->tx_tail;
- if (dev->dma) {
- flags=claim_dma_lock();
- disable_dma(dev->dma);
- clear_dma_ff(dev->dma);
- res = get_dma_residue(dev->dma);
+ if (priv->param.dma >= 0) {
+ disable_dma(priv->param.dma);
+ flags = claim_dma_lock();
+ res = get_dma_residue(priv->param.dma);
release_dma_lock(flags);
} else {
res = priv->tx_len[i] - priv->tx_ptr;
- if (res) write_scc(cmd, R0, RES_Tx_P);
priv->tx_ptr = 0;
}
- /* Remove frame from FIFO */
- priv->tx_tail = (i + 1) % NUM_TX_BUF;
- priv->tx_count--;
- /* Check if another frame is available and we are allowed to transmit */
- if (priv->tx_count && (jiffies - priv->tx_start) < priv->param.txtime) {
- if (dev->dma) {
- flags=claim_dma_lock();
- set_dma_addr(dev->dma, (int) priv->tx_buf[priv->tx_tail]);
- set_dma_count(dev->dma, priv->tx_len[priv->tx_tail]);
- enable_dma(dev->dma);
- release_dma_lock(flags);
- } else {
- /* If we have an ESCC, we are allowed to write data bytes
- immediately. Otherwise we have to wait for the next
- TX interrupt. See Figure 2-22. */
- if (info->chip == Z85230) {
- tx_isr(dev);
- }
- }
- } else {
- /* No frame available. Disable interrupts. */
- priv->tx_state = TX_SQDELAY;
- delay(dev, priv->param.sqdelay);
- write_scc(cmd, R15, DCDIE | CTSIE | SYNCIE);
- write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN);
- }
- /* Update packet statistics */
+ /* Disable DREQ / TX interrupt */
+ if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
+ outb(0, priv->card_base + TWIN_DMA_CFG);
+ else
+ write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
if (res) {
+ /* Update packet statistics */
priv->stats.tx_errors++;
priv->stats.tx_fifo_errors++;
+ /* Other underrun interrupts may already be waiting */
+ write_scc(priv, R0, RES_EXT_INT);
+ write_scc(priv, R0, RES_EXT_INT);
} else {
+ /* Update packet statistics */
priv->stats.tx_packets++;
+ priv->stats.tx_bytes += priv->tx_len[i];
+ /* Remove frame from FIFO */
+ priv->tx_tail = (i + 1) % NUM_TX_BUF;
+ priv->tx_count--;
+ /* Inform upper layers */
+ netif_wake_queue(priv->dev);
+ }
+ /* Switch state */
+ write_scc(priv, R15, 0);
+ if (priv->tx_count &&
+ (jiffies - priv->tx_start) < priv->param.txtimeout) {
+ priv->state = TX_PAUSE;
+ start_timer(priv, priv->param.txpause, 0);
+ } else {
+ priv->state = TX_TAIL;
+ start_timer(priv, priv->param.txtail, 0);
}
- /* Inform upper layers */
- netif_wake_queue(dev);
}
/* DCD transition */
- if ((priv->tx_state < TX_TXDELAY) && (dst & DCD)) {
- /* Transmitter state change */
- priv->tx_state = TX_OFF;
- /* Enable or disable receiver */
- if (st & DCD) {
- if (dev->dma) {
- /* Program DMA controller */
- flags=claim_dma_lock();
- disable_dma(dev->dma);
- clear_dma_ff(dev->dma);
- set_dma_mode(dev->dma, DMA_MODE_READ);
- set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]);
- set_dma_count(dev->dma, BUF_SIZE);
- enable_dma(dev->dma);
- release_dma_lock(flags);
- /* Configure PackeTwin DMA */
- if (info->type == TYPE_TWIN) {
- outb_p((dev->dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3,
- dev->base_addr + TWIN_DMA_CFG);
- }
- /* Sp. cond. intr. only, ext int enable */
- write_scc(cmd, R1, EXT_INT_ENAB | INT_ERR_Rx |
- WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB);
- } else {
- /* Intr. on all Rx characters and Sp. cond., ext int enable */
- write_scc(cmd, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT |
- WT_FN_RDYFN);
- }
- if (priv->rx_count < NUM_RX_BUF) {
- /* Enable receiver */
- write_scc(cmd, R3, RxENABLE | Rx8 | RxCRC_ENAB);
+ if (drr0 & DCD) {
+ if (rr0 & DCD) {
+ switch (priv->state) {
+ case IDLE:
+ case WAIT:
+ priv->state = DCD_ON;
+ write_scc(priv, R15, 0);
+ start_timer(priv, priv->param.dcdon, 0);
}
} else {
- /* Disable DMA */
- if (dev->dma)
- {
- flags=claim_dma_lock();
- disable_dma(dev->dma);
- release_dma_lock(flags);
- }
- /* Disable receiver */
- write_scc(cmd, R3, Rx8);
- /* DMA disable, RX int disable, Ext int enable */
- write_scc(cmd, R1, EXT_INT_ENAB | WT_RDY_RT | WT_FN_RDYFN);
- /* Transmitter state change */
- if (random() > priv->param.persist)
- delay(dev, priv->param.slottime);
- else {
- if (priv->tx_count) {
- priv->tx_state = TX_TXDELAY;
- write_scc(cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
- priv->tx_start = jiffies;
- delay(dev, priv->param.txdelay);
- } else {
- priv->tx_state = TX_IDLE;
- }
+ switch (priv->state) {
+ case RX_ON:
+ rx_off(priv);
+ priv->state = DCD_OFF;
+ write_scc(priv, R15, 0);
+ start_timer(priv, priv->param.dcdoff, 0);
}
}
}
/* CTS transition */
- if ((info->type <= TYPE_PI2) && (dst & CTS) && (~st & CTS)) {
- /* Timer has expired */
- tm_isr(dev);
- }
+ if ((drr0 & CTS) && (~rr0 & CTS) && priv->type != TYPE_TWIN)
+ tm_isr(priv);
- /* /SYNC/HUNT transition */
- if ((dst & SYNC_HUNT) && (~st & SYNC_HUNT)) {
- /* Reset current frame and clear RX FIFO */
- while (read_scc(cmd, R0) & Rx_CH_AV) read_scc(cmd, R8);
- priv->rx_over = 0;
- if (dev->dma) {
- flags=claim_dma_lock();
- disable_dma(dev->dma);
- clear_dma_ff(dev->dma);
- set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]);
- set_dma_count(dev->dma, BUF_SIZE);
- enable_dma(dev->dma);
- release_dma_lock(flags);
+}
+
+
+static void tm_isr(struct scc_priv *priv) {
+ switch (priv->state) {
+ case TX_HEAD:
+ case TX_PAUSE:
+ tx_on(priv);
+ priv->state = TX_DATA;
+ break;
+ case TX_TAIL:
+ write_scc(priv, R5, TxCRC_ENAB | Tx8);
+ priv->state = RTS_OFF;
+ if (priv->type != TYPE_TWIN) write_scc(priv, R15, 0);
+ start_timer(priv, priv->param.rtsoff, 0);
+ break;
+ case RTS_OFF:
+ write_scc(priv, R15, DCDIE);
+ priv->rr0 = read_scc(priv, R0);
+ if (priv->rr0 & DCD) {
+ priv->stats.collisions++;
+ rx_on(priv);
+ priv->state = RX_ON;
} else {
- priv->rx_ptr = 0;
+ priv->state = WAIT;
+ start_timer(priv, priv->param.waittime, DCDIE);
+ }
+ break;
+ case WAIT:
+ if (priv->tx_count) {
+ priv->state = TX_HEAD;
+ priv->tx_start = jiffies;
+ write_scc(priv, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
+ write_scc(priv, R15, 0);
+ start_timer(priv, priv->param.txdelay, 0);
+ } else {
+ priv->state = IDLE;
+ if (priv->type != TYPE_TWIN) write_scc(priv, R15, DCDIE);
}
+ break;
+ case DCD_ON:
+ case DCD_OFF:
+ write_scc(priv, R15, DCDIE);
+ priv->rr0 = read_scc(priv, R0);
+ if (priv->rr0 & DCD) {
+ rx_on(priv);
+ priv->state = RX_ON;
+ } else {
+ priv->state = WAIT;
+ start_timer(priv,
+ random()/priv->param.persist*priv->param.slottime,
+ DCDIE);
+ }
+ break;
}
}
-static void tm_isr(struct net_device *dev)
-{
- struct scc_priv *priv = dev->priv;
- struct scc_info *info = priv->info;
- int cmd = priv->cmd;
+static inline void tx_on(struct scc_priv *priv) {
+ int i, n;
unsigned long flags;
- switch (priv->tx_state) {
- case TX_OFF:
- if (~priv->status & DCD) {
- if (random() > priv->param.persist) delay(dev, priv->param.slottime);
- else {
- if (priv->tx_count) {
- priv->tx_state = TX_TXDELAY;
- write_scc(cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
- priv->tx_start = jiffies;
- delay(dev, priv->param.txdelay);
- } else {
- priv->tx_state = TX_IDLE;
- }
- }
- }
- break;
- case TX_TXDELAY:
- priv->tx_state = TX_ACTIVE;
- if (dev->dma) {
- /* Program DMA controller */
-
- flags=claim_dma_lock();
- disable_dma(dev->dma);
- clear_dma_ff(dev->dma);
- set_dma_mode(dev->dma, DMA_MODE_WRITE);
- set_dma_addr(dev->dma, (int) priv->tx_buf[priv->tx_tail]);
- set_dma_count(dev->dma, priv->tx_len[priv->tx_tail]);
- enable_dma(dev->dma);
- release_dma_lock(flags);
-
- /* Configure PackeTwin DMA */
- if (info->type == TYPE_TWIN) {
- outb_p((dev->dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3,
- dev->base_addr + TWIN_DMA_CFG);
- }
- /* Enable interrupts and DMA. On the PackeTwin, the DTR//REQ pin
- is used for TX DMA requests, but we enable the WAIT/DMA request
- pin, anyway */
- write_scc(cmd, R15, TxUIE | DCDIE | CTSIE | SYNCIE);
- write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB);
- } else {
- write_scc(cmd, R15, TxUIE | DCDIE | CTSIE | SYNCIE);
- write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB);
- tx_isr(dev);
+ if (priv->param.dma >= 0) {
+ n = (priv->chip == Z85230) ? 3 : 1;
+ /* Program DMA controller */
+ flags = claim_dma_lock();
+ set_dma_mode(priv->param.dma, DMA_MODE_WRITE);
+ set_dma_addr(priv->param.dma, (int) priv->tx_buf[priv->tx_tail]+n);
+ set_dma_count(priv->param.dma, priv->tx_len[priv->tx_tail]-n);
+ release_dma_lock(flags);
+ /* Enable TX underrun interrupt */
+ write_scc(priv, R15, TxUIE);
+ /* Configure DREQ */
+ if (priv->type == TYPE_TWIN)
+ outb((priv->param.dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3,
+ priv->card_base + TWIN_DMA_CFG);
+ else
+ write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB);
+ /* Write first byte(s) */
+ save_flags(flags);
+ cli();
+ for (i = 0; i < n; i++)
+ write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1);
+ enable_dma(priv->param.dma);
+ restore_flags(flags);
+ } else {
+ write_scc(priv, R15, TxUIE);
+ write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB);
+ tx_isr(priv);
+ }
+ /* Reset EOM latch if we do not have the AUTOEOM feature */
+ if (priv->chip == Z8530) write_scc(priv, R0, RES_EOM_L);
+}
+
+
+static inline void rx_on(struct scc_priv *priv) {
+ unsigned long flags;
+
+ /* Clear RX FIFO */
+ while (read_scc(priv, R0) & Rx_CH_AV) read_scc_data(priv);
+ priv->rx_over = 0;
+ if (priv->param.dma >= 0) {
+ /* Program DMA controller */
+ flags = claim_dma_lock();
+ set_dma_mode(priv->param.dma, DMA_MODE_READ);
+ set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]);
+ set_dma_count(priv->param.dma, BUF_SIZE);
+ release_dma_lock(flags);
+ enable_dma(priv->param.dma);
+ /* Configure PackeTwin DMA */
+ if (priv->type == TYPE_TWIN) {
+ outb((priv->param.dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3,
+ priv->card_base + TWIN_DMA_CFG);
}
- if (info->chip == Z8530) write_scc(cmd, R0, RES_EOM_L);
- break;
- case TX_SQDELAY:
- /* Disable transmitter */
- write_scc(cmd, R5, TxCRC_ENAB | Tx8);
- /* Transmitter state change: Switch to TX_OFF and wait at least
- 1 slottime. */
- priv->tx_state = TX_OFF;
- if (~priv->status & DCD) delay(dev, priv->param.waittime);
+ /* Sp. cond. intr. only, ext int enable, RX DMA enable */
+ write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx |
+ WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB);
+ } else {
+ /* Reset current frame */
+ priv->rx_ptr = 0;
+ /* Intr. on all Rx characters and Sp. cond., ext int enable */
+ write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT |
+ WT_FN_RDYFN);
}
+ write_scc(priv, R0, ERR_RES);
+ write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB);
}
-static inline void delay(struct net_device *dev, int t)
-{
- struct scc_priv *priv = dev->priv;
- int tmr = priv->tmr;
+static inline void rx_off(struct scc_priv *priv) {
+ /* Disable receiver */
+ write_scc(priv, R3, Rx8);
+ /* Disable DREQ / RX interrupt */
+ if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
+ outb(0, priv->card_base + TWIN_DMA_CFG);
+ else
+ write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
+ /* Disable DMA */
+ if (priv->param.dma >= 0) disable_dma(priv->param.dma);
+}
+
+
+static void start_timer(struct scc_priv *priv, int t, int r15) {
+ unsigned long flags;
- outb_p(t & 0xFF, tmr);
- outb_p((t >> 8) & 0xFF, tmr);
+ outb(priv->tmr_mode, priv->tmr_ctrl);
+ if (t == 0) {
+ tm_isr(priv);
+ } else if (t > 0) {
+ save_flags(flags);
+ cli();
+ outb(t & 0xFF, priv->tmr_cnt);
+ outb((t >> 8) & 0xFF, priv->tmr_cnt);
+ if (priv->type != TYPE_TWIN) {
+ write_scc(priv, R15, r15 | CTSIE);
+ priv->rr0 |= CTS;
+ }
+ restore_flags(flags);
+ }
}
-static inline unsigned char random(void)
-{
+static inline unsigned char random(void) {
/* See "Numerical Recipes in C", second edition, p. 284 */
rand = rand * 1664525L + 1013904223L;
return (unsigned char) (rand >> 24);
}
-
@@ -326,6+326,7 @@ static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
sp->stats.rx_packets++;
+ sp->stats.rx_bytes += len;
} else {
printk ("%s: Memory squeeze, deferring packet.\n",
dev->name);
@@ -500,6+501,7 @@ static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Setup... */
skblen = skb->len;
len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
+ sp->stats.tx_bytes += len;
entry = sp->tx_new;
td = &sp->srings.tx_desc[entry];
@@ -690,7+692,7 @@ static inline void str2eaddr(unsigned char *ea, unsigned char *str)
int sgiseeq_probe(struct net_device *dev)
{
- static int initialized;
+ static int initialized = 0;
char *ep;
if (initialized) /* Already initialized? */
#ifndef MULTIPLE_PAD_SIZES
+#ifdef CONFIG_CPU_HAS_WB
+#include <asm/wbflush.h>
+#define esp_write(__reg, __val) do{(__reg) = (__val); wbflush();} while(0)
+#else
#define esp_write(__reg, __val) ((__reg) = (__val))
+#endif
#define esp_read(__reg) (__reg)
struct ESP_regs {
#include <asm/dec/ioasic_ints.h>
#include <asm/dec/machtype.h>
+/*
+ * Once upon a time the pmaz code used to be working but
+ * it hasn't been maintained for quite some time.
+ * It isn't working anymore but I'll leave here as a
+ * starting point. #define this an be prepared for tons
+ * of warnings and errors :)
+ */
+#undef PMAZ_A
+
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
static void dma_drain(struct NCR_ESP *esp);
-static void pmaz_dma_drain(struct NCR_ESP *esp);
-static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd * sp);
+static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd * sp);
static void dma_dump_state(struct NCR_ESP *esp);
static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length);
static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
static void dma_ints_off(struct NCR_ESP *esp);
static void dma_ints_on(struct NCR_ESP *esp);
-static void pmaz_dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length);
-static void pmaz_dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
-static void pmaz_dma_ints_off(struct NCR_ESP *esp);
-static void pmaz_dma_ints_on(struct NCR_ESP *esp);
static int dma_irq_p(struct NCR_ESP *esp);
static int dma_ports_p(struct NCR_ESP *esp);
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp);
static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp);
+static void dma_advance_sg(Scsi_Cmnd * sp);
+
+#ifdef PMAZ_A
+static void pmaz_dma_drain(struct NCR_ESP *esp);
+static void pmaz_dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length);
+static void pmaz_dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
+static void pmaz_dma_ints_off(struct NCR_ESP *esp);
+static void pmaz_dma_ints_on(struct NCR_ESP *esp);
static void pmaz_dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
static void pmaz_dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp);
-// static void pmaz_dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp);
-static void dma_advance_sg(Scsi_Cmnd * sp);
+static void pmaz_dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp);
+
+volatile int *scsi_pmaz_dma_ptr_tc;
+#endif
#define TC_ESP_RAM_SIZE 0x20000
#define ESP_TGT_DMA_SIZE ((TC_ESP_RAM_SIZE/7) & ~(sizeof(int)-1))
@@ -89,18+103,18 @@ volatile unsigned long *ioasic_ssr; volatile unsigned long *scsi_sdr0;
volatile unsigned long *scsi_sdr1;
-volatile int *scsi_pmaz_dma_ptr_tc;
-
static void scsi_dma_int(int, void *, struct pt_regs *);
/***************************************************************** Detection */
int dec_esp_detect(Scsi_Host_Template * tpnt)
{
- struct NCR_ESP *esp;
- struct ConfigDev *esp_dev;
+ struct NCR_ESP *esp;
+ struct ConfigDev *esp_dev;
+#ifdef PMAZ_A
int slot, i;
unsigned long mem_start;
volatile unsigned char *buffer;
+#endif
if (IOASIC) {
esp_dev = 0;
@@ -150,10+164,10 @@ int dec_esp_detect(Scsi_Host_Template * tpnt) /* SCSI chip speed */
esp->cfreq = 25000000;
- /*
+ /*
* we don't give the address of DMA channel, but the number
* of DMA channel, so we can use the jazz DMA functions
- *
+ *
*/
esp->dregs = JAZZ_SCSI_DMA;
@@ -164,7+178,7 @@ int dec_esp_detect(Scsi_Host_Template * tpnt) esp->esp_command = (volatile unsigned char *) cmd_buffer;
/* get virtual dma address for command buffer */
- esp->esp_command_dvma = KSEG1ADDR((volatile unsigned char *) cmd_buffer);
+ esp->esp_command_dvma = (__u32) KSEG1ADDR((volatile unsigned char *) cmd_buffer);
esp->irq = SCSI_INT;
request_irq(esp->irq, esp_intr, SA_INTERRUPT, "NCR 53C94 SCSI",
@@ -181,8+195,9 @@ int dec_esp_detect(Scsi_Host_Template * tpnt)
}
+#ifdef PMAZ_A
if (TURBOCHANNEL) {
- while ((slot = search_tc_card("PMAZ-AA")) >= 0) {
+ while ((slot = search_tc_card("PMAZ_AA")) >= 0) {
claim_tc_card(slot);
mem_start = get_tc_base_addr(slot);
@@ -242,12+257,13 @@ int dec_esp_detect(Scsi_Host_Template * tpnt) esp->dma_mmu_release_scsi_sgl = 0;
esp->dma_advance_sg = 0;
- request_irq(esp->irq, esp_intr, SA_INTERRUPT, "PMAZ-AA", NULL);
+ request_irq(esp->irq, esp_intr, SA_INTERRUPT, "PMAZ_AA", NULL);
esp->scsi_id = 7;
esp->diff = 0;
esp_initialize(esp);
}
}
+#endif
if(nesps) {
printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use);
@@ -321,20+337,14 @@ static void dma_drain(struct NCR_ESP *esp) }
}
-static void pmaz_dma_drain(struct NCR_ESP *esp)
-{
- memcpy((volatile void *) (KSEG0ADDR(esp_virt_buffer)),
- (void *) scsi_pmaz_dma_ptrs_tc[scsi_cur_buff], scsi_current_length);
-}
-
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd * sp)
{
return sp->SCp.this_residual;;
}
-
+
static void dma_dump_state(struct NCR_ESP *esp)
{
-/*
+/*
ESPLOG(("esp%d: dma -- enable <%08x> residue <%08x\n",
esp->esp_id, vdma_get_enable((int)esp->dregs), vdma_get_resdiue((int)esp->dregs)));
*/
@@ -400,6+410,66 @@ static void dma_ints_on(struct NCR_ESP *esp) enable_irq(SCSI_DMA_INT);
}
+static int dma_irq_p(struct NCR_ESP *esp)
+{
+ return (esp->eregs->esp_status & ESP_STAT_INTR);
+}
+
+static int dma_ports_p(struct NCR_ESP *esp)
+{
+/*
+ * FIXME: what's this good for?
+ */
+ return 1;
+}
+
+static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
+{
+ /*
+ * On the Sparc, DMA_ST_WRITE means "move data from device to memory"
+ * so when (write) is true, it actually means READ!
+ */
+ if (write) {
+ dma_init_read(esp, addr, count);
+ } else {
+ dma_init_write(esp, addr, count);
+ }
+}
+
+/*
+ * These aren't used yet
+ */
+static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp)
+{
+ sp->SCp.have_data_in = PHYSADDR(sp->SCp.buffer);
+ sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.have_data_in);
+}
+
+static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp)
+{
+ int sz = sp->SCp.buffers_residual;
+ struct mmu_sglist *sg = (struct mmu_sglist *) sp->SCp.buffer;
+
+ while (sz >= 0) {
+ sg[sz].dvma_addr = PHYSADDR(sg[sz].addr);
+ sz--;
+ }
+ sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dvma_address);
+}
+
+static void dma_advance_sg(Scsi_Cmnd * sp)
+{
+ sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dvma_address);
+}
+
+#ifdef PMAZ_A
+
+static void pmaz_dma_drain(struct NCR_ESP *esp)
+{
+ memcpy((void *) (KSEG0ADDR(esp_virt_buffer)),
+ (void *) scsi_pmaz_dma_ptrs_tc[scsi_cur_buff], scsi_current_length);
+}
+
static void pmaz_dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
{
@@ -413,7+483,7 @@ static void pmaz_dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
static void pmaz_dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length)
{
- memcpy(scsi_pmaz_dma_ptrs_tc[scsi_cur_buff], KSEG0ADDR((void *) vaddress), length);
+ memcpy((void *)scsi_pmaz_dma_ptrs_tc[scsi_cur_buff], KSEG0ADDR((void *) vaddress), length);
*scsi_pmaz_dma_ptr_tc = TC_ESP_DMAR_WRITE | TC_ESP_DMA_ADDR(scsi_pmaz_dma_ptrs_tc[scsi_cur_buff]);
@@ -427,35+497,9 @@ static void pmaz_dma_ints_on(struct NCR_ESP *esp) {
}
-static int dma_irq_p(struct NCR_ESP *esp)
-{
- return (esp->eregs->esp_status & ESP_STAT_INTR);
-}
-
-static int dma_ports_p(struct NCR_ESP *esp)
-{
-/*
- * FIXME: what's this good for?
- */
- return 1;
-}
-
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
-{
- /*
- * On the Sparc, DMA_ST_WRITE means "move data from device to memory"
- * so when (write) is true, it actually means READ!
- */
- if (write) {
- dma_init_read(esp, addr, count);
- } else {
- dma_init_write(esp, addr, count);
- }
-}
-
static void pmaz_dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
{
- /*
+ /*
* On the Sparc, DMA_ST_WRITE means "move data from device to memory"
* so when (write) is true, it actually means READ!
*/
@@ -474,35+518,10 @@ static void pmaz_dma_mmu_release_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp) scsi_pmaz_dma_buff_used[x] = 0;
}
-
static void pmaz_dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp)
{
sp->SCp.have_data_in = (int) sp->SCp.ptr =
(char *) KSEG0ADDR((sp->request_buffer));
}
-/*
- * These aren't used yet
- */
-static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp)
-{
- sp->SCp.have_data_in = PHYSADDR(sp->SCp.buffer);
- sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.have_data_in);
-}
-
-static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp)
-{
- int sz = sp->SCp.buffers_residual;
- struct mmu_sglist *sg = (struct mmu_sglist *) sp->SCp.buffer;
-
- while (sz >= 0) {
- sg[sz].dvma_addr = PHYSADDR(sg[sz].addr);
- sz--;
- }
- sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dvma_address);
-}
-
-static void dma_advance_sg(Scsi_Cmnd * sp)
-{
- sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dvma_address);
-}
+#endif
\ No newline at end of file
@@ -136,7+136,6 @@ const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] = */
extern void scsi_times_out(Scsi_Cmnd * SCpnt);
void scsi_build_commandblocks(Scsi_Device * SDpnt);
-static int scsi_unregister_device(struct Scsi_Device_Template *tpnt);
/*
* These are the interface to the old error handling code. It should go away
@@ -2293,6+2292,8 @@ static void scsi_unregister_host(Scsi_Host_Template * tpnt) MOD_DEC_USE_COUNT;
}
+static int scsi_unregister_device(struct Scsi_Device_Template *tpnt);
+
/*
* This entry point should be called by a loadable module if it is trying
* add a high level scsi driver to the system.
@@ -5,6+5,9 @@ mainmenu_option next_comment comment 'SGI devices'
bool 'SGI Zilog85C30 serial support' CONFIG_SGI_SERIAL
+if [ "$CONFIG_SGI_SERIAL" = "y" ]; then
+ bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE
+fi
bool 'SGI DS1286 RTC support' CONFIG_SGI_DS1286
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-/* $Id: ds1286.c,v 1.7 2000/02/23 00:41:21 ralf Exp $
+/* $Id: ds1286.c,v 1.6 1999/10/09 00:01:31 ralf Exp $
*
* Real Time Clock interface for Linux
*
-/* $Id: graphics.c,v 1.23 2000/02/23 00:41:21 ralf Exp $
+/* $Id: graphics.c,v 1.22 2000/02/18 00:24:43 ralf Exp $
*
* gfx.c: support for SGI's /dev/graphics, /dev/opengl
*
-/* $Id: sgicons.c,v 1.11 1999/01/04 16:07:19 ralf Exp $
+/* $Id: sgicons.c,v 1.10 1998/08/25 09:18:58 ralf Exp $
*
* sgicons.c: Setting up and registering console I/O on the SGI.
*
@@ -665,19+665,6 @@ static void do_serial_hangup(void *private_) }
-/*
- * This subroutine is called when the RS_TIMER goes off. It is used
- * by the serial driver to handle ports that do not have an interrupt
- * (irq=0). This doesn't work at all for 16450's, as a sun has a Z8530.
- */
-
-static void rs_timer(void)
-{
- printk("rs_timer called\n");
- prom_halt();
- return;
-}
-
static int startup(struct sgi_serial * info)
{
volatile unsigned char junk;
@@ -2237,7+2224,8 @@ static struct console sgi_console_driver = { /*
* Register console.
*/
-void __init serial_console_init(void)
+void __init sgi_serial_console_init(void)
{
register_console(&sgi_console_driver);
}
+__initcall(rs_init);
-/* $Id: shmiq.c,v 1.20 2000/02/24 00:13:10 ralf Exp $
+/* $Id: shmiq.c,v 1.19 2000/02/23 00:41:21 ralf Exp $
*
* shmiq.c: shared memory input queue driver
* written 1997 Miguel de Icaza (miguel@nuclecu.unam.mx)
#include <linux/devfs_fs_kernel.h>
#include <asm/shmiq.h>
+#include <asm/gfx.h>
#include <asm/mman.h>
#include <asm/uaccess.h>
#include <asm/poll.h>
@@ -236,8+237,8 @@ shmiq_ioctl (struct inode *inode, struct file *f, unsigned int cmd, unsigned lon }
return -EINVAL;
+
bad_file:
- unlock_kernel ();
return -EBADF;
}
@@ -250,51+251,62 @@ qcntl_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned struct vm_area_struct *vma;
int v;
- switch (cmd){
+ switch (cmd) {
/*
* The address space is already mapped as a /dev/zero
* mapping. FIXME: check that /dev/zero is what the user
* had mapped before :-)
*/
- case QIOCATTACH: {
- unsigned long vaddr;
- int s;
-
- v = verify_area (VERIFY_READ, (void *) arg, sizeof (struct shmiqreq));
- if (v)
- return v;
- if (copy_from_user (&req, (void *) arg, sizeof (req)))
- return -EFAULT;
- /* Do not allow to attach to another region if it has been already attached */
- if (shmiqs [minor].mapped){
- printk ("SHMIQ:The thingie is already mapped\n");
- return -EINVAL;
- }
-
- vaddr = (unsigned long) req.user_vaddr;
- vma = find_vma (current->mm, vaddr);
- if (!vma){
- printk ("SHMIQ: could not find %lx the vma\n", vaddr);
- return -EINVAL;
+ case QIOCATTACH: {
+ unsigned long vaddr;
+ int s;
+
+ v = verify_area (VERIFY_READ, (void *) arg,
+ sizeof (struct shmiqreq));
+ if (v)
+ return v;
+ if (copy_from_user(&req, (void *) arg, sizeof (req)))
+ return -EFAULT;
+ /*
+ * Do not allow to attach to another region if it has
+ * already been attached
+ */
+ if (shmiqs [minor].mapped) {
+ printk("SHMIQ:The thingie is already mapped\n");
+ return -EINVAL;
+ }
+
+ vaddr = (unsigned long) req.user_vaddr;
+ vma = find_vma (current->mm, vaddr);
+ if (!vma) {
+ printk ("SHMIQ: could not find %lx the vma\n",
+ vaddr);
+ return -EINVAL;
+ }
+ s = req.arg * sizeof (struct shmqevent) +
+ sizeof (struct sharedMemoryInputQueue);
+ v = sys_munmap (vaddr, s);
+ down(¤t->mm->mmap_sem);
+ do_munmap(current->mm, vaddr, s);
+ do_mmap(filp, vaddr, s, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE|MAP_FIXED, 0);
+ up(¤t->mm->mmap_sem);
+ shmiqs[minor].events = req.arg;
+ shmiqs[minor].mapped = 1;
+
+ return 0;
}
- s = req.arg * sizeof (struct shmqevent) + sizeof (struct sharedMemoryInputQueue);
- down(¤t->mm->mmap_sem);
- do_munmap (current->mm, vaddr, s);
- do_mmap (filp, vaddr, s, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 0);
- up(¤t->mm->mmap_sem);
- shmiqs [minor].events = req.arg;
- shmiqs [minor].mapped = 1;
- return 0;
- }
}
+
return -EINVAL;
}
-unsigned long
-shmiq_nopage (struct vm_area_struct *vma, unsigned long address, int write_access)
+struct page *
+shmiq_nopage (struct vm_area_struct *vma, unsigned long address,
+ int write_access)
{
/* Do not allow for mremap to expand us */
- return 0;
+ return NULL;
}
static struct vm_operations_struct qcntl_mmap = {
@@ -336,14+348,12 @@ shmiq_qcntl_mmap (struct file *file, struct vm_area_struct *vma)
return error;
}
-
+
static int
shmiq_qcntl_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
int minor = MINOR (inode->i_rdev);
- lock_kernel ();
-
if (minor-- == 0)
return shmiq_ioctl (inode, filp, cmd, arg);
@@ -387,6+397,7 @@ shmiq_qcntl_open (struct inode *inode, struct file *filp) shmiqs [minor].opened = 1;
shmiqs [minor].shmiq_vaddr = 0;
unlock_kernel ();
+
return 0;
}
@@ -427,6+438,7 @@ shmiq_qcntl_close (struct inode *inode, struct file *filp) vfree (shmiqs [minor].shmiq_vaddr);
shmiqs [minor].shmiq_vaddr = 0;
unlock_kernel ();
+
return 0;
}
-/* $Id: streamable.c,v 1.11 2000/02/23 00:41:21 ralf Exp $
+/* $Id: streamable.c,v 1.10 2000/02/05 06:47:30 ralf Exp $
*
* streamable.c: streamable devices. /dev/gfx
* (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -52,14+52,14 @@ get_sioc (struct strioctl *sioc, unsigned long arg) static int
sgi_gfx_open (struct inode *inode, struct file *file)
{
- printk ("GFX: Opened by %ld\n", current->pid);
+ printk ("GFX: Opened by %d\n", current->pid);
return 0;
}
static int
sgi_gfx_close (struct inode *inode, struct file *file)
{
- printk ("GFX: Closed by %ld\n", current->pid);
+ printk ("GFX: Closed by %d\n", current->pid);
return 0;
}
@@ -67,7+67,7 @@ sgi_usemaclone_ioctl(struct inode *inode, struct file *file, unsigned int cmd, struct irix_usema *usema = file->private_data;
int retval;
- printk("[%s:%ld] wants ioctl 0x%xd (arg 0x%lx)",
+ printk("[%s:%d] wants ioctl 0x%xd (arg 0x%lx)",
current->comm, current->pid, cmd, arg);
switch(cmd) {
@@ -79,7+79,7 @@ sgi_usemaclone_ioctl(struct inode *inode, struct file *file, unsigned int cmd, usattach_t *attach = (usattach_t *)arg;
retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
if (retval) {
- printk("[%s:%ld] sgi_usema_ioctl(UIOCATTACHSEMA): "
+ printk("[%s:%d] sgi_usema_ioctl(UIOCATTACHSEMA): "
"verify_area failure",
current->comm, current->pid);
return retval;
@@ -87,7+87,7 @@ sgi_usemaclone_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if (usema == 0)
return -EINVAL;
- printk("UIOCATTACHSEMA: attaching usema %p to process %ld\n",
+ printk("UIOCATTACHSEMA: attaching usema %p to process %d\n",
usema, current->pid);
/* XXX what is attach->us_handle for? */
return sgi_usema_attach(attach, usema);
@@ -101,12+101,12 @@ sgi_usemaclone_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
if (retval) {
- printk("[%s:%ld] sgi_usema_ioctl(UIOC*BLOCK): "
+ printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): "
"verify_area failure",
current->comm, current->pid);
return retval;
}
- printk("UIOC*BLOCK: putting process %ld to sleep on usema %p",
+ printk("UIOC*BLOCK: putting process %d to sleep on usema %p",
current->pid, usema);
if (cmd == UIOCNOIBLOCK)
interruptible_sleep_on(&usema->proc_list);
@@ -121,13+121,13 @@ sgi_usemaclone_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
if (retval) {
- printk("[%s:%ld] sgi_usema_ioctl(UIOC*BLOCK): "
+ printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): "
"verify_area failure",
current->comm, current->pid);
return retval;
}
- printk("[%s:%ld] releasing usema %p",
+ printk("[%s:%d] releasing usema %p",
current->comm, current->pid, usema);
wake_up(&usema->proc_list);
return 0;
@@ -141,7+141,7 @@ sgi_usemaclone_poll(struct file *filp, poll_table *wait) {
struct irix_usema *usema = filp->private_data;
- printk("[%s:%ld] wants to poll usema %p",
+ printk("[%s:%d] wants to poll usema %p",
current->comm, current->pid, usema);
return 0;
@@ -1572,7+1572,6 @@ static void __init probe_sccs(void) {
struct dec_serial **pp;
int i, n, n_chips = 0, n_channels, chip, channel;
- unsigned long flags;
/*
* did we get here by accident?
@@ -1833,7+1832,6 @@ static void serial_console_write(struct console *co, const char *s, {
struct dec_serial *info;
int i;
- unsigned char nine;
info = zs_soft + co->index;
#undef DEBUG
#ifdef DEBUG
-#define DBG(x) printk(KERN_DEBUG "aty128fb: %s\n",(x));
+#define DBG(fmt, args...) printk(KERN_DEBUG "aty128fb: %s " fmt, __FUNCTION__, ##args);
#else
-#define DBG(x)
+#define DBG(fmt, args...)
#endif
#ifndef CONFIG_PPC
@@ -104,10+104,20 @@ static struct fb_var_screeninfo default_var = {
#ifndef MODULE
/* default modedb mode */
+/* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
static struct fb_videomode defaultmode __initdata = {
- /* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
- NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2,
- 0, FB_VMODE_NONINTERLACED
+ refresh: 60,
+ xres: 640,
+ yres: 480,
+ pixclock: 39722,
+ left_margin: 48,
+ right_margin: 16,
+ upper_margin: 33,
+ lower_margin: 10,
+ hsync_len: 96,
+ vsync_len: 2,
+ sync: 0,
+ vmode: FB_VMODE_NONINTERLACED
};
#endif /* MODULE */
@@ -141,32+151,30 @@ static const struct aty128_chip_info aty128_pci_probe_list[] __initdata =
/* packed BIOS settings */
#ifndef CONFIG_PPC
-#pragma pack(1)
typedef struct {
- u8 clock_chip_type;
- u8 struct_size;
- u8 accelerator_entry;
- u8 VGA_entry;
- u16 VGA_table_offset;
- u16 POST_table_offset;
- u16 XCLK;
- u16 MCLK;
- u8 num_PLL_blocks;
- u8 size_PLL_blocks;
- u16 PCLK_ref_freq;
- u16 PCLK_ref_divider;
- u32 PCLK_min_freq;
- u32 PCLK_max_freq;
- u16 MCLK_ref_freq;
- u16 MCLK_ref_divider;
- u32 MCLK_min_freq;
- u32 MCLK_max_freq;
- u16 XCLK_ref_freq;
- u16 XCLK_ref_divider;
- u32 XCLK_min_freq;
- u32 XCLK_max_freq;
-} PLL_BLOCK;
-#pragma pack()
+ u8 clock_chip_type;
+ u8 struct_size;
+ u8 accelerator_entry;
+ u8 VGA_entry;
+ u16 VGA_table_offset;
+ u16 POST_table_offset;
+ u16 XCLK;
+ u16 MCLK;
+ u8 num_PLL_blocks;
+ u8 size_PLL_blocks;
+ u16 PCLK_ref_freq;
+ u16 PCLK_ref_divider;
+ u32 PCLK_min_freq;
+ u32 PCLK_max_freq;
+ u16 MCLK_ref_freq;
+ u16 MCLK_ref_divider;
+ u32 MCLK_min_freq;
+ u32 MCLK_max_freq;
+ u16 XCLK_ref_freq;
+ u16 XCLK_ref_divider;
+ u32 XCLK_min_freq;
+ u32 XCLK_max_freq;
+} __attribute__ ((packed)) PLL_BLOCK;
#endif /* !CONFIG_PPC */
/* onboard memory information */
@@ -194,12+202,9 @@ static const struct aty128_meminfo sdr_sgram = static const struct aty128_meminfo ddr_sgram =
{ 4, 4, 3, 3, 2, 3, 1, 16, 31, 16, "64-bit DDR SGRAM" };
-static int currcon = 0;
-
-static char *aty128fb_name = "ATY Rage128";
+static const char *aty128fb_name = "ATY Rage128";
static char fontname[40] __initdata = { 0 };
-static char noaccel __initdata = 0;
-static unsigned int initdepth __initdata = 8;
+static int noaccel __initdata = 0;
#ifndef MODULE
static const char *mode_option __initdata = NULL;
@@ -291,13+296,14 @@ struct fb_info_aty128 { u32 cfb32[16];
#endif
} fbcon_cmap;
- int blitter_may_be_busy;
#ifdef CONFIG_PCI
struct pci_dev *pdev;
#endif
#ifdef CONFIG_MTRR
struct { int vram; int vram_valid; } mtrr;
#endif
+ int currcon;
+ int blitter_may_be_busy;
int fifo_slots; /* free slots in FIFO (64 max) */
};
@@ -515,10+521,8 @@ aty_pll_wait_readupdate(const struct fb_info_aty128 *info) break;
}
-#ifdef DEBUG
if (reset) /* reset engine?? */
- DBG("PLL write timeout!");
-#endif
+ printk(KERN_DEBUG "aty128fb: PLL write timeout!");
}
@@ -645,9+649,7 @@ aty128_reset_engine(const struct fb_info_aty128 *info) /* use old pio mode */
aty_st_le32(PM4_BUFFER_CNTL, PM4_BUFFER_CNTL_NONPM4);
-#ifdef DEBUG
DBG("engine reset");
-#endif
}
@@ -1075,12+1077,10 @@ aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll, pll->feedback_divider = round_div(n, d);
pll->vclk = vclk;
-#ifdef DEBUG
- printk(KERN_DEBUG "var_to_pll: post %d feedback %d vlck %d output %d ref_divider %d\n",
- pll->post_divider, pll->feedback_divider, vclk, output_freq,
- c.ref_divider);
- printk(KERN_DEBUG "var_to_pll: vclk_per: %d\n", period_in_ps);
-#endif
+ DBG("post %d feedback %d vlck %d output %d ref_divider %d "
+ "vclk_per: %d\n", pll->post_divider,
+ pll->feedback_divider, vclk, output_freq,
+ c.ref_divider, period_in_ps);
return 0;
}
@@ -1134,9+1134,8 @@ aty128_ddafifo(struct aty128_ddafifo *dsp, m->Tr2w +
x;
-#ifdef DEBUG
- printk(KERN_DEBUG "aty128fb: x %x\n", x);
-#endif
+ DBG("x %x\n", x);
+
b = 0;
while (x) {
x >>= 1;
@@ -1155,10+1154,9 @@ aty128_ddafifo(struct aty128_ddafifo *dsp, return -EINVAL;
}
-#ifdef DEBUG
- printk(KERN_DEBUG "aty128fb: p: %x rloop: %x x: %x ron: %x roff: %x\n",
- p, m->Rloop, x, ron, roff);
-#endif
+ DBG("p: %x rloop: %x x: %x ron: %x roff: %x\n",
+ p, m->Rloop, x, ron, roff);
+
dsp->dda_config = p << 16 | m->Rloop << 20 | x;
dsp->dda_on_off = ron << 16 | roff;
@@ -1543,7+1541,12 @@ static int aty128fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
- if (con == currcon) /* current console? */
+#if 1
+ fb_copy_cmap(&info->cmap, cmap, kspc ? 0 : 2);
+#else
+ struct fb_info_aty128 fb = (struct fb_info_aty128 *)info;
+
+ if (con == fb->currcon) /* current console? */
return fb_get_cmap(cmap, kspc, aty128_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
@@ -1551,6+1554,7 @@ aty128fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 32;
fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
}
+#endif
return 0;
}
@@ -1564,6+1568,7 @@ aty128fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
{
int err;
+ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info;
struct display *disp;
if (con >= 0)
@@ -1577,7+1582,7 @@ aty128fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, return err;
}
- if (con == currcon) /* current console? */
+ if (con == fb->currcon) /* current console? */
return fb_set_cmap(cmap, kspc, aty128_setcolreg, info);
else
fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
@@ -1632,24+1637,6 @@ aty128fb_setup(char *options) fontname[i] = 0;
} else if (!strncmp(this_opt, "noaccel", 7)) {
noaccel = 1;
- } else if (!strncmp(this_opt, "depth:", 6)) {
- unsigned int depth = simple_strtoul(this_opt+6, NULL, 0);
- switch (depth) {
- case 0 ... 8:
- initdepth = 8;
- break;
- case 9 ... 16:
- initdepth = 16;
- break;
- case 17 ... 24:
- initdepth = 24;
- break;
- case 25 ... 32:
- initdepth = 32;
- break;
- default:
- initdepth = 8;
- }
}
#ifdef CONFIG_MTRR
else if(!strncmp(this_opt, "nomtrr", 6)) {
@@ -1762,7+1749,7 @@ aty128_init(struct fb_info_aty128 *info, const char *name) #endif /* CONFIG_PPC */
{
if (fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0,
- &defaultmode, initdepth) == 0)
+ &defaultmode, 8) == 0)
var = default_var;
}
#endif /* MODULE */
@@ -1859,16+1846,6 @@ aty128_pci_register(struct pci_dev *pdev, u32 fb_addr, reg_addr, io_addr = 0;
int err;
-#if 0
- /* Request resources we're going to use */
- io_addr = pci_resource_start(pdev, 1);
- if (!request_region(io_addr, pci_resource_len(pdev, 1),
- "aty128fb IO")) {
- printk(KERN_ERR "aty128fb: cannot reserve I/O ports\n");
- goto err_out_none;
- }
-#endif
-
fb_addr = pci_resource_start(pdev, 0);
if (!request_mem_region(fb_addr, pci_resource_len(pdev, 0),
"aty128fb FB")) {
@@ -1894,6+1871,8 @@ aty128_pci_register(struct pci_dev *pdev, /* Copy PCI device info into info->pdev */
info->pdev = pdev;
+ info->currcon = -1;
+
/* Virtualize mmio region */
info->regbase_phys = reg_addr;
info->regbase = ioremap(reg_addr, 0x1FFF);
@@ -1966,7+1945,6 @@ err_free_mmio: err_free_fb:
release_mem_region(pci_resource_start(pdev, 1),
pci_resource_len(pdev, 1));
-err_out_none:
return -ENODEV;
}
#endif /* CONFIG_PCI */
@@ -2072,13+2050,12 @@ aty128_get_pllinfo(struct fb_info_aty128 *info) if (bios_seg)
iounmap(bios_seg);
-#ifdef DEBUG
- printk(KERN_DEBUG "get_pllinfo: ppll_max %d ppll_min %d xclk %d "
- "ref_divider %d dotclock %d\n",
- info->constants.ppll_max, info->constants.ppll_min,
- info->constants.xclk, info->constants.ref_divider,
- info->constants.dotclock);
-#endif
+ DBG("ppll_max %d ppll_min %d xclk %d "
+ "ref_divider %d dotclock %d\n",
+ info->constants.ppll_max, info->constants.ppll_min,
+ info->constants.xclk, info->constants.ref_divider,
+ info->constants.dotclock);
+
return;
}
#endif /* !CONFIG_PPC */
@@ -2159,11+2136,12 @@ aty128fbcon_switch(int con, struct fb_info *fb) struct aty128fb_par par;
/* Do we have to save the colormap? */
- if (fb_display[currcon].cmap.len)
- fb_get_cmap(&fb_display[currcon].cmap, 1, aty128_getcolreg, fb);
+ if (fb_display[info->currcon].cmap.len)
+ fb_get_cmap(&fb_display[info->currcon].cmap, 1,
+ aty128_getcolreg, fb);
/* set the current console */
- currcon = con;
+ info->currcon = con;
aty128_decode_var(&fb_display[con].var, &par, info);
aty128_set_par(&par, info);
@@ -2319,7+2297,9 @@ aty128_setcolreg(u_int regno, u_int red, u_int green, u_int blue, static void
do_install_cmap(int con, struct fb_info *info)
{
- if (con != currcon)
+ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info;
+
+ if (con != fb->currcon)
return;
if (fb_display[con].cmap.len)
@@ -85,7+85,7 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, int mode,
unsigned int pos) {
u_int32_t tmp;
- struct matrox_fb_info* minfo = m2info->primary_dev;
+ MINFO_FROM(m2info->primary_dev);
switch (mode) {
case 15:
@@ -250,9+250,9 @@ static void initMatroxDH(struct matroxfb_dh_fb_info* m2info, struct display* p)
static int matroxfb_dh_open(struct fb_info* info, int user) {
#define m2info ((struct matroxfb_dh_fb_info*)info)
- struct matrox_fb_info* minfo = m2info->primary_dev;
+ MINFO_FROM(m2info->primary_dev);
- if (minfo) {
+ if (MINFO) {
if (ACCESS_FBINFO(dead)) {
return -ENXIO;
}
@@ -263,9+263,9 @@ static int matroxfb_dh_open(struct fb_info* info, int user) {
static int matroxfb_dh_release(struct fb_info* info, int user) {
#define m2info ((struct matroxfb_dh_fb_info*)info)
- struct matrox_fb_info* minfo = m2info->primary_dev;
+ MINFO_FROM(m2info->primary_dev);
- if (minfo) {
+ if (MINFO) {
}
return 0;
#undef m2info
@@ -320,7+320,7 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con, int cmap_len;
int mode;
int err;
- struct matrox_fb_info* minfo = m2info->primary_dev;
+ MINFO_FROM(m2info->primary_dev);
if (con < 0)
p = m2info->fbcon.disp;
@@ -477,7+477,7 @@ static int matroxfb_dh_pan_display(struct fb_var_screeninfo* var, int con, static int matroxfb_dh_switch(int con, struct fb_info* info);
static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, struct fb_vblank* vblank) {
- struct matrox_fb_info* minfo = m2info->primary_dev;
+ MINFO_FROM(m2info->primary_dev);
memset(vblank, 0, sizeof(*vblank));
vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VBLANK;
@@ -496,7+496,7 @@ static int matroxfb_dh_ioctl(struct inode* inode, int con,
struct fb_info* info) {
#define m2info ((struct matroxfb_dh_fb_info*)info)
- struct matrox_fb_info* minfo = m2info->primary_dev;
+ MINFO_FROM(m2info->primary_dev);
DBG("matroxfb_crtc2_ioctl")
@@ -516,7+516,7 @@ static int matroxfb_dh_ioctl(struct inode* inode, case MATROXFB_GET_OUTPUT_MODE:
case MATROXFB_GET_ALL_OUTPUTS:
{
- return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(inode, file, cmd, arg, con, &minfo->fbcon);
+ return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(inode, file, cmd, arg, con, &ACCESS_FBINFO(fbcon));
}
case MATROXFB_SET_OUTPUT_CONNECTION:
{
@@ -660,15+660,15 @@ static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) { if (mem < 64*1024)
mem *= 1024;
mem &= ~0x00000FFF; /* PAGE_MASK? */
- if (minfo->video.len_usable + mem <= minfo->video.len)
- m2info->video.offbase = minfo->video.len - mem;
- else if (minfo->video.len < mem) {
+ if (ACCESS_FBINFO(video.len_usable) + mem <= ACCESS_FBINFO(video.len))
+ m2info->video.offbase = ACCESS_FBINFO(video.len) - mem;
+ else if (ACCESS_FBINFO(video.len) < mem) {
kfree(d);
return -ENOMEM;
} else { /* check yres on first head... */
m2info->video.borrowed = mem;
- minfo->video.len_usable -= mem;
- m2info->video.offbase = minfo->video.len_usable;
+ ACCESS_FBINFO(video.len_usable) -= mem;
+ m2info->video.offbase = ACCESS_FBINFO(video.len_usable);
}
m2info->video.base = ACCESS_FBINFO(video.base) + m2info->video.offbase;
m2info->video.len = m2info->video.len_usable = m2info->video.len_maximum = mem;
@@ -698,8+698,8 @@ static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) { matroxfb_dh_set_var(&matroxfb_dh_defined, -1, &m2info->fbcon);
}
down_write(&ACCESS_FBINFO(crtc2.lock));
- oldcrtc2 = minfo->crtc2.info;
- minfo->crtc2.info = &m2info->fbcon;
+ oldcrtc2 = ACCESS_FBINFO(crtc2.info);
+ ACCESS_FBINFO(crtc2.info) = &m2info->fbcon;
up_write(&ACCESS_FBINFO(crtc2.lock));
if (oldcrtc2) {
printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 already present: %p\n",
@@ -731,9+731,9 @@ static void matroxfb_dh_deregisterfb(struct matroxfb_dh_fb_info* m2info) { struct fb_info* crtc2;
down_write(&ACCESS_FBINFO(crtc2.lock));
- crtc2 = minfo->crtc2.info;
+ crtc2 = ACCESS_FBINFO(crtc2.info);
if (crtc2 == &m2info->fbcon)
- minfo->crtc2.info = NULL;
+ ACCESS_FBINFO(crtc2.info) = NULL;
up_write(&ACCESS_FBINFO(crtc2.lock));
if (crtc2 != &m2info->fbcon) {
printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 mismatch at unload: %p != %p\n",
@@ -756,7+756,7 @@ static void* matroxfb_crtc2_probe(struct matrox_fb_info* minfo) { struct matroxfb_dh_fb_info* m2info;
/* hardware is CRTC2 incapable... */
- if (!minfo->devflags.crtc2)
+ if (!ACCESS_FBINFO(devflags.crtc2))
return NULL;
m2info = (struct matroxfb_dh_fb_info*)kmalloc(sizeof(*m2info), GFP_KERNEL);
if (!m2info) {
@@ -764,7+764,7 @@ static void* matroxfb_crtc2_probe(struct matrox_fb_info* minfo) { return NULL;
}
memset(m2info, 0, sizeof(*m2info));
- m2info->primary_dev = minfo;
+ m2info->primary_dev = MINFO;
if (matroxfb_dh_registerfb(m2info)) {
kfree(m2info);
printk(KERN_ERR "matroxfb_crtc2: CRTC2 framebuffer failed to register\n");
@@ -892,9+892,9 @@ static struct matrox_altout maven_altout = {
static int maven_init_client(struct i2c_client* clnt) {
struct i2c_adapter* a = clnt->adapter;
- struct matroxfb_dh_maven_info* m2info = ((struct i2c_bit_adapter*)a)->minfo;
struct maven_data* md = clnt->data;
- struct matrox_fb_info* minfo = m2info->primary_dev;
+ struct matroxfb_dh_maven_info* m2info __attribute__((unused)) = ((struct i2c_bit_adapter*)a)->minfo;
+ MINFO_FROM(m2info->primary_dev);
md->mode = MODE_MONITOR;
md->primary_head = MINFO;
-/* $Id: newport_con.c,v 1.14 1999/06/24 01:10:24 ulfc Exp $
- *
+/*
* newport_con.c: Abscon for newport hardware
*
* (C) 1998 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
@@ -504,7+503,7 @@ static int newport_scroll(struct vc_data *vc, int t, int b, int dir, int lines) x = 0; y = b-lines;
for (count = 0; count < (lines * vc->vc_cols); count++) {
if (scr_readw(d) != vc->vc_video_erase_char) {
- newport_putc (vc, chattr, y, x);
+ newport_putc (vc, vc->vc_video_erase_char, y, x);
scr_writew (vc->vc_video_erase_char, d);
}
d++;
* Created 8 August 1998 by Martin Costabel and Kevin Schoedel
*
* Vmode-switching changes and vmode 15/17 modifications created 29 August
- * 1998 by Barry Nathan <barryn@pobox.com>.
+ * 1998 by Barry K. Nathan <barryn@pobox.com>.
*
* Derived directly from:
*
* Created 8 August 1998 by Martin Costabel and Kevin Schoedel
*
* Vmode-switching changes and vmode 15/17 modifications created 29 August
- * 1998 by Barry Nathan <barryn@pobox.com>.
+ * 1998 by Barry K. Nathan <barryn@pobox.com>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -407,13+407,21 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) goto out;
if (!elf_check_arch(elf_ex.e_machine))
goto out;
-#ifdef __mips__
- /* IRIX binaries handled elsewhere. */
+#if defined(__mips__) && !defined(__mips64)
+ /* IRIX5 binaries handled elsewhere. */
if (elf_ex.e_flags & EF_MIPS_ARCH) {
retval = -ENOEXEC;
goto out;
}
#endif
+#if defined(__mips__) && defined(__mips64)
+ /* Linux/MIPS 32-bit binaries handled elsewhere. */
+ if (sizeof(elf_caddr_t) == 8 &&
+ elf_ex.e_ident[EI_CLASS] == ELFCLASS32) {
+ retval = -ENOEXEC;
+ goto out;
+ }
+#endif
if (!bprm->file->f_op||!bprm->file->f_op->mmap)
goto out;
@@ -557,7+557,7 @@ int shrink_dcache_memory(int priority, unsigned int gfp_mask) {
int count = 0;
if (priority)
- count = dentry_stat.nr_unused >> (priority >> 2);
+ count = dentry_stat.nr_unused / priority;
prune_dcache(count);
/* FIXME: kmem_cache_shrink here should tell us
the number of pages freed, and it should
@@ -854,6+854,7 @@ retry: if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) {
return;
}
+ lock_kernel();
if (!(bh = fat_bread(sb, i_pos >> MSDOS_DPB_BITS))) {
printk("dev = %s, ino = %d\n", kdevname(inode->i_dev), i_pos);
fat_fs_panic(sb, "msdos_write_inode: unable to read i-node block");
@@ -25,13+25,15 @@ if [ "$CONFIG_PARTITION_ADVANCED" = "y" ]; then bool ' Unixware slices support' CONFIG_UNIXWARE_DISKLABEL
fi
bool ' SGI partition support' CONFIG_SGI_PARTITION
+ bool ' Ultrix partition table support' CONFIG_ULTRIX_PARTITION
bool ' Sun partition tables support' CONFIG_SUN_PARTITION
else
if [ "$ARCH" = "alpha" ]; then
define_bool CONFIG_OSF_PARTITION y
fi
if [ "$CONFIG_AMIGA" != "y" -a "$CONFIG_ATARI" != "y" -a \
- "$CONFIG_MAC" != "y" ]; then
+ "$CONFIG_MAC" != "y" -a "$CONFIG_SGI_IP22" != "y" -a \
+ "$CONFIG_SGI_IP27" != "y" ]; then
define_bool CONFIG_MSDOS_PARTITION y
fi
if [ "$CONFIG_AMIGA" = "y" ]; then
if [ "$CONFIG_ATARI" = "y" ]; then
define_bool CONFIG_ATARI_PARTITION y
fi
- if [ "$CONFIG_SGI" = "y" ]; then
+ if [ "$CONFIG_SGI_IP22" = "y" -o "$CONFIG_SGI_IP27" = "y" ]; then
define_bool CONFIG_SGI_PARTITION y
fi
+ if [ "$CONFIG_DECSTATION" = "y" ]; then
+ define_bool CONFIG_ULTRIX_PARTITION y
+ fi
if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
define_bool CONFIG_SUN_PARTITION y
fi
#include "sgi.h"
#include "sun.h"
#include "ibm.h"
+#include "ultrix.h"
extern void device_init(void);
extern void md_run_setup(void);
#include "check.h"
-static int ultrix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
+int ultrix_partition(struct gendisk *hd, kdev_t dev,
+ unsigned long first_sector, int first_part_minor)
{
- int i, minor = current_minor;
+ int i;
struct buffer_head *bh;
struct ultrix_disklabel {
s32 pt_magic; /* magic no. indicating part. info exits */
@@ -44,9+45,9 @@ static int ultrix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_ - sizeof(struct ultrix_disklabel));
if (label->pt_magic == PT_MAGIC && label->pt_valid == PT_VALID) {
- for (i=0; i<8; i++, minor++)
+ for (i=0; i<8; i++, first_part_minor++)
if (label->pt_part[i].pi_nblocks)
- add_gd_partition(hd, minor,
+ add_gd_partition(hd, first_part_minor,
label->pt_part[i].pi_blkoff,
label->pt_part[i].pi_nblocks);
brelse(bh);
@@ -57,4+58,3 @@ static int ultrix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_ return 0;
}
}
-
--- /dev/null
+/*
+ * fs/partitions/ultrix.h
+ */
+
+int ultrix_partition(struct gendisk *hd, kdev_t dev,
+ unsigned long first_sector, int first_part_minor);
+
@@ -259,7+259,7 @@ asmlinkage long sys_readlink(const char * path, char * buf, int bufsiz)
/* ---------- LFS-64 ----------- */
-#if !defined(__alpha__) && !defined(__ia64__)
+#if !defined(__alpha__) && !defined (__ia64__) && !defined(__mips64)
static long cp_new_stat64(struct inode * inode, struct stat64 * statbuf)
{
#define SO_DETACH_FILTER 27
#define SO_PEERNAME 28
+#define SO_TIMESTAMP 29
+#define SCM_TIMESTAMP SO_TIMESTAMP
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 19
#define SO_DETACH_FILTER 27
#define SO_PEERNAME 28
+#define SO_TIMESTAMP 29
+#define SCM_TIMESTAMP SO_TIMESTAMP
/* Nast libc5 fixup - bletch */
#if defined(__KERNEL__)
#define SO_DETACH_FILTER 27
#define SO_PEERNAME 28
+#define SO_TIMESTAMP 29
+#define SCM_TIMESTAMP SO_TIMESTAMP
/* Nasty libc5 fixup - bletch */
#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
* four billion cycles just basically sounds like a good idea,
* regardless of how fast the machine is.
*/
-typedef unsigned long cycles_t;
+typedef unsigned long long cycles_t;
extern cycles_t cacheflush_time;
@@ -38,10+38,10 @@ static inline cycles_t get_cycles (void) #ifndef CONFIG_X86_TSC
return 0;
#else
- unsigned long eax, edx;
+ unsigned long long ret;
- rdtsc(eax,edx);
- return eax;
+ rdtscll(ret);
+ return ret;
#endif
}
#define SO_DETACH_FILTER 27
#define SO_PEERNAME 28
-
-#define SO_PEERNAME 28
+#define SO_TIMESTAMP 29
+#define SCM_TIMESTAMP SO_TIMESTAMP
/* Nast libc5 fixup - bletch */
#if defined(__KERNEL__)
#define SO_DETACH_FILTER 27
#define SO_PEERNAME 28
+#define SO_TIMESTAMP 29
+#define SCM_TIMESTAMP SO_TIMESTAMP
/* Nast libc5 fixup - bletch */
#if defined(__KERNEL__)
@@ -36,11+36,12 @@ __delay(unsigned long loops) */
extern __inline__ void __udelay(unsigned long usecs, unsigned long lps)
{
+ unsigned long lo;
+
usecs *= 0x000010c6; /* 2**32 / 1000000 */
- __asm__("multu\t%0,%2\n\t"
- "mfhi\t%0"
- :"=r" (usecs)
- :"0" (usecs),"r" (lps));
+ __asm__("multu\t%2,%3"
+ :"=h" (usecs), "=l" (lo)
+ :"r" (usecs),"r" (lps));
__delay(usecs);
}
-/* $Id: floppy.h,v 1.6 1999/01/04 16:09:21 ralf Exp $
- *
+/*
* Architecture specific parts of the Floppy driver
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1995, 1996, 1997, 1998 Ralf Baechle
+ * Copyright (C) 1995 - 2000 Ralf Baechle
*/
#ifndef _ASM_FLOPPY_H
#define _ASM_FLOPPY_H
@@ -41,30+40,30 @@ struct fd_ops {
extern struct fd_ops *fd_ops;
-#define fd_inb(port) fd_ops->fd_inb(port)
-#define fd_outb(value,port) fd_ops->fd_outb(value,port)
-
-#define fd_enable_dma(channel) fd_ops->fd_enable_dma(channel)
-#define fd_disable_dma(channel) fd_ops->fd_disable_dma(channel)
-#define fd_request_dma(channel) fd_ops->fd_request_dma(channel)
-#define fd_free_dma(channel) fd_ops->fd_free_dma(channel)
-#define fd_clear_dma_ff(channel) fd_ops->fd_clear_dma_ff(channel)
-#define fd_set_dma_mode(channel, mode) fd_ops->fd_set_dma_mode(channel, mode)
-#define fd_set_dma_addr(channel, addr) fd_ops->fd_set_dma_addr(channel, \
- virt_to_bus(addr))
-#define fd_set_dma_count(channel,count) fd_ops->fd_set_dma_count(channel,count)
-#define fd_get_dma_residue(channel) fd_ops->fd_get_dma_residue(channel)
-
-#define fd_enable_irq(irq) fd_ops->fd_enable_irq(irq)
-#define fd_disable_irq(irq) fd_ops->fd_disable_irq(irq)
-#define fd_request_irq(irq) request_irq(irq, floppy_interrupt, \
- SA_INTERRUPT \
- | SA_SAMPLE_RANDOM, \
- "floppy", NULL)
-#define fd_free_irq(irq) free_irq(irq, NULL);
-#define fd_dma_mem_alloc(size) fd_ops->fd_dma_mem_alloc(size)
+#define fd_inb(port) fd_ops->fd_inb(port)
+#define fd_outb(value,port) fd_ops->fd_outb(value,port)
+
+#define fd_enable_dma() fd_ops->fd_enable_dma(FLOPPY_DMA)
+#define fd_disable_dma() fd_ops->fd_disable_dma(FLOPPY_DMA)
+#define fd_request_dma() fd_ops->fd_request_dma(FLOPPY_DMA)
+#define fd_free_dma() fd_ops->fd_free_dma(FLOPPY_DMA)
+#define fd_clear_dma_ff() fd_ops->fd_clear_dma_ff(FLOPPY_DMA)
+#define fd_set_dma_mode(mode) fd_ops->fd_set_dma_mode(FLOPPY_DMA, mode)
+#define fd_set_dma_addr(addr) fd_ops->fd_set_dma_addr(FLOPPY_DMA, \
+ virt_to_bus(addr))
+#define fd_set_dma_count(count) fd_ops->fd_set_dma_count(FLOPPY_DMA,count)
+#define fd_get_dma_residue() fd_ops->fd_get_dma_residue(FLOPPY_DMA)
+
+#define fd_enable_irq() fd_ops->fd_enable_irq(FLOPPY_IRQ)
+#define fd_disable_irq() fd_ops->fd_disable_irq(FLOPPY_IRQ)
+#define fd_request_irq() request_irq(FLOPPY_IRQ, floppy_interrupt, \
+ SA_INTERRUPT | SA_SAMPLE_RANDOM, \
+ "floppy", NULL)
+#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL);
+#define fd_dma_mem_alloc(size) fd_ops->fd_dma_mem_alloc(size)
#define fd_dma_mem_free(mem,size) fd_ops->fd_dma_mem_free(mem,size)
-#define fd_drive_type(n) fd_ops->fd_drive_type(n)
+#define fd_drive_type(n) fd_ops->fd_drive_type(n)
+#define fd_cacheflush(addr,size) dma_cache_wback_inv(addr,size)
#define MAX_BUFFER_SECTORS 24
@@ -79,7+78,14 @@ extern struct fd_ops *fd_ops; #define FLOPPY1_TYPE fd_drive_type(1)
#define FDC1 fd_ops->fd_getfdaddr1();
-static int FDC2=-1;
+
+/*
+ * Hack: The floppy drivrer defines this, before including fdreg.h. We use
+ * to define FDC2 only one and keep it a static variable in floppy.c.
+ */
+#ifdef FDPATCHES
+static int FDC2 = -1;
+#endif
#define N_FDC 1 /* do you *really* want a second controller? */
#define N_DRIVE 8
@@ -20,9+20,17 @@ extern pte_t *kmap_pte; extern pgprot_t kmap_prot;
#define kmap_init() do { } while(0)
-#define kmap(page) page_address(page)
+
+static __inline__ unsigned long kmap(struct page * page) {
+ return page_address(page);
+}
+
#define kunmap(page) do { } while(0)
-#define kmap_atomic(page, type) page_address(page)
+
+static __inline__ unsigned long kmap_atomic(struct page *page, int type) {
+ return page_address(page)
+}
+
#define kunmap_atomic(page, type) do { } while(0)
#endif /* _ASM_HIGHMEM_H */
-/* $Id: ide.h,v 1.6 1999/10/09 00:01:42 ralf Exp $
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
*
- * linux/include/asm-mips/ide.h
+ * This file contains the MIPS architecture specific IDE code.
*
- * Copyright (C) 1994-1996 Linus Torvalds & authors
+ * Copyright (C) 1994-1996 Linus Torvalds & authors
*/
/*
* This file contains the MIPS architecture specific IDE code.
*/
-#ifndef __ASM_MIPS_IDE_H
-#define __ASM_MIPS_IDE_H
+#ifndef __ASM_IDE_H
+#define __ASM_IDE_H
#ifdef __KERNEL__
@@ -53,27+56,34 @@ static __inline__ ide_ioreg_t ide_default_io_base(int index) return ide_ops->ide_default_io_base(index);
}
-static __inline__ void ide_init_hwif_ports(hw_regs_t *hw,
- ide_ioreg_t data_port,
- ide_ioreg_t ctrl_port, int *irq)
+static inline void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port,
+ ide_ioreg_t ctrl_port, int *irq)
{
- ide_ops->ide_init_hwif_ports(hw, data_port, ctrl_port, &hw->irq);
+ ide_ioreg_t reg = data_port;
+ int i;
- hw->irq = ide_ops->ide_default_irq(data_port);
+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+ hw->io_ports[i] = reg;
+ reg += 1;
+ }
+ if (ctrl_port) {
+ hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+ } else {
+ hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+ }
+ if (irq != NULL)
+ *irq = 0;
+ hw->io_ports[IDE_IRQ_OFFSET] = 0;
}
-/*
- * This registers the standard ports for this architecture with the IDE
- * driver.
- */
static __inline__ void ide_init_default_hwifs(void)
{
#ifndef CONFIG_BLK_DEV_IDEPCI
hw_regs_t hw;
int index;
- for (index = 0; index < MAX_HWIFS; index++) {
- ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, 0);
+ for(index = 0; index < MAX_HWIFS; index++) {
+ ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
hw.irq = ide_default_irq(ide_default_io_base(index));
ide_register_hw(&hw, NULL);
}
@@ -129,4+139,4 @@ static __inline__ void ide_release_region(ide_ioreg_t from,
#endif /* __KERNEL__ */
-#endif /* __ASM_MIPS_IDE_H */
+#endif /* __ASM_IDE_H */
@@ -25,6+25,7 @@ extern char pckbd_unexpected_up(unsigned char keycode); extern void pckbd_leds(unsigned char leds);
extern void pckbd_init_hw(void);
extern unsigned char pckbd_sysrq_xlate[128];
+extern void kbd_forward_char (int ch);
#define kbd_setkeycode pckbd_setkeycode
#define kbd_getkeycode pckbd_getkeycode
@@ -234,6+234,8 @@ __BUILD_SET_CP0(config,CP0_CONFIG) #define ST0_UX 0x00000020
#define ST0_SX 0x00000040
#define ST0_KX 0x00000080
+#define ST0_DE 0x00010000
+#define ST0_CE 0x00020000
/*
* Bitfields in the R[23]000 cp0 status register.
@@ -245,6+247,8 @@ __BUILD_SET_CP0(config,CP0_CONFIG) #define ST0_IEO 0x00000010
#define ST0_KUO 0x00000020
/* bits 6 & 7 are reserved on R[23]000 */
+#define ST0_ISC 0x00010000
+#define ST0_SWC 0x00020000
/*
* Bits specific to the R4640/R4650
@@ -273,8+277,6 @@ __BUILD_SET_CP0(config,CP0_CONFIG) #define STATUSF_IP6 (1 << 14)
#define STATUSB_IP7 15
#define STATUSF_IP7 (1 << 15)
-#define ST0_DE 0x00010000
-#define ST0_CE 0x00020000
#define ST0_CH 0x00040000
#define ST0_SR 0x00100000
#define ST0_BEV 0x00400000
+++ /dev/null
-/* DO NOT TOUCH, AUTOGENERATED BY OFFSET.C */
-
-#ifndef _MIPS_OFFSET_H
-#define _MIPS_OFFSET_H
-
-/* MIPS pt_regs offsets. */
-#define PT_R0 24
-#define PT_R1 28
-#define PT_R2 32
-#define PT_R3 36
-#define PT_R4 40
-#define PT_R5 44
-#define PT_R6 48
-#define PT_R7 52
-#define PT_R8 56
-#define PT_R9 60
-#define PT_R10 64
-#define PT_R11 68
-#define PT_R12 72
-#define PT_R13 76
-#define PT_R14 80
-#define PT_R15 84
-#define PT_R16 88
-#define PT_R17 92
-#define PT_R18 96
-#define PT_R19 100
-#define PT_R20 104
-#define PT_R21 108
-#define PT_R22 112
-#define PT_R23 116
-#define PT_R24 120
-#define PT_R25 124
-#define PT_R26 128
-#define PT_R27 132
-#define PT_R28 136
-#define PT_R29 140
-#define PT_R30 144
-#define PT_R31 148
-#define PT_LO 152
-#define PT_HI 156
-#define PT_EPC 160
-#define PT_BVADDR 164
-#define PT_STATUS 168
-#define PT_CAUSE 172
-#define PT_SIZE 176
-
-/* MIPS task_struct offsets. */
-#define TASK_STATE 0
-#define TASK_FLAGS 4
-#define TASK_SIGPENDING 8
-#define TASK_NEED_RESCHED 20
-#define TASK_COUNTER 32
-#define TASK_PRIORITY 36
-#define TASK_MM 44
-#define TASK_STRUCT_SIZE 880
-
-/* MIPS specific thread_struct offsets. */
-#define THREAD_REG16 584
-#define THREAD_REG17 588
-#define THREAD_REG18 592
-#define THREAD_REG19 596
-#define THREAD_REG20 600
-#define THREAD_REG21 604
-#define THREAD_REG22 608
-#define THREAD_REG23 612
-#define THREAD_REG29 616
-#define THREAD_REG30 620
-#define THREAD_REG31 624
-#define THREAD_STATUS 628
-#define THREAD_FPU 632
-#define THREAD_BVADDR 768
-#define THREAD_BUADDR 772
-#define THREAD_ECODE 776
-#define THREAD_TRAPNO 780
-#define THREAD_MFLAGS 784
-#define THREAD_CURDS 788
-#define THREAD_TRAMP 792
-#define THREAD_OLDCTX 796
-
-/* Linux mm_struct offsets. */
-#define MM_USERS 16
-#define MM_PGD 12
-#define MM_CONTEXT 68
-
-/* Linux sigcontext offsets. */
-#define SC_REGS 16
-#define SC_FPREGS 272
-#define SC_MDHI 544
-#define SC_MDLO 552
-#define SC_PC 8
-#define SC_STATUS 4
-#define SC_OWNEDFP 528
-#define SC_FPC_CSR 532
-#define SC_FPC_EIR 536
-#define SC_CAUSE 560
-#define SC_BADVADDR 564
-
-#endif /* !(_MIPS_OFFSET_H) */
*/
# define QUOTIENT ((1UL << (32 - LOG_2_HZ)) * 100)
# define HZ_TO_STD(a) \
- ({ int __res; \
- __asm__( \
- "multu\t%0,%2\n\t" \
- "mfhi\t%0" \
- : "=r" (__res): "0" (a), "r" (QUOTIENT)); \
- __res;})
+ ({ unsigned int __res; \
+ unsigned long lo; \
+ __asm__("multu\t%2,%3\n\t" \
+ :"=h" (__res), "=l" (lo) \
+ :"r" (a),"r" (QUOTIENT)); \
+ (__typeof__(a)) __res;})
#else
# define HZ 100
# define HZ_TO_STD(a) (a)
-/* $Id: pgtable.h,v 1.31 2000/03/02 02:37:13 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
@@ -43,7+42,13 @@ extern void (*_flush_page_to_ram)(struct page * page); #define flush_page_to_ram(page) _flush_page_to_ram(page)
#define flush_icache_range(start, end) flush_cache_all()
-#define flush_icache_page(start,page) do { } while(0)
+
+#define flush_icache_page(vma, page) \
+do { \
+ unsigned long addr; \
+ addr = page_address(page); \
+ _flush_cache_page(vma, addr); \
+} while (0)
/*
* assume GCC is being used.
*/
-typedef unsigned long __kernel_dev_t;
+typedef unsigned int __kernel_dev_t;
typedef unsigned long __kernel_ino_t;
-typedef unsigned long __kernel_mode_t;
-typedef unsigned long __kernel_nlink_t;
+typedef unsigned int __kernel_mode_t;
+typedef int __kernel_nlink_t;
typedef long __kernel_off_t;
-typedef long __kernel_pid_t;
-typedef long __kernel_ipc_pid_t;
-typedef long __kernel_uid_t;
-typedef long __kernel_gid_t;
+typedef int __kernel_pid_t;
+typedef int __kernel_ipc_pid_t;
+typedef int __kernel_uid_t;
+typedef int __kernel_gid_t;
typedef unsigned int __kernel_size_t;
typedef int __kernel_ssize_t;
typedef int __kernel_ptrdiff_t;
@@ -35,8+35,8 @@ typedef char * __kernel_caddr_t;
typedef unsigned short __kernel_uid16_t;
typedef unsigned short __kernel_gid16_t;
-typedef long __kernel_uid32_t;
-typedef long __kernel_gid32_t;
+typedef int __kernel_uid32_t;
+typedef int __kernel_gid32_t;
typedef __kernel_uid_t __kernel_old_uid_t;
typedef __kernel_gid_t __kernel_old_gid_t;
#define FPC_CSR 69
#define FPC_EIR 70
-#ifndef __ASSEMBLY__
+#ifndef _LANGUAGE_ASSEMBLY
/*
* This struct defines the way the registers are stored on the stack during a
* system call/exception. As usual the registers k0/k1 aren't being saved.
@@ -50,13+50,15 @@ struct pt_regs { unsigned long cp0_cause;
};
-#endif /* !(__ASSEMBLY__) */
+#endif /* !(_LANGUAGE_ASSEMBLY) */
+#ifdef _LANGUAGE_ASSEMBLY
#include <asm/offset.h>
+#endif
#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
+#ifndef _LANGUAGE_ASSEMBLY
/*
* Does the process account for user or for system time?
*/
@@ -65,7+67,7 @@ struct pt_regs { #define instruction_pointer(regs) ((regs)->cp0_epc)
extern void show_regs(struct pt_regs *);
-#endif /* !(__ASSEMBLY__) */
+#endif /* !(_LANGUAGE_ASSEMBLY) */
#endif
@@ -133,8+133,6 @@ waking_non_zero_interruptible(struct semaphore *sem, struct task_struct *tsk) {
long ret, tmp;
-#ifdef __MIPSEB__
-
__asm__ __volatile__("
.set push
.set mips3
@@ -159,46+157,6 @@ waking_non_zero_interruptible(struct semaphore *sem, struct task_struct *tsk) : "=&r"(ret), "=&r"(tmp), "=m"(*sem)
: "r"(signal_pending(tsk)), "i"(-EINTR));
-#elif defined(__MIPSEL__)
-
- __asm__ __volatile__("
- .set mips3
- .set push
- .set noat
-0:
- lld %1, %2
- li %0, 0
- blez %1, 1f
- dli $1, 0x0000000100000000
- dsubu %1, %1, $1
- li %0, 1
- b 2f
-1:
- beqz %3, 2f
- li %0, %4
- /*
- * It would be nice to assume that sem->count
- * is != -1, but we will guard against that case
- */
- daddiu $1, %1, 1
- dsll32 $1, $1, 0
- dsrl32 $1, $1, 0
- dsrl32 %1, %1, 0
- dsll32 %1, %1, 0
- or %1, %1, $1
-2:
- scd %1, %2
- beqz %1, 0b
-
- .set pop
- .set mips0"
- : "=&r"(ret), "=&r"(tmp), "=m"(*sem)
- : "r"(signal_pending(tsk)), "i"(-EINTR));
-
-#else
-#error "MIPS but neither __MIPSEL__ nor __MIPSEB__?"
-#endif
-
return ret;
}
--- /dev/null
+#define _FP_W_TYPE_SIZE 32
+#define _FP_W_TYPE unsigned long
+#define _FP_WS_TYPE signed long
+#define _FP_I_TYPE long
+
+#define _FP_MUL_MEAT_S(R,X,Y) \
+ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y) \
+ _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y) \
+ _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1
+#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#define _FP_NANSIGN_S 0
+#define _FP_NANSIGN_D 0
+#define _FP_NANSIGN_Q 0
+
+#define _FP_KEEPNANFRACP 1
+/* From my experiments it seems X is chosen unless one of the
+ NaNs is sNaN, in which case the result is NANSIGN/NANFRAC. */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
+ do { \
+ if ((_FP_FRAC_HIGH_RAW_##fs(X) | \
+ _FP_FRAC_HIGH_RAW_##fs(Y)) & _FP_QNANBIT_##fs) \
+ { \
+ R##_s = _FP_NANSIGN_##fs; \
+ _FP_FRAC_SET_##wc(R,_FP_NANFRAC_##fs); \
+ } \
+ else \
+ { \
+ R##_s = X##_s; \
+ _FP_FRAC_COPY_##wc(R,X); \
+ } \
+ R##_c = FP_CLS_NAN; \
+ } while (0)
+
+#define FP_EX_INVALID (1 << 4)
+#define FP_EX_DIVZERO (1 << 3)
+#define FP_EX_OVERFLOW (1 << 2)
+#define FP_EX_UNDERFLOW (1 << 1)
+#define FP_EX_INEXACT (1 << 0)
#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
typedef struct {
- __u32 sig[_NSIG_WORDS];
+ unsigned long sig[_NSIG_WORDS];
} sigset_t;
typedef unsigned long old_sigset_t; /* at least 32 bits */
-/*
- * $Id: socket.h,v 1.6 2000/02/25 21:52:09 ralf Exp $
- */
#ifndef _ASM_SOCKET_H
#define _ASM_SOCKET_H
@@ -56,9+53,9 @@ To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */ #define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
-#ifdef __KERNEL__
-
#define SO_PEERNAME 28
+#define SO_TIMESTAMP 29
+#define SCM_TIMESTAMP SO_TIMESTAMP
/* Nast libc5 fixup - bletch */
#if defined(__KERNEL__)
-#ifndef __ASM_MIPS_STAT_H
-#define __ASM_MIPS_STAT_H
+#ifndef _ASM_STAT_H
+#define _ASM_STAT_H
#include <linux/types.h>
@@ -52,41+52,35 @@ struct stat { unsigned int st_gen;
};
-/* This matches struct stat64 in glibc2.1, hence the absolutely
- * insane amounts of padding around dev_t's.
- * XXX We don't ship glibc 2.1 for MIPS yet, so this structure may be
- * changed without breaking compatibility. You've been warned.
+/*
+ * This matches struct stat64 in glibc2.1, hence the absolutely insane
+ * amounts of padding around dev_t's. The memory layout is the same as of
+ * struct stat of the 64-bit kernel.
*/
+
struct stat64 {
unsigned long st_dev;
- unsigned char __pad0[8];
-
- unsigned long st_ino;
- unsigned int st_mode;
- unsigned int st_nlink;
-
- unsigned long st_uid;
- unsigned long st_gid;
-
- unsigned short st_rdev;
- unsigned char __pad3[10];
-
+ unsigned long st_pad0[3]; /* Reserved for st_dev expansion */
+ ino_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ unsigned long st_rdev;
+ unsigned long st_pad1[3]; /* Reserved for st_rdev expansion */
long long st_size;
+ /*
+ * Actually this should be timestruc_t st_atime, st_mtime and st_ctime
+ * but we don't have it under Linux.
+ */
+ time_t st_atime;
+ unsigned long reserved0; /* Reserved for st_atime expansion */
+ time_t st_mtime;
+ unsigned long reserved1; /* Reserved for st_atime expansion */
+ time_t st_ctime;
+ unsigned long reserved2; /* Reserved for st_atime expansion */
unsigned long st_blksize;
-
- unsigned long st_blocks; /* Number 512-byte blocks allocated. */
- unsigned long __pad4; /* future possible st_blocks high bits */
-
- unsigned long st_atime;
- unsigned long __pad5;
-
- unsigned long st_mtime;
- unsigned long __pad6;
-
- unsigned long st_ctime;
- unsigned long __pad7; /* will be high 32 bits of ctime someday */
-
- unsigned long __unused1;
- unsigned long __unused2;
+ long long st_blocks;
};
-#endif /* __ASM_MIPS_STAT_H */
+
+#endif /* _ASM_STAT_H */
@@ -267,6+267,7 @@ extern void __die(const char *, struct pt_regs *, const char *where, unsigned long line) __attribute__((noreturn));
extern void __die_if_kernel(const char *, struct pt_regs *, const char *where,
unsigned long line);
+extern int abs(int);
#define die(msg, regs) \
__die(msg, regs, __FILE__ ":"__FUNCTION__, __LINE__)
#ifndef _ASM_TYPES_H
#define _ASM_TYPES_H
-typedef unsigned long umode_t;
+typedef unsigned short umode_t;
/*
* __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
-/* $Id: uaccess.h,v 1.12 2000/02/21 18:05:07 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1996, 1997, 1998, 1999 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#ifndef _ASM_UACCESS_H
#define _ASM_UACCESS_H
@@ -70,16+69,20 @@ extern inline int verify_area(int type, const void * addr, unsigned long size) * (a) re-use the arguments for side effects (sizeof is ok)
* (b) require any knowledge of processes at this stage
*/
-#define put_user(x,ptr) __put_user_check((x),(ptr),sizeof(*(ptr)),__access_mask)
-#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr)),__access_mask)
+#define put_user(x,ptr) \
+ __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+#define get_user(x,ptr) \
+ __get_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
/*
* The "__xxx" versions do not do address space checking, useful when
* doing multiple accesses to the same area (the user has to do the
* checks by hand with "access_ok()")
*/
-#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
-#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+#define __put_user(x,ptr) \
+ __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+#define __get_user(x,ptr) \
+ __get_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
/*
* The "xxx_ret" versions return constant specified in third argument, if
@@ -127,14+130,14 @@ case 8: __GET_USER_DW; break; \ default: __get_user_unknown(); break; \
} x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
-#define __get_user_check(x,ptr,size,mask) ({ \
+#define __get_user_check(x,ptr,size) ({ \
long __gu_err; \
__typeof__(*(ptr)) __gu_val; \
long __gu_addr; \
__asm__("":"=r" (__gu_val)); \
__gu_addr = (long) (ptr); \
__asm__("":"=r" (__gu_err)); \
-if (__access_ok(__gu_addr,size,mask)) { \
+if (__access_ok(__gu_addr,size,__access_mask)) { \
switch (size) { \
case 1: __get_user_asm("lb"); break; \
case 2: __get_user_asm("lh"); break; \
@@ -210,14+213,14 @@ case 8: __PUT_USER_DW; break; \ default: __put_user_unknown(); break; \
} __pu_err; })
-#define __put_user_check(x,ptr,size,mask) ({ \
+#define __put_user_check(x,ptr,size) ({ \
long __pu_err; \
__typeof__(*(ptr)) __pu_val; \
long __pu_addr; \
__pu_val = (x); \
__pu_addr = (long) (ptr); \
__asm__("":"=r" (__pu_err)); \
-if (__access_ok(__pu_addr,size,mask)) { \
+if (__access_ok(__pu_addr,size,__access_mask)) { \
switch (size) { \
case 1: __put_user_asm("sb"); break; \
case 2: __put_user_asm("sh"); break; \
#define PHYS_TO_COMPATK1(x) ((x) | COMPAT_K1BASE32) /* 32-bit compat k1 */
#endif
+#define KDM_TO_PHYS(x) ((unsigned long)(x) & TO_PHYS_MASK)
+#define PHYS_TO_K0(x) ((unsigned long)(x) | K0BASE)
+
#endif /* _ASM_ADDRSPACE_H */
-/* $Id$
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1994 by Waldorf Electronics
- * Copyright (C) 1995 - 1999 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1995 - 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#ifndef _ASM_DELAY_H
#define _ASM_DELAY_H
#include <linux/config.h>
+#include <linux/config.h>
+
extern __inline__ void
__delay(unsigned long loops)
{
@@ -37,11+38,12 @@ __delay(unsigned long loops) */
extern __inline__ void __udelay(unsigned long usecs, unsigned long lps)
{
+ unsigned long lo;
+
usecs *= 0x000010c6f7a0b5edUL; /* 2**64 / 1000000 */
- __asm__("dmultu\t%0,%2\n\t"
- "mfhi\t%0"
- :"=r" (usecs)
- :"0" (usecs),"r" (lps));
+ __asm__("dmultu\t%2,%3"
+ :"=h" (usecs), "=l" (lo)
+ :"r" (usecs),"r" (lps));
__delay(usecs);
}
#ifndef _ASM_DMA_H
#define _ASM_DMA_H
-#include <linux/config.h>
#include <asm/io.h> /* need byte IO */
#include <linux/spinlock.h> /* And spinlocks */
#include <linux/delay.h>
-/* $Id: floppy.h,v 1.6 1999/01/04 16:09:21 ralf Exp $
- *
+/*
* Architecture specific parts of the Floppy driver
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1995, 1996, 1997, 1998 Ralf Baechle
+ * Copyright (C) 1995 - 2000 Ralf Baechle
*/
#ifndef _ASM_FLOPPY_H
#define _ASM_FLOPPY_H
#include <asm/bootinfo.h>
-#include <asm/jazz.h>
-#include <asm/jazzdma.h>
struct fd_ops {
unsigned char (*fd_inb)(unsigned int port);
@@ -41,30+38,30 @@ struct fd_ops {
extern struct fd_ops *fd_ops;
-#define fd_inb(port) fd_ops->fd_inb(port)
-#define fd_outb(value,port) fd_ops->fd_outb(value,port)
-
-#define fd_enable_dma(channel) fd_ops->fd_enable_dma(channel)
-#define fd_disable_dma(channel) fd_ops->fd_disable_dma(channel)
-#define fd_request_dma(channel) fd_ops->fd_request_dma(channel)
-#define fd_free_dma(channel) fd_ops->fd_free_dma(channel)
-#define fd_clear_dma_ff(channel) fd_ops->fd_clear_dma_ff(channel)
-#define fd_set_dma_mode(channel, mode) fd_ops->fd_set_dma_mode(channel, mode)
-#define fd_set_dma_addr(channel, addr) fd_ops->fd_set_dma_addr(channel, \
- virt_to_bus(addr))
-#define fd_set_dma_count(channel,count) fd_ops->fd_set_dma_count(channel,count)
-#define fd_get_dma_residue(channel) fd_ops->fd_get_dma_residue(channel)
-
-#define fd_enable_irq(irq) fd_ops->fd_enable_irq(irq)
-#define fd_disable_irq(irq) fd_ops->fd_disable_irq(irq)
-#define fd_request_irq(irq) request_irq(irq, floppy_interrupt, \
- SA_INTERRUPT \
- | SA_SAMPLE_RANDOM, \
- "floppy", NULL)
-#define fd_free_irq(irq) free_irq(irq, NULL);
-#define fd_dma_mem_alloc(size) fd_ops->fd_dma_mem_alloc(size)
+#define fd_inb(port) fd_ops->fd_inb(port)
+#define fd_outb(value,port) fd_ops->fd_outb(value,port)
+
+#define fd_enable_dma() fd_ops->fd_enable_dma(FLOPPY_DMA)
+#define fd_disable_dma() fd_ops->fd_disable_dma(FLOPPY_DMA)
+#define fd_request_dma() fd_ops->fd_request_dma(FLOPPY_DMA)
+#define fd_free_dma() fd_ops->fd_free_dma(FLOPPY_DMA)
+#define fd_clear_dma_ff() fd_ops->fd_clear_dma_ff(FLOPPY_DMA)
+#define fd_set_dma_mode(mode) fd_ops->fd_set_dma_mode(FLOPPY_DMA, mode)
+#define fd_set_dma_addr(addr) fd_ops->fd_set_dma_addr(FLOPPY_DMA, \
+ virt_to_bus(addr))
+#define fd_set_dma_count(count) fd_ops->fd_set_dma_count(FLOPPY_DMA,count)
+#define fd_get_dma_residue() fd_ops->fd_get_dma_residue(FLOPPY_DMA)
+
+#define fd_enable_irq() fd_ops->fd_enable_irq(FLOPPY_IRQ)
+#define fd_disable_irq() fd_ops->fd_disable_irq(FLOPPY_IRQ)
+#define fd_request_irq() request_irq(FLOPPY_IRQ, floppy_interrupt, \
+ SA_INTERRUPT | SA_SAMPLE_RANDOM, \
+ "floppy", NULL)
+#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL);
+#define fd_dma_mem_alloc(size) fd_ops->fd_dma_mem_alloc(size)
#define fd_dma_mem_free(mem,size) fd_ops->fd_dma_mem_free(mem,size)
-#define fd_drive_type(n) fd_ops->fd_drive_type(n)
+#define fd_drive_type(n) fd_ops->fd_drive_type(n)
+#define fd_cacheflush(addr,size) dma_cache_wback_inv(addr,size)
#define MAX_BUFFER_SECTORS 24
@@ -79,7+76,14 @@ extern struct fd_ops *fd_ops; #define FLOPPY1_TYPE fd_drive_type(1)
#define FDC1 fd_ops->fd_getfdaddr1();
+
+/*
+ * Hack: The floppy drivrer defines this, before including fdreg.h. We use
+ * to define FDC2 only one and keep it a static variable in floppy.c.
+ */
+#ifdef FDPATCHES
static int FDC2=-1;
+#endif
#define N_FDC 1 /* do you *really* want a second controller? */
#define N_DRIVE 8
-/* $Id: ide.h,v 1.6 1999/10/09 00:01:42 ralf Exp $
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
*
- * linux/include/asm-mips/ide.h
+ * This file contains the MIPS architecture specific IDE code.
*
- * Copyright (C) 1994-1996 Linus Torvalds & authors
+ * Copyright (C) 1994-1996 Linus Torvalds & authors
*/
/*
* This file contains the MIPS architecture specific IDE code.
*/
-#ifndef __ASM_MIPS_IDE_H
-#define __ASM_MIPS_IDE_H
+#ifndef __ASM_IDE_H
+#define __ASM_IDE_H
#ifdef __KERNEL__
@@ -53,27+56,34 @@ static __inline__ ide_ioreg_t ide_default_io_base(int index) return ide_ops->ide_default_io_base(index);
}
-static __inline__ void ide_init_hwif_ports(hw_regs_t *hw,
- ide_ioreg_t data_port,
- ide_ioreg_t ctrl_port, int *irq)
+static inline void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port,
+ ide_ioreg_t ctrl_port, int *irq)
{
- ide_ops->ide_init_hwif_ports(hw, data_port, ctrl_port, &hw->irq);
+ ide_ioreg_t reg = data_port;
+ int i;
- hw->irq = ide_ops->ide_default_irq(data_port);
+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+ hw->io_ports[i] = reg;
+ reg += 1;
+ }
+ if (ctrl_port) {
+ hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+ } else {
+ hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+ }
+ if (irq != NULL)
+ *irq = 0;
+ hw->io_ports[IDE_IRQ_OFFSET] = 0;
}
-/*
- * This registers the standard ports for this architecture with the IDE
- * driver.
- */
static __inline__ void ide_init_default_hwifs(void)
{
#ifndef CONFIG_BLK_DEV_IDEPCI
hw_regs_t hw;
int index;
- for (index = 0; index < MAX_HWIFS; index++) {
- ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, 0);
+ for(index = 0; index < MAX_HWIFS; index++) {
+ ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
hw.irq = ide_default_irq(ide_default_io_base(index));
ide_register_hw(&hw, NULL);
}
@@ -129,4+139,4 @@ static __inline__ void ide_release_region(ide_ioreg_t from,
#endif /* __KERNEL__ */
-#endif /* __ASM_MIPS_IDE_H */
+#endif /* __ASM_IDE_H */
*/
#define __OUT1(s) \
-extern inline void __out##s(unsigned int value, unsigned int port) {
+extern inline void __out##s(unsigned int value, unsigned long port) {
#define __OUT2(m) \
__asm__ __volatile__ ("s" #m "\t%0,%1(%2)"
@@ -176,7+176,7 @@ __OUT1(s##c_p) __OUT2(m) : : "r" (value), "ir" (port), "r" (mips_io_port_base)); SLOW_DOWN_IO; }
#define __IN1(t,s) \
-extern __inline__ t __in##s(unsigned int port) { t _v;
+extern __inline__ t __in##s(unsigned long port) { t _v;
/*
* Required nops will be inserted by the assembler
@@ -191,7+191,7 @@ __IN1(t,s##_p) __IN2(m) : "=r" (_v) : "i" (0), "r" (mips_io_port_base+port)); SL __IN1(t,s##c_p) __IN2(m) : "=r" (_v) : "ir" (port), "r" (mips_io_port_base)); SLOW_DOWN_IO; return _v; }
#define __INS1(s) \
-extern inline void __ins##s(unsigned int port, void * addr, unsigned long count) {
+extern inline void __ins##s(unsigned long port, void * addr, unsigned long count) {
#define __INS2(m) \
if (count) \
@@ -217,7+217,7 @@ __INS1(s##c) __INS2(m) \ : "$1");}
#define __OUTS1(s) \
-extern inline void __outs##s(unsigned int port, const void * addr, unsigned long count) {
+extern inline void __outs##s(unsigned long port, const void * addr, unsigned long count) {
#define __OUTS2(m) \
if (count) \
#ifndef _ASM_IRQ_H
#define _ASM_IRQ_H
-#define NR_IRQS 64
+#define NR_IRQS 256
#define TIMER_IRQ 0
@@ -213,6+213,8 @@ __BUILD_SET_CP0(config,CP0_CONFIG) #define ST0_UX 0x00000020
#define ST0_SX 0x00000040
#define ST0_KX 0x00000080
+#define ST0_DE 0x00010000
+#define ST0_CE 0x00020000
/*
* Status register bits available in all MIPS CPUs.
@@ -234,8+236,6 @@ __BUILD_SET_CP0(config,CP0_CONFIG) #define STATUSF_IP6 (1 << 14)
#define STATUSB_IP7 15
#define STATUSF_IP7 (1 << 15)
-#define ST0_DE 0x00010000
-#define ST0_CE 0x00020000
#define ST0_CH 0x00040000
#define ST0_SR 0x00100000
#define ST0_TS 0x00200000
#include <asm/pgalloc.h>
#include <asm/processor.h>
+/*
+ * For the fast tlb miss handlers, we currently keep a per cpu array
+ * of pointers to the current pgd for each processor. Also, the proc.
+ * id is stuffed into the context register. This should be changed to
+ * use the processor id via current->processor, where current is stored
+ * in watchhi/lo. The context register should be used to contiguously
+ * map the page tables.
+ */
+#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
+ pgd_current[smp_processor_id()] = (unsigned long)(pgd)
+#define TLBMISS_HANDLER_SETUP() \
+ set_context((unsigned long) smp_processor_id() << (23 + 3)); \
+ TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
+extern unsigned long pgd_current[];
+
#ifndef CONFIG_SMP
#define CPU_CONTEXT(cpu, mm) (mm)->context
#else
@@ -85,7+100,8 @@ extern inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, if ((CPU_CONTEXT(cpu, next) ^ ASID_CACHE(cpu)) & ASID_VERSION_MASK)
get_new_cpu_mmu_context(next, cpu);
- set_entryhi(CPU_CONTEXT(cpu, next));
+ set_entryhi(CPU_CONTEXT(cpu, next) & 0xff);
+ TLBMISS_HANDLER_SETUP_PGD(next->pgd);
}
/*
@@ -110,7+126,8 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next) /* Unconditionally get a new ASID. */
get_new_cpu_mmu_context(next, smp_processor_id());
- set_entryhi(CPU_CONTEXT(smp_processor_id(), next));
+ set_entryhi(CPU_CONTEXT(smp_processor_id(), next) & 0xff);
+ TLBMISS_HANDLER_SETUP_PGD(next->pgd);
}
#endif /* _ASM_MMU_CONTEXT_H */
#include <asm/sn/types.h>
#include <asm/sn/addrs.h>
#include <asm/sn/arch.h>
+#include <asm/sn/klkernvars.h>
typedef struct plat_pglist_data {
pg_data_t gendata;
+ kern_vars_t kern_vars;
} plat_pg_data_t;
/*
@@ -27,6+29,8 @@ extern plat_pg_data_t *plat_node_data[]; #define PLAT_NODE_DATA_LOCALNR(p, n) \
(((p) - PLAT_NODE_DATA(n)->gendata.node_start_paddr) >> PAGE_SHIFT)
+#define numa_node_id() cputocnode(current->processor)
+
#ifdef CONFIG_DISCONTIGMEM
/*
+++ /dev/null
-/* DO NOT TOUCH, AUTOGENERATED BY OFFSET.C */
-
-#ifndef _MIPS_OFFSET_H
-#define _MIPS_OFFSET_H
-
-/* MIPS pt_regs offsets. */
-#define PT_R0 0
-#define PT_R1 8
-#define PT_R2 16
-#define PT_R3 24
-#define PT_R4 32
-#define PT_R5 40
-#define PT_R6 48
-#define PT_R7 56
-#define PT_R8 64
-#define PT_R9 72
-#define PT_R10 80
-#define PT_R11 88
-#define PT_R12 96
-#define PT_R13 104
-#define PT_R14 112
-#define PT_R15 120
-#define PT_R16 128
-#define PT_R17 136
-#define PT_R18 144
-#define PT_R19 152
-#define PT_R20 160
-#define PT_R21 168
-#define PT_R22 176
-#define PT_R23 184
-#define PT_R24 192
-#define PT_R25 200
-#define PT_R26 208
-#define PT_R27 216
-#define PT_R28 224
-#define PT_R29 232
-#define PT_R30 240
-#define PT_R31 248
-#define PT_LO 256
-#define PT_HI 264
-#define PT_EPC 272
-#define PT_BVADDR 280
-#define PT_STATUS 288
-#define PT_CAUSE 296
-#define PT_SIZE 304
-
-/* MIPS task_struct offsets. */
-#define TASK_STATE 0
-#define TASK_FLAGS 8
-#define TASK_SIGPENDING 16
-#define TASK_NEED_RESCHED 40
-#define TASK_COUNTER 56
-#define TASK_PRIORITY 64
-#define TASK_MM 80
-#define TASK_PROCESSOR 100
-#define TASK_STRUCT_SIZE 1432
-
-/* MIPS specific thread_struct offsets. */
-#define THREAD_REG16 896
-#define THREAD_REG17 904
-#define THREAD_REG18 912
-#define THREAD_REG19 920
-#define THREAD_REG20 928
-#define THREAD_REG21 936
-#define THREAD_REG22 944
-#define THREAD_REG23 952
-#define THREAD_REG29 960
-#define THREAD_REG30 968
-#define THREAD_REG31 976
-#define THREAD_STATUS 984
-#define THREAD_FPU 992
-#define THREAD_BVADDR 1256
-#define THREAD_BUADDR 1264
-#define THREAD_ECODE 1272
-#define THREAD_TRAPNO 1280
-#define THREAD_MFLAGS 1288
-#define THREAD_CURDS 1296
-#define THREAD_TRAMP 1304
-#define THREAD_OLDCTX 1312
-
-/* Linux mm_struct offsets. */
-#define MM_USERS 32
-#define MM_PGD 24
-#define MM_CONTEXT 112
-
-/* Linux sigcontext offsets. */
-#define SC_REGS 0
-#define SC_FPREGS 256
-#define SC_MDHI 512
-#define SC_MDLO 520
-#define SC_PC 528
-#define SC_STATUS 536
-#define SC_OWNEDFP 540
-#define SC_FPC_CSR 544
-#define SC_FPC_EIR 548
-#define SC_CAUSE 552
-#define SC_BADVADDR 556
-
-#endif /* !(_MIPS_OFFSET_H) */
-/* $Id: page.h,v 1.6 2000/02/24 00:13:20 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1994 - 1999 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1994 - 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#ifndef _ASM_PAGE_H
#define _ASM_PAGE_H
#ifndef HZ
#define HZ 100
# define HZ 100
+#ifdef __KERNEL__
# define HZ_TO_STD(a) (a)
#endif
+#endif
#define EXEC_PAGESIZE 4096
@@ -149,32+149,11 @@ extern void __bad_pte(pmd_t *pmd); extern void __bad_pte_kernel(pmd_t *pmd);
extern void __bad_pmd(pgd_t *pgd);
-#define pte_free_kernel(pte) free_pte_fast(pte)
#define pte_free(pte) free_pte_fast(pte)
-#define pmd_free_kernel(pte) free_pmd_fast(pte)
#define pmd_free(pte) free_pmd_fast(pte)
#define pgd_free(pgd) free_pgd_fast(pgd)
#define pgd_alloc() get_pgd_fast()
-extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
-{
- address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
-
- if (pmd_none(*pmd)) {
- pte_t *page = get_pte_fast();
- if (page) {
- pmd_val(*pmd) = (unsigned long) page;
- return page + address;
- }
- return get_pte_kernel_slow(pmd, address);
- }
- if (pmd_bad(*pmd)) {
- __bad_pte_kernel(pmd);
- return NULL;
- }
- return (pte_t *) pmd_page(*pmd) + address;
-}
-
extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
{
address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
@@ -212,35+191,22 @@ extern inline pmd_t *pmd_alloc(pgd_t * pgd, unsigned long address) return (pmd_t *) pgd_page(*pgd) + address;
}
-#define pmd_alloc_kernel pmd_alloc
+extern pte_t kptbl[(PAGE_SIZE<<KPTBL_PAGE_ORDER)/sizeof(pte_t)];
+extern pmd_t kpmdtbl[PTRS_PER_PMD];
+
+#define pmd_alloc_kernel(d,a) (pmd_t *)kpmdtbl
+
+extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
+{
+ return (kptbl + (address >> PAGE_SHIFT));
+}
extern int do_check_pgt_cache(int, int);
extern inline void set_pgdir(unsigned long address, pgd_t entry)
{
- struct task_struct * p;
- pgd_t *pgd;
-#ifdef CONFIG_SMP
- int i;
-#endif
-
- read_lock(&tasklist_lock);
- for_each_task(p) {
- if (!p->mm)
- continue;
- *pgd_offset(p->mm, address) = entry;
- }
- read_unlock(&tasklist_lock);
-#ifndef CONFIG_SMP
- for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
- pgd[address >> PGDIR_SHIFT] = entry;
-#else
- /* To pgd_alloc/pgd_free, one holds master kernel lock and so does our
- callee, so we can modify pgd caches of other CPUs as well. -jj */
- for (i = 0; i < NR_CPUS; i++)
- for (pgd = (pgd_t *)cpu_data[i].pgd_quick; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
- pgd[address >> PGDIR_SHIFT] = entry;
-#endif
+ printk("set_pgdir!\n");
+ while(1);
}
#endif /* _ASM_PGALLOC_H */
-/* $Id: pgtable.h,v 1.14 2000/03/02 02:37:13 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1994 - 1999 by Ralf Baechle at alii
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1994 - 2000 by Ralf Baechle at alii
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#ifndef _ASM_PGTABLE_H
#define _ASM_PGTABLE_H
@@ -44,14+43,32 @@ extern void (*_flush_page_to_ram)(struct page * page); #define flush_page_to_ram(page) _flush_page_to_ram(page)
#define flush_icache_range(start, end) flush_cache_all()
-#define flush_icache_page(start, page) do { } while(0)
+#define flush_icache_page(vma, page) \
+do { \
+ unsigned long addr; \
+ addr = page_address(page); \
+ _flush_cache_page(vma, addr); \
+} while (0)
-/* Basically we have the same two-level (which is the logical three level
- * Linux page table layout folded) page tables as the i386. Some day
- * when we have proper page coloring support we can have a 1% quicker
- * tlb refill handling mechanism, but for now it is a bit slower but
- * works even with the cache aliasing problem the R4k and above have.
+/*
+ * Each address space has 2 4K pages as its page directory, giving 1024
+ * (== PTRS_PER_PGD) 8 byte pointers to pmd tables. Each pmd table is a
+ * pair of 4K pages, giving 1024 (== PTRS_PER_PMD) 8 byte pointers to
+ * page tables. Each page table is a single 4K page, giving 512 (==
+ * PTRS_PER_PTE) 8 byte ptes. Each pgde is initialized to point to
+ * invalid_pmd_table, each pmde is initialized to point to
+ * invalid_pte_table, each pte is initialized to 0. When memory is low,
+ * and a pmd table or a page table allocation fails, empty_bad_pmd_table
+ * and empty_bad_page_table is returned back to higher layer code, so
+ * that the failure is recognized later on. Linux does not seem to
+ * handle these failures very well though. The empty_bad_page_table has
+ * invalid pte entries in it, to force page faults.
+ * Vmalloc handling: vmalloc uses swapper_pg_dir[0] (returned by
+ * pgd_offset_k), which is initalized to point to kpmdtbl. kpmdtbl is
+ * the only single page pmd in the system. kpmdtbl entries point into
+ * kptbl[] array. We reserve 1<<KPTBL_PAGE_ORDER pages to hold the
+ * vmalloc range translations, which the fault handler looks at.
*/
#endif /* !defined (_LANGUAGE_ASSEMBLY) */
@@ -74,9+91,11 @@ extern void (*_flush_page_to_ram)(struct page * page); #define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
#define FIRST_USER_PGD_NR 0
+#define KPTBL_PAGE_ORDER 1
#define VMALLOC_START XKSEG
#define VMALLOC_VMADDR(x) ((unsigned long)(x))
-#define VMALLOC_END (KSEG3 + (1UL << 40)) /* 1 TB */
+#define VMALLOC_END \
+ (VMALLOC_START + ((1 << KPTBL_PAGE_ORDER) * PTRS_PER_PTE * PAGE_SIZE))
/* Note that we shift the lower 32bits of each EntryLo[01] entry
* 6 bits to the left. That way we can convert the PFN into the
@@ -205,8+224,10 @@ extern unsigned long zero_page_mask; #define PAGE_PTR(address) \
((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
-extern pte_t invalid_pte_table[2*PAGE_SIZE/sizeof(pte_t)];
+extern pte_t invalid_pte_table[PAGE_SIZE/sizeof(pte_t)];
+extern pte_t empty_bad_page_table[PAGE_SIZE/sizeof(pte_t)];
extern pmd_t invalid_pmd_table[2*PAGE_SIZE/sizeof(pmd_t)];
+extern pmd_t empty_bad_pmd_table[2*PAGE_SIZE/sizeof(pmd_t)];
/*
* Conversion functions: convert a page and protection to a page entry,
@@ -271,13+292,7 @@ extern inline int pmd_none(pmd_t pmd)
extern inline int pmd_bad(pmd_t pmd)
{
- return ((pmd_page(pmd) > (unsigned long) high_memory) ||
- (pmd_page(pmd) < PAGE_OFFSET));
-}
-
-extern inline int pmd_present(pmd_t pmd)
-{
- return pmd_val(pmd) != (unsigned long) invalid_pte_table;
+ return pmd_val(pmd) == (unsigned long) empty_bad_page_table;
}
extern inline void pmd_clear(pmd_t *pmdp)
@@ -295,13+310,7 @@ extern inline int pgd_none(pgd_t pgd)
extern inline int pgd_bad(pgd_t pgd)
{
- return ((pgd_page(pgd) > (unsigned long) high_memory) ||
- (pgd_page(pgd) < PAGE_OFFSET));
-}
-
-extern inline int pgd_present(pgd_t pgd)
-{
- return pgd_val(pgd) != (unsigned long) invalid_pmd_table;
+ return pgd_val(pgd) == (unsigned long) empty_bad_pmd_table;
}
extern inline void pgd_clear(pgd_t *pgdp)
@@ -438,7+447,7 @@ extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) #define page_pte(page) page_pte_prot(page, __pgprot(0))
/* to find an entry in a kernel page-table-directory */
-#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+#define pgd_offset_k(address) pgd_offset(&init_mm, 0)
#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
@@ -465,9+474,8 @@ extern inline pte_t *pte_offset(pmd_t * dir, unsigned long address) /*
* Initialize a new pgd / pmd table with invalid pointers.
*/
-extern void pte_init(unsigned long page);
extern void pgd_init(unsigned long page);
-extern void pmd_init(unsigned long page);
+extern void pmd_init(unsigned long page, unsigned long pagetable);
extern pgd_t swapper_pg_dir[1024];
extern void paging_init(void);
-/* $Id: posix_types.h,v 1.5 2000/02/29 20:49:16 ulfc Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1996, 1997, 1998, 1999 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#ifndef _ASM_POSIX_TYPES_H
#define _ASM_POSIX_TYPES_H
@@ -28,9+27,9 @@ typedef int __kernel_gid_t; typedef unsigned long __kernel_size_t;
typedef long __kernel_ssize_t;
typedef long __kernel_ptrdiff_t;
-typedef int __kernel_time_t;
+typedef long __kernel_time_t;
typedef long __kernel_suseconds_t;
-typedef int __kernel_clock_t;
+typedef long __kernel_clock_t;
typedef long __kernel_daddr_t;
typedef char * __kernel_caddr_t;
@@ -66,7+65,7 @@ typedef int __kernel_time_t32; typedef int __kernel_suseconds_t32;
typedef int __kernel_clock_t32;
typedef int __kernel_daddr_t32;
-typedef char * __kernel_caddr_t32;
+typedef unsigned int __kernel_caddr_t32;
typedef __kernel_fsid_t __kernel_fsid_t32;
#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
-/* $Id: processor.h,v 1.11 2000/03/14 01:39:27 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1994 Waldorf GMBH
- * Copyright (C) 1995, 1996, 1997, 1998, 1999 Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000 Ralf Baechle
* Modified further for R[236]000 compatibility by Paul M. Antoine
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#ifndef _ASM_PROCESSOR_H
#define _ASM_PROCESSOR_H
#include <linux/config.h>
/*
- * Default implementation of macro that returns current
- * instruction pointer ("program counter").
+ * Return current * instruction pointer ("program counter").
+ *
+ * Two implementations. The ``la'' version results in shorter code for
+ * the kernel which we assume to reside in the 32-bit compat address space.
+ * The ``jal'' version is for use by modules which live in outer space.
+ * This is just a single instruction unlike the long dla macro expansion.
*/
-#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+#ifdef MODULE
+#define current_text_addr() \
+({ \
+ void *_a; \
+ \
+ __asm__ ("jal\t1f, 1f\n\t" \
+ "1:" \
+ : "=r" (_a)); \
+ \
+ _a; \
+})
+#else
+#define current_text_addr() \
+({ \
+ void *_a; \
+ \
+ __asm__ ("dla\t%0, 1f\n\t" \
+ "1:" \
+ : "=r" (_a)); \
+ \
+ _a; \
+})
+#endif
#if !defined (_LANGUAGE_ASSEMBLY)
#include <asm/cachectl.h>
@@ -41,6+66,7 @@ struct cpuinfo_mips { unsigned int irq_count, bh_count;
unsigned long asid_cache;
#if defined(CONFIG_SGI_IP27)
+ cpuid_t p_cpuid; /* PROM assigned cpuid */
cnodeid_t p_nodeid; /* my node ID in compact-id-space */
nasid_t p_nasid; /* my node ID in numa-as-id-space */
unsigned char p_slice; /* Physical position on node board */
#define FPC_CSR 69
#define FPC_EIR 70
-#ifndef __ASSEMBLY__
+#ifndef _LANGUAGE_ASSEMBLY
#define abi64_no_regargs \
unsigned long __dummy0, \
@@ -55,19+55,21 @@ struct pt_regs { unsigned long cp0_cause;
};
-#endif /* !(__ASSEMBLY__) */
+#endif /* !(_LANGUAGE_ASSEMBLY__) */
+#ifdef _LANGUAGE_ASSEMBLY
#include <asm/offset.h>
+#endif /* (_LANGUAGE_ASSEMBLY__) */
#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
+#ifndef _LANGUAGE_ASSEMBLY
#define instruction_pointer(regs) ((regs)->cp0_epc)
extern void (*_show_regs)(struct pt_regs *);
#define show_regs(regs) _show_regs(regs)
-#endif /* !(__ASSEMBLY__) */
+#endif /* !(_LANGUAGE_ASSEMBLY__) */
#endif
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ _STK_LIM, RLIM_INFINITY }, \
{ 0, RLIM_INFINITY }, \
- { NR_OPEN, NR_OPEN }, \
+ { INR_OPEN, INR_OPEN }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ 0, 0 }, \
* The IOC3 serials use a 22MHz clock rate with an additional divider by 3.
*/
#define IOC3_BAUD (22000000 / (3*16))
-#define IOC3_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_IOC3)
+#define IOC3_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
/* Let the compiler figure out the size. */
#define RS_TABLE_SIZE
--- /dev/null
+#define _FP_W_TYPE_SIZE 64
+#define _FP_W_TYPE unsigned long
+#define _FP_WS_TYPE signed long
+#define _FP_I_TYPE long
+
+#define _FP_MUL_MEAT_S(R,X,Y) \
+ _FP_MUL_MEAT_1_imm(_FP_WFRACBITS_S,R,X,Y)
+#define _FP_MUL_MEAT_D(R,X,Y) \
+ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y) \
+ _FP_MUL_MEAT_2_wide_3mul(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
+#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1)
+#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1
+#define _FP_NANSIGN_S 0
+#define _FP_NANSIGN_D 0
+#define _FP_NANSIGN_Q 0
+
+#define _FP_KEEPNANFRACP 1
+/* From my experiments it seems X is chosen unless one of the
+ NaNs is sNaN, in which case the result is NANSIGN/NANFRAC. */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
+ do { \
+ if ((_FP_FRAC_HIGH_RAW_##fs(X) | \
+ _FP_FRAC_HIGH_RAW_##fs(Y)) & _FP_QNANBIT_##fs) \
+ { \
+ R##_s = _FP_NANSIGN_##fs; \
+ _FP_FRAC_SET_##wc(R,_FP_NANFRAC_##fs); \
+ } \
+ else \
+ { \
+ R##_s = X##_s; \
+ _FP_FRAC_COPY_##wc(R,X); \
+ } \
+ R##_c = FP_CLS_NAN; \
+ } while (0)
+
+#define FP_EX_INVALID (1 << 4)
+#define FP_EX_DIVZERO (1 << 3)
+#define FP_EX_OVERFLOW (1 << 2)
+#define FP_EX_UNDERFLOW (1 << 1)
+#define FP_EX_INEXACT (1 << 0)
#ifndef _ASM_SN_ADDRS_H
#define _ASM_SN_ADDRS_H
-#include <linux/config.h>
#if _LANGUAGE_C
#include <linux/types.h>
#endif /* _LANGUAGE_C */
#define UALIAS_FLIP_BASE UALIAS_BASE
#define UALIAS_FLIP_SIZE 0x20000
#define UALIAS_FLIP_BIT 0x10000
-#define UALIAS_FLIP_ADDR(_x) (cputoslice(getcpuid()) ? \
+#define UALIAS_FLIP_ADDR(_x) (cputoslice(smp_processor_id()) ? \
(_x) ^ UALIAS_FLIP_BIT : (_x))
#define LBOOT_BASE (HSPEC_BASE + 0x10000000)
#ifndef _ASM_SGI_SN_AGENT_H
#define _ASM_SGI_SN_AGENT_H
-#include <linux/config.h>
#include <asm/sn/addrs.h>
#include <asm/sn/arch.h>
//#include <asm/sn/io.h>
@@ -54,7+54,7 @@ typedef u64 nic_t; #define INVALID_PARTID (partid_t)-1
extern nasid_t get_nasid(void);
-extern cnodeid_t get_cpu_cnode(int);
+extern cnodeid_t get_cpu_cnode(cpuid_t);
extern int get_cpu_slice(cpuid_t);
/*
#ifndef _ASM_SN_IO_H
#define _ASM_SN_IO_H
-#include <linux/config.h>
#if !defined(CONFIG_SGI_IO)
#include <asm/sn/sn0/addrs.h>
* that offsets of existing fields do not change.
*/
-#include <linux/config.h>
#include <linux/types.h>
#include <asm/sn/types.h>
-#if defined(CONFIG_SGI_IP27) || defined(CONFIG_SGI_IP35)
-#include <asm/sn/agent.h>
-#include <asm/arc/types.h>
-#include <asm/arc/hinv.h>
-#endif /* !CONFIG_SGI_IP27 || !CONFIG_SGI_IP35 */
#if defined(CONFIG_SGI_IP27)
#include <asm/sn/sn0/addrs.h>
//#include <sys/SN/router.h>
// XXX Stolen from <sys/SN/router.h>:
#define MAX_ROUTER_PORTS (6) /* Max. number of ports on a router */
#include <asm/sn/sn0/sn0_fru.h>
+#include <asm/sn/agent.h>
//#include <sys/graph.h>
+#include <asm/arc/types.h>
+#include <asm/arc/hinv.h>
//#include <sys/xtalk/xbow.h>
+#if defined(CONFIG_SGI_IO)
+// The hack file has to be before vector and after sn0_fru....
+#include <asm/hack.h>
+#include <asm/sn/vector.h>
+#include <asm/xtalk/xtalk.h>
+#endif /* CONFIG_SGI_IO */
#elif defined(CONFIG_SGI_IP35)
+#include <asm/hack.h>
#include <asm/sn/sn1/addrs.h>
+#include <asm/sn/vector.h>
#include <sys/sn/router.h>
+#include <asm/sn/agent.h>
#include <sys/graph.h>
+#include <asm/arc/types.h>
+#include <asm/arc/hinv.h>
#include <asm/xtalk/xbow.h>
-#endif /* !CONFIG_SGI_IP27 && !CONFIG_SGI_IP35 */
-#if (defined(CONFIG_SGI_IP27) && defined(CONFIG_SGI_IO)) || \
- defined(CONFIG_SGI_IP35)
-// The hack file has to be before vector and after sn0_fru....
-#include <asm/hack.h>
-#include <asm/sn/vector.h>
#include <asm/xtalk/xtalk.h>
-#endif /* !(CONFIG_SGI_IP27 && CONFIG_SGI_IO) || !CONFIG_SGI_IP35 */
+#endif /* !CONFIG_SGI_IP27 && !CONFIG_SGI_IP35 */
#define KLCFGINFO_MAGIC 0xbeedbabe
#ifndef _ASM_SN_KLDIR_H
#define _ASM_SN_KLDIR_H
-#include <linux/config.h>
#if defined(CONFIG_SGI_IO)
#include <asm/hack.h>
#endif
--- /dev/null
+/*
+ * File ported from IRIX to Linux by Kanoj Sarcar, 06/08/00.
+ * Copyright 2000 Silicon Graphics, Inc.
+ */
+#ifndef __ASM_SN_KLKERNVARS_H
+#define __ASM_SN_KLKERNVARS_H
+
+#define KV_MAGIC_OFFSET 0x0
+#define KV_RO_NASID_OFFSET 0x4
+#define KV_RW_NASID_OFFSET 0x6
+
+#define KV_MAGIC 0x5f4b565f
+
+#if _LANGUAGE_C
+
+#include <asm/sn/types.h>
+
+typedef struct kern_vars_s {
+ int kv_magic;
+ nasid_t kv_ro_nasid;
+ nasid_t kv_rw_nasid;
+ unsigned long kv_ro_baseaddr;
+ unsigned long kv_rw_baseaddr;
+} kern_vars_t;
+
+#endif /* _LANGUAGE_C */
+
+#endif /* __ASM_SN_KLKERNVARS_H */
+
--- /dev/null
+/*
+ * File created by Kanoj Sarcar 06/06/00.
+ * Copyright 2000 Silicon Graphics, Inc.
+ */
+#ifndef __ASM_SN_MAPPED_KERNEL_H
+#define __ASM_SN_MAPPED_KERNEL_H
+
+/*
+ * Note on how mapped kernels work: the text and data section is
+ * compiled at cksseg segment (LOADADDR = 0xc001c000), and the
+ * init/setup/data section gets a 16M virtual address bump in the
+ * ld.script file (so that tlblo0 and tlblo1 maps the sections).
+ * The vmlinux.64 section addresses are put in the xkseg range
+ * using the change-addresses makefile option. Use elfdump -of
+ * on IRIX to see where the sections go. The Origin loader loads
+ * the two sections contiguously in physical memory. The loader
+ * sets the entry point into kernel_entry using a xkphys address,
+ * but instead of using 0xa800000001160000, it uses the address
+ * 0xa800000000160000, which is where it physically loaded that
+ * code. So no jumps can be done before we have switched to using
+ * cksseg addresses.
+ */
+#include <linux/config.h>
+#include <asm/addrspace.h>
+
+#ifdef CONFIG_MAPPED_KERNEL
+
+#define MAPPED_KERN_RO_TO_PHYS(x) (x - CKSSEG)
+#define MAPPED_KERN_RW_TO_PHYS(x) (x - CKSSEG - 16777216)
+
+#else /* CONFIG_MAPPED_KERNEL */
+
+#define MAPPED_KERN_RO_TO_PHYS(x) (x - CKSEG0)
+#define MAPPED_KERN_RW_TO_PHYS(x) (x - CKSEG0)
+
+#endif /* CONFIG_MAPPED_KERNEL */
+
+#define MAPPED_KERN_RO_TO_K0(x) PHYS_TO_K0(MAPPED_KERN_RO_TO_PHYS(x))
+#define MAPPED_KERN_RW_TO_K0(x) PHYS_TO_K0(MAPPED_KERN_RW_TO_PHYS(x))
+
+#endif __ASM_SN_MAPPED_KERNEL_H
#ifndef __ASM_SN_NMI_H
#define __ASM_SN_NMI_H
-#ident "$Revision: 1.1 $"
+#ident "$Revision: 1.2 $"
#include <asm/sn/addrs.h>
/* Sanity hazzard ... Below all the Origin hacks are following. */
-#define SCSI0_INT 0
-#define SCSI1_INT 1
-#define CPU_RESCHED_A_IRQ 3
-#define CPU_RESCHED_B_IRQ 4
-#define QLOGICFC_SLOT5 5
-#define CPU_CALL_A_IRQ 6
-#define CPU_CALL_B_IRQ 7
-#define IOC3_SERIAL_INT 8
-/*#define IOC3_ETH_INT 9*/
-#define IOC3_ETH_INT 0x0809 /* nasid 0, wid 0x8 */
+#define CPU_RESCHED_A_IRQ 0
+#define CPU_RESCHED_B_IRQ 1
+#define CPU_CALL_A_IRQ 2
+#define CPU_CALL_B_IRQ 3
+#define IOC3_ETH_INT 4
+#define BASE_PCI_IRQ 4
#define SN00_BRIDGE 0x9200000008000000
#define SN00I_BRIDGE0 0x920000000b000000
+extern nasid_t master_nasid;
+
extern cnodeid_t get_compact_nodeid(void);
extern void hub_rtc_init(cnodeid_t);
extern void cpu_time_init(void);
extern void per_cpu_init(void);
-extern void install_cpuintr(cpuid_t cpu);
-extern void install_tlbintr(cpuid_t cpu);
+extern void install_cpuintr(int cpu);
+extern void install_tlbintr(int cpu);
+extern void setup_replication_mask(int);
+extern void replicate_kernel_text(int);
+extern pfn_t node_getfirstfree(cnodeid_t);
@@ -21,6+21,7 @@ typedef signed char partid_t; /* partition ID type */ typedef signed short moduleid_t; /* user-visible module number type */
typedef signed short cmoduleid_t; /* kernel compact module id type */
typedef unsigned char clusterid_t; /* Clusterid of the cell */
+typedef unsigned long pfn_t;
typedef dev_t vertex_hdl_t; /* hardware graph vertex handle */
@@ -62,6+62,8 @@ To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */ #define SO_DETACH_FILTER 27
#define SO_PEERNAME 28
+#define SO_TIMESTAMP 29
+#define SCM_TIMESTAMP SO_TIMESTAMP
/* Nast libc5 fixup - bletch */
#if defined(__KERNEL__)
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1995, 1999 Ralf Baechle
+ * Copyright (C) 1995, 1999, 2000 Ralf Baechle
+ * Copyright (C) 2000 Silicon Graphics, Inc.
*/
#ifndef _ASM_STAT_H
#define _ASM_STAT_H
@@ -54,35+55,30 @@ struct stat32 { unsigned int st_gen;
};
+/* The memory layout is the same as of struct stat64 of the 32-bit kernel. */
struct stat {
dev_t st_dev;
- long st_pad1[3]; /* Reserved for network id */
+ unsigned int st_pad0[3]; /* Reserved for st_dev expansion */
ino_t st_ino;
mode_t st_mode;
nlink_t st_nlink;
uid_t st_uid;
gid_t st_gid;
dev_t st_rdev;
- long st_pad2[2];
+ unsigned int st_pad1[3]; /* Reserved for st_rdev expansion */
off_t st_size;
- long st_pad3;
/*
* Actually this should be timestruc_t st_atime, st_mtime and st_ctime
* but we don't have it under Linux.
*/
time_t st_atime;
- long reserved0;
+ unsigned int reserved0; /* Reserved for st_atime expansion */
time_t st_mtime;
- long reserved1;
+ unsigned int reserved1; /* Reserved for st_atime expansion */
time_t st_ctime;
- long reserved2;
- long st_blksize;
- long st_blocks;
- char st_fstype[16]; /* Filesystem type name */
- long st_pad4[8];
- /* Linux specific fields */
- unsigned int st_flags;
- unsigned int st_gen;
+ unsigned int reserved2; /* Reserved for st_atime expansion */
+ unsigned int st_blksize;
+ unsigned long st_blocks;
};
#endif /* _ASM_STAT_H */
-/* $Id: uaccess.h,v 1.4 2000/02/19 00:33:10 ralf Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1996, 1997, 1998, 1999 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#ifndef _ASM_UACCESS_H
#define _ASM_UACCESS_H
@@ -70,16+69,20 @@ extern inline int verify_area(int type, const void * addr, unsigned long size) * (a) re-use the arguments for side effects (sizeof is ok)
* (b) require any knowledge of processes at this stage
*/
-#define put_user(x,ptr) __put_user_check((x),(ptr),sizeof(*(ptr)),__access_mask)
-#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr)),__access_mask)
+#define put_user(x,ptr) \
+ __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+#define get_user(x,ptr) \
+ __get_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
/*
* The "__xxx" versions do not do address space checking, useful when
* doing multiple accesses to the same area (the user has to do the
* checks by hand with "access_ok()")
*/
-#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
-#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+#define __put_user(x,ptr) \
+ __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+#define __get_user(x,ptr) \
+ __get_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
/*
* The "xxx_ret" versions return constant specified in third argument, if
@@ -87,17+90,11 @@ extern inline int verify_area(int type, const void * addr, unsigned long size) * case of just returning from the function xxx_ret is used.
*/
-#define put_user_ret(x,ptr,ret) ({ \
-if (put_user(x,ptr)) return ret; })
-
-#define get_user_ret(x,ptr,ret) ({ \
-if (get_user(x,ptr)) return ret; })
-
-#define __put_user_ret(x,ptr,ret) ({ \
-if (__put_user(x,ptr)) return ret; })
+#define put_user_ret(x,ptr,ret) ({ if (put_user(x,ptr)) return ret; })
+#define get_user_ret(x,ptr,ret) ({ if (get_user(x,ptr)) return ret; })
-#define __get_user_ret(x,ptr,ret) ({ \
-if (__get_user(x,ptr)) return ret; })
+#define __put_user_ret(x,ptr,ret) ({ if (__put_user(x,ptr)) return ret; })
+#define __get_user_ret(x,ptr,ret) ({ if (__get_user(x,ptr)) return ret; })
struct __large_struct { unsigned long buf[100]; };
#define __m(x) (*(struct __large_struct *)(x))
@@ -117,14+114,14 @@ case 8: __get_user_asm("ld"); break; \ default: __get_user_unknown(); break; \
} x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
-#define __get_user_check(x,ptr,size,mask) ({ \
+#define __get_user_check(x,ptr,size) ({ \
long __gu_err; \
__typeof__(*(ptr)) __gu_val; \
long __gu_addr; \
__asm__("":"=r" (__gu_val)); \
__gu_addr = (long) (ptr); \
__asm__("":"=r" (__gu_err)); \
-if (__access_ok(__gu_addr,size,mask)) { \
+if (__access_ok(__gu_addr,size,__access_mask)) { \
switch (size) { \
case 1: __get_user_asm("lb"); break; \
case 2: __get_user_asm("lh"); break; \
@@ -167,14+164,14 @@ case 8: __put_user_asm("sd"); break; \ default: __put_user_unknown(); break; \
} __pu_err; })
-#define __put_user_check(x,ptr,size,mask) ({ \
+#define __put_user_check(x,ptr,size) ({ \
long __pu_err; \
__typeof__(*(ptr)) __pu_val; \
long __pu_addr; \
__pu_val = (x); \
__pu_addr = (long) (ptr); \
__asm__("":"=r" (__pu_err)); \
-if (__access_ok(__pu_addr,size,mask)) { \
+if (__access_ok(__pu_addr,size,__access_mask)) { \
switch (size) { \
case 1: __put_user_asm("sb"); break; \
case 2: __put_user_asm("sh"); break; \
#define SO_DETACH_FILTER 27
#define SO_PEERNAME 28
+#define SO_TIMESTAMP 29
+#define SCM_TIMESTAMP SO_TIMESTAMP
/* Nast libc5 fixup - bletch */
#if defined(__KERNEL__)
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
-#define SO_PEERNAME 28
+#define SO_PEERNAME 28
+#define SO_TIMESTAMP 29
+#define SCM_TIMESTAMP SO_TIMESTAMP
/* Nast libc5 fixup - bletch */
#if defined(__KERNEL__)
#define SO_DETACH_FILTER 27
#define SO_PEERNAME 28
+#define SO_TIMESTAMP 29
+#define SCM_TIMESTAMP SO_TIMESTAMP
/* Nast libc5 fixup - bletch */
#if defined(__KERNEL__)
-/* $Id: socket.h,v 1.14 2000/06/09 07:35:28 davem Exp $ */
+/* $Id: socket.h,v 1.15 2000/07/08 00:20:43 davem Exp $ */
#ifndef _ASM_SOCKET_H
#define _ASM_SOCKET_H
#define SO_DETACH_FILTER 0x001b
#define SO_PEERNAME 0x001c
+#define SO_TIMESTAMP 0x001d
+#define SCM_TIMESTAMP SO_TIMESTAMP
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 0x5001
-/* $Id: socket.h,v 1.7 2000/06/09 07:35:28 davem Exp $ */
+/* $Id: socket.h,v 1.8 2000/07/08 00:20:43 davem Exp $ */
#ifndef _ASM_SOCKET_H
#define _ASM_SOCKET_H
#define SO_DETACH_FILTER 0x001b
#define SO_PEERNAME 0x001c
+#define SO_TIMESTAMP 0x001d
+#define SCM_TIMESTAMP SO_TIMESTAMP
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 0x5001
+++ /dev/null
-/*
- * $Id: dmascc.h,v 1.1 1997/12/01 10:44:55 oe1kib Exp $
- *
- * Driver for high-speed SCC boards (those with DMA support)
- * Copyright (C) 1997 Klaus Kudielka
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* Ioctls */
-#define SIOCGSCCPARAM SIOCDEVPRIVATE
-#define SIOCSSCCPARAM (SIOCDEVPRIVATE+1)
-
-/* Frequency of timer 0 */
-#define TMR_0_HZ 25600
-
-/* Configurable parameters */
-struct scc_param {
- int pclk_hz; /* frequency of BRG input (read-only - don't change) */
- int brg_tc; /* baud rate generator terminal count - BRG disabled if < 0 */
- int nrzi; /* 0 (nrz), 1 (nrzi) */
- int clocks; /* see documentation */
- int txdelay; /* [1/TMR_0_HZ] */
- int txtime; /* [1/HZ] */
- int sqdelay; /* [1/TMR_0_HZ] */
- int waittime; /* [1/TMR_0_HZ] */
- int slottime; /* [1/TMR_0_HZ] */
- int persist; /* 0 ... 255 */
- int dma; /* 1, 3 */
-};
-
@@ -138,7+138,7 @@ struct in6_flowlabel_req */
#define IPV6_TLV_PAD0 0
#define IPV6_TLV_PADN 1
-#define IPV6_TLV_ROUTERALERT 20
+#define IPV6_TLV_ROUTERALERT 5
#define IPV6_TLV_JUMBO 194
/*
#define PCI_VENDOR_ID_NEC 0x1033
#define PCI_DEVICE_ID_NEC_PCX2 0x0046
+#define PCI_DEVICE_ID_NEC_NILE4 0x005a
#define PCI_VENDOR_ID_FD 0x1036
#define PCI_DEVICE_ID_FD_36C70 0x0000
@@ -259,7+259,6 @@ struct task_struct { struct exec_domain *exec_domain;
volatile long need_resched;
- cycles_t avg_slice;
int lock_depth; /* Lock depth. We can context switch in and out of holding a syscall kernel lock... */
/* begin intel cache line */
long counter;
@@ -267,8+266,8 @@ struct task_struct { unsigned long policy;
/* memory management info */
struct mm_struct *mm, *active_mm;
- int has_cpu;
- int processor;
+ int has_cpu, processor;
+ unsigned long cpus_allowed;
unsigned long ptrace;
struct list_head run_list;
struct task_struct *next_task, *prev_task;
@@ -399,6+398,7 @@ struct task_struct { policy: SCHED_OTHER, \
mm: NULL, \
active_mm: &init_mm, \
+ cpus_allowed: -1, \
run_list: LIST_HEAD_INIT(tsk.run_list), \
next_task: &tsk, \
prev_task: &tsk, \
@@ -148,16+148,8 @@ struct sk_buff { #endif
};
-/* These are just the default values. This is run time configurable.
- * FIXME: Probably the config option should go away. -- erics
- */
-#ifdef CONFIG_SKB_LARGE
#define SK_WMEM_MAX 65535
#define SK_RMEM_MAX 65535
-#else
-#define SK_WMEM_MAX 32767
-#define SK_RMEM_MAX 32767
-#endif
#ifdef __KERNEL__
/*
@@ -108,7+108,12 @@ extern struct screen_info screen_info; #define VIDEO_TYPE_EGAM 0x20 /* EGA/VGA in Monochrome Mode */
#define VIDEO_TYPE_EGAC 0x21 /* EGA in Color Mode */
#define VIDEO_TYPE_VGAC 0x22 /* VGA+ in Color Mode */
-#define VIDEO_TYPE_VLFB 0x23 /* VESA VGA in graphic mode */
+#define VIDEO_TYPE_VLFB 0x23 /* VESA VGA in graphic mode */
+
+#define VIDEO_TYPE_PICA_S3 0x30 /* ACER PICA-61 local S3 video */
+#define VIDEO_TYPE_MIPS_G364 0x31 /* MIPS Magnum 4000 G364 video */
+#define VIDEO_TYPE_SNI_RM 0x32 /* SNI RM200 PCI video */
+#define VIDEO_TYPE_SGI 0x33 /* Various SGI graphics hardware */
#define VIDEO_TYPE_TGAC 0x40 /* DEC TGA */
@@ -117,9+122,6 @@ extern struct screen_info screen_info;
#define VIDEO_TYPE_PMAC 0x60 /* PowerMacintosh frame buffer. */
-#define VIDEO_TYPE_SGI 0x70 /* Various SGI graphics hardware */
-#define VIDEO_TYPE_MIPS_G364 0x71 /* MIPS Magnum 4000 G364 video */
-
/*
* This character is the same as _POSIX_VDISABLE: it cannot be used as
* a c_cc[] character, but indicates that a particular special character
@@ -124,5+124,10 @@ static __inline__ unsigned int csum_and_copy_to_user }
#endif
+static inline unsigned int csum_chain(unsigned int csum, unsigned int addend)
+{
+ csum += addend;
+ return csum + (csum < addend);
+}
#endif
--- /dev/null
+#ifndef _INET_ECN_H_
+#define _INET_ECN_H_
+
+#include <linux/config.h>
+
+#ifdef CONFIG_INET_ECN
+
+static inline int INET_ECN_is_ce(__u8 dsfield)
+{
+ return (dsfield&3) == 3;
+}
+
+static inline int INET_ECN_is_not_ce(__u8 dsfield)
+{
+ return (dsfield&3) == 2;
+}
+
+static inline int INET_ECN_is_capable(__u8 dsfield)
+{
+ return (dsfield&2);
+}
+
+static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner)
+{
+ outer &= ~3;
+ if (INET_ECN_is_capable(inner))
+ outer |= (inner & 3);
+ return outer;
+}
+
+#define INET_ECN_xmit(sk) do { (sk)->protinfo.af_inet.tos |= 2; } while (0)
+#define INET_ECN_dontxmit(sk) do { (sk)->protinfo.af_inet.tos &= ~3; } while (0)
+
+#define IP6_ECN_flow_init(label) do { \
+ (label) &= ~htonl(3<<20); \
+ } while (0)
+
+#define IP6_ECN_flow_xmit(sk, label) do { \
+ if (INET_ECN_is_capable((sk)->protinfo.af_inet.tos)) \
+ (label) |= __constant_htons(2 << 4); \
+ } while (0)
+
+
+#else
+#define INET_ECN_is_ce(x...) (0)
+#define INET_ECN_is_not_ce(x...) (0)
+#define INET_ECN_is_capable(x...) (0)
+#define INET_ECN_encapsulate(x, y) (x)
+#define IP6_ECN_flow_init(x...) do { } while (0)
+#define IP6_ECN_flow_xmit(x...) do { } while (0)
+#define INET_ECN_xmit(x...) do { } while (0)
+#define INET_ECN_dontxmit(x...) do { } while (0)
+#endif
+
+static inline void IP_ECN_set_ce(struct iphdr *iph)
+{
+ u32 check = iph->check;
+ check += __constant_htons(0xFFFE);
+ iph->check = check + (check>=0xFFFF);
+ iph->tos |= 1;
+}
+
+struct ipv6hdr;
+
+static inline void IP6_ECN_set_ce(struct ipv6hdr *iph)
+{
+ *(u32*)iph |= htonl(1<<20);
+}
+
+#define ip6_get_dsfield(iph) ((ntohs(*(u16*)(iph)) >> 4) & 0xFF)
+
+#endif
@@ -167,12+167,14 @@ extern __inline__ int ip_send(struct sk_buff *skb) return ip_finish_output(skb);
}
+/* The function in 2.2 was invalid, producing wrong result for
+ * check=0xFEFF. It was noticed by Arthur Skawina _year_ ago. --ANK(000625) */
extern __inline__
int ip_decrease_ttl(struct iphdr *iph)
{
u32 check = iph->check;
check += __constant_htons(0x0100);
- iph->check = check + (check>>16);
+ iph->check = check + (check>=0xFFFF);
return --iph->ttl;
}
@@ -220,6+222,8 @@ extern int ip_call_ra_chain(struct sk_buff *skb); */
struct sk_buff *ip_defrag(struct sk_buff *skb);
+extern int ip_frag_nqueues;
+extern atomic_t ip_frag_mem;
/*
* Functions provided by ip_forward.c
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: ipv6.h,v 1.20 2000/02/27 19:51:38 davem Exp $
+ * $Id: ipv6.h,v 1.21 2000/07/07 22:29:42 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -189,6+189,9 @@ extern u8 * ipv6_parse_exthdrs(struct sk_buff **skb, u8 *nhptr);
extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt);
+extern int ip6_frag_nqueues;
+extern atomic_t ip6_frag_mem;
+
#define IPV6_FRAG_TIMEOUT (60*HZ) /* 60 seconds */
/*
@@ -259,6+259,19 @@ __neigh_lookup(struct neigh_table *tbl, const void *pkey, struct net_device *dev if (n || !creat)
return n;
+ n = neigh_create(tbl, pkey, dev);
+ return IS_ERR(n) ? NULL : n;
+}
+
+extern __inline__ struct neighbour *
+__neigh_lookup_errno(struct neigh_table *tbl, const void *pkey,
+ struct net_device *dev)
+{
+ struct neighbour *n = neigh_lookup(tbl, pkey, dev);
+
+ if (n)
+ return n;
+
return neigh_create(tbl, pkey, dev);
}
@@ -118,6+118,13 @@ extern __inline__ void ip_rt_put(struct rtable * rt) dst_release(&rt->u.dst);
}
+#ifdef CONFIG_INET_ECN
+#define IPTOS_RT_MASK (IPTOS_TOS_MASK & ~3)
+#else
+#define IPTOS_RT_MASK IPTOS_TOS_MASK
+#endif
+
+
extern __u8 ip_tos2prio[16];
extern __inline__ char rt_tos2priority(u8 tos)
@@ -515,6+515,8 @@ struct sock { broadcast,
bsdism;
unsigned char debug;
+ unsigned char rcvtstamp;
+ unsigned char userlocks;
int proc;
unsigned long lingertime;
@@ -1222,7+1224,7 @@ extern __inline__ long sock_sndtimeo(struct sock *sk, int noblock)
extern __inline__ int sock_rcvlowat(struct sock *sk, int waitall, int len)
{
- return waitall ? len : min(sk->rcvlowat, len);
+ return (waitall ? len : min(sk->rcvlowat, len)) ? : 1;
}
/* Alas, with timeout socket operations are not restartable.
@@ -1233,6+1235,15 @@ extern __inline__ int sock_intr_errno(long timeo) return timeo == MAX_SCHEDULE_TIMEOUT ? -ERESTARTSYS : -EINTR;
}
+static __inline__ void
+sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
+{
+ if (sk->rcvtstamp)
+ put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP, sizeof(skb->stamp), &skb->stamp);
+ else
+ sk->stamp = skb->stamp;
+}
+
/*
* Enable debug/info messages
*/
@@ -133,6+133,7 @@ EXPORT_SYMBOL(get_fs_type); EXPORT_SYMBOL(get_super);
EXPORT_SYMBOL(get_empty_super);
EXPORT_SYMBOL(getname);
+EXPORT_SYMBOL(names_cachep);
EXPORT_SYMBOL(_fput);
EXPORT_SYMBOL(igrab);
EXPORT_SYMBOL(iunique);
@@ -78,18+78,20 @@ static union { } aligned_data [NR_CPUS] __cacheline_aligned = { {{&init_task,0}}};
#define cpu_curr(cpu) aligned_data[(cpu)].schedule_data.curr
+#define last_schedule(cpu) aligned_data[(cpu)].schedule_data.last_schedule
struct kernel_stat kstat = { 0 };
#ifdef CONFIG_SMP
#define idle_task(cpu) (init_tasks[cpu_number_map(cpu)])
-#define can_schedule(p) (!(p)->has_cpu)
+#define can_schedule(p,cpu) ((!(p)->has_cpu) && \
+ ((p)->cpus_allowed & (1 << cpu)))
#else
#define idle_task(cpu) (&init_task)
-#define can_schedule(p) (1)
+#define can_schedule(p,cpu) (1)
#endif
@@ -119,7+121,7 @@ static inline int goodness(struct task_struct * p, int this_cpu, struct mm_struc * into account).
*/
if (p->policy != SCHED_OTHER) {
- weight = 1000 + p->rt_priority;
+ weight = 1000 + 2*DEF_PRIORITY + p->rt_priority;
goto out;
}
@@ -183,87+185,108 @@ static inline int preemption_goodness(struct task_struct * prev, struct task_str * up unlocking it early, so the caller must not unlock the
* runqueue, it's always done by reschedule_idle().
*/
-static inline void reschedule_idle(struct task_struct * p, unsigned long flags)
+static void reschedule_idle(struct task_struct * p, unsigned long flags)
{
#ifdef CONFIG_SMP
- int this_cpu = smp_processor_id(), target_cpu;
- struct task_struct *tsk;
- int cpu, best_cpu, i;
+ int this_cpu = smp_processor_id();
+ struct task_struct *tsk, *target_tsk;
+ int cpu, best_cpu, i, max_prio;
+ cycles_t oldest_idle;
/*
* shortcut if the woken up task's last CPU is
* idle now.
*/
best_cpu = p->processor;
- tsk = idle_task(best_cpu);
- if (cpu_curr(best_cpu) == tsk)
- goto send_now;
+ if (can_schedule(p, best_cpu)) {
+ tsk = idle_task(best_cpu);
+ if (cpu_curr(best_cpu) == tsk)
+ goto send_now_idle;
+
+ /*
+ * Maybe this process has enough priority to preempt
+ * its preferred CPU. (this is a shortcut):
+ */
+ tsk = cpu_curr(best_cpu);
+ if (preemption_goodness(tsk, p, best_cpu) > 1)
+ goto preempt_now;
+ }
/*
* We know that the preferred CPU has a cache-affine current
* process, lets try to find a new idle CPU for the woken-up
- * process:
+ * process. Select the least recently active idle CPU. (that
+ * one will have the least active cache context.) Also find
+ * the executing process which has the least priority.
*/
- for (i = smp_num_cpus - 1; i >= 0; i--) {
+ oldest_idle = -1ULL;
+ target_tsk = NULL;
+ max_prio = 1;
+
+ for (i = 0; i < smp_num_cpus; i++) {
cpu = cpu_logical_map(i);
- if (cpu == best_cpu)
+ if (!can_schedule(p, cpu))
continue;
tsk = cpu_curr(cpu);
/*
- * We use the last available idle CPU. This creates
+ * We use the first available idle CPU. This creates
* a priority list between idle CPUs, but this is not
* a problem.
*/
- if (tsk == idle_task(cpu))
- goto send_now;
- }
-
- /*
- * No CPU is idle, but maybe this process has enough priority
- * to preempt it's preferred CPU.
- */
- tsk = cpu_curr(best_cpu);
- if (preemption_goodness(tsk, p, best_cpu) > 0)
- goto send_now;
+ if (tsk == idle_task(cpu)) {
+ if (last_schedule(cpu) < oldest_idle) {
+ oldest_idle = last_schedule(cpu);
+ target_tsk = tsk;
+ }
+ } else {
+ if (oldest_idle == -1ULL) {
+ int prio = preemption_goodness(tsk, p, cpu);
- /*
- * We will get here often - or in the high CPU contention
- * case. No CPU is idle and this process is either lowprio or
- * the preferred CPU is highprio. Try to preempt some other CPU
- * only if it's RT or if it's iteractive and the preferred
- * cpu won't reschedule shortly.
- */
- if (p->avg_slice < cacheflush_time || (p->policy & ~SCHED_YIELD) != SCHED_OTHER) {
- for (i = smp_num_cpus - 1; i >= 0; i--) {
- cpu = cpu_logical_map(i);
- if (cpu == best_cpu)
- continue;
- tsk = cpu_curr(cpu);
- if (preemption_goodness(tsk, p, cpu) > 0)
- goto send_now;
+ if (prio > max_prio) {
+ max_prio = prio;
+ target_tsk = tsk;
+ }
+ }
}
}
+ tsk = target_tsk;
+ if (tsk) {
+ if (oldest_idle != -1ULL)
+ goto send_now_idle;
+ goto preempt_now;
+ }
spin_unlock_irqrestore(&runqueue_lock, flags);
return;
-send_now:
- target_cpu = tsk->processor;
+send_now_idle:
+ /*
+ * If need_resched == -1 then we can skip sending the IPI
+ * altogether, tsk->need_resched is actively watched by the
+ * idle thread.
+ */
+ if (!tsk->need_resched)
+ smp_send_reschedule(tsk->processor);
+ tsk->need_resched = 1;
+ spin_unlock_irqrestore(&runqueue_lock, flags);
+ return;
+
+preempt_now:
tsk->need_resched = 1;
spin_unlock_irqrestore(&runqueue_lock, flags);
/*
* the APIC stuff can go outside of the lock because
* it uses no task information, only CPU#.
*/
- if (target_cpu != this_cpu)
- smp_send_reschedule(target_cpu);
+ if (tsk->processor != this_cpu)
+ smp_send_reschedule(tsk->processor);
return;
#else /* UP */
int this_cpu = smp_processor_id();
struct task_struct *tsk;
tsk = cpu_curr(this_cpu);
- if (preemption_goodness(tsk, p, this_cpu) > 0)
+ if (preemption_goodness(tsk, p, this_cpu) > 1)
tsk->need_resched = 1;
spin_unlock_irqrestore(&runqueue_lock, flags);
#endif
@@ -413,10+436,12 @@ static inline void __schedule_tail(struct task_struct *prev) unsigned long flags;
spin_lock_irqsave(&runqueue_lock, flags);
+ prev->has_cpu = 0;
reschedule_idle(prev, flags); // spin_unlocks runqueue
+ } else {
+ wmb();
+ prev->has_cpu = 0;
}
- wmb();
- prev->has_cpu = 0;
#endif /* CONFIG_SMP */
}
@@ -501,7+526,7 @@ repeat_schedule: still_running_back:
list_for_each(tmp, &runqueue_head) {
p = list_entry(tmp, struct task_struct, run_list);
- if (can_schedule(p)) {
+ if (can_schedule(p, this_cpu)) {
int weight = goodness(p, this_cpu, prev->active_mm);
if (weight > c)
c = weight, next = p;
@@ -540,13+565,6 @@ still_running_back: t = get_cycles();
this_slice = t - sched_data->last_schedule;
sched_data->last_schedule = t;
-
- /*
- * Exponentially fading average calculation, with
- * some weight so it doesnt get fooled easily by
- * smaller irregularities.
- */
- prev->avg_slice = (this_slice*1 + prev->avg_slice*1)/2;
}
/*
@@ -641,15+659,20 @@ scheduling_in_interrupt: return;
}
-static inline void __wake_up_common(wait_queue_head_t *q, unsigned int mode, const int sync)
+static inline void __wake_up_common (wait_queue_head_t *q, unsigned int mode,
+ const int sync)
{
struct list_head *tmp, *head;
- struct task_struct *p;
+ struct task_struct *p, *best_exclusive;
unsigned long flags;
+ int best_cpu, irq;
if (!q)
goto out;
+ best_cpu = smp_processor_id();
+ irq = in_interrupt();
+ best_exclusive = NULL;
wq_write_lock_irqsave(&q->lock, flags);
#if WAITQUEUE_DEBUG
@@ -661,10+684,13 @@ static inline void __wake_up_common(wait_queue_head_t *q, unsigned int mode, con if (!head->next || !head->prev)
WQ_BUG();
#endif
- list_for_each(tmp, head) {
+ tmp = head->next;
+ while (tmp != head) {
unsigned int state;
wait_queue_t *curr = list_entry(tmp, wait_queue_t, task_list);
+ tmp = tmp->next;
+
#if WAITQUEUE_DEBUG
CHECK_MAGIC(curr->__magic);
#endif
@@ -674,15+700,37 @@ static inline void __wake_up_common(wait_queue_head_t *q, unsigned int mode, con #if WAITQUEUE_DEBUG
curr->__waker = (long)__builtin_return_address(0);
#endif
- if (sync)
- wake_up_process_synchronous(p);
- else
- wake_up_process(p);
- if (state & mode & TASK_EXCLUSIVE)
- break;
+ /*
+ * If waking up from an interrupt context then
+ * prefer processes which are affine to this
+ * CPU.
+ */
+ if (irq && (state & mode & TASK_EXCLUSIVE)) {
+ if (!best_exclusive)
+ best_exclusive = p;
+ else if ((p->processor == best_cpu) &&
+ (best_exclusive->processor != best_cpu))
+ best_exclusive = p;
+ } else {
+ if (sync)
+ wake_up_process_synchronous(p);
+ else
+ wake_up_process(p);
+ if (state & mode & TASK_EXCLUSIVE)
+ break;
+ }
}
}
+ if (best_exclusive)
+ best_exclusive->state = TASK_RUNNING;
wq_write_unlock_irqrestore(&q->lock, flags);
+
+ if (best_exclusive) {
+ if (sync)
+ wake_up_process_synchronous(best_exclusive);
+ else
+ wake_up_process(best_exclusive);
+ }
out:
return;
}
@@ -697,6+745,7 @@ void __wake_up_sync(wait_queue_head_t *q, unsigned int mode) __wake_up_common(q, mode, 1);
}
+
#define SLEEP_ON_VAR \
unsigned long flags; \
wait_queue_t wait; \
@@ -798,7+847,7 @@ asmlinkage long sys_nice(int increment) * timeslice instead (default 200 ms). The rounding is
* why we want to avoid negative values.
*/
- newprio = (newprio * DEF_PRIORITY + 10) / 20;
+ newprio = (newprio * DEF_PRIORITY + 10)/20;
increment = newprio;
if (increase)
increment = -increment;
@@ -812,7+861,7 @@ asmlinkage long sys_nice(int increment) */
newprio = current->priority - increment;
if ((signed) newprio < 1)
- newprio = 1;
+ newprio = DEF_PRIORITY/20;
if (newprio > DEF_PRIORITY*2)
newprio = DEF_PRIORITY*2;
current->priority = newprio;
@@ -355,7+355,6 @@ static kmem_cache_t cache_cache = { spinlock: SPIN_LOCK_UNLOCKED,
colour_off: L1_CACHE_BYTES,
name: "kmem_cache",
- next: LIST_HEAD_INIT(cache_cache.next)
};
/* Guard access to the cache-chain. */
@@ -412,7+411,7 @@ void __init kmem_cache_init(void) size_t left_over;
init_MUTEX(&cache_chain_sem);
- list_add(&cache_cache.next,&cache_chain);
+ INIT_LIST_HEAD(&cache_chain);
kmem_cache_estimate(0, cache_cache.objsize, 0,
&left_over, &cache_cache.num);
@@ -443,7+442,7 @@ void __init kmem_cache_sizes_init(void) * eliminates "false sharing".
* Note for systems short on memory removing the alignment will
* allow tighter packing of the smaller caches. */
- sprintf(name,"size-%d",sizes->cs_size);
+ sprintf(name,"size-%Zd",sizes->cs_size);
if (!(sizes->cs_cachep =
kmem_cache_create(name, sizes->cs_size,
0, SLAB_HWCACHE_ALIGN, NULL, NULL))) {
@@ -455,7+454,7 @@ void __init kmem_cache_sizes_init(void) offslab_limit = sizes->cs_size-sizeof(slab_t);
offslab_limit /= 2;
}
- sprintf(name, "size-%d(DMA)",sizes->cs_size);
+ sprintf(name, "size-%Zd(DMA)",sizes->cs_size);
sizes->cs_dmacachep = kmem_cache_create(name, sizes->cs_size, 0,
SLAB_CACHE_DMA|SLAB_HWCACHE_ALIGN, NULL, NULL);
if (!sizes->cs_dmacachep)
@@ -281,25+281,27 @@ struct neighbour * neigh_create(struct neigh_table *tbl, const void *pkey, struct neighbour *n, *n1;
u32 hash_val;
int key_len = tbl->key_len;
+ int error;
n = neigh_alloc(tbl);
if (n == NULL)
- return NULL;
+ return ERR_PTR(-ENOBUFS);
memcpy(n->primary_key, pkey, key_len);
n->dev = dev;
dev_hold(dev);
/* Protocol specific setup. */
- if (tbl->constructor && tbl->constructor(n) < 0) {
+ if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
neigh_release(n);
- return NULL;
+ return ERR_PTR(error);
}
/* Device specific setup. */
- if (n->parms && n->parms->neigh_setup && n->parms->neigh_setup(n) < 0) {
+ if (n->parms && n->parms->neigh_setup &&
+ (error = n->parms->neigh_setup(n)) < 0) {
neigh_release(n);
- return NULL;
+ return ERR_PTR(error);
}
n->confirmed = jiffies - (n->parms->base_reachable_time<<1);
@@ -1242,6+1244,7 @@ int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) if (nda[NDA_LLADDR-1] != NULL &&
nda[NDA_LLADDR-1]->rta_len != RTA_LENGTH(dev->addr_len))
goto out;
+ err = 0;
n = neigh_lookup(tbl, RTA_DATA(nda[NDA_DST-1]), dev);
if (n) {
if (nlh->nlmsg_flags&NLM_F_EXCL)
@@ -1249,9+1252,11 @@ int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) } else if (!(nlh->nlmsg_flags&NLM_F_CREATE))
err = -ENOENT;
else {
- n = __neigh_lookup(tbl, RTA_DATA(nda[NDA_DST-1]), dev, 1);
- if (n == NULL)
- err = -ENOBUFS;
+ n = __neigh_lookup_errno(tbl, RTA_DATA(nda[NDA_DST-1]), dev);
+ if (IS_ERR(n)) {
+ err = PTR_ERR(n);
+ n = NULL;
+ }
}
if (err == 0) {
err = neigh_update(n, nda[NDA_LLADDR-1] ? RTA_DATA(nda[NDA_LLADDR-1]) : NULL,
* handler for protocols to use and generic option handler.
*
*
- * Version: $Id: sock.c,v 1.93 2000/04/13 03:13:29 davem Exp $
+ * Version: $Id: sock.c,v 1.95 2000/07/08 00:20:43 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -308,6+308,10 @@ int sock_setsockopt(struct socket *sock, int level, int optname, sock->passcred = valbool;
break;
+ case SO_TIMESTAMP:
+ sk->rcvtstamp = valbool;
+ break;
+
case SO_RCVLOWAT:
if (val < 0)
val = INT_MAX;
@@ -485,7+489,11 @@ int sock_getsockopt(struct socket *sock, int level, int optname, case SO_BSDCOMPAT:
v.val = sk->bsdism;
break;
-
+
+ case SO_TIMESTAMP:
+ v.val = sk->rcvtstamp;
+ break;
+
case SO_RCVTIMEO:
lv=sizeof(struct timeval);
if (sk->rcvtimeo == MAX_SCHEDULE_TIMEOUT) {
@@ -599,7+607,16 @@ void __init sk_init(void) {
sk_cachep = kmem_cache_create("sock", sizeof(struct sock), 0,
SLAB_HWCACHE_ALIGN, 0, 0);
-
+
+ if (num_physpages <= 4096) {
+ sysctl_wmem_max = 32767;
+ sysctl_rmem_max = 32767;
+ sysctl_wmem_default = 32767;
+ sysctl_wmem_default = 32767;
+ } else if (num_physpages >= 131072) {
+ sysctl_wmem_max = 131071;
+ sysctl_rmem_max = 131071;
+ }
}
/*
@@ -789,13+789,14 @@ static int dn_route_input_slow(struct sk_buff *skb) if (dn_db->router && ((neigh = neigh_clone(dn_db->router)) != NULL))
goto add_entry;
- if ((neigh = neigh_create(&dn_neigh_table, &cb->src, dev)) != NULL) {
+ neigh = neigh_create(&dn_neigh_table, &cb->src, dev);
+ if (!IS_ERR(neigh)) {
if (dev->type == ARPHRD_ETHER)
memcpy(neigh->ha, skb->mac.ethernet->h_source, ETH_ALEN);
goto add_entry;
}
- return -ENOBUFS;
+ return PTR_ERR(neigh);
non_local_input:
@@ -44,15+44,8 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool ' IP: ARP daemon support (EXPERIMENTAL)' CONFIG_ARPD
fi
fi
+bool ' IP: TCP Explicit Congestion Notification support' CONFIG_INET_ECN
bool ' IP: TCP syncookie support (disabled per default)' CONFIG_SYN_COOKIES
-comment '(it is safe to leave these untouched)'
-#bool ' IP: PC/TCP compatibility mode' CONFIG_INET_PCTCP
-#bool ' IP: Path MTU Discovery (normally enabled)' CONFIG_PATH_MTU_DISCOVERY
-#bool ' IP: Disable NAGLE algorithm (normally enabled)' CONFIG_TCP_NAGLE_OFF
-bool ' IP: Allow large windows (not recommended if <16Mb of memory)' CONFIG_SKB_LARGE
-#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-# bool ' IP: support checksum copy to user for UDP (EXPERIMENTAL)' CONFIG_UDP_DELAY_CSUM
-#fi
if [ "$CONFIG_NETFILTER" != "n" ]; then
source net/ipv4/netfilter/Config.in
fi
/* linux/net/inet/arp.c
*
- * Version: $Id: arp.c,v 1.86 2000/04/26 09:36:36 davem Exp $
+ * Version: $Id: arp.c,v 1.87 2000/07/07 22:40:35 davem Exp $
*
* Copyright (C) 1994 by Florian La Roche
*
@@ -424,20+424,24 @@ int arp_find(unsigned char *haddr, struct sk_buff *skb) int arp_bind_neighbour(struct dst_entry *dst)
{
struct net_device *dev = dst->dev;
+ struct neighbour *n = dst->neighbour;
if (dev == NULL)
- return 0;
- if (dst->neighbour == NULL) {
+ return -EINVAL;
+ if (n == NULL) {
u32 nexthop = ((struct rtable*)dst)->rt_gateway;
if (dev->flags&(IFF_LOOPBACK|IFF_POINTOPOINT))
nexthop = 0;
- dst->neighbour = __neigh_lookup(
+ n = __neigh_lookup_errno(
#ifdef CONFIG_ATM_CLIP
dev->type == ARPHRD_ATM ? &clip_tbl :
#endif
- &arp_tbl, &nexthop, dev, 1);
+ &arp_tbl, &nexthop, dev);
+ if (IS_ERR(n))
+ return PTR_ERR(n);
+ dst->neighbour = n;
}
- return (dst->neighbour != NULL);
+ return 0;
}
/*
@@ -847,9+851,9 @@ int arp_req_set(struct arpreq *r, struct net_device * dev) if (r->arp_ha.sa_family != dev->type)
return -EINVAL;
- err = -ENOBUFS;
- neigh = __neigh_lookup(&arp_tbl, &ip, dev, 1);
- if (neigh) {
+ neigh = __neigh_lookup_errno(&arp_tbl, &ip, dev);
+ err = PTR_ERR(neigh);
+ if (!IS_ERR(neigh)) {
unsigned state = NUD_STALE;
if (r->arp_flags & ATF_PERM)
state = NUD_PERMANENT;
*
* The IP fragmentation functionality.
*
- * Version: $Id: ip_fragment.c,v 1.49 2000/04/15 01:48:10 davem Exp $
+ * Version: $Id: ip_fragment.c,v 1.50 2000/07/07 22:29:42 davem Exp $
*
* Authors: Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>
* Alan Cox <Alan.Cox@linux.org>
* Ultima : ip_expire() kernel panic.
* Bill Hawes : Frag accounting and evictor fixes.
* John McDonald : 0 length frag bug.
+ * Alexey Kuznetsov: SMP races, threading, cleanup.
*/
#include <linux/config.h>
#include <net/sock.h>
#include <net/ip.h>
#include <net/icmp.h>
+#include <net/checksum.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/inet.h>
#include <linux/netfilter_ipv4.h>
+/* NOTE. Logic of IP defragmentation is parallel to corresponding IPv6
+ * code now. If you change something here, _PLEASE_ update ipv6/reassembly.c
+ * as well. Or notify me, at least. --ANK
+ */
+
/* Fragment cache limits. We will commit 256K at one time. Should we
* cross that limit we will prune down to 192K. This should cope with
* even the most extreme cases without allowing an attacker to measurably
@@ -46,38+53,77 @@ int sysctl_ipfrag_low_thresh = 192*1024;
int sysctl_ipfrag_time = IP_FRAG_TIME;
-/* Describe an IP fragment. */
-struct ipfrag {
- int offset; /* offset of fragment in IP datagram */
- int end; /* last byte of data in datagram */
- int len; /* length of this fragment */
- struct sk_buff *skb; /* complete received fragment */
- unsigned char *ptr; /* pointer into real fragment data */
- struct ipfrag *next; /* linked list pointers */
- struct ipfrag *prev;
+struct ipfrag_skb_cb
+{
+ struct inet_skb_parm h;
+ int offset;
};
+#define FRAG_CB(skb) ((struct ipfrag_skb_cb*)((skb)->cb))
+
/* Describe an entry in the "incomplete datagrams" queue. */
struct ipq {
- struct iphdr *iph; /* pointer to IP header */
struct ipq *next; /* linked list pointers */
- struct ipfrag *fragments; /* linked list of received fragments */
+ u32 saddr;
+ u32 daddr;
+ u16 id;
+ u8 protocol;
+ u8 last_in;
+#define COMPLETE 4
+#define FIRST_IN 2
+#define LAST_IN 1
+
+ struct sk_buff *fragments; /* linked list of received fragments */
int len; /* total length of original datagram */
- short ihlen; /* length of the IP header */
+ int meat;
+ spinlock_t lock;
+ atomic_t refcnt;
struct timer_list timer; /* when will this queue expire? */
struct ipq **pprev;
- struct net_device *dev; /* Device - for icmp replies */
+ struct net_device *dev; /* Device - for icmp replies */
};
+/* Hash table. */
+
#define IPQ_HASHSZ 64
+/* Per-bucket lock is easy to add now. */
static struct ipq *ipq_hash[IPQ_HASHSZ];
-static spinlock_t ipfrag_lock = SPIN_LOCK_UNLOCKED;
+static rwlock_t ipfrag_lock = RW_LOCK_UNLOCKED;
+int ip_frag_nqueues = 0;
-#define ipqhashfn(id, saddr, daddr, prot) \
- ((((id) >> 1) ^ (saddr) ^ (daddr) ^ (prot)) & (IPQ_HASHSZ - 1))
+static __inline__ void __ipq_unlink(struct ipq *qp)
+{
+ if(qp->next)
+ qp->next->pprev = qp->pprev;
+ *qp->pprev = qp->next;
+ ip_frag_nqueues--;
+}
+
+static __inline__ void ipq_unlink(struct ipq *ipq)
+{
+ write_lock(&ipfrag_lock);
+ __ipq_unlink(ipq);
+ write_unlock(&ipfrag_lock);
+}
-static atomic_t ip_frag_mem = ATOMIC_INIT(0); /* Memory used for fragments */
+/*
+ * Was: ((((id) >> 1) ^ (saddr) ^ (daddr) ^ (prot)) & (IPQ_HASHSZ - 1))
+ *
+ * I see, I see evil hand of bigendian mafia. On Intel all the packets hit
+ * one hash bucket with this hash function. 8)
+ */
+static __inline__ unsigned int ipqhashfn(u16 id, u32 saddr, u32 daddr, u8 prot)
+{
+ unsigned int h = saddr ^ daddr;
+
+ h ^= (h>>16)^id;
+ h ^= (h>>8)^prot;
+ return h & (IPQ_HASHSZ - 1);
+}
+
+
+atomic_t ip_frag_mem = ATOMIC_INIT(0); /* Memory used for fragments */
/* Memory Tracking Functions. */
extern __inline__ void frag_kfree_skb(struct sk_buff *skb)
@@ -86,112+132,106 @@ extern __inline__ void frag_kfree_skb(struct sk_buff *skb) kfree_skb(skb);
}
-extern __inline__ void frag_kfree_s(void *ptr, int len)
+extern __inline__ void frag_free_queue(struct ipq *qp)
{
- atomic_sub(len, &ip_frag_mem);
- kfree(ptr);
+ atomic_sub(sizeof(struct ipq), &ip_frag_mem);
+ kfree(qp);
}
-
-extern __inline__ void *frag_kmalloc(int size, int pri)
+
+extern __inline__ struct ipq *frag_alloc_queue(void)
{
- void *vp = kmalloc(size, pri);
+ struct ipq *qp = kmalloc(sizeof(struct ipq), GFP_ATOMIC);
- if(!vp)
+ if(!qp)
return NULL;
- atomic_add(size, &ip_frag_mem);
- return vp;
+ atomic_add(sizeof(struct ipq), &ip_frag_mem);
+ return qp;
}
-
-/* Create a new fragment entry. */
-static struct ipfrag *ip_frag_create(int offset, int end,
- struct sk_buff *skb, unsigned char *ptr)
+
+
+/* Destruction primitives. */
+
+/* Complete destruction of ipq. */
+static void ip_frag_destroy(struct ipq *qp)
{
- struct ipfrag *fp;
+ struct sk_buff *fp;
- fp = (struct ipfrag *) frag_kmalloc(sizeof(struct ipfrag), GFP_ATOMIC);
- if (fp == NULL)
- goto out_nomem;
+ BUG_TRAP(qp->last_in&COMPLETE);
+ BUG_TRAP(del_timer(&qp->timer) == 0);
- /* Fill in the structure. */
- fp->offset = offset;
- fp->end = end;
- fp->len = end - offset;
- fp->skb = skb;
- fp->ptr = ptr;
- fp->next = fp->prev = NULL;
-
- /* Charge for the SKB as well. */
- atomic_add(skb->truesize, &ip_frag_mem);
+ /* Release all fragment data. */
+ fp = qp->fragments;
+ while (fp) {
+ struct sk_buff *xp = fp->next;
- return(fp);
+ frag_kfree_skb(fp);
+ fp = xp;
+ }
-out_nomem:
- NETDEBUG(printk(KERN_ERR "IP: frag_create: no memory left !\n"));
- return(NULL);
+ /* Finally, release the queue descriptor itself. */
+ frag_free_queue(qp);
}
-/* Find the correct entry in the "incomplete datagrams" queue for
- * this IP datagram, and return the queue entry address if found.
- */
-static inline struct ipq *ip_find(struct iphdr *iph, struct dst_entry *dst)
+static __inline__ void ipq_put(struct ipq *ipq)
{
- __u16 id = iph->id;
- __u32 saddr = iph->saddr;
- __u32 daddr = iph->daddr;
- __u8 protocol = iph->protocol;
- unsigned int hash = ipqhashfn(id, saddr, daddr, protocol);
- struct ipq *qp;
-
- /* We are always in BH context, and protected by the
- * ipfrag lock.
- */
- for(qp = ipq_hash[hash]; qp; qp = qp->next) {
- if(qp->iph->id == id &&
- qp->iph->saddr == saddr &&
- qp->iph->daddr == daddr &&
- qp->iph->protocol == protocol) {
- del_timer(&qp->timer);
- break;
- }
- }
- return qp;
+ if (atomic_dec_and_test(&ipq->refcnt))
+ ip_frag_destroy(ipq);
}
-/* Remove an entry from the "incomplete datagrams" queue, either
- * because we completed, reassembled and processed it, or because
- * it timed out.
- *
- * This is called _only_ from BH contexts with the ipfrag lock held,
- * on packet reception processing and from frag queue expiration
- * timers. -DaveM
+/* Kill ipq entry. It is not destroyed immediately,
+ * because caller (and someone more) holds reference count.
*/
-static void ip_free(struct ipq *qp)
+static __inline__ void ipq_kill(struct ipq *ipq)
{
- struct ipfrag *fp;
-
- /* Stop the timer for this entry. */
- del_timer(&qp->timer);
-
- /* Remove this entry from the "incomplete datagrams" queue. */
- if(qp->next)
- qp->next->pprev = qp->pprev;
- *qp->pprev = qp->next;
-
- /* Release all fragment data. */
- fp = qp->fragments;
- while (fp) {
- struct ipfrag *xp = fp->next;
+ if (del_timer(&ipq->timer))
+ atomic_dec(&ipq->refcnt);
- frag_kfree_skb(fp->skb);
- frag_kfree_s(fp, sizeof(struct ipfrag));
- fp = xp;
+ if (!(ipq->last_in & COMPLETE)) {
+ ipq_unlink(ipq);
+ atomic_dec(&ipq->refcnt);
+ ipq->last_in |= COMPLETE;
}
+}
- /* Release the IP header. */
- frag_kfree_s(qp->iph, 64 + 8);
+/* Memory limiting on fragments. Evictor trashes the oldest
+ * fragment queue until we are back under the low threshold.
+ */
+static void ip_evictor(void)
+{
+ int i, progress;
- /* Finally, release the queue descriptor itself. */
- frag_kfree_s(qp, sizeof(struct ipq));
+ do {
+ if (atomic_read(&ip_frag_mem) <= sysctl_ipfrag_low_thresh)
+ return;
+ progress = 0;
+ /* FIXME: Make LRU queue of frag heads. -DaveM */
+ for (i = 0; i < IPQ_HASHSZ; i++) {
+ struct ipq *qp;
+ if (ipq_hash[i] == NULL)
+ continue;
+
+ write_lock(&ipfrag_lock);
+ if ((qp = ipq_hash[i]) != NULL) {
+ /* find the oldest queue for this hash bucket */
+ while (qp->next)
+ qp = qp->next;
+ __ipq_unlink(qp);
+ write_unlock(&ipfrag_lock);
+
+ spin_lock(&qp->lock);
+ if (del_timer(&qp->timer))
+ atomic_dec(&qp->refcnt);
+ qp->last_in |= COMPLETE;
+ spin_unlock(&qp->lock);
+
+ ipq_put(qp);
+ IP_INC_STATS_BH(IpReasmFails);
+ progress = 1;
+ continue;
+ }
+ write_unlock(&ipfrag_lock);
+ }
+ } while (progress);
}
/*
@@ -201,181+241,310 @@ static void ip_expire(unsigned long arg) {
struct ipq *qp = (struct ipq *) arg;
- spin_lock(&ipfrag_lock);
- if(!qp->fragments)
- {
-#ifdef IP_EXPIRE_DEBUG
- printk("warning: possible ip-expire attack\n");
-#endif
+ spin_lock(&qp->lock);
+
+ if (qp->last_in & COMPLETE)
goto out;
- }
-
- /* Send an ICMP "Fragment Reassembly Timeout" message. */
+
+ ipq_kill(qp);
+
IP_INC_STATS_BH(IpReasmTimeout);
IP_INC_STATS_BH(IpReasmFails);
- icmp_send(qp->fragments->skb, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
+ if ((qp->last_in&FIRST_IN) && qp->fragments != NULL) {
+ /* Send an ICMP "Fragment Reassembly Timeout" message. */
+ icmp_send(qp->fragments, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
+ }
out:
- /* Nuke the fragment queue. */
- ip_free(qp);
- spin_unlock(&ipfrag_lock);
+ spin_unlock(&qp->lock);
+ ipq_put(qp);
}
-/* Memory limiting on fragments. Evictor trashes the oldest
- * fragment queue until we are back under the low threshold.
- *
- * We are always called in BH with the ipfrag lock held.
- */
-static void ip_evictor(void)
+/* Creation primitives. */
+
+static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in)
{
- int i, progress;
+ struct ipq *qp;
-restart:
- progress = 0;
- /* FIXME: Make LRU queue of frag heads. -DaveM */
- for (i = 0; i < IPQ_HASHSZ; i++) {
- struct ipq *qp;
- if (atomic_read(&ip_frag_mem) <= sysctl_ipfrag_low_thresh)
- return;
- qp = ipq_hash[i];
- if (qp) {
- /* find the oldest queue for this hash bucket */
- while (qp->next)
- qp = qp->next;
- ip_free(qp);
- progress = 1;
+ write_lock(&ipfrag_lock);
+#ifdef CONFIG_SMP
+ /* With SMP race we have to recheck hash table, because
+ * such entry could be created on other cpu, while we
+ * promoted read lock to write lock.
+ */
+ for(qp = ipq_hash[hash]; qp; qp = qp->next) {
+ if(qp->id == qp_in->id &&
+ qp->saddr == qp_in->saddr &&
+ qp->daddr == qp_in->daddr &&
+ qp->protocol == qp_in->protocol) {
+ atomic_inc(&qp->refcnt);
+ write_unlock(&ipfrag_lock);
+ qp_in->last_in |= COMPLETE;
+ ipq_put(qp_in);
+ return qp;
}
}
- if (progress)
- goto restart;
- panic("ip_evictor: memcount");
+#endif
+ qp = qp_in;
+
+ atomic_inc(&qp->refcnt);
+ if((qp->next = ipq_hash[hash]) != NULL)
+ qp->next->pprev = &qp->next;
+ ipq_hash[hash] = qp;
+ qp->pprev = &ipq_hash[hash];
+ ip_frag_nqueues++;
+ write_unlock(&ipfrag_lock);
+ return qp;
}
-/* Add an entry to the 'ipq' queue for a newly received IP datagram.
- * We will (hopefully :-) receive all other fragments of this datagram
- * in time, so we just create a queue for this datagram, in which we
- * will insert the received fragments at their respective positions.
- */
-static struct ipq *ip_create(struct sk_buff *skb, struct iphdr *iph)
+/* Add an entry to the 'ipq' queue for a newly received IP datagram. */
+static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph)
{
struct ipq *qp;
- unsigned int hash;
- int ihlen;
- qp = (struct ipq *) frag_kmalloc(sizeof(struct ipq), GFP_ATOMIC);
- if (qp == NULL)
+ if ((qp = frag_alloc_queue()) == NULL)
goto out_nomem;
- /* Allocate memory for the IP header (plus 8 octets for ICMP). */
- ihlen = iph->ihl * 4;
-
- qp->iph = (struct iphdr *) frag_kmalloc(64 + 8, GFP_ATOMIC);
- if (qp->iph == NULL)
- goto out_free;
-
- memcpy(qp->iph, iph, ihlen + 8);
+ qp->protocol = iph->protocol;
+ qp->last_in = 0;
+ qp->id = iph->id;
+ qp->saddr = iph->saddr;
+ qp->daddr = iph->daddr;
qp->len = 0;
- qp->ihlen = ihlen;
+ qp->meat = 0;
qp->fragments = NULL;
- qp->dev = skb->dev;
/* Initialize a timer for this entry. */
init_timer(&qp->timer);
- qp->timer.expires = 0; /* (to be set later) */
qp->timer.data = (unsigned long) qp; /* pointer to queue */
qp->timer.function = ip_expire; /* expire function */
+ qp->lock = SPIN_LOCK_UNLOCKED;
+ atomic_set(&qp->refcnt, 1);
- /* Add this entry to the queue. */
- hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);
+ return ip_frag_intern(hash, qp);
- /* In a BH context and ipfrag lock is held. -DaveM */
- if((qp->next = ipq_hash[hash]) != NULL)
- qp->next->pprev = &qp->next;
- ipq_hash[hash] = qp;
- qp->pprev = &ipq_hash[hash];
+out_nomem:
+ NETDEBUG(printk(KERN_ERR "ip_frag_create: no memory left !\n"));
+ return NULL;
+}
- return qp;
+/* Find the correct entry in the "incomplete datagrams" queue for
+ * this IP datagram, and create new one, if nothing is found.
+ */
+static inline struct ipq *ip_find(struct iphdr *iph)
+{
+ __u16 id = iph->id;
+ __u32 saddr = iph->saddr;
+ __u32 daddr = iph->daddr;
+ __u8 protocol = iph->protocol;
+ unsigned int hash = ipqhashfn(id, saddr, daddr, protocol);
+ struct ipq *qp;
-out_free:
- frag_kfree_s(qp, sizeof(struct ipq));
-out_nomem:
- NETDEBUG(printk(KERN_ERR "IP: create: no memory left !\n"));
- return(NULL);
+ read_lock(&ipfrag_lock);
+ for(qp = ipq_hash[hash]; qp; qp = qp->next) {
+ if(qp->id == id &&
+ qp->saddr == saddr &&
+ qp->daddr == daddr &&
+ qp->protocol == protocol) {
+ atomic_inc(&qp->refcnt);
+ read_unlock(&ipfrag_lock);
+ return qp;
+ }
+ }
+ read_unlock(&ipfrag_lock);
+
+ return ip_frag_create(hash, iph);
}
-/* See if a fragment queue is complete. */
-static int ip_done(struct ipq *qp)
+/* Add new segment to existing queue. */
+static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
{
- struct ipfrag *fp;
- int offset;
+ struct iphdr *iph = skb->nh.iph;
+ struct sk_buff *prev, *next;
+ int flags, offset;
+ int ihl, end;
- /* Only possible if we received the final fragment. */
- if (qp->len == 0)
- return 0;
+ if (qp->last_in & COMPLETE)
+ goto err;
- /* Check all fragment offsets to see if they connect. */
- fp = qp->fragments;
- offset = 0;
- while (fp) {
- if (fp->offset > offset)
- return(0); /* fragment(s) missing */
- offset = fp->end;
- fp = fp->next;
+ if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time))
+ atomic_inc(&qp->refcnt);
+
+ offset = ntohs(iph->frag_off);
+ flags = offset & ~IP_OFFSET;
+ offset &= IP_OFFSET;
+ offset <<= 3; /* offset is in 8-byte chunks */
+ ihl = iph->ihl * 4;
+
+ /* Determine the position of this fragment. */
+ end = offset + (ntohs(iph->tot_len) - ihl);
+
+ /* Is this the final fragment? */
+ if ((flags & IP_MF) == 0) {
+ /* If we already have some bits beyond end
+ * or have different end, the segment is corrrupted.
+ */
+ if (end < qp->len ||
+ ((qp->last_in & LAST_IN) && end != qp->len))
+ goto err;
+ qp->last_in |= LAST_IN;
+ qp->len = end;
+ } else {
+ if (end&7) {
+ end &= ~7;
+ if (skb->ip_summed != CHECKSUM_UNNECESSARY)
+ skb->ip_summed = CHECKSUM_NONE;
+ }
+ if (end > qp->len) {
+ /* Some bits beyond end -> corruption. */
+ if (qp->last_in & LAST_IN)
+ goto err;
+ qp->len = end;
+ }
}
+ if (end == offset)
+ goto err;
+
+ /* Point into the IP datagram 'data' part. */
+ skb_pull(skb, (skb->nh.raw+ihl) - skb->data);
+ skb_trim(skb, end - offset);
+
+ /* Find out which fragments are in front and at the back of us
+ * in the chain of fragments so far. We must know where to put
+ * this fragment, right?
+ */
+ prev = NULL;
+ for(next = qp->fragments; next != NULL; next = next->next) {
+ if (FRAG_CB(next)->offset >= offset)
+ break; /* bingo! */
+ prev = next;
+ }
+
+ /* We found where to put this one. Check for overlap with
+ * preceding fragment, and, if needed, align things so that
+ * any overlaps are eliminated.
+ */
+ if (prev) {
+ int i = (FRAG_CB(prev)->offset + prev->len) - offset;
+
+ if (i > 0) {
+ offset += i;
+ if (end <= offset)
+ goto err;
+ skb_pull(skb, i);
+ if (skb->ip_summed != CHECKSUM_UNNECESSARY)
+ skb->ip_summed = CHECKSUM_NONE;
+ }
+ }
+
+ while (next && FRAG_CB(next)->offset < end) {
+ int i = end - FRAG_CB(next)->offset; /* overlap is 'i' bytes */
+
+ if (i < next->len) {
+ /* Eat head of the next overlapped fragment
+ * and leave the loop. The next ones cannot overlap.
+ */
+ FRAG_CB(next)->offset += i;
+ skb_pull(next, i);
+ qp->meat -= i;
+ if (next->ip_summed != CHECKSUM_UNNECESSARY)
+ next->ip_summed = CHECKSUM_NONE;
+ break;
+ } else {
+ struct sk_buff *free_it = next;
- /* All fragments are present. */
- return 1;
+ /* Old fragmnet is completely overridden with
+ * new one drop it.
+ */
+ next = next->next;
+
+ if (prev)
+ prev->next = next;
+ else
+ qp->fragments = next;
+
+ qp->meat -= free_it->len;
+ frag_kfree_skb(free_it);
+ }
+ }
+
+ FRAG_CB(skb)->offset = offset;
+
+ /* Insert this fragment in the chain of fragments. */
+ skb->next = next;
+ if (prev)
+ prev->next = skb;
+ else
+ qp->fragments = skb;
+
+ qp->dev = skb->dev;
+ qp->meat += skb->len;
+ atomic_add(skb->truesize, &ip_frag_mem);
+ if (offset == 0)
+ qp->last_in |= FIRST_IN;
+
+ return;
+
+err:
+ kfree_skb(skb);
}
+
/* Build a new IP datagram from all its fragments.
*
* FIXME: We copy here because we lack an effective way of handling lists
* of bits on input. Until the new skb data handling is in I'm not going
* to touch this with a bargepole.
*/
-static struct sk_buff *ip_glue(struct ipq *qp)
+static struct sk_buff *ip_frag_reasm(struct ipq *qp)
{
struct sk_buff *skb;
struct iphdr *iph;
- struct ipfrag *fp;
- unsigned char *ptr;
- int count, len;
+ struct sk_buff *fp, *head = qp->fragments;
+ int len;
+ int ihlen;
+
+ ipq_kill(qp);
+
+ BUG_TRAP(head != NULL);
+ BUG_TRAP(FRAG_CB(head)->offset == 0);
/* Allocate a new buffer for the datagram. */
- len = qp->ihlen + qp->len;
-
+ ihlen = head->nh.iph->ihl*4;
+ len = ihlen + qp->len;
+
if(len > 65535)
goto out_oversize;
-
+
skb = dev_alloc_skb(len);
if (!skb)
goto out_nomem;
/* Fill in the basic details. */
- skb->mac.raw = ptr = skb->data;
- skb->nh.iph = iph = (struct iphdr *) skb_put(skb, len);
+ skb->mac.raw = skb->data;
+ skb->nh.raw = skb->data;
+ FRAG_CB(skb)->h = FRAG_CB(head)->h;
+ skb->ip_summed = head->ip_summed;
+ skb->csum = 0;
/* Copy the original IP headers into the new buffer. */
- memcpy(ptr, qp->iph, qp->ihlen);
- ptr += qp->ihlen;
+ memcpy(skb_put(skb, ihlen), head->nh.iph, ihlen);
/* Copy the data portions of all fragments into the new buffer. */
- fp = qp->fragments;
- count = qp->ihlen;
- while(fp) {
- if ((fp->len <= 0) || ((count + fp->len) > skb->len))
- goto out_invalid;
- memcpy((ptr + fp->offset), fp->ptr, fp->len);
- if (count == qp->ihlen) {
- skb->dst = dst_clone(fp->skb->dst);
- skb->dev = fp->skb->dev;
- }
- count += fp->len;
- fp = fp->next;
+ for (fp=head; fp; fp = fp->next) {
+ memcpy(skb_put(skb, fp->len), fp->data, fp->len);
+
+ if (skb->ip_summed != fp->ip_summed)
+ skb->ip_summed = CHECKSUM_NONE;
+ else if (skb->ip_summed == CHECKSUM_HW)
+ skb->csum = csum_chain(skb->csum, fp->csum);
}
- skb->pkt_type = qp->fragments->skb->pkt_type;
- skb->protocol = qp->fragments->skb->protocol;
+ skb->dst = dst_clone(head->dst);
+ skb->pkt_type = head->pkt_type;
+ skb->protocol = head->protocol;
+ skb->dev = qp->dev;
+
/*
* Clearly bogus, because security markings of the individual
* fragments should have been checked for consistency before
@@ -385,29+554,24 @@ static struct sk_buff *ip_glue(struct ipq *qp) * as well take the value associated with the first fragment.
* --rct
*/
- skb->security = qp->fragments->skb->security;
+ skb->security = head->security;
#ifdef CONFIG_NETFILTER
/* Connection association is same as fragment (if any). */
- skb->nfct = qp->fragments->skb->nfct;
+ skb->nfct = head->nfct;
nf_conntrack_get(skb->nfct);
#ifdef CONFIG_NETFILTER_DEBUG
- skb->nf_debug = qp->fragments->skb->nf_debug;
+ skb->nf_debug = head->nf_debug;
#endif
#endif
/* Done with all fragments. Fixup the new IP header. */
iph = skb->nh.iph;
iph->frag_off = 0;
- iph->tot_len = htons(count);
+ iph->tot_len = htons(len);
IP_INC_STATS_BH(IpReasmOKs);
return skb;
-out_invalid:
- NETDEBUG(printk(KERN_ERR
- "Invalid fragment list: Fragment over size.\n"));
- kfree_skb(skb);
- goto out_fail;
out_nomem:
NETDEBUG(printk(KERN_ERR
"IP: queue_glue: no memory for gluing queue %p\n",
@@ -417,7+581,7 @@ out_oversize: if (net_ratelimit())
printk(KERN_INFO
"Oversized IP packet from %d.%d.%d.%d.\n",
- NIPQUAD(qp->iph->saddr));
+ NIPQUAD(qp->saddr));
out_fail:
IP_INC_STATS_BH(IpReasmFails);
return NULL;
@@ -427,185+591,32 @@ out_fail: struct sk_buff *ip_defrag(struct sk_buff *skb)
{
struct iphdr *iph = skb->nh.iph;
- struct ipfrag *prev, *next, *tmp, *tfp;
struct ipq *qp;
- unsigned char *ptr;
- int flags, offset;
- int i, ihl, end;
IP_INC_STATS_BH(IpReasmReqds);
- spin_lock(&ipfrag_lock);
-
/* Start by cleaning up the memory. */
if (atomic_read(&ip_frag_mem) > sysctl_ipfrag_high_thresh)
ip_evictor();
- /*
- * Look for the entry for this IP datagram in the
- * "incomplete datagrams" queue. If found, the
- * timer is removed.
- */
- qp = ip_find(iph, skb->dst);
-
- /* Is this a non-fragmented datagram? */
- offset = ntohs(iph->frag_off);
- flags = offset & ~IP_OFFSET;
- offset &= IP_OFFSET;
+ /* Lookup (or create) queue header */
+ if ((qp = ip_find(iph)) != NULL) {
+ struct sk_buff *ret = NULL;
- offset <<= 3; /* offset is in 8-byte chunks */
- ihl = iph->ihl * 4;
+ spin_lock(&qp->lock);
- /*
- * Check whether to create a fresh queue entry. If the
- * queue already exists, its timer will be restarted as
- * long as we continue to receive fragments.
- */
- if (qp) {
- /* ANK. If the first fragment is received,
- * we should remember the correct IP header (with options)
- */
- if (offset == 0) {
- /* Fragmented frame replaced by unfragmented copy? */
- if ((flags & IP_MF) == 0)
- goto out_freequeue;
- qp->ihlen = ihl;
- memcpy(qp->iph, iph, (ihl + 8));
- }
- } else {
- /* Fragmented frame replaced by unfragmented copy? */
- if ((offset == 0) && ((flags & IP_MF) == 0))
- goto out_skb;
-
- /* If we failed to create it, then discard the frame. */
- qp = ip_create(skb, iph);
- if (!qp)
- goto out_freeskb;
- }
-
- /* Attempt to construct an oversize packet. */
- if((ntohs(iph->tot_len) + ((int) offset)) > 65535)
- goto out_oversize;
+ ip_frag_queue(qp, skb);
- /* Determine the position of this fragment. */
- end = offset + ntohs(iph->tot_len) - ihl;
+ if (qp->last_in == (FIRST_IN|LAST_IN) &&
+ qp->meat == qp->len)
+ ret = ip_frag_reasm(qp);
- /* Is this the final fragment? */
- if ((flags & IP_MF) == 0)
- qp->len = end;
-
- /* Find out which fragments are in front and at the back of us
- * in the chain of fragments so far. We must know where to put
- * this fragment, right?
- */
- prev = NULL;
- for(next = qp->fragments; next != NULL; next = next->next) {
- if (next->offset >= offset)
- break; /* bingo! */
- prev = next;
+ spin_unlock(&qp->lock);
+ ipq_put(qp);
+ return ret;
}
- /* Point into the IP datagram 'data' part. */
- ptr = skb->data + ihl;
-
- /* We found where to put this one. Check for overlap with
- * preceding fragment, and, if needed, align things so that
- * any overlaps are eliminated.
- */
- if ((prev != NULL) && (offset < prev->end)) {
- i = prev->end - offset;
- offset += i; /* ptr into datagram */
- ptr += i; /* ptr into fragment data */
- }
-
- /* Look for overlap with succeeding segments.
- * If we can merge fragments, do it.
- */
- for (tmp = next; tmp != NULL; tmp = tfp) {
- tfp = tmp->next;
- if (tmp->offset >= end)
- break; /* no overlaps at all */
-
- i = end - next->offset; /* overlap is 'i' bytes */
- tmp->len -= i; /* so reduce size of */
- tmp->offset += i; /* next fragment */
- tmp->ptr += i;
-
- /* If we get a frag size of <= 0, remove it and the packet
- * that it goes with.
- */
- if (tmp->len <= 0) {
- if (tmp->prev != NULL)
- tmp->prev->next = tmp->next;
- else
- qp->fragments = tmp->next;
-
- if (tmp->next != NULL)
- tmp->next->prev = tmp->prev;
-
- /* We have killed the original next frame. */
- next = tfp;
-
- frag_kfree_skb(tmp->skb);
- frag_kfree_s(tmp, sizeof(struct ipfrag));
- }
- }
-
- /*
- * Create a fragment to hold this skb.
- * No memory to save the fragment? throw the lot ...
- */
- tfp = ip_frag_create(offset, end, skb, ptr);
- if (!tfp)
- goto out_freeskb;
-
- /* Insert this fragment in the chain of fragments. */
- tfp->prev = prev;
- tfp->next = next;
- if (prev != NULL)
- prev->next = tfp;
- else
- qp->fragments = tfp;
-
- if (next != NULL)
- next->prev = tfp;
-
- /* OK, so we inserted this new fragment into the chain.
- * Check if we now have a full IP datagram which we can
- * bump up to the IP layer...
- */
- if (ip_done(qp)) {
- /* Glue together the fragments. */
- skb = ip_glue(qp);
- /* Free the queue entry. */
-out_freequeue:
- ip_free(qp);
-out_skb:
- spin_unlock(&ipfrag_lock);
- return skb;
- }
-
- /*
- * The queue is still active ... reset its timer.
- */
-out_timer:
- mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time); /* ~ 30 seconds */
-out:
- spin_unlock(&ipfrag_lock);
- return NULL;
-
- /*
- * Error exits ... we need to reset the timer if there's a queue.
- */
-out_oversize:
- if (net_ratelimit())
- printk(KERN_INFO "Oversized packet received from %u.%u.%u.%u\n",
- NIPQUAD(iph->saddr));
- /* the skb isn't in a fragment, so fall through to free it */
-out_freeskb:
- kfree_skb(skb);
IP_INC_STATS_BH(IpReasmFails);
- if (qp)
- goto out_timer;
- goto out;
+ kfree_skb(skb);
+ return NULL;
}
#include <net/ipip.h>
#include <net/arp.h>
#include <net/checksum.h>
+#include <net/inet_ecn.h>
#ifdef CONFIG_IPV6
#include <net/ipv6.h>
@@ -119,11+120,11 @@ static int ipgre_tunnel_init(struct net_device *dev); static int ipgre_fb_tunnel_init(struct net_device *dev);
static struct net_device ipgre_fb_tunnel_dev = {
- "gre%d", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipgre_fb_tunnel_init,
+ "gre0", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipgre_fb_tunnel_init,
};
static struct ip_tunnel ipgre_fb_tunnel = {
- NULL, &ipgre_fb_tunnel_dev, {0, }, 0, 0, 0, 0, 0, 0, 0, {"gre%d", }
+ NULL, &ipgre_fb_tunnel_dev, {0, }, 0, 0, 0, 0, 0, 0, 0, {"gre0", }
};
/* Tunnel hash table */
#endif
}
+static inline void ipgre_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
+{
+ if (INET_ECN_is_ce(iph->tos)) {
+ if (skb->protocol == __constant_htons(ETH_P_IP)) {
+ if (INET_ECN_is_not_ce(skb->nh.iph->tos))
+ IP_ECN_set_ce(skb->nh.iph);
+ } else if (skb->protocol == __constant_htons(ETH_P_IPV6)) {
+ if (INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h)))
+ IP6_ECN_set_ce(skb->nh.ipv6h);
+ }
+ }
+}
+
+static inline u8
+ipgre_ecn_encapsulate(u8 tos, struct iphdr *old_iph, struct sk_buff *skb)
+{
+#ifdef CONFIG_INET_ECN
+ u8 inner = 0;
+ if (skb->protocol == __constant_htons(ETH_P_IP))
+ inner = old_iph->tos;
+ else if (skb->protocol == __constant_htons(ETH_P_IPV6))
+ inner = ip6_get_dsfield((struct ipv6hdr*)old_iph);
+ return INET_ECN_encapsulate(tos, inner);
+#else
+ return tos;
+#endif
+}
+
int ipgre_rcv(struct sk_buff *skb, unsigned short len)
{
struct iphdr *iph = skb->nh.iph;
@@ -604,6+633,7 @@ int ipgre_rcv(struct sk_buff *skb, unsigned short len) nf_conntrack_put(skb->nfct);
skb->nfct = NULL;
#endif
+ ipgre_ecn_decapsulate(iph, skb);
netif_rx(skb);
read_unlock(&ipgre_lock);
return(0);
@@ -638,6+668,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) int gre_hlen;
u32 dst;
int mtu;
+ int err;
if (tunnel->recursion++) {
tunnel->stat.collisions++;
@@ -789,7+820,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) iph->ihl = sizeof(struct iphdr) >> 2;
iph->frag_off = df;
iph->protocol = IPPROTO_GRE;
- iph->tos = tos;
+ iph->tos = ipgre_ecn_encapsulate(tos, old_iph, skb);
iph->daddr = rt->rt_dst;
iph->saddr = rt->rt_src;
@@ -834,10+865,17 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) skb->nfct = NULL;
#endif
+ err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
+ do_ip_send);
+ if(err < 0) {
+ if(net_ratelimit())
+ printk(KERN_ERR "ipgre_tunnel_xmit: ip_send() failed, err=%d\n", -err);
+ skb = NULL;
+ goto tx_error;
+ }
+
stats->tx_bytes += skb->len;
stats->tx_packets++;
- NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
- do_ip_send);
tunnel->recursion--;
return 0;
@@ -846,7+884,8 @@ tx_error_icmp:
tx_error:
stats->tx_errors++;
- dev_kfree_skb(skb);
+ if(skb)
+ dev_kfree_skb(skb);
tunnel->recursion--;
return 0;
}
*
* The IP to API glue.
*
- * Version: $Id: ip_sockglue.c,v 1.47 2000/01/16 05:11:23 davem Exp $
+ * Version: $Id: ip_sockglue.c,v 1.49 2000/07/08 00:20:43 davem Exp $
*
* Authors: see ip.c
*
@@ -327,6+327,8 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len) if (err)
goto out_free_skb;
+ sock_recv_timestamp(msg, sk, skb);
+
serr = SKB_EXT_ERR(skb);
sin = (struct sockaddr_in *)msg->msg_name;
@@ -462,8+464,15 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt break;
case IP_TOS: /* This sets both TOS and Precedence */
/* Reject setting of unused bits */
+#ifndef CONFIG_INET_ECN
if (val & ~(IPTOS_TOS_MASK|IPTOS_PREC_MASK))
goto e_inval;
+#else
+ if (sk->type == SOCK_STREAM) {
+ val &= ~3;
+ val |= sk->protinfo.af_inet.tos & 3;
+ }
+#endif
if (IPTOS_PREC(val) >= IPTOS_PREC_CRITIC_ECP &&
!capable(CAP_NET_ADMIN)) {
err = -EPERM;
/*
* Linux NET3: IP/IP protocol decoder.
*
- * Version: $Id: ipip.c,v 1.35 2000/07/07 01:55:20 davem Exp $
+ * Version: $Id: ipip.c,v 1.37 2000/07/07 23:47:45 davem Exp $
*
* Authors:
* Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95
#include <net/icmp.h>
#include <net/protocol.h>
#include <net/ipip.h>
+#include <net/inet_ecn.h>
#define HASH_SIZE 16
#define HASH(addr) ((addr^(addr>>4))&0xF)
@@ -122,11+123,11 @@ static int ipip_fb_tunnel_init(struct net_device *dev); static int ipip_tunnel_init(struct net_device *dev);
static struct net_device ipip_fb_tunnel_dev = {
- "tunl%d", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipip_fb_tunnel_init,
+ "tunl0", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipip_fb_tunnel_init,
};
static struct ip_tunnel ipip_fb_tunnel = {
- NULL, &ipip_fb_tunnel_dev, {0, }, 0, 0, 0, 0, 0, 0, 0, {"tunl%d", }
+ NULL, &ipip_fb_tunnel_dev, {0, }, 0, 0, 0, 0, 0, 0, 0, {"tunl0", }
};
static struct ip_tunnel *tunnels_r_l[HASH_SIZE];
#endif
}
+static inline void ipip_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
+{
+ if (INET_ECN_is_ce(iph->tos) &&
+ INET_ECN_is_not_ce(skb->nh.iph->tos))
+ IP_ECN_set_ce(iph);
+}
+
int ipip_rcv(struct sk_buff *skb, unsigned short len)
{
struct iphdr *iph;
@@ -489,6+497,7 @@ int ipip_rcv(struct sk_buff *skb, unsigned short len) nf_conntrack_put(skb->nfct);
skb->nfct = NULL;
#endif
+ ipip_ecn_decapsulate(iph, skb);
netif_rx(skb);
read_unlock(&ipip_lock);
return 0;
@@ -525,6+534,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) int max_headroom; /* The extra header space needed */
u32 dst = tiph->daddr;
int mtu;
+ int err;
if (tunnel->recursion++) {
tunnel->stat.collisions++;
@@ -620,7+630,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) iph->ihl = sizeof(struct iphdr)>>2;
iph->frag_off = df;
iph->protocol = IPPROTO_IPIP;
- iph->tos = tos;
+ iph->tos = INET_ECN_encapsulate(tos, old_iph->tos);
iph->daddr = rt->rt_dst;
iph->saddr = rt->rt_src;
@@ -636,10+646,17 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) skb->nfct = NULL;
#endif
+ err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
+ do_ip_send);
+ if(err < 0) {
+ if(net_ratelimit())
+ printk(KERN_ERR "ipip_tunnel_xmit: ip_send() failed, err=%d\n", -err);
+ skb = NULL;
+ goto tx_error;
+ }
+
stats->tx_bytes += skb->len;
stats->tx_packets++;
- NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
- do_ip_send);
tunnel->recursion--;
return 0;
@@ -647,7+664,8 @@ tx_error_icmp: dst_link_failure(skb);
tx_error:
stats->tx_errors++;
- dev_kfree_skb(skb);
+ if(skb)
+ dev_kfree_skb(skb);
tunnel->recursion--;
return 0;
}
* PROC file system. It is mainly used for debugging and
* statistics.
*
- * Version: $Id: proc.c,v 1.42 2000/04/16 01:11:37 davem Exp $
+ * Version: $Id: proc.c,v 1.43 2000/07/07 22:29:42 davem Exp $
*
* Authors: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
@@ -78,6+78,8 @@ int afinet_get_info(char *buffer, char **start, off_t offset, int length) fold_prot_inuse(&udp_prot));
len += sprintf(buffer+len,"RAW: inuse %d\n",
fold_prot_inuse(&raw_prot));
+ len += sprintf(buffer+len, "FRAG: inuse %d memory %d\n",
+ ip_frag_nqueues, atomic_read(&ip_frag_mem));
if (offset >= len)
{
*start = buffer;
*
* RAW - implementation of IP "raw" sockets.
*
- * Version: $Id: raw.c,v 1.50 2000/05/03 06:37:06 davem Exp $
+ * Version: $Id: raw.c,v 1.52 2000/07/08 00:20:43 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -502,7+502,7 @@ int raw_recvmsg(struct sock *sk, struct msghdr *msg, int len, if (err)
goto done;
- sk->stamp=skb->stamp;
+ sock_recv_timestamp(msg, sk, skb);
/* Copy the address. */
if (sin) {
@@ -580,6+580,36 @@ static int raw_getsockopt(struct sock *sk, int level, int optname, return -ENOPROTOOPT;
}
+static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
+{
+ switch(cmd) {
+ case SIOCOUTQ:
+ {
+ int amount = atomic_read(&sk->wmem_alloc);
+ return put_user(amount, (int *)arg);
+ }
+ case SIOCINQ:
+ {
+ struct sk_buff *skb;
+ int amount = 0;
+
+ spin_lock_irq(&sk->receive_queue.lock);
+ skb = skb_peek(&sk->receive_queue);
+ if (skb != NULL)
+ amount = skb->len;
+ spin_unlock_irq(&sk->receive_queue.lock);
+ return put_user(amount, (int *)arg);
+ }
+
+ default:
+#ifdef CONFIG_IP_MROUTE
+ return ipmr_ioctl(sk, cmd, arg);
+#else
+ return -ENOIOCTLCMD;
+#endif
+ }
+}
+
static void get_raw_sock(struct sock *sp, char *tmpbuf, int i)
{
unsigned int dest, src;
@@ -648,9+678,7 @@ struct proto raw_prot = { close: raw_close,
connect: udp_connect,
disconnect: udp_disconnect,
-#ifdef CONFIG_IP_MROUTE
- ioctl: ipmr_ioctl,
-#endif
+ ioctl: raw_ioctl,
init: raw_init,
setsockopt: raw_setsockopt,
getsockopt: raw_getsockopt,
*
* ROUTE - implementation of the IP router.
*
- * Version: $Id: route.c,v 1.86 2000/04/24 07:03:14 davem Exp $
+ * Version: $Id: route.c,v 1.88 2000/07/07 23:47:45 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -152,23+152,29 @@ struct dst_ops ipv4_dst_ops = sizeof(struct rtable),
};
+#ifdef CONFIG_INET_ECN
+#define ECN_OR_COST(class) TC_PRIO_##class
+#else
+#define ECN_OR_COST(class) TC_PRIO_FILLER
+#endif
+
__u8 ip_tos2prio[16] = {
TC_PRIO_BESTEFFORT,
- TC_PRIO_FILLER,
+ ECN_OR_COST(FILLER),
TC_PRIO_BESTEFFORT,
- TC_PRIO_FILLER,
+ ECN_OR_COST(BESTEFFORT),
TC_PRIO_BULK,
- TC_PRIO_FILLER,
+ ECN_OR_COST(BULK),
TC_PRIO_BULK,
- TC_PRIO_FILLER,
+ ECN_OR_COST(BULK),
TC_PRIO_INTERACTIVE,
- TC_PRIO_FILLER,
+ ECN_OR_COST(INTERACTIVE),
TC_PRIO_INTERACTIVE,
- TC_PRIO_FILLER,
+ ECN_OR_COST(INTERACTIVE),
TC_PRIO_INTERACTIVE_BULK,
- TC_PRIO_FILLER,
+ ECN_OR_COST(INTERACTIVE_BULK),
TC_PRIO_INTERACTIVE_BULK,
- TC_PRIO_FILLER
+ ECN_OR_COST(INTERACTIVE_BULK)
};
@@ -582,9+588,15 @@ restart: route or unicast forwarding path.
*/
if (rt->rt_type == RTN_UNICAST || rt->key.iif == 0) {
- if (!arp_bind_neighbour(&rt->u.dst)) {
+ int err = arp_bind_neighbour(&rt->u.dst);
+ if (err) {
write_unlock_bh(&rt_hash_table[hash].lock);
+ if (err != -ENOBUFS) {
+ rt_drop(rt);
+ return err;
+ }
+
/* Neighbour tables are full and nothing
can be released. Try to shrink route cache,
it is most likely it holds some neighbour records.
@@ -600,13+612,8 @@ restart: goto restart;
}
- if (net_ratelimit()) {
- if ((rt->u.dst.dev->flags&IFF_UP) &&
- __in_dev_get(rt->u.dst.dev))
- printk("Neighbour table overflow.\n");
- else
- printk("Device %s is down.\n", rt->u.dst.dev->name);
- }
+ if (net_ratelimit())
+ printk("Neighbour table overflow.\n");
rt_drop(rt);
return -ENOBUFS;
}
@@ -712,7+719,7 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw, u32 skeys[2] = { saddr, 0 };
int ikeys[2] = { dev->ifindex, 0 };
- tos &= IPTOS_TOS_MASK;
+ tos &= IPTOS_RT_MASK;
if (!in_dev)
return;
@@ -791,7+798,7 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw, if (rt->peer)
atomic_inc(&rt->peer->refcnt);
- if (!arp_bind_neighbour(&rt->u.dst) ||
+ if (arp_bind_neighbour(&rt->u.dst) ||
!(rt->u.dst.neighbour->nud_state&NUD_VALID)) {
if (rt->u.dst.neighbour)
neigh_event_send(rt->u.dst.neighbour, NULL);
@@ -967,7+974,7 @@ unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu) struct rtable *rth;
u32 skeys[2] = { iph->saddr, 0, };
u32 daddr = iph->daddr;
- u8 tos = iph->tos & IPTOS_TOS_MASK;
+ u8 tos = iph->tos & IPTOS_RT_MASK;
unsigned short est_mtu = 0;
if (ipv4_config.no_pmtu_disc)
@@ -1546,7+1553,7 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr, unsigned hash;
int iif = dev->ifindex;
- tos &= IPTOS_TOS_MASK;
+ tos &= IPTOS_RT_MASK;
hash = rt_hash_code(daddr, saddr^(iif<<5), tos);
read_lock(&rt_hash_table[hash].lock);
@@ -1616,10+1623,10 @@ int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int int free_res = 0;
int err;
- tos &= IPTOS_TOS_MASK|RTO_ONLINK;
+ tos &= IPTOS_RT_MASK|RTO_ONLINK;
key.dst = daddr;
key.src = saddr;
- key.tos = tos&IPTOS_TOS_MASK;
+ key.tos = tos&IPTOS_RT_MASK;
key.iif = loopback_dev.ifindex;
key.oif = oif;
key.scope = (tos&RTO_ONLINK) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
@@ -1889,7+1896,7 @@ int ip_route_output(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int oif) rth->key.src == saddr &&
rth->key.iif == 0 &&
rth->key.oif == oif &&
- !((rth->key.tos^tos)&(IPTOS_TOS_MASK|RTO_ONLINK)) &&
+ !((rth->key.tos^tos)&(IPTOS_RT_MASK|RTO_ONLINK)) &&
((tos&RTO_TPROXY) || !(rth->rt_flags&RTCF_TPROXY))
) {
rth->u.dst.lastuse = jiffies;
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp.c,v 1.169 2000/04/20 14:41:16 davem Exp $
+ * Version: $Id: tcp.c,v 1.170 2000/07/08 00:20:43 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1018,9+1018,13 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size) tcp_send_skb(sk, skb, queue_it, mss_now);
}
}
- sk->err = 0;
err = copied;
- goto out;
+out:
+ __tcp_push_pending_frames(sk, tp, mss_now);
+ TCP_CHECK_TIMER(sk);
+out_unlock:
+ release_sock(sk);
+ return err;
do_sock_err:
if(copied)
@@ -1048,12+1052,7 @@ do_fault: kfree_skb(skb);
do_fault2:
err = -EFAULT;
-out:
- __tcp_push_pending_frames(sk, tp, mss_now);
- TCP_CHECK_TIMER(sk);
-out_unlock:
- release_sock(sk);
- return err;
+ goto out;
}
#undef PSH_NEEDED
@@ -1270,10+1269,6 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
TCP_CHECK_TIMER(sk);
-
- if (sk->err)
- goto out_err;
-
err = -ENOTCONN;
if (sk->state == TCP_LISTEN)
goto out;
@@ -1292,13+1287,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
- /*
- * BUG BUG BUG
- * This violates 1003.1g compliance. We must wait for
- * data to exist even if we read none!
- */
-
- while (len > 0) {
+ do {
struct sk_buff * skb;
u32 offset;
@@ -1519,29+1508,6 @@ do_prequeue: continue;
skb->used = 1;
tcp_eat_skb(sk, skb);
-
-#ifdef TCP_LESS_COARSE_ACKS
- /* Possible improvement. When sender is faster than receiver,
- * traffic looks like: fill window ... wait for window open ...
- * fill window. We lose at least one rtt, because call
- * cleanup_rbuf only once. Probably, if "len" was large
- * we should insert several intermediate cleanup_rbuf(s).
- *
- * F.e.:
- */
- do {
- u32 full_space = min(tp->window_clamp, tcp_full_space(sk));
-
- /* Try to ACK, if total buffer length is larger
- than maximal window and if rcv_window has
- chances to increase twice. It will result
- to exponentially decreased ACKing during
- read to huge (usually, mmapped) buffer.
- */
- if (len >= full_space && tp->rcv_wnd <= full_space/2)
- cleanup_rbuf(sk, copied);
- } while (0);
-#endif
continue;
found_fin_ok:
@@ -1552,7+1518,7 @@ do_prequeue: /* All is done. */
skb->used = 1;
break;
- }
+ } while (len > 0);
if (user_recv) {
if (skb_queue_len(&tp->ucopy.prequeue)) {
@@ -1584,9+1550,6 @@ do_prequeue: release_sock(sk);
return copied;
-out_err:
- err = sock_error(sk);
-
out:
TCP_CHECK_TIMER(sk);
release_sock(sk);
@@ -2012,7+1975,6 @@ struct sock *tcp_accept(struct sock *sk, int flags, int *err) struct open_request *req;
struct sock *newsk;
int error;
- long timeo;
lock_sock(sk);
@@ -2023,10+1985,10 @@ struct sock *tcp_accept(struct sock *sk, int flags, int *err) if (sk->state != TCP_LISTEN)
goto out;
- timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
-
/* Find already established connection */
if (!tp->accept_queue) {
+ long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
+
/* If this is a non blocking socket don't sleep */
error = -EAGAIN;
if (!timeo)
@@ -2099,6+2061,8 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval, break;
}
tp->nonagle = (val == 0) ? 0 : 1;
+ if (val)
+ tcp_push_pending_frames(sk, tp);
break;
case TCP_CORK:
*
* The User Datagram Protocol (UDP).
*
- * Version: $Id: udp.c,v 1.83 2000/06/09 07:35:49 davem Exp $
+ * Version: $Id: udp.c,v 1.84 2000/07/08 00:20:43 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -710,7+710,8 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
if (err)
goto out_free;
- sk->stamp=skb->stamp;
+
+ sock_recv_timestamp(msg, sk, skb);
/* Copy the address. */
if (sin)
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: datagram.c,v 1.19 2000/02/27 19:51:47 davem Exp $
+ * $Id: datagram.c,v 1.20 2000/07/08 00:20:43 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -127,6+127,8 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) if (err)
goto out_free_skb;
+ sock_recv_timestamp(msg, sk, skb);
+
serr = SKB_EXT_ERR(skb);
sin = (struct sockaddr_in6 *)msg->msg_name;
* PROC file system. This is very similar to the IPv4 version,
* except it reports the sockets in the INET6 address family.
*
- * Version: $Id: proc.c,v 1.14 2000/04/16 01:11:37 davem Exp $
+ * Version: $Id: proc.c,v 1.15 2000/07/07 22:29:42 davem Exp $
*
* Authors: David S. Miller (davem@caip.rutgers.edu)
*
@@ -46,6+46,8 @@ int afinet6_get_info(char *buffer, char **start, off_t offset, int length, int d fold_prot_inuse(&udpv6_prot));
len += sprintf(buffer+len, "RAW6: inuse %d\n",
fold_prot_inuse(&rawv6_prot));
+ len += sprintf(buffer+len, "FRAG6: inuse %d memory %d\n",
+ ip6_frag_nqueues, atomic_read(&ip6_frag_mem));
*start = buffer + offset;
len -= offset;
if(len > length)
*
* Adapted from linux/net/ipv4/raw.c
*
- * $Id: raw.c,v 1.36 2000/05/03 06:37:07 davem Exp $
+ * $Id: raw.c,v 1.39 2000/07/08 00:20:43 davem Exp $
*
* Fixes:
* Hideaki YOSHIFUJI : sin6_scope_id support
@@ -331,7+331,6 @@ int rawv6_recvmsg(struct sock *sk, struct msghdr *msg, int len, }
err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
- sk->stamp=skb->stamp;
if (err)
goto out_free;
@@ -348,6+347,8 @@ int rawv6_recvmsg(struct sock *sk, struct msghdr *msg, int len, }
}
+ sock_recv_timestamp(msg, sk, skb);
+
if (sk->net_pinfo.af_inet6.rxopt.all)
datagram_recv_ctl(sk, msg, skb);
err = copied;
@@ -535,6+536,8 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, int len)
fl.proto = proto;
fl.fl6_dst = daddr;
+ if (fl.fl6_src == NULL && !ipv6_addr_any(&np->saddr))
+ fl.fl6_src = &np->saddr;
fl.uli_u.icmpt.type = 0;
fl.uli_u.icmpt.code = 0;
@@ -694,6+697,31 @@ static int rawv6_getsockopt(struct sock *sk, int level, int optname, return 0;
}
+static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
+{
+ switch(cmd) {
+ case SIOCOUTQ:
+ {
+ int amount = atomic_read(&sk->wmem_alloc);
+ return put_user(amount, (int *)arg);
+ }
+ case SIOCINQ:
+ {
+ struct sk_buff *skb;
+ int amount = 0;
+
+ spin_lock_irq(&sk->receive_queue.lock);
+ skb = skb_peek(&sk->receive_queue);
+ if (skb != NULL)
+ amount = skb->tail - skb->h.raw;
+ spin_unlock_irq(&sk->receive_queue.lock);
+ return put_user(amount, (int *)arg);
+ }
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
static void rawv6_close(struct sock *sk, long timeout)
{
@@ -790,6+818,7 @@ struct proto rawv6_prot = { close: rawv6_close,
connect: udpv6_connect,
disconnect: udp_disconnect,
+ ioctl: rawv6_ioctl,
init: rawv6_init_sk,
destroy: inet6_destroy_sock,
setsockopt: rawv6_setsockopt,
-/*
- * IPv6 fragment reassembly
- * Linux INET6 implementation
- *
- * Authors:
- * Pedro Roque <roque@di.fc.ul.pt>
- *
- * $Id: reassembly.c,v 1.17 2000/05/03 06:37:07 davem Exp $
- *
- * Based on: net/ipv4/ip_fragment.c
- *
- * 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.
- */
-
-/*
- * Fixes:
- * Andi Kleen Make it work with multiple hosts.
- * More RFC compliance.
- *
- * Horst von Brand Add missing #include <linux/string.h>
- */
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/sched.h>
-#include <linux/net.h>
-#include <linux/netdevice.h>
-#include <linux/in6.h>
-#include <linux/ipv6.h>
-#include <linux/icmpv6.h>
-
-#include <net/sock.h>
-#include <net/snmp.h>
-
-#include <net/ipv6.h>
-#include <net/protocol.h>
-#include <net/transp_v6.h>
-#include <net/rawv6.h>
-#include <net/ndisc.h>
-#include <net/addrconf.h>
-
-int sysctl_ip6frag_high_thresh = 256*1024;
-int sysctl_ip6frag_low_thresh = 192*1024;
-int sysctl_ip6frag_time = IPV6_FRAG_TIMEOUT;
-
-atomic_t ip6_frag_mem = ATOMIC_INIT(0);
-
-static spinlock_t ip6_frag_lock = SPIN_LOCK_UNLOCKED;
-
-struct ipv6_frag {
- __u16 offset;
- __u16 len;
- struct sk_buff *skb;
-
- struct frag_hdr *fhdr;
-
- struct ipv6_frag *next;
-};
-
-/*
- * Equivalent of ipv4 struct ipq
- */
-
-struct frag_queue {
-
- struct frag_queue *next;
- struct frag_queue *prev;
-
- __u32 id; /* fragment id */
- struct in6_addr saddr;
- struct in6_addr daddr;
- struct timer_list timer; /* expire timer */
- struct ipv6_frag *fragments;
- struct net_device *dev;
- int iif;
- __u8 last_in; /* has first/last segment arrived? */
-#define FIRST_IN 2
-#define LAST_IN 1
- __u8 nexthdr;
- __u16 nhoffset;
-};
-
-static struct frag_queue ipv6_frag_queue = {
- &ipv6_frag_queue, &ipv6_frag_queue,
-};
-
-/* Memory Tracking Functions. */
-extern __inline__ void frag_kfree_skb(struct sk_buff *skb)
-{
- atomic_sub(skb->truesize, &ip6_frag_mem);
- kfree_skb(skb);
-}
-
-extern __inline__ void frag_kfree_s(void *ptr, int len)
-{
- atomic_sub(len, &ip6_frag_mem);
- kfree(ptr);
-}
-
-extern __inline__ void *frag_kmalloc(int size, int pri)
-{
- void *vp = kmalloc(size, pri);
-
- if(!vp)
- return NULL;
- atomic_add(size, &ip6_frag_mem);
- return vp;
-}
-
-
-static void create_frag_entry(struct sk_buff *skb,
- __u8 *nhptr,
- struct frag_hdr *fhdr);
-static u8 * reasm_frag(struct frag_queue *fq,
- struct sk_buff **skb_in);
-
-static void reasm_queue(struct frag_queue *fq,
- struct sk_buff *skb,
- struct frag_hdr *fhdr,
- u8 *nhptr);
-
-static void fq_free(struct frag_queue *fq);
-
-static void frag_prune(void)
-{
- struct frag_queue *fq;
-
- spin_lock(&ip6_frag_lock);
- while ((fq = ipv6_frag_queue.next) != &ipv6_frag_queue) {
- IP6_INC_STATS_BH(Ip6ReasmFails);
- fq_free(fq);
- if (atomic_read(&ip6_frag_mem) <= sysctl_ip6frag_low_thresh) {
- spin_unlock(&ip6_frag_lock);
- return;
- }
- }
- if (atomic_read(&ip6_frag_mem))
- printk(KERN_DEBUG "IPv6 frag_prune: memleak\n");
- atomic_set(&ip6_frag_mem, 0);
- spin_unlock(&ip6_frag_lock);
-}
-
-
-u8* ipv6_reassembly(struct sk_buff **skbp, __u8 *nhptr)
-{
- struct sk_buff *skb = *skbp;
- struct frag_hdr *fhdr = (struct frag_hdr *) (skb->h.raw);
- struct frag_queue *fq;
- struct ipv6hdr *hdr;
-
- hdr = skb->nh.ipv6h;
-
- IP6_INC_STATS_BH(Ip6ReasmReqds);
-
- /* Jumbo payload inhibits frag. header */
- if (hdr->payload_len==0) {
- icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw);
- return NULL;
- }
- if ((u8 *)(fhdr+1) > skb->tail) {
- icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw);
- return NULL;
- }
- if (atomic_read(&ip6_frag_mem) > sysctl_ip6frag_high_thresh)
- frag_prune();
-
- spin_lock(&ip6_frag_lock);
- for (fq = ipv6_frag_queue.next; fq != &ipv6_frag_queue; fq = fq->next) {
- if (fq->id == fhdr->identification &&
- !ipv6_addr_cmp(&hdr->saddr, &fq->saddr) &&
- !ipv6_addr_cmp(&hdr->daddr, &fq->daddr)) {
- u8 *ret = NULL;
-
- reasm_queue(fq, skb, fhdr, nhptr);
-
- if (fq->last_in == (FIRST_IN|LAST_IN))
- ret = reasm_frag(fq, skbp);
-
- spin_unlock(&ip6_frag_lock);
- return ret;
- }
- }
-
- create_frag_entry(skb, nhptr, fhdr);
- spin_unlock(&ip6_frag_lock);
-
- return NULL;
-}
-
-
-static void fq_free(struct frag_queue *fq)
-{
- struct ipv6_frag *fp, *back;
-
- del_timer(&fq->timer);
-
- for (fp = fq->fragments; fp; ) {
- frag_kfree_skb(fp->skb);
- back = fp;
- fp=fp->next;
- frag_kfree_s(back, sizeof(*back));
- }
-
- fq->prev->next = fq->next;
- fq->next->prev = fq->prev;
-
- fq->prev = fq->next = NULL;
-
- frag_kfree_s(fq, sizeof(*fq));
-}
-
-static void frag_expire(unsigned long data)
-{
- struct frag_queue *fq;
- struct ipv6_frag *frag;
-
- fq = (struct frag_queue *) data;
-
- spin_lock(&ip6_frag_lock);
-
- frag = fq->fragments;
-
- IP6_INC_STATS_BH(Ip6ReasmTimeout);
- IP6_INC_STATS_BH(Ip6ReasmFails);
-
- if (frag == NULL) {
- spin_unlock(&ip6_frag_lock);
- printk(KERN_DEBUG "invalid fragment queue\n");
- return;
- }
-
- /* Send error only if the first segment arrived.
- (fixed --ANK (980728))
- */
- if (fq->last_in&FIRST_IN) {
- struct net_device *dev = dev_get_by_index(fq->iif);
-
- /*
- But use as source device on which LAST ARRIVED
- segment was received. And do not use fq->dev
- pointer directly, device might already disappeared.
- */
- if (dev) {
- frag->skb->dev = dev;
- icmpv6_send(frag->skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0,
- dev);
- dev_put(dev);
- }
- }
-
- fq_free(fq);
- spin_unlock(&ip6_frag_lock);
-}
-
-
-static void create_frag_entry(struct sk_buff *skb,
- __u8 *nhptr,
- struct frag_hdr *fhdr)
-{
- struct frag_queue *fq;
- struct ipv6hdr *hdr;
-
- fq = (struct frag_queue *) frag_kmalloc(sizeof(struct frag_queue),
- GFP_ATOMIC);
-
- if (fq == NULL) {
- IP6_INC_STATS_BH(Ip6ReasmFails);
- kfree_skb(skb);
- return;
- }
-
- memset(fq, 0, sizeof(struct frag_queue));
-
- fq->id = fhdr->identification;
-
- hdr = skb->nh.ipv6h;
- ipv6_addr_copy(&fq->saddr, &hdr->saddr);
- ipv6_addr_copy(&fq->daddr, &hdr->daddr);
-
- /* init_timer has been done by the memset */
- fq->timer.function = frag_expire;
- fq->timer.data = (long) fq;
- fq->timer.expires = jiffies + sysctl_ip6frag_time;
-
- reasm_queue(fq, skb, fhdr, nhptr);
-
- if (fq->fragments) {
- fq->prev = ipv6_frag_queue.prev;
- fq->next = &ipv6_frag_queue;
- fq->prev->next = fq;
- ipv6_frag_queue.prev = fq;
-
- add_timer(&fq->timer);
- } else
- frag_kfree_s(fq, sizeof(*fq));
-}
-
-
-/*
- * We queue the packet even if it's the last.
- * It's a trade off. This allows the reassembly
- * code to be simpler (=faster) and of the
- * steps we do for queueing the only unnecessary
- * one it's the kmalloc for a struct ipv6_frag.
- * Feel free to try other alternatives...
- */
-
-static void reasm_queue(struct frag_queue *fq, struct sk_buff *skb,
- struct frag_hdr *fhdr, u8 *nhptr)
-{
- struct ipv6_frag *nfp, *fp, **bptr;
-
- nfp = (struct ipv6_frag *) frag_kmalloc(sizeof(struct ipv6_frag),
- GFP_ATOMIC);
-
- if (nfp == NULL) {
- kfree_skb(skb);
- return;
- }
-
- nfp->offset = ntohs(fhdr->frag_off) & ~0x7;
- nfp->len = (ntohs(skb->nh.ipv6h->payload_len) -
- ((u8 *) (fhdr + 1) - (u8 *) (skb->nh.ipv6h + 1)));
-
- if ((u32)nfp->offset + (u32)nfp->len >= 65536) {
- icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off);
- goto err;
- }
- if (fhdr->frag_off & __constant_htons(0x0001)) {
- /* Check if the fragment is rounded to 8 bytes.
- * Required by the RFC.
- * ... and would break our defragmentation algorithm 8)
- */
- if (nfp->len & 0x7) {
- printk(KERN_DEBUG "fragment not rounded to 8bytes\n");
-
- /*
- It is not in specs, but I see no reasons
- to send an error in this case. --ANK
- */
- if (nfp->offset == 0)
- icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
- &skb->nh.ipv6h->payload_len);
- goto err;
- }
- }
-
- nfp->skb = skb;
- nfp->fhdr = fhdr;
- nfp->next = NULL;
-
- bptr = &fq->fragments;
-
- for (fp = fq->fragments; fp; fp=fp->next) {
- if (nfp->offset <= fp->offset)
- break;
- bptr = &fp->next;
- }
- if (fp && fp->offset == nfp->offset) {
- if (nfp->len != fp->len) {
- printk(KERN_DEBUG "reasm_queue: dup with wrong len\n");
- }
-
- /* duplicate. discard it. */
- goto err;
- }
-
- atomic_add(skb->truesize, &ip6_frag_mem);
-
- /* All the checks are done, fragment is acepted.
- Only now we are allowed to update reassembly data!
- (fixed --ANK (980728))
- */
-
- /* iif always set to one of the last arrived segment */
- fq->dev = skb->dev;
- fq->iif = skb->dev->ifindex;
-
- /* Last fragment */
- if ((fhdr->frag_off & __constant_htons(0x0001)) == 0)
- fq->last_in |= LAST_IN;
-
- /* First fragment.
- nexthdr and nhptr are get from the first fragment.
- Moreover, nexthdr is UNDEFINED for all the fragments but the
- first one.
- (fixed --ANK (980728))
- */
- if (nfp->offset == 0) {
- fq->nexthdr = fhdr->nexthdr;
- fq->last_in |= FIRST_IN;
- fq->nhoffset = nhptr - skb->nh.raw;
- }
-
- *bptr = nfp;
- nfp->next = fp;
- return;
-
-err:
- frag_kfree_s(nfp, sizeof(*nfp));
- kfree_skb(skb);
-}
-
-/*
- * check if this fragment completes the packet
- * returns true on success
- */
-static u8* reasm_frag(struct frag_queue *fq, struct sk_buff **skb_in)
-{
- struct ipv6_frag *fp;
- struct ipv6_frag *head = fq->fragments;
- struct ipv6_frag *tail = NULL;
- struct sk_buff *skb;
- __u32 offset = 0;
- __u32 payload_len;
- __u16 unfrag_len;
- __u16 copy;
- u8 *nhptr;
-
- for(fp = head; fp; fp=fp->next) {
- if (offset != fp->offset)
- return NULL;
-
- offset += fp->len;
- tail = fp;
- }
-
- /*
- * we know the m_flag arrived and we have a queue,
- * starting from 0, without gaps.
- * this means we have all fragments.
- */
-
- /* Unfragmented part is taken from the first segment.
- (fixed --ANK (980728))
- */
- unfrag_len = (u8 *) (head->fhdr) - (u8 *) (head->skb->nh.ipv6h + 1);
-
- payload_len = (unfrag_len + tail->offset +
- (tail->skb->tail - (__u8 *) (tail->fhdr + 1)));
-
- if (payload_len > 65535) {
- if (net_ratelimit())
- printk(KERN_DEBUG "reasm_frag: payload len = %d\n", payload_len);
- IP6_INC_STATS_BH(Ip6ReasmFails);
- fq_free(fq);
- return NULL;
- }
-
- if ((skb = dev_alloc_skb(sizeof(struct ipv6hdr) + payload_len))==NULL) {
- if (net_ratelimit())
- printk(KERN_DEBUG "reasm_frag: no memory for reassembly\n");
- IP6_INC_STATS_BH(Ip6ReasmFails);
- fq_free(fq);
- return NULL;
- }
-
- copy = unfrag_len + sizeof(struct ipv6hdr);
-
- skb->nh.ipv6h = (struct ipv6hdr *) skb->data;
- skb->dev = fq->dev;
- skb->protocol = __constant_htons(ETH_P_IPV6);
- skb->pkt_type = head->skb->pkt_type;
- memcpy(skb->cb, head->skb->cb, sizeof(skb->cb));
- skb->dst = dst_clone(head->skb->dst);
-
- memcpy(skb_put(skb, copy), head->skb->nh.ipv6h, copy);
- nhptr = skb->nh.raw + fq->nhoffset;
- *nhptr = fq->nexthdr;
-
- skb->h.raw = skb->tail;
-
- skb->nh.ipv6h->payload_len = ntohs(payload_len);
-
- *skb_in = skb;
-
- /*
- * FIXME: If we don't have a checksum we ought to be able
- * to defragment and checksum in this pass. [AC]
- * Note that we don't really know yet whether the protocol
- * needs checksums at all. It might still be a good idea. -AK
- */
- for(fp = fq->fragments; fp; ) {
- struct ipv6_frag *back;
-
- memcpy(skb_put(skb, fp->len), (__u8*)(fp->fhdr + 1), fp->len);
- frag_kfree_skb(fp->skb);
- back = fp;
- fp=fp->next;
- frag_kfree_s(back, sizeof(*back));
- }
-
- del_timer(&fq->timer);
- fq->prev->next = fq->next;
- fq->next->prev = fq->prev;
- fq->prev = fq->next = NULL;
-
- frag_kfree_s(fq, sizeof(*fq));
-
- IP6_INC_STATS_BH(Ip6ReasmOKs);
- return nhptr;
-}
+/*
+ * IPv6 fragment reassembly
+ * Linux INET6 implementation
+ *
+ * Authors:
+ * Pedro Roque <roque@di.fc.ul.pt>
+ *
+ * $Id: reassembly.c,v 1.18 2000/07/07 22:29:42 davem Exp $
+ *
+ * Based on: net/ipv4/ip_fragment.c
+ *
+ * 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.
+ */
+
+/*
+ * Fixes:
+ * Andi Kleen Make it work with multiple hosts.
+ * More RFC compliance.
+ *
+ * Horst von Brand Add missing #include <linux/string.h>
+ * Alexey Kuznetsov SMP races, threading, cleanup.
+ */
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/sched.h>
+#include <linux/net.h>
+#include <linux/netdevice.h>
+#include <linux/in6.h>
+#include <linux/ipv6.h>
+#include <linux/icmpv6.h>
+
+#include <net/sock.h>
+#include <net/snmp.h>
+
+#include <net/ipv6.h>
+#include <net/protocol.h>
+#include <net/transp_v6.h>
+#include <net/rawv6.h>
+#include <net/ndisc.h>
+#include <net/addrconf.h>
+
+int sysctl_ip6frag_high_thresh = 256*1024;
+int sysctl_ip6frag_low_thresh = 192*1024;
+
+int sysctl_ip6frag_time = IPV6_FRAG_TIMEOUT;
+
+struct ip6frag_skb_cb
+{
+ struct inet6_skb_parm h;
+ int offset;
+};
+
+#define FRAG6_CB(skb) ((struct ip6frag_skb_cb*)((skb)->cb))
+
+
+/*
+ * Equivalent of ipv4 struct ipq
+ */
+
+struct frag_queue
+{
+ struct frag_queue *next;
+
+ __u32 id; /* fragment id */
+ struct in6_addr saddr;
+ struct in6_addr daddr;
+
+ spinlock_t lock;
+ atomic_t refcnt;
+ struct timer_list timer; /* expire timer */
+ struct sk_buff *fragments;
+ int len;
+ int meat;
+ struct net_device *dev;
+ int iif;
+ __u8 last_in; /* has first/last segment arrived? */
+#define COMPLETE 4
+#define FIRST_IN 2
+#define LAST_IN 1
+ __u8 nexthdr;
+ __u16 nhoffset;
+ struct frag_queue **pprev;
+};
+
+/* Hash table. */
+
+#define IP6Q_HASHSZ 64
+
+static struct frag_queue *ip6_frag_hash[IP6Q_HASHSZ];
+static rwlock_t ip6_frag_lock = RW_LOCK_UNLOCKED;
+int ip6_frag_nqueues = 0;
+
+static __inline__ void __fq_unlink(struct frag_queue *fq)
+{
+ if(fq->next)
+ fq->next->pprev = fq->pprev;
+ *fq->pprev = fq->next;
+ ip6_frag_nqueues--;
+}
+
+static __inline__ void fq_unlink(struct frag_queue *fq)
+{
+ write_lock(&ip6_frag_lock);
+ __fq_unlink(fq);
+ write_unlock(&ip6_frag_lock);
+}
+
+static __inline__ unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr,
+ struct in6_addr *daddr)
+{
+ unsigned int h = saddr->s6_addr32[3] ^ daddr->s6_addr32[3] ^ id;
+
+ h ^= (h>>16);
+ h ^= (h>>8);
+ return h & (IP6Q_HASHSZ - 1);
+}
+
+
+atomic_t ip6_frag_mem = ATOMIC_INIT(0);
+
+/* Memory Tracking Functions. */
+extern __inline__ void frag_kfree_skb(struct sk_buff *skb)
+{
+ atomic_sub(skb->truesize, &ip6_frag_mem);
+ kfree_skb(skb);
+}
+
+extern __inline__ void frag_free_queue(struct frag_queue *fq)
+{
+ atomic_sub(sizeof(struct frag_queue), &ip6_frag_mem);
+ kfree(fq);
+}
+
+extern __inline__ struct frag_queue *frag_alloc_queue(void)
+{
+ struct frag_queue *fq = kmalloc(sizeof(struct frag_queue), GFP_ATOMIC);
+
+ if(!fq)
+ return NULL;
+ atomic_add(sizeof(struct frag_queue), &ip6_frag_mem);
+ return fq;
+}
+
+/* Destruction primitives. */
+
+/* Complete destruction of fq. */
+static void ip6_frag_destroy(struct frag_queue *fq)
+{
+ struct sk_buff *fp;
+
+ BUG_TRAP(fq->last_in&COMPLETE);
+ BUG_TRAP(del_timer(&fq->timer) == 0);
+
+ /* Release all fragment data. */
+ fp = fq->fragments;
+ while (fp) {
+ struct sk_buff *xp = fp->next;
+
+ frag_kfree_skb(fp);
+ fp = xp;
+ }
+
+ frag_free_queue(fq);
+}
+
+static __inline__ void fq_put(struct frag_queue *fq)
+{
+ if (atomic_dec_and_test(&fq->refcnt))
+ ip6_frag_destroy(fq);
+}
+
+/* Kill fq entry. It is not destroyed immediately,
+ * because caller (and someone more) holds reference count.
+ */
+static __inline__ void fq_kill(struct frag_queue *fq)
+{
+ if (del_timer(&fq->timer))
+ atomic_dec(&fq->refcnt);
+
+ if (!(fq->last_in & COMPLETE)) {
+ fq_unlink(fq);
+ atomic_dec(&fq->refcnt);
+ fq->last_in |= COMPLETE;
+ }
+}
+
+static void ip6_evictor(void)
+{
+ int i, progress;
+
+ do {
+ if (atomic_read(&ip6_frag_mem) <= sysctl_ip6frag_low_thresh)
+ return;
+ progress = 0;
+ for (i = 0; i < IP6Q_HASHSZ; i++) {
+ struct frag_queue *fq;
+ if (ip6_frag_hash[i] == NULL)
+ continue;
+
+ write_lock(&ip6_frag_lock);
+ if ((fq = ip6_frag_hash[i]) != NULL) {
+ /* find the oldest queue for this hash bucket */
+ while (fq->next)
+ fq = fq->next;
+ __fq_unlink(fq);
+ write_unlock(&ip6_frag_lock);
+
+ spin_lock(&fq->lock);
+ if (del_timer(&fq->timer))
+ atomic_dec(&fq->refcnt);
+ fq->last_in |= COMPLETE;
+ spin_unlock(&fq->lock);
+
+ fq_put(fq);
+ IP6_INC_STATS_BH(Ip6ReasmFails);
+ progress = 1;
+ continue;
+ }
+ write_unlock(&ip6_frag_lock);
+ }
+ } while (progress);
+}
+
+static void ip6_frag_expire(unsigned long data)
+{
+ struct frag_queue *fq = (struct frag_queue *) data;
+
+ spin_lock(&fq->lock);
+
+ if (fq->last_in & COMPLETE)
+ goto out;
+
+ fq_kill(fq);
+
+ IP6_INC_STATS_BH(Ip6ReasmTimeout);
+ IP6_INC_STATS_BH(Ip6ReasmFails);
+
+ /* Send error only if the first segment arrived. */
+ if (fq->last_in&FIRST_IN && fq->fragments) {
+ struct net_device *dev = dev_get_by_index(fq->iif);
+
+ /*
+ But use as source device on which LAST ARRIVED
+ segment was received. And do not use fq->dev
+ pointer directly, device might already disappeared.
+ */
+ if (dev) {
+ fq->fragments->dev = dev;
+ icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0,
+ dev);
+ dev_put(dev);
+ }
+ }
+out:
+ spin_unlock(&fq->lock);
+ fq_put(fq);
+}
+
+/* Creation primitives. */
+
+
+static struct frag_queue *ip6_frag_intern(unsigned int hash,
+ struct frag_queue *fq_in)
+{
+ struct frag_queue *fq;
+
+ write_lock(&ip6_frag_lock);
+#ifdef CONFIG_SMP
+ for (fq = ip6_frag_hash[hash]; fq; fq = fq->next) {
+ if (fq->id == fq_in->id &&
+ !ipv6_addr_cmp(&fq_in->saddr, &fq->saddr) &&
+ !ipv6_addr_cmp(&fq_in->daddr, &fq->daddr)) {
+ atomic_inc(&fq->refcnt);
+ write_unlock(&ip6_frag_lock);
+ fq_in->last_in |= COMPLETE;
+ fq_put(fq_in);
+ return fq;
+ }
+ }
+#endif
+ fq = fq_in;
+
+ atomic_inc(&fq->refcnt);
+ if((fq->next = ip6_frag_hash[hash]) != NULL)
+ fq->next->pprev = &fq->next;
+ ip6_frag_hash[hash] = fq;
+ fq->pprev = &ip6_frag_hash[hash];
+ ip6_frag_nqueues++;
+ write_unlock(&ip6_frag_lock);
+ return fq;
+}
+
+
+static struct frag_queue *
+ip6_frag_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr *dst)
+{
+ struct frag_queue *fq;
+
+ if ((fq = frag_alloc_queue()) == NULL)
+ goto oom;
+
+ memset(fq, 0, sizeof(struct frag_queue));
+
+ fq->id = id;
+ ipv6_addr_copy(&fq->saddr, src);
+ ipv6_addr_copy(&fq->daddr, dst);
+
+ /* init_timer has been done by the memset */
+ fq->timer.function = ip6_frag_expire;
+ fq->timer.data = (long) fq;
+ fq->lock = SPIN_LOCK_UNLOCKED;
+ atomic_set(&fq->refcnt, 1);
+
+ return ip6_frag_intern(hash, fq);
+
+oom:
+ IP6_INC_STATS_BH(Ip6ReasmFails);
+ return NULL;
+}
+
+static __inline__ struct frag_queue *
+fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst)
+{
+ struct frag_queue *fq;
+ unsigned int hash = ip6qhashfn(id, src, dst);
+
+ read_lock(&ip6_frag_lock);
+ for(fq = ip6_frag_hash[hash]; fq; fq = fq->next) {
+ if (fq->id == id &&
+ !ipv6_addr_cmp(src, &fq->saddr) &&
+ !ipv6_addr_cmp(dst, &fq->daddr)) {
+ atomic_inc(&fq->refcnt);
+ read_unlock(&ip6_frag_lock);
+ return fq;
+ }
+ }
+ read_unlock(&ip6_frag_lock);
+
+ return ip6_frag_create(hash, id, src, dst);
+}
+
+
+static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
+ struct frag_hdr *fhdr, u8 *nhptr)
+{
+ struct sk_buff *prev, *next;
+ int offset, end;
+
+ if (fq->last_in & COMPLETE)
+ goto err;
+
+ if (!mod_timer(&fq->timer, jiffies + sysctl_ip6frag_time))
+ atomic_inc(&fq->refcnt);
+
+ offset = ntohs(fhdr->frag_off) & ~0x7;
+ end = offset + (ntohs(skb->nh.ipv6h->payload_len) -
+ ((u8 *) (fhdr + 1) - (u8 *) (skb->nh.ipv6h + 1)));
+
+ if ((unsigned int)end >= 65536) {
+ icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off);
+ goto err;
+ }
+
+ /* Is this the final fragment? */
+ if (!(fhdr->frag_off & __constant_htons(0x0001))) {
+ /* If we already have some bits beyond end
+ * or have different end, the segment is corrupted.
+ */
+ if (end < fq->len ||
+ ((fq->last_in & LAST_IN) && end != fq->len))
+ goto err;
+ fq->last_in |= LAST_IN;
+ fq->len = end;
+ } else {
+ /* Check if the fragment is rounded to 8 bytes.
+ * Required by the RFC.
+ */
+ if (end & 0x7) {
+ printk(KERN_DEBUG "fragment not rounded to 8bytes\n");
+
+ /*
+ It is not in specs, but I see no reasons
+ to send an error in this case. --ANK
+ */
+ if (offset == 0)
+ icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
+ &skb->nh.ipv6h->payload_len);
+ goto err;
+ }
+ if (end > fq->len) {
+ /* Some bits beyond end -> corruption. */
+ if (fq->last_in & LAST_IN)
+ goto err;
+ fq->len = end;
+ }
+ }
+
+ if (end == offset)
+ goto err;
+
+ /* Point into the IP datagram 'data' part. */
+ skb_pull(skb, (u8 *) (fhdr + 1) - skb->data);
+ skb_trim(skb, end - offset);
+
+ /* Find out which fragments are in front and at the back of us
+ * in the chain of fragments so far. We must know where to put
+ * this fragment, right?
+ */
+ prev = NULL;
+ for(next = fq->fragments; next != NULL; next = next->next) {
+ if (FRAG6_CB(next)->offset >= offset)
+ break; /* bingo! */
+ prev = next;
+ }
+
+ /* We found where to put this one. Check for overlap with
+ * preceding fragment, and, if needed, align things so that
+ * any overlaps are eliminated.
+ */
+ if (prev) {
+ int i = (FRAG6_CB(prev)->offset + prev->len) - offset;
+
+ if (i > 0) {
+ offset += i;
+ if (end <= offset)
+ goto err;
+ skb_pull(skb, i);
+ }
+ }
+
+ /* Look for overlap with succeeding segments.
+ * If we can merge fragments, do it.
+ */
+ while (next && FRAG6_CB(next)->offset < end) {
+ int i = end - FRAG6_CB(next)->offset; /* overlap is 'i' bytes */
+
+ if (i < next->len) {
+ /* Eat head of the next overlapped fragment
+ * and leave the loop. The next ones cannot overlap.
+ */
+ FRAG6_CB(next)->offset += i; /* next fragment */
+ skb_pull(next, i);
+ fq->meat -= i;
+ break;
+ } else {
+ struct sk_buff *free_it = next;
+
+ /* Old fragmnet is completely overridden with
+ * new one drop it.
+ */
+ next = next->next;
+
+ if (prev)
+ prev->next = next;
+ else
+ fq->fragments = next;
+
+ fq->meat -= free_it->len;
+ frag_kfree_skb(free_it);
+ }
+ }
+
+ FRAG6_CB(skb)->offset = offset;
+
+ /* Insert this fragment in the chain of fragments. */
+ skb->next = next;
+ if (prev)
+ prev->next = skb;
+ else
+ fq->fragments = skb;
+
+ fq->dev = skb->dev;
+ fq->iif = skb->dev->ifindex;
+ fq->meat += skb->len;
+ atomic_add(skb->truesize, &ip6_frag_mem);
+
+ /* First fragment.
+ nexthdr and nhptr are get from the first fragment.
+ Moreover, nexthdr is UNDEFINED for all the fragments but the
+ first one.
+ (fixed --ANK (980728))
+ */
+ if (offset == 0) {
+ fq->nexthdr = fhdr->nexthdr;
+ fq->nhoffset = nhptr - skb->nh.raw;
+ fq->last_in |= FIRST_IN;
+ }
+ return;
+
+err:
+ kfree_skb(skb);
+}
+
+/*
+ * Check if this packet is complete.
+ * Returns NULL on failure by any reason, and pointer
+ * to current nexthdr field in reassembled frame.
+ *
+ * It is called with locked fq, and caller must check that
+ * queue is eligible for reassembly i.e. it is not COMPLETE,
+ * the last and the first frames arrived and all the bits are here.
+ */
+static u8* ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in)
+{
+ struct sk_buff *fp, *head = fq->fragments;
+ struct sk_buff *skb;
+ int payload_len;
+ int unfrag_len;
+ int copy;
+ u8 *nhptr;
+
+ /*
+ * we know the m_flag arrived and we have a queue,
+ * starting from 0, without gaps.
+ * this means we have all fragments.
+ */
+
+ fq_kill(fq);
+
+ BUG_TRAP(head != NULL);
+ BUG_TRAP(FRAG6_CB(head)->offset == 0);
+
+ /* Unfragmented part is taken from the first segment. */
+ unfrag_len = head->h.raw - (u8 *) (head->nh.ipv6h + 1);
+ payload_len = unfrag_len + fq->len;
+
+ if (payload_len > 65535)
+ goto out_oversize;
+
+ if ((skb = dev_alloc_skb(sizeof(struct ipv6hdr) + payload_len))==NULL)
+ goto out_oom;
+
+ copy = unfrag_len + sizeof(struct ipv6hdr);
+
+ skb->mac.raw = skb->data;
+ skb->nh.ipv6h = (struct ipv6hdr *) skb->data;
+ skb->dev = fq->dev;
+ skb->protocol = __constant_htons(ETH_P_IPV6);
+ skb->pkt_type = head->pkt_type;
+ FRAG6_CB(skb)->h = FRAG6_CB(head)->h;
+ skb->dst = dst_clone(head->dst);
+
+ memcpy(skb_put(skb, copy), head->nh.ipv6h, copy);
+ nhptr = skb->nh.raw + fq->nhoffset;
+ *nhptr = fq->nexthdr;
+
+ skb->h.raw = skb->tail;
+
+ skb->nh.ipv6h->payload_len = ntohs(payload_len);
+
+ *skb_in = skb;
+
+ for (fp = fq->fragments; fp; fp=fp->next)
+ memcpy(skb_put(skb, fp->len), fp->data, fp->len);
+
+ IP6_INC_STATS_BH(Ip6ReasmOKs);
+ return nhptr;
+
+out_oversize:
+ if (net_ratelimit())
+ printk(KERN_DEBUG "ip6_frag_reasm: payload len = %d\n", payload_len);
+ goto out_fail;
+out_oom:
+ if (net_ratelimit())
+ printk(KERN_DEBUG "ip6_frag_reasm: no memory for reassembly\n");
+out_fail:
+ IP6_INC_STATS_BH(Ip6ReasmFails);
+ return NULL;
+}
+
+u8* ipv6_reassembly(struct sk_buff **skbp, __u8 *nhptr)
+{
+ struct sk_buff *skb = *skbp;
+ struct frag_hdr *fhdr = (struct frag_hdr *) (skb->h.raw);
+ struct frag_queue *fq;
+ struct ipv6hdr *hdr;
+
+ hdr = skb->nh.ipv6h;
+
+ IP6_INC_STATS_BH(Ip6ReasmReqds);
+
+ /* Jumbo payload inhibits frag. header */
+ if (hdr->payload_len==0) {
+ icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw);
+ return NULL;
+ }
+ if ((u8 *)(fhdr+1) > skb->tail) {
+ icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw);
+ return NULL;
+ }
+
+ if (!(fhdr->frag_off & __constant_htons(0xFFF9))) {
+ /* It is not a fragmented frame */
+ skb->h.raw += sizeof(struct frag_hdr);
+ IP6_INC_STATS_BH(Ip6ReasmOKs);
+
+ return &fhdr->nexthdr;
+ }
+
+ if (atomic_read(&ip6_frag_mem) > sysctl_ip6frag_high_thresh)
+ ip6_evictor();
+
+ if ((fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr)) != NULL) {
+ u8 *ret = NULL;
+
+ spin_lock(&fq->lock);
+
+ ip6_frag_queue(fq, skb, fhdr, nhptr);
+
+ if (fq->last_in == (FIRST_IN|LAST_IN) &&
+ fq->meat == fq->len)
+ ret = ip6_frag_reasm(fq, skbp);
+
+ spin_unlock(&fq->lock);
+ fq_put(fq);
+ return ret;
+ }
+
+ IP6_INC_STATS_BH(Ip6ReasmFails);
+ kfree_skb(skb);
+ return NULL;
+}
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: route.c,v 1.45 2000/01/16 05:11:38 davem Exp $
+ * $Id: route.c,v 1.46 2000/07/07 22:40:35 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -769,10+769,12 @@ int ip6_route_add(struct in6_rtmsg *rtmsg) goto out;
if (rtmsg->rtmsg_flags & (RTF_GATEWAY|RTF_NONEXTHOP)) {
- rt->rt6i_nexthop = ndisc_get_neigh(dev, &rt->rt6i_gateway);
- err = -ENOMEM;
- if (rt->rt6i_nexthop == NULL)
+ rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev);
+ if (IS_ERR(rt->rt6i_nexthop)) {
+ err = PTR_ERR(rt->rt6i_nexthop);
+ rt->rt6i_nexthop = NULL;
goto out;
+ }
}
if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr))
* Pedro Roque <roque@di.fc.ul.pt>
* Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
*
- * $Id: sit.c,v 1.39 2000/07/07 01:55:20 davem Exp $
+ * $Id: sit.c,v 1.41 2000/07/07 23:47:45 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
#include <net/udp.h>
#include <net/icmp.h>
#include <net/ipip.h>
+#include <net/inet_ecn.h>
/*
This version of net/ipv6/sit.c is cloned of net/ipv4/ip_gre.c
@@ -59,7+60,7 @@ static int ipip6_fb_tunnel_init(struct net_device *dev); static int ipip6_tunnel_init(struct net_device *dev);
static struct net_device ipip6_fb_tunnel_dev = {
- "", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipip6_fb_tunnel_init,
+ "sit0", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipip6_fb_tunnel_init,
};
static struct ip_tunnel ipip6_fb_tunnel = {
@@ -174,10+175,10 @@ struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create) dev->priv = (void*)(dev+1);
nt = (struct ip_tunnel*)dev->priv;
nt->dev = dev;
- strcpy(dev->name, nt->parms.name);
dev->init = ipip6_tunnel_init;
dev->new_style = 1;
memcpy(&nt->parms, parms, sizeof(*parms));
+ strcpy(dev->name, nt->parms.name);
if (dev->name[0] == 0) {
int i;
for (i=1; i<100; i++) {
#endif
}
+static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
+{
+ if (INET_ECN_is_ce(iph->tos) &&
+ INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h)))
+ IP6_ECN_set_ce(skb->nh.ipv6h);
+}
+
int ipip6_rcv(struct sk_buff *skb, unsigned short len)
{
struct iphdr *iph;
@@ -394,6+402,7 @@ int ipip6_rcv(struct sk_buff *skb, unsigned short len) nf_conntrack_put(skb->nfct);
skb->nfct = NULL;
#endif
+ ipip6_ecn_decapsulate(iph, skb);
netif_rx(skb);
read_unlock(&ipip6_lock);
return 0;
@@ -431,6+440,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) int mtu;
struct in6_addr *addr6;
int addr_type;
+ int err;
if (tunnel->recursion++) {
tunnel->stat.collisions++;
@@ -548,7+558,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) iph->frag_off = 0;
iph->protocol = IPPROTO_IPV6;
- iph->tos = tos;
+ iph->tos = INET_ECN_encapsulate(tos, ip6_get_dsfield(iph6));
iph->daddr = rt->rt_dst;
iph->saddr = rt->rt_src;
@@ -564,10+574,17 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) skb->nfct = NULL;
#endif
+ err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
+ do_ip_send);
+ if(err < 0) {
+ if(net_ratelimit())
+ printk(KERN_ERR "ipip6_tunnel_xmit: ip_send() failed, err=%d\n", -err);
+ skb = NULL;
+ goto tx_error;
+ }
+
stats->tx_bytes += skb->len;
stats->tx_packets++;
- NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
- do_ip_send);
tunnel->recursion--;
return 0;
@@ -576,7+593,8 @@ tx_error_icmp: dst_link_failure(skb);
tx_error:
stats->tx_errors++;
- dev_kfree_skb(skb);
+ if(skb)
+ dev_kfree_skb(skb);
tunnel->recursion--;
return 0;
}
*
* Based on linux/ipv4/udp.c
*
- * $Id: udp.c,v 1.53 2000/05/03 06:37:07 davem Exp $
+ * $Id: udp.c,v 1.55 2000/07/08 00:20:43 davem Exp $
*
* Fixes:
* Hideaki YOSHIFUJI : sin6_scope_id support
@@ -400,7+400,7 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, int len, if (err)
goto out_free;
- sk->stamp=skb->stamp;
+ sock_recv_timestamp(msg, sk, skb);
/* Copy the address. */
if (msg->msg_name) {
@@ -868,6+868,8 @@ static int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, int ulen)
fl.proto = IPPROTO_UDP;
fl.fl6_dst = daddr;
+ if (fl.fl6_src == NULL && !ipv6_addr_any(&np->saddr))
+ fl.fl6_src = &np->saddr;
fl.uli_u.ports.dport = udh.uh.dest;
fl.uli_u.ports.sport = udh.uh.source;
@@ -69,17+69,6 @@ extern int netdev_finish_unregister(struct net_device *dev);
#include <linux/rtnetlink.h>
-#if defined(CONFIG_ULTRA) || defined(CONFIG_WD80x3) || \
- defined(CONFIG_EL2) || defined(CONFIG_NE2000) || \
- defined(CONFIG_E2100) || defined(CONFIG_HPLAN_PLUS) || \
- defined(CONFIG_HPLAN) || defined(CONFIG_AC3200) || \
- defined(CONFIG_ES3210) || defined(CONFIG_ULTRA32) || \
- defined(CONFIG_LNE390) || defined(CONFIG_NE3210) || \
- defined(CONFIG_NE2K_PCI) || defined(CONFIG_APNE) || \
- defined(CONFIG_DAYNAPORT)
-#include "../drivers/net/8390.h"
-#endif
-
#ifdef CONFIG_IPX_MODULE
extern struct datalink_proto *make_EII_client(void);
extern struct datalink_proto *make_8023_client(void);
*
* PACKET - implements raw packet sockets.
*
- * Version: $Id: af_packet.c,v 1.34 2000/04/25 04:13:35 davem Exp $
+ * Version: $Id: af_packet.c,v 1.36 2000/07/08 00:20:43 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1053,7+1053,8 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, int len, err = memcpy_toiovec(msg->msg_iov, skb->data, copied);
if (err)
goto out_free;
- sk->stamp=skb->stamp;
+
+ sock_recv_timestamp(msg, sk, skb);
if (msg->msg_name)
memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
@@ -1392,6+1393,23 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg
switch(cmd)
{
+ case SIOCOUTQ:
+ {
+ int amount = atomic_read(&sk->wmem_alloc);
+ return put_user(amount, (int *)arg);
+ }
+ case SIOCINQ:
+ {
+ struct sk_buff *skb;
+ int amount = 0;
+
+ spin_lock_bh(&sk->receive_queue.lock);
+ skb = skb_peek(&sk->receive_queue);
+ if (skb)
+ amount = skb->len;
+ spin_unlock_bh(&sk->receive_queue.lock);
+ return put_user(amount, (int *)arg);
+ }
case FIOSETOWN:
case SIOCSPGRP:
err = get_user(pid, (int *) arg);
#include <linux/skbuff.h>
#include <net/sock.h>
#include <net/pkt_sched.h>
+#include <net/inet_ecn.h>
#define RED_ECN_ECT 0x02
#define RED_ECN_CE 0x01
@@ -170,14+171,9 @@ static int red_ecn_mark(struct sk_buff *skb) if (!(tos & RED_ECN_ECT))
return 0;
- if (!(tos & RED_ECN_CE)) {
- u32 check = skb->nh.iph->check;
+ if (!(tos & RED_ECN_CE))
+ IP_ECN_set_ce(skb->nh.iph);
- check += __constant_htons(0xFFFE);
- skb->nh.iph->check = check + (check>>16);
-
- skb->nh.iph->tos = tos | RED_ECN_CE;
- }
return 1;
}
@@ -242,9+242,9 @@ __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device * memcmp(n->primary_key, mn->primary_key, mn->tbl->key_len) == 0) {
atomic_inc(&n->refcnt);
} else {
- n = __neigh_lookup(mn->tbl, mn->primary_key, dev, 1);
- if (n == NULL)
- return -ENOBUFS;
+ n = __neigh_lookup_errno(mn->tbl, mn->primary_key, dev);
+ if (IS_ERR(n))
+ return PTR_ERR(n);
}
if (neigh_event_send(n, skb_res) == 0) {
int err;