## Automatically generated incremental diff
## From: linux-2.4.22-bk4
## To: linux-2.4.22-bk5
## Robot: $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $
diff -urN linux-2.4.22-bk4/Documentation/Configure.help linux-2.4.22-bk5/Documentation/Configure.help
--- linux-2.4.22-bk4/Documentation/Configure.help 2003-08-30 02:51:13.000000000 -0700
+++ linux-2.4.22-bk5/Documentation/Configure.help 2003-08-30 02:51:16.000000000 -0700
@@ -2037,6 +2037,17 @@
The board uses the R4300 and a R5230 CPUs. For more information
about this board see .
+SGI SN2 L1 serial port support
+CONFIG_SGI_L1_SERIAL
+ If you have an SGI SN2 and you want to use the serial port connected
+ to the system controller (you want this!), say Y. Otherwise, say N.
+
+SGI SN2 L1 serial console support
+CONFIG_SGI_L1_SERIAL_CONSOLE
+ If you have an SGI SN2 and you would like to use the system
+ controller serial port as your console (you want this!), say Y.
+ Otherwise, say N.
+
Support for BAGET MIPS series
CONFIG_BAGET_MIPS
This enables support for the Baget, a Russian embedded system. For
diff -urN linux-2.4.22-bk4/Documentation/networking/00-INDEX linux-2.4.22-bk5/Documentation/networking/00-INDEX
--- linux-2.4.22-bk4/Documentation/networking/00-INDEX 2003-06-13 07:51:29.000000000 -0700
+++ linux-2.4.22-bk5/Documentation/networking/00-INDEX 2003-08-30 02:51:16.000000000 -0700
@@ -97,8 +97,8 @@
sis900.txt
- SiS 900/7016 Fast Ethernet device driver info.
sk98lin.txt
- - SysKonnect SK-98xx and SK-98xx Gigabit Ethernet Adapter family
- driver info.
+ - Marvell Yukon Chipset / SysKonnect SK-98xx compliant Gigabit
+ Ethernet Adapter family driver info
skfp.txt
- SysKonnect FDDI (SK-5xxx, Compaq Netelligent) driver info.
smc9.txt
diff -urN linux-2.4.22-bk4/Documentation/wolfson-touchscreen.txt linux-2.4.22-bk5/Documentation/wolfson-touchscreen.txt
--- linux-2.4.22-bk4/Documentation/wolfson-touchscreen.txt 1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.22-bk5/Documentation/wolfson-touchscreen.txt 2003-08-30 02:51:16.000000000 -0700
@@ -0,0 +1,178 @@
+
+Wolfson Microelectronics WM9705 and WM9712 Touchscreen Controllers
+===================================================================
+
+The WM9705 and WM9712 are high performance AC97 audio codecs with built
+in touchscreen controllers that are mainly found in portable devices.
+i.e. Dell Axim and Toshiba e740.
+
+This driver uses the AC97 link controller for all communication with the
+codec and can be either built into the kernel or built as a module.
+
+Build Instructions
+==================
+
+The driver will be built into the kernel if "sound card support" = y and
+"wolfson AC97 touchscreen support" = y in the kernel sound configuration.
+
+To build as a module, "wolfson AC97 touchscreen support" = m
+in the kernel sound configuration.
+
+
+Driver Features
+===============
+
+ * supports WM9705, WM9712
+ * polling mode
+ * coordinate polling
+ * adjustable rpu/dpp settings
+ * adjustable pressure current
+ * adjustable sample settle delay
+ * 4 and 5 wire touchscreens (5 wire is WM9712 only)
+ * pen down detection
+ * power management
+ * AUX ADC sampling
+
+
+Driver Usage
+============
+
+In order to use this driver, a char device called wm97xx with a major
+number of 10 and minor number 16 will have to be created under
+/dev/touchscreen.
+
+e.g.
+mknod /dev/touchscreen/wm97xx c 10 16
+
+
+Driver Parameters
+=================
+The driver can accept several parameters for fine tuning the touchscreen.
+However, the syntax is different between module options and passing the
+options in the kernel command line.
+
+e.g.
+
+rpu=1 (module)
+rpu:1 (kernel command line)
+
+
+1. Codec sample mode. (mode)
+
+ The WM9712 can sample touchscreen data in 3 different operating
+ modes. i.e. polling, coordinate and continous.
+
+ Polling:- The driver polls the codec and issues 3 seperate commands
+ over the AC97 link to read X,Y and pressure.
+
+ Coordinate: - The driver polls the codec and only issues 1 command over
+ the AC97 link to read X,Y and pressure. This mode has
+ strict timing requirements and may drop samples if
+ interrupted. However, it is less demanding on the AC97
+ link. Note: this mode requires a larger delay than polling
+ mode.
+
+ Continuous:- The codec automatically samples X,Y and pressure and then
+ sends the data over the AC97 link in slots. This is then
+ same method used by the codec when recording audio.
+
+ Set mode = 0 for polling, 1 for coordinate and 2 for continuous.
+
+ Default mode = 0
+
+
+
+2. WM9712 Internal pull up for pen detect. (rpu)
+
+ Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
+ i.e. pull up resistance = 64k Ohms / rpu.
+
+ Adjust this value if you are having problems with pen detect not
+ detecting any down events.
+
+ Set rpu = value
+
+ Default rpu = 1
+
+
+
+3. WM9705 Pen detect comparator threshold. (pdd)
+
+ 0 to Vmid in 15 steps, 0 = use zero power comparator with Vmid threshold
+ i.e. 1 = Vmid/15 threshold
+ 15 = Vmid/1 threshold
+
+ Adjust this value if you are having problems with pen detect not
+ detecting any down events.
+
+ Set pdd = value
+
+ Default pdd = 0
+
+
+
+4. Set current used for pressure measurement. (pil)
+
+ Set pil = 2 to use 400uA
+ pil = 1 to use 200uA and
+ pil = 0 to disable pressure measurement.
+
+ This is used to increase the range of values returned by the adc
+ when measureing touchpanel pressure.
+
+ Default pil = 0
+
+
+
+5. WM9712 Set 5 wire touchscreen mode. (five_wire)
+
+ Set five_wire = 1 to enable 5 wire mode on the WM9712.
+
+ Default five_wire = 0
+
+ NOTE: Five wire mode does not allow for readback of pressure.
+
+
+
+6. ADC sample delay. (delay)
+
+ For accurate touchpanel measurements, some settling time may be
+ required between the switch matrix applying a voltage across the
+ touchpanel plate and the ADC sampling the signal.
+
+ This delay can be set by setting delay = n, where n is the array
+ position of the delay in the array delay_table below.
+ Long delays > 1ms are supported for completeness, but are not
+ recommended.
+
+ Default delay = 4
+
+ wm_delay uS AC97 link frames
+ ====================================
+ 0 21 1
+ 1 42 2
+ 2 84 4
+ 3 167 8
+ 4 333 16
+ 5 667 32
+ 6 1000 48
+ 7 1333 64
+ 8 2000 96
+ 9 2667 128
+ 10 3333 160
+ 11 4000 192
+ 12 4667 224
+ 13 5333 256
+ 14 6000 288
+ 15 0 0 (No delay, switch matrix always on)
+
+
+
+Contact
+=======
+
+Further information about the WM9705 and WM9712 can be found on the
+Wolfson Website. http://www.wolfsonmicro.com
+
+Please report bugs to liam.girdwood@wolfsonmicro.com or
+ linux@wolfsonmicro.com
diff -urN linux-2.4.22-bk4/Makefile linux-2.4.22-bk5/Makefile
--- linux-2.4.22-bk4/Makefile 2003-08-30 02:51:13.000000000 -0700
+++ linux-2.4.22-bk5/Makefile 2003-08-30 02:51:16.000000000 -0700
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 22
-EXTRAVERSION = -bk4
+EXTRAVERSION = -bk5
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
diff -urN linux-2.4.22-bk4/arch/i386/kernel/dmi_scan.c linux-2.4.22-bk5/arch/i386/kernel/dmi_scan.c
--- linux-2.4.22-bk4/arch/i386/kernel/dmi_scan.c 2003-08-30 02:51:13.000000000 -0700
+++ linux-2.4.22-bk5/arch/i386/kernel/dmi_scan.c 2003-08-30 02:51:16.000000000 -0700
@@ -400,37 +400,6 @@
}
/*
- * The Intel 440GX hall of shame.
- *
- * On many (all we have checked) of these boxes the $PIRQ table is wrong.
- * The MP1.4 table is right however and so SMP kernels tend to work.
- */
-
-#ifdef CONFIG_PCI
-extern int broken_440gx_bios;
-extern unsigned int pci_probe;
-#endif
-static __init int broken_pirq(struct dmi_blacklist *d)
-{
- printk(KERN_INFO " *** Possibly defective BIOS detected (irqtable)\n");
- printk(KERN_INFO " *** Many BIOSes matching this signature have incorrect IRQ routing tables.\n");
- printk(KERN_INFO " *** If you see IRQ problems, in paticular SCSI resets and hangs at boot\n");
- printk(KERN_INFO " *** contact your hardware vendor and ask about updates.\n");
- printk(KERN_INFO " *** Building an SMP kernel may evade the bug some of the time.\n");
-#ifdef CONFIG_X86_IO_APIC
- {
- extern int skip_ioapic_setup;
- skip_ioapic_setup = 0;
- }
-#endif
-#ifdef CONFIG_PCI
- broken_440gx_bios = 1;
- pci_probe |= PCI_BIOS_IRQ_SCAN;
-#endif
- return 0;
-}
-
-/*
* ASUS K7V-RM has broken ACPI table defining sleep modes
*/
@@ -824,77 +793,17 @@
NO_MATCH, NO_MATCH
} },
- /* Problem Intel 440GX bioses */
-
- { broken_pirq, "SABR1 Bios", { /* Bad $PIR */
- MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
- MATCH(DMI_BIOS_VERSION,"SABR1"),
- NO_MATCH, NO_MATCH
- } },
- { broken_pirq, "l44GX Bios", { /* Bad $PIR */
- MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
- MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0066.P07"),
- NO_MATCH, NO_MATCH
- } },
- { broken_pirq, "IBM xseries 370", { /* Bad $PIR */
- MATCH(DMI_BIOS_VENDOR, "IBM"),
- MATCH(DMI_BIOS_VERSION,"MMKT33AUS"),
- NO_MATCH, NO_MATCH
- } },
- { broken_pirq, "l44GX Bios", { /* Bad $PIR */
- MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
- MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0094.P10"),
- NO_MATCH, NO_MATCH
- } },
- { broken_pirq, "l44GX Bios", { /* Bad $PIR */
- MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
- MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0115.P12"),
- NO_MATCH, NO_MATCH
- } },
- { broken_pirq, "l44GX Bios", { /* Bad $PIR */
- MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
- MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0120.P12"),
- NO_MATCH, NO_MATCH
- } },
- { broken_pirq, "l44GX Bios", { /* Bad $PIR */
- MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
- MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0125.P13"),
- NO_MATCH, NO_MATCH
- } },
- { broken_pirq, "l44GX Bios", { /* Bad $PIR */
- MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
- MATCH(DMI_BIOS_VERSION,"C440GX0.86B"),
- NO_MATCH, NO_MATCH
- } },
- { broken_pirq, "l44GX Bios", { /* Bad $PIR */
- MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
- MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0133.P14"),
- NO_MATCH, NO_MATCH
- } },
- { broken_pirq, "l44GX Bios", { /* Bad $PIR */
- MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
- MATCH(DMI_BIOS_VERSION,"L440GX0"),
- NO_MATCH, NO_MATCH
- } },
-
- /* Intel in disgiuse - In this case they can't hide and they don't run
- too well either... */
- { broken_pirq, "Dell PowerEdge 8450", { /* Bad $PIR */
- MATCH(DMI_PRODUCT_NAME, "Dell PowerEdge 8450"),
+ { init_ints_after_s1, "Toshiba Satellite 4030cdt", { /* Reinitialization of 8259 is needed after S1 resume */
+ MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
NO_MATCH, NO_MATCH, NO_MATCH
} },
-
+
{ broken_acpi_Sx, "ASUS K7V-RM", { /* Bad ACPI Sx table */
MATCH(DMI_BIOS_VERSION,"ASUS K7V-RM ACPI BIOS Revision 1003A"),
MATCH(DMI_BOARD_NAME, ""),
NO_MATCH, NO_MATCH
} },
- { init_ints_after_s1, "Toshiba Satellite 4030cdt", { /* Reinitialization of 8259 is needed after S1 resume */
- MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
- NO_MATCH, NO_MATCH, NO_MATCH
- } },
-
{ print_if_true, KERN_WARNING "IBM T23 - BIOS 1.03b+ and controller firmware 1.02+ may be needed for Linux APM.", {
MATCH(DMI_SYS_VENDOR, "IBM"),
MATCH(DMI_BIOS_VERSION, "1AET38WW (1.01b)"),
diff -urN linux-2.4.22-bk4/arch/i386/kernel/pci-irq.c linux-2.4.22-bk5/arch/i386/kernel/pci-irq.c
--- linux-2.4.22-bk4/arch/i386/kernel/pci-irq.c 2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.22-bk5/arch/i386/kernel/pci-irq.c 2003-08-30 02:51:16.000000000 -0700
@@ -23,7 +23,6 @@
#define PIRQ_VERSION 0x0100
int broken_hp_bios_irq9;
-int broken_440gx_bios;
static struct irq_routing_table *pirq_table;
@@ -46,6 +45,11 @@
int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, int new);
};
+struct irq_router_handler {
+ u16 vendor;
+ int (*probe)(struct irq_router *r, struct pci_dev *router, u16 device);
+};
+
/*
* Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
*/
@@ -257,111 +261,221 @@
}
/*
- * PIRQ routing for SiS 85C503 router used in several SiS chipsets
- * According to the SiS 5595 datasheet (preliminary V1.0, 12/24/1997)
- * the related registers work as follows:
- *
- * general: one byte per re-routable IRQ,
+ * PIRQ routing for SiS 85C503 router used in several SiS chipsets.
+ * We have to deal with the following issues here:
+ * - vendors have different ideas about the meaning of link values
+ * - some onboard devices (integrated in the chipset) have special
+ * links and are thus routed differently (i.e. not via PCI INTA-INTD)
+ * - different revision of the router have a different layout for
+ * the routing registers, particularly for the onchip devices
+ *
+ * For all routing registers the common thing is we have one byte
+ * per routeable link which is defined as:
* bit 7 IRQ mapping enabled (0) or disabled (1)
- * bits [6:4] reserved
+ * bits [6:4] reserved (sometimes used for onchip devices)
* bits [3:0] IRQ to map to
* allowed: 3-7, 9-12, 14-15
* reserved: 0, 1, 2, 8, 13
*
- * individual registers in device config space:
+ * The config-space registers located at 0x41/0x42/0x43/0x44 are
+ * always used to route the normal PCI INT A/B/C/D respectively.
+ * Apparently there are systems implementing PCI routing table using
+ * link values 0x01-0x04 and others using 0x41-0x44 for PCI INTA..D.
+ * We try our best to handle both link mappings.
+ *
+ * Currently (2003-05-21) it appears most SiS chipsets follow the
+ * definition of routing registers from the SiS-5595 southbridge.
+ * According to the SiS 5595 datasheets the revision id's of the
+ * router (ISA-bridge) should be 0x01 or 0xb0.
*
- * 0x41/0x42/0x43/0x44: PCI INT A/B/C/D - bits as in general case
+ * Furthermore we've also seen lspci dumps with revision 0x00 and 0xb1.
+ * Looks like these are used in a number of SiS 5xx/6xx/7xx chipsets.
+ * They seem to work with the current routing code. However there is
+ * some concern because of the two USB-OHCI HCs (original SiS 5595
+ * had only one). YMMV.
*
- * 0x61: IDEIRQ: bits as in general case - but:
- * bits [6:5] must be written 01
- * bit 4 channel-select primary (0), secondary (1)
+ * Onchip routing for router rev-id 0x01/0xb0 and probably 0x00/0xb1:
*
- * 0x62: USBIRQ: bits as in general case - but:
- * bit 4 OHCI function disabled (0), enabled (1)
+ * 0x61: IDEIRQ:
+ * bits [6:5] must be written 01
+ * bit 4 channel-select primary (0), secondary (1)
+ *
+ * 0x62: USBIRQ:
+ * bit 6 OHCI function disabled (0), enabled (1)
*
- * 0x6a: ACPI/SCI IRQ - bits as in general case
+ * 0x6a: ACPI/SCI IRQ: bits 4-6 reserved
+ *
+ * 0x7e: Data Acq. Module IRQ - bits 4-6 reserved
+ *
+ * We support USBIRQ (in addition to INTA-INTD) and keep the
+ * IDE, ACPI and DAQ routing untouched as set by the BIOS.
+ *
+ * Currently the only reported exception is the new SiS 65x chipset
+ * which includes the SiS 69x southbridge. Here we have the 85C503
+ * router revision 0x04 and there are changes in the register layout
+ * mostly related to the different USB HCs with USB 2.0 support.
*
- * 0x7e: Data Acq. Module IRQ - bits as in general case
+ * Onchip routing for router rev-id 0x04 (try-and-error observation)
*
- * Apparently there are systems implementing PCI routing table using both
- * link values 0x01-0x04 and 0x41-0x44 for PCI INTA..D, but register offsets
- * like 0x62 as link values for USBIRQ e.g. So there is no simple
- * "register = offset + pirq" relation.
- * Currently we support PCI INTA..D and USBIRQ and try our best to handle
- * both link mappings.
- * IDE/ACPI/DAQ mapping is currently unsupported (left untouched as set by BIOS).
+ * 0x60/0x61/0x62/0x63: 1xEHCI and 3xOHCI (companion) USB-HCs
+ * bit 6-4 are probably unused, not like 5595
*/
-static int pirq_sis_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+#define PIRQ_SIS_IRQ_MASK 0x0f
+#define PIRQ_SIS_IRQ_DISABLE 0x80
+#define PIRQ_SIS_USB_ENABLE 0x40
+#define PIRQ_SIS_DETECT_REGISTER 0x40
+
+/* return value:
+ * -1 on error
+ * 0 for PCI INTA-INTD
+ * 0 or enable bit mask to check or set for onchip functions
+ */
+static inline int pirq_sis5595_onchip(int pirq, int *reg)
{
- u8 x;
- int reg = pirq;
+ int ret = -1;
+ *reg = pirq;
switch(pirq) {
- case 0x01:
- case 0x02:
- case 0x03:
- case 0x04:
- reg += 0x40;
- case 0x41:
- case 0x42:
- case 0x43:
- case 0x44:
- case 0x62:
- pci_read_config_byte(router, reg, &x);
- if (reg != 0x62)
- break;
- if (!(x & 0x40))
- return 0;
- break;
- case 0x61:
- case 0x6a:
- case 0x7e:
- printk(KERN_INFO "SiS pirq: advanced IDE/ACPI/DAQ mapping not yet implemented\n");
- return 0;
- default:
- printk(KERN_INFO "SiS router pirq escape (%d)\n", pirq);
- return 0;
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ *reg += 0x40;
+ case 0x41:
+ case 0x42:
+ case 0x43:
+ case 0x44:
+ ret = 0;
+ break;
+
+ case 0x62:
+ ret = PIRQ_SIS_USB_ENABLE; /* documented for 5595 */
+ break;
+
+ case 0x61:
+ case 0x6a:
+ case 0x7e:
+ printk(KERN_INFO "SiS pirq: IDE/ACPI/DAQ mapping not implemented: (%u)\n",
+ (unsigned) pirq);
+ /* fall thru */
+ default:
+ printk(KERN_INFO "SiS router unknown request: (%u)\n",
+ (unsigned) pirq);
+ break;
+ }
+ return ret;
+}
+
+/* return value:
+ * -1 on error
+ * 0 for PCI INTA-INTD
+ * 0 or enable bit mask to check or set for onchip functions
+ */
+static inline int pirq_sis96x_onchip(int pirq, int *reg)
+{
+ int ret = -1;
+
+ *reg = pirq;
+ switch(pirq) {
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ *reg += 0x40;
+ case 0x41:
+ case 0x42:
+ case 0x43:
+ case 0x44:
+ case 0x60:
+ case 0x61:
+ case 0x62:
+ case 0x63:
+ ret = 0;
+ break;
+
+ default:
+ printk(KERN_INFO "SiS router unknown request: (%u)\n",
+ (unsigned) pirq);
+ break;
}
- return (x & 0x80) ? 0 : (x & 0x0f);
+ return ret;
+}
+
+
+static int pirq_sis5595_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+ u8 x;
+ int reg, check;
+
+ check = pirq_sis5595_onchip(pirq, ®);
+ if (check < 0)
+ return 0;
+
+ pci_read_config_byte(router, reg, &x);
+ if (check != 0 && !(x & check))
+ return 0;
+
+ return (x & PIRQ_SIS_IRQ_DISABLE) ? 0 : (x & PIRQ_SIS_IRQ_MASK);
}
-static int pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+static int pirq_sis96x_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
{
u8 x;
- int reg = pirq;
+ int reg, check;
+
+ check = pirq_sis96x_onchip(pirq, ®);
+ if (check < 0)
+ return 0;
+
+ pci_read_config_byte(router, reg, &x);
+ if (check != 0 && !(x & check))
+ return 0;
+
+ return (x & PIRQ_SIS_IRQ_DISABLE) ? 0 : (x & PIRQ_SIS_IRQ_MASK);
+}
+
+static int pirq_sis5595_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+ u8 x;
+ int reg, set;
+
+ set = pirq_sis5595_onchip(pirq, ®);
+ if (set < 0)
+ return 0;
+
+ x = (irq & PIRQ_SIS_IRQ_MASK);
+ if (x == 0)
+ x = PIRQ_SIS_IRQ_DISABLE;
+ else
+ x |= set;
- switch(pirq) {
- case 0x01:
- case 0x02:
- case 0x03:
- case 0x04:
- reg += 0x40;
- case 0x41:
- case 0x42:
- case 0x43:
- case 0x44:
- case 0x62:
- x = (irq&0x0f) ? (irq&0x0f) : 0x80;
- if (reg != 0x62)
- break;
- /* always mark OHCI enabled, as nothing else knows about this */
- x |= 0x40;
- break;
- case 0x61:
- case 0x6a:
- case 0x7e:
- printk(KERN_INFO "advanced SiS pirq mapping not yet implemented\n");
- return 0;
- default:
- printk(KERN_INFO "SiS router pirq escape (%d)\n", pirq);
- return 0;
- }
pci_write_config_byte(router, reg, x);
return 1;
}
+static int pirq_sis96x_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+ u8 x;
+ int reg, set;
+
+ set = pirq_sis96x_onchip(pirq, ®);
+ if (set < 0)
+ return 0;
+
+ x = (irq & PIRQ_SIS_IRQ_MASK);
+ if (x == 0)
+ x = PIRQ_SIS_IRQ_DISABLE;
+ else
+ x |= set;
+
+ pci_write_config_byte(router, reg, x);
+
+ return 1;
+}
+
+
/*
* VLSI: nibble offset 0x74 - educated guess due to routing table and
* config space of VLSI 82C534 PCI-bridge/router (1004:0102)
@@ -454,96 +568,262 @@
return pcibios_set_irq_routing(bridge, pin, irq);
}
-static struct irq_router pirq_bios_router =
- { "BIOS", 0, 0, NULL, pirq_bios_set };
-
#endif
-static struct irq_router pirq_routers[] = {
- { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, pirq_piix_get, pirq_piix_set },
- { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, pirq_piix_get, pirq_piix_set },
- { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, pirq_piix_get, pirq_piix_set },
- { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX, pirq_piix_get, pirq_piix_set },
- { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_0, pirq_piix_get, pirq_piix_set },
- { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, pirq_piix_get, pirq_piix_set },
- { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, pirq_piix_get, pirq_piix_set },
- { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, pirq_piix_get, pirq_piix_set },
- { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, pirq_piix_get, pirq_piix_set },
- { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, pirq_piix_get, pirq_piix_set },
- { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, pirq_piix_get, pirq_piix_set },
- { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, pirq_piix_get, pirq_piix_set },
- { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, pirq_piix_get, pirq_piix_set },
- { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, pirq_piix_get, pirq_piix_set },
- { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_0, pirq_piix_get, pirq_piix_set },
-
- { "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pirq_ali_get, pirq_ali_set },
-
- { "ITE", PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8330G_0, pirq_ite_get, pirq_ite_set },
-
- { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, pirq_via_get, pirq_via_set },
- { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, pirq_via_get, pirq_via_set },
- { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, pirq_via_get, pirq_via_set },
-
- { "OPTI", PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C700, pirq_opti_get, pirq_opti_set },
-
- { "NatSemi", PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, pirq_cyrix_get, pirq_cyrix_set },
- { "SIS", PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, pirq_sis_get, pirq_sis_set },
- { "VLSI 82C534", PCI_VENDOR_ID_VLSI, PCI_DEVICE_ID_VLSI_82C534, pirq_vlsi_get, pirq_vlsi_set },
- { "ServerWorks", PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4,
- pirq_serverworks_get, pirq_serverworks_set },
- { "ServerWorks", PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5,
- pirq_serverworks_get, pirq_serverworks_set },
- { "AMD756 VIPER", PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B,
- pirq_amd756_get, pirq_amd756_set },
- { "AMD766", PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413,
- pirq_amd756_get, pirq_amd756_set },
- { "AMD768", PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7443,
- pirq_amd756_get, pirq_amd756_set },
- { "default", 0, 0, NULL, NULL }
-};
+static __init int intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+ /* We must not touch 440GX even if we have tables. 440GX has
+ different IRQ routing weirdness */
+ if(pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82450GX, NULL))
+ return 0;
+ switch(device)
+ {
+ case PCI_DEVICE_ID_INTEL_82371FB_0:
+ case PCI_DEVICE_ID_INTEL_82371SB_0:
+ case PCI_DEVICE_ID_INTEL_82371AB_0:
+ case PCI_DEVICE_ID_INTEL_82371MX:
+ case PCI_DEVICE_ID_INTEL_82443MX_0:
+ case PCI_DEVICE_ID_INTEL_82801AA_0:
+ case PCI_DEVICE_ID_INTEL_82801AB_0:
+ case PCI_DEVICE_ID_INTEL_82801BA_0:
+ case PCI_DEVICE_ID_INTEL_82801BA_10:
+ case PCI_DEVICE_ID_INTEL_82801CA_0:
+ case PCI_DEVICE_ID_INTEL_82801CA_12:
+ case PCI_DEVICE_ID_INTEL_82801DB_0:
+ case PCI_DEVICE_ID_INTEL_82801E_0:
+ case PCI_DEVICE_ID_INTEL_82801EB_0:
+ case PCI_DEVICE_ID_INTEL_ESB_0:
+ r->name = "PIIX/ICH";
+ r->get = pirq_piix_get;
+ r->set = pirq_piix_set;
+ return 1;
+ }
+ return 0;
+}
-static struct irq_router *pirq_router;
+static __init int via_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+ /* FIXME: We should move some of the quirk fixup stuff here */
+ switch(device)
+ {
+ case PCI_DEVICE_ID_VIA_82C586_0:
+ case PCI_DEVICE_ID_VIA_82C596:
+ case PCI_DEVICE_ID_VIA_82C686:
+ /* FIXME: add new ones for 8233/5 */
+ r->name = "VIA";
+ r->get = pirq_via_get;
+ r->set = pirq_via_set;
+ return 1;
+ }
+ return 0;
+}
+
+static __init int vlsi_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+ switch(device)
+ {
+ case PCI_DEVICE_ID_VLSI_82C534:
+ r->name = "VLSI 82C534";
+ r->get = pirq_vlsi_get;
+ r->set = pirq_vlsi_set;
+ return 1;
+ }
+ return 0;
+}
+
+
+static __init int serverworks_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+ switch(device)
+ {
+ case PCI_DEVICE_ID_SERVERWORKS_OSB4:
+ case PCI_DEVICE_ID_SERVERWORKS_CSB5:
+ r->name = "ServerWorks";
+ r->get = pirq_serverworks_get;
+ r->set = pirq_serverworks_set;
+ return 1;
+ }
+ return 0;
+}
+
+static __init int sis_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+ u8 reg;
+ u16 devid;
+
+ if (device != PCI_DEVICE_ID_SI_503)
+ return 0;
+
+ /*
+ * In case of SiS south bridge, we need to detect the two
+ * kinds of routing tables we have seen so far (5595 and 96x).
+ * Since the maintain the same device ID, we need to do poke
+ * the PCI configuration space to find the router type we are
+ * dealing with.
+ */
+
+ /*
+ * Factoid: writing bit6 of register 0x40 of the router config space
+ * will make the SB to show up 0x096x inside the device id. Note,
+ * we need to restore register 0x40 after the device id poke.
+ */
+
+ pci_read_config_byte(router, PIRQ_SIS_DETECT_REGISTER, ®);
+ pci_write_config_byte(router, PIRQ_SIS_DETECT_REGISTER, reg | (1 << 6));
+ pci_read_config_word(router, PCI_DEVICE_ID, &devid);
+ pci_write_config_byte(router, PIRQ_SIS_DETECT_REGISTER, reg);
+
+ if ((devid & 0xfff0) == 0x0960) {
+ r->name = "SIS96x";
+ r->get = pirq_sis96x_get;
+ r->set = pirq_sis96x_set;
+ DBG("PCI: Detecting SiS router at %02x:%02x : SiS096x detected\n",
+ rt->rtr_bus, rt->rtr_devfn);
+ } else {
+ r->name = "SIS5595";
+ r->get = pirq_sis5595_get;
+ r->set = pirq_sis5595_set;
+ DBG("PCI: Detecting SiS router at %02x:%02x : SiS5595 detected\n",
+ rt->rtr_bus, rt->rtr_devfn);
+ }
+ return 1;
+}
+
+static __init int cyrix_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+ switch(device)
+ {
+ case PCI_DEVICE_ID_CYRIX_5520:
+ r->name = "NatSemi";
+ r->get = pirq_cyrix_get;
+ r->set = pirq_cyrix_set;
+ return 1;
+ }
+ return 0;
+}
+
+static __init int opti_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+ switch(device)
+ {
+ case PCI_DEVICE_ID_OPTI_82C700:
+ r->name = "OPTI";
+ r->get = pirq_opti_get;
+ r->set = pirq_opti_set;
+ return 1;
+ }
+ return 0;
+}
+
+static __init int ite_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+ switch(device)
+ {
+ case PCI_DEVICE_ID_ITE_IT8330G_0:
+ r->name = "ITE";
+ r->get = pirq_ite_get;
+ r->set = pirq_ite_set;
+ return 1;
+ }
+ return 0;
+}
+
+static __init int ali_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+ switch(device)
+ {
+ case PCI_DEVICE_ID_AL_M1533:
+ r->name = "ALI";
+ r->get = pirq_ali_get;
+ r->set = pirq_ali_set;
+ return 1;
+ /* Should add 156x some day */
+ }
+ return 0;
+}
+
+static __init int amd_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+ switch(device)
+ {
+ case PCI_DEVICE_ID_AMD_VIPER_740B:
+ r->name = "AMD756";
+ break;
+ case PCI_DEVICE_ID_AMD_VIPER_7413:
+ r->name = "AMD766";
+ break;
+ case PCI_DEVICE_ID_AMD_VIPER_7443:
+ r->name = "AMD768";
+ break;
+ default:
+ return 0;
+ }
+ r->get = pirq_amd756_get;
+ r->set = pirq_amd756_set;
+ return 1;
+}
+
+static __initdata struct irq_router_handler pirq_routers[] = {
+ { PCI_VENDOR_ID_INTEL, intel_router_probe },
+ { PCI_VENDOR_ID_AL, ali_router_probe },
+ { PCI_VENDOR_ID_ITE, ite_router_probe },
+ { PCI_VENDOR_ID_VIA, via_router_probe },
+ { PCI_VENDOR_ID_OPTI, opti_router_probe },
+ { PCI_VENDOR_ID_SI, sis_router_probe },
+ { PCI_VENDOR_ID_CYRIX, cyrix_router_probe },
+ { PCI_VENDOR_ID_VLSI, vlsi_router_probe },
+ { PCI_VENDOR_ID_SERVERWORKS, serverworks_router_probe },
+ { PCI_VENDOR_ID_AMD, amd_router_probe },
+ /* Someone with docs needs to add the ATI Radeon IGP */
+ { 0, NULL }
+};
+static struct irq_router pirq_router;
static struct pci_dev *pirq_router_dev;
-static void __init pirq_find_router(void)
+/*
+ * FIXME: should we have an option to say "generic for
+ * chipset" ?
+ */
+
+static void __init pirq_find_router(struct irq_router *r)
{
struct irq_routing_table *rt = pirq_table;
- struct irq_router *r;
+ struct irq_router_handler *h;
#ifdef CONFIG_PCI_BIOS
if (!rt->signature) {
printk(KERN_INFO "PCI: Using BIOS for IRQ routing\n");
- pirq_router = &pirq_bios_router;
+ r->set = pirq_bios_set;
+ r->name = "BIOS";
return;
}
#endif
+ /* Default unless a driver reloads it */
+ r->name = "default";
+ r->get = NULL;
+ r->set = NULL;
+
DBG("PCI: Attempting to find IRQ router for %04x:%04x\n",
rt->rtr_vendor, rt->rtr_device);
- /* fall back to default router if nothing else found */
- pirq_router = &pirq_routers[ARRAY_SIZE(pirq_routers) - 1];
-
pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn);
if (!pirq_router_dev) {
DBG("PCI: Interrupt router not found at %02x:%02x\n", rt->rtr_bus, rt->rtr_devfn);
return;
}
- for(r=pirq_routers; r->vendor; r++) {
- /* Exact match against router table entry? Use it! */
- if (r->vendor == rt->rtr_vendor && r->device == rt->rtr_device) {
- pirq_router = r;
+ for( h = pirq_routers; h->vendor; h++) {
+ /* First look for a router match */
+ if (rt->rtr_vendor == h->vendor && h->probe(r, pirq_router_dev, rt->rtr_device))
+ break;
+ /* Fall back to a device match */
+ if (pirq_router_dev->vendor == h->vendor && h->probe(r, pirq_router_dev, pirq_router_dev->device))
break;
- }
- /* Match against router device entry? Use it as a fallback */
- if (r->vendor == pirq_router_dev->vendor && r->device == pirq_router_dev->device) {
- pirq_router = r;
- }
}
printk(KERN_INFO "PCI: Using IRQ router %s [%04x/%04x] at %s\n",
- pirq_router->name,
+ pirq_router.name,
pirq_router_dev->vendor,
pirq_router_dev->device,
pirq_router_dev->slot_name);
@@ -572,7 +852,7 @@
int i, pirq, newirq;
int irq = 0;
u32 mask;
- struct irq_router *r = pirq_router;
+ struct irq_router *r = &pirq_router;
struct pci_dev *dev2;
char *msg = NULL;
@@ -685,17 +965,14 @@
void __init pcibios_irq_init(void)
{
DBG("PCI: IRQ init\n");
- if (broken_440gx_bios)
- pirq_table = NULL;
- else
- pirq_table = pirq_find_routing_table();
+ pirq_table = pirq_find_routing_table();
#ifdef CONFIG_PCI_BIOS
if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN))
pirq_table = pcibios_get_irq_routing_table();
#endif
if (pirq_table) {
pirq_peer_trick();
- pirq_find_router();
+ pirq_find_router(&pirq_router);
if (pirq_table->exclusive_irqs) {
int i;
for (i=0; i<16; i++)
diff -urN linux-2.4.22-bk4/drivers/char/Config.in linux-2.4.22-bk5/drivers/char/Config.in
--- linux-2.4.22-bk4/drivers/char/Config.in 2003-08-30 02:51:13.000000000 -0700
+++ linux-2.4.22-bk5/drivers/char/Config.in 2003-08-30 02:51:16.000000000 -0700
@@ -105,6 +105,12 @@
fi
fi
fi
+if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_SGI_SN2" = "y" ] ; then
+ bool 'SGI SN2 l1 serial port support' CONFIG_SGI_L1_SERIAL
+ if [ "$CONFIG_SGI_L1_SERIAL" = "y" ]; then
+ bool ' SGI SN2 l1 Console support' CONFIG_SGI_L1_SERIAL_CONSOLE
+ fi
+fi
if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_ZORRO" = "y" ]; then
tristate 'Commodore A2232 serial support (EXPERIMENTAL)' CONFIG_A2232
fi
diff -urN linux-2.4.22-bk4/drivers/char/Makefile linux-2.4.22-bk5/drivers/char/Makefile
--- linux-2.4.22-bk4/drivers/char/Makefile 2003-08-30 02:51:13.000000000 -0700
+++ linux-2.4.22-bk5/drivers/char/Makefile 2003-08-30 02:51:17.000000000 -0700
@@ -211,6 +211,7 @@
obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o
obj-$(CONFIG_SERIAL_TX3912) += generic_serial.o serial_tx3912.o
obj-$(CONFIG_TXX927_SERIAL) += serial_txx927.o
+obj-$(CONFIG_SGI_L1_SERIAL) += sn_serial.o
subdir-$(CONFIG_RIO) += rio
subdir-$(CONFIG_INPUT) += joystick
diff -urN linux-2.4.22-bk4/drivers/char/amd7xx_tco.c linux-2.4.22-bk5/drivers/char/amd7xx_tco.c
--- linux-2.4.22-bk4/drivers/char/amd7xx_tco.c 2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.22-bk5/drivers/char/amd7xx_tco.c 2003-08-30 02:51:17.000000000 -0700
@@ -1,6 +1,6 @@
/*
* AMD 766/768 TCO Timer Driver
- * (c) Copyright 2002 Zwane Mwaikambo
+ * (c) Copyright 2002 Zwane Mwaikambo
* All Rights Reserved.
*
* Parts from;
@@ -34,35 +34,48 @@
#include
#include
-#define AMDTCO_MODULE_VER "build 20020601"
+#define AMDTCO_MODULE_VER "build 20021116"
#define AMDTCO_MODULE_NAME "amd7xx_tco"
#define PFX AMDTCO_MODULE_NAME ": "
-#define MAX_TIMEOUT 38 /* max of 38 seconds */
+#define MAX_TIMEOUT 38 /* max of 38 seconds, although the system will only
+ * reset itself after the second timeout */
/* pmbase registers */
-#define GLOBAL_SMI_REG 0x2a
-#define TCO_EN (1 << 1) /* bit 1 in global SMI register */
#define TCO_RELOAD_REG 0x40 /* bits 0-5 are current count, 6-7 are reserved */
#define TCO_INITVAL_REG 0x41 /* bits 0-5 are value to load, 6-7 are reserved */
#define TCO_TIMEOUT_MASK 0x3f
+#define TCO_STATUS1_REG 0x44
#define TCO_STATUS2_REG 0x46
#define NDTO_STS2 (1 << 1) /* we're interested in the second timeout */
#define BOOT_STS (1 << 2) /* will be set if NDTO_STS2 was set before reboot */
#define TCO_CTRL1_REG 0x48
#define TCO_HALT (1 << 11)
+#define NO_REBOOT (1 << 10) /* in DevB:3x48 */
-static char banner[] __initdata = KERN_INFO PFX AMDTCO_MODULE_VER;
+static char banner[] __initdata = KERN_INFO PFX AMDTCO_MODULE_VER "\n";
static int timeout = 38;
static u32 pmbase; /* PMxx I/O base */
static struct pci_dev *dev;
static struct semaphore open_sem;
-spinlock_t amdtco_lock; /* only for device access */
+static spinlock_t amdtco_lock; /* only for device access */
static int expect_close = 0;
MODULE_PARM(timeout, "i");
MODULE_PARM_DESC(timeout, "range is 0-38 seconds, default is 38");
+static inline u8 seconds_to_ticks(int seconds)
+{
+ /* the internal timer is stored as ticks which decrement
+ * every 0.6 seconds */
+ return (seconds * 10) / 6;
+}
+
+static inline int ticks_to_seconds(u8 ticks)
+{
+ return (ticks * 6) / 10;
+}
+
static inline int amdtco_status(void)
{
u16 reg;
@@ -81,28 +94,19 @@
static inline void amdtco_ping(void)
{
- u8 reg;
-
- spin_lock(&amdtco_lock);
- reg = inb(pmbase+TCO_RELOAD_REG);
- outb(1 | reg, pmbase+TCO_RELOAD_REG);
- spin_unlock(&amdtco_lock);
+ outb(1, pmbase+TCO_RELOAD_REG);
}
static inline int amdtco_gettimeout(void)
{
- return inb(TCO_RELOAD_REG) & TCO_TIMEOUT_MASK;
+ u8 reg = inb(pmbase+TCO_RELOAD_REG) & TCO_TIMEOUT_MASK;
+ return ticks_to_seconds(reg);
}
static inline void amdtco_settimeout(unsigned int timeout)
{
- u8 reg;
-
- spin_lock(&amdtco_lock);
- reg = inb(pmbase+TCO_INITVAL_REG);
- reg |= timeout & TCO_TIMEOUT_MASK;
+ u8 reg = seconds_to_ticks(timeout) & TCO_TIMEOUT_MASK;
outb(reg, pmbase+TCO_INITVAL_REG);
- spin_unlock(&amdtco_lock);
}
static inline void amdtco_global_enable(void)
@@ -110,9 +114,12 @@
u16 reg;
spin_lock(&amdtco_lock);
- reg = inw(pmbase+GLOBAL_SMI_REG);
- reg |= TCO_EN;
- outw(reg, pmbase+GLOBAL_SMI_REG);
+
+ /* clear NO_REBOOT on DevB:3x48 p97 */
+ pci_read_config_word(dev, 0x48, ®);
+ reg &= ~NO_REBOOT;
+ pci_write_config_word(dev, 0x48, reg);
+
spin_unlock(&amdtco_lock);
}
@@ -150,10 +157,12 @@
if (timeout > MAX_TIMEOUT)
timeout = MAX_TIMEOUT;
+ amdtco_disable();
amdtco_settimeout(timeout);
amdtco_global_enable();
+ amdtco_enable();
amdtco_ping();
- printk(KERN_INFO PFX "Watchdog enabled, timeout = %d/%d seconds",
+ printk(KERN_INFO PFX "Watchdog enabled, timeout = %ds of %ds\n",
amdtco_gettimeout(), timeout);
return 0;
@@ -202,7 +211,7 @@
case WDIOC_GETTIMEOUT:
return put_user(amdtco_gettimeout(), (int *)arg);
-
+
case WDIOC_SETOPTIONS:
if (copy_from_user(&tmp, (int *)arg, sizeof tmp))
return -EFAULT;
@@ -225,7 +234,7 @@
printk(KERN_INFO PFX "Watchdog disabled\n");
} else {
amdtco_ping();
- printk(KERN_CRIT PFX "Unexpected close!, timeout in %d seconds)\n", timeout);
+ printk(KERN_CRIT PFX "Unexpected close!, timeout in %d seconds\n", timeout);
}
up(&open_sem);
@@ -253,10 +262,9 @@
}
#endif
amdtco_ping();
- return len;
}
- return 0;
+ return len;
}
@@ -291,7 +299,6 @@
};
static struct pci_device_id amdtco_pci_tbl[] __initdata = {
- /* AMD 766 PCI_IDs here */
{ 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, },
{ 0, }
};
@@ -361,6 +368,9 @@
if (ints[0] > 0)
timeout = ints[1];
+ if (!timeout || timeout > 38)
+ timeout = MAX_TIMEOUT;
+
return 1;
}
@@ -370,7 +380,7 @@
module_init(amdtco_init);
module_exit(amdtco_exit);
-MODULE_AUTHOR("Zwane Mwaikambo ");
+MODULE_AUTHOR("Zwane Mwaikambo ");
MODULE_DESCRIPTION("AMD 766/768 TCO Timer Driver");
MODULE_LICENSE("GPL");
EXPORT_NO_SYMBOLS;
diff -urN linux-2.4.22-bk4/drivers/char/i810-tco.c linux-2.4.22-bk5/drivers/char/i810-tco.c
--- linux-2.4.22-bk4/drivers/char/i810-tco.c 2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.22-bk5/drivers/char/i810-tco.c 2003-08-30 02:51:17.000000000 -0700
@@ -25,7 +25,8 @@
* 82801AA & 82801AB chip : document number 290655-003, 290677-004,
* 82801BA & 82801BAM chip : document number 290687-002, 298242-005,
* 82801CA & 82801CAM chip : document number 290716-001, 290718-001,
- * 82801DB & 82801E chip : document number 290744-001, 273599-001
+ * 82801DB & 82801E chip : document number 290744-001, 273599-001,
+ * 82801EB & 82801ER chip : document number 252516-001
*
* 20000710 Nils Faerber
* Initial Version 0.01
@@ -42,9 +43,11 @@
* clean up ioctls (WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS and
* WDIOC_SETOPTIONS), made i810tco_getdevice __init,
* removed boot_status, removed tco_timer_read,
- * added support for 82801DB and 82801E chipset, general cleanup.
+ * added support for 82801DB and 82801E chipset,
+ * added support for 82801EB and 8280ER chipset,
+ * general cleanup.
*/
-
+
#include
#include
#include
@@ -167,7 +170,7 @@
* Reload (trigger) the timer. Lock is needed so we dont reload it during
* a reprogramming event
*/
-
+
static void tco_timer_reload (void)
{
spin_lock(&tco_lock);
@@ -310,6 +313,7 @@
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, },
{ 0, },
};
MODULE_DEVICE_TABLE (pci, i810tco_pci_tbl);
diff -urN linux-2.4.22-bk4/drivers/char/i810-tco.h linux-2.4.22-bk5/drivers/char/i810-tco.h
--- linux-2.4.22-bk4/drivers/char/i810-tco.h 2002-08-02 17:39:43.000000000 -0700
+++ linux-2.4.22-bk5/drivers/char/i810-tco.h 2003-08-30 02:51:17.000000000 -0700
@@ -1,5 +1,5 @@
/*
- * i810-tco 0.05: TCO timer driver for i8xx chipsets
+ * i810-tco: TCO timer driver for i8xx chipsets
*
* (c) Copyright 2000 kernel concepts , All Rights Reserved.
* http://www.kernelconcepts.de
@@ -8,7 +8,7 @@
* 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.
- *
+ *
* Neither kernel concepts nor Nils Faerber admit liability nor provide
* warranty for any of this software. This material is provided
* "AS-IS" and at no charge.
diff -urN linux-2.4.22-bk4/drivers/char/keyboard.c linux-2.4.22-bk5/drivers/char/keyboard.c
--- linux-2.4.22-bk4/drivers/char/keyboard.c 2003-08-25 04:44:41.000000000 -0700
+++ linux-2.4.22-bk5/drivers/char/keyboard.c 2003-08-30 02:51:17.000000000 -0700
@@ -198,6 +198,7 @@
unsigned char keycode;
char up_flag = down ? 0 : 0200;
char raw_mode;
+ char have_keycode;
pm_access(pm_kbd);
add_keyboard_randomness(scancode | up_flag);
@@ -214,16 +215,30 @@
tty = NULL;
}
kbd = kbd_table + fg_console;
- if ((raw_mode = (kbd->kbdmode == VC_RAW))) {
+ /*
+ * Convert scancode to keycode
+ */
+ raw_mode = (kbd->kbdmode == VC_RAW);
+ have_keycode = kbd_translate(scancode, &keycode, raw_mode);
+ if (raw_mode) {
/*
* The following is a workaround for hardware
* which sometimes send the key release event twice
*/
unsigned char next_scancode = scancode|up_flag;
- if (up_flag && next_scancode==prev_scancode) {
+ if (have_keycode && up_flag && next_scancode==prev_scancode) {
/* unexpected 2nd release event */
} else {
- prev_scancode=next_scancode;
+ /*
+ * Only save previous scancode if it was a key-up
+ * and had a single-byte scancode.
+ */
+ if (!have_keycode)
+ prev_scancode = 1;
+ else if (!up_flag || prev_scancode == 1)
+ prev_scancode = 0;
+ else
+ prev_scancode = next_scancode;
put_queue(next_scancode);
}
/* we do not return yet, because we want to maintain
@@ -231,10 +246,7 @@
values when finishing RAW mode or when changing VT's */
}
- /*
- * Convert scancode to keycode
- */
- if (!kbd_translate(scancode, &keycode, raw_mode))
+ if (!have_keycode)
goto out;
/*
diff -urN linux-2.4.22-bk4/drivers/char/sn_serial.c linux-2.4.22-bk5/drivers/char/sn_serial.c
--- linux-2.4.22-bk4/drivers/char/sn_serial.c 1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.22-bk5/drivers/char/sn_serial.c 2003-08-30 02:51:17.000000000 -0700
@@ -0,0 +1,1190 @@
+/*
+ * C-Brick Serial Port (and console) driver for SGI Altix machines.
+ *
+ * This driver is NOT suitable for talking to the l1-controller for
+ * anything other than 'console activities' --- please use the l1
+ * driver for that.
+ *
+ *
+ * Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#ifdef CONFIG_MAGIC_SYSRQ
+#include
+#endif
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef CONFIG_KDB
+#include
+#include
+
+/*
+ * The following KDB configuration info is borrowed from
+ * linux/drivers/char/serial.c:
+ */
+
+/*
+ * "kdb_serial_str[] is the sequence that the user must enter on the serial
+ * console to invoke kdb. It can be a single character such as "\001"
+ * (control-A) or multiple characters such as "\eKdB". NOTE: All except the
+ * last character are passed through to the application reading from the serial
+ * console.
+ *
+ * I tried to make the sequence a CONFIG_ option but most of CML1 cannot cope
+ * with '\' in strings, CML2 should be able to do it. KAO."
+ */
+
+static int kdb_serial_line = -1;
+static const char kdb_serial_str[] = "\eKDB";
+static char *kdb_serial_ptr = kdb_serial_str;
+#endif /* CONFIG_KDB */
+
+#if defined(CONFIG_SGI_L1_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+static char sysrq_serial_str[] = "\eSYS";
+static char *sysrq_serial_ptr = sysrq_serial_str;
+static unsigned long sysrq_requested;
+#endif /* CONFIG_SGI_L1_SERIAL_CONSOLE && CONFIG_MAGIC_SYSRQ */
+
+static char *serial_revdate = "2003-07-31";
+
+/* driver subtype - what does this mean? */
+#define SN_SAL_SUBTYPE 1
+
+/* minor device number */
+#define SN_SAL_MINOR 64
+
+/* number of characters left in xmit buffer before we ask for more */
+#define WAKEUP_CHARS 128
+
+/* number of characters we can transmit to the SAL console at a time */
+#define SN_SAL_MAX_CHARS 120
+
+/* event types for our task queue -- so far just one */
+#define SN_SAL_EVENT_WRITE_WAKEUP 0
+
+#define CONSOLE_RESTART 1
+
+/* 64K, when we're asynch, it must be at least printk's LOG_BUF_LEN to
+ * avoid losing chars, (always has to be a power of 2) */
+#if 1
+#define SN_SAL_BUFFER_SIZE (64 * (1 << 10))
+#else
+#define SN_SAL_BUFFER_SIZE (64)
+#endif
+
+#define SN_SAL_UART_FIFO_DEPTH 16
+#define SN_SAL_UART_FIFO_SPEED_CPS 9600/10
+
+/* we don't kmalloc/get_free_page these as we want them available
+ * before either of those are initialized */
+static volatile char xmit_buff_mem[SN_SAL_BUFFER_SIZE];
+
+struct volatile_circ_buf {
+ volatile char *buf;
+ int head;
+ int tail;
+};
+
+static volatile struct volatile_circ_buf xmit = { .buf = xmit_buff_mem };
+static char sal_tmp_buffer[SN_SAL_BUFFER_SIZE];
+
+static volatile struct tty_struct *sn_sal_tty;
+
+static struct timer_list sn_sal_timer;
+static int sn_sal_event; /* event type for task queue */
+static int sn_sal_refcount;
+
+static volatile int sn_sal_is_asynch;
+static volatile int sn_sal_irq;
+static spinlock_t sn_sal_lock = SPIN_LOCK_UNLOCKED;
+static volatile int tx_count;
+static volatile int rx_count;
+
+static struct tty_struct *sn_sal_table;
+static struct termios *sn_sal_termios;
+static struct termios *sn_sal_termios_locked;
+
+static void sn_sal_tasklet_action(unsigned long data);
+static DECLARE_TASKLET(sn_sal_tasklet, sn_sal_tasklet_action, 0);
+
+static volatile unsigned long interrupt_timeout;
+
+extern u64 master_node_bedrock_address;
+
+int debug_printf(const char *fmt, ...);
+
+#undef DEBUG
+#ifdef DEBUG
+#define DPRINTF(x...) debug_printf(x)
+#else
+#define DPRINTF(x...) do { } while (0)
+#endif
+
+static void intr_transmit_chars(void);
+static void poll_transmit_chars(void);
+static int sn_sal_write(struct tty_struct *tty, int from_user,
+ const unsigned char *buf, int count);
+
+struct sn_sal_ops {
+ int (*puts)(const char *s, int len);
+ int (*getc)(void);
+ int (*input_pending)(void);
+ void (*wakeup_transmit)(void);
+};
+
+static volatile struct sn_sal_ops *sn_sal_ops;
+
+
+/* the console does output in two distinctly different ways:
+ * synchronous and asynchronous (buffered). initally, early_printk
+ * does synchronous output. any data written goes directly to the SAL
+ * to be output (incidentally, it is internally buffered by the SAL)
+ * after interrupts and timers are initialized and available for use,
+ * the console init code switches to asynchronous output. this is
+ * also the earliest opportunity to begin polling for console input.
+ * after console initialization, console output and tty (serial port)
+ * output is buffered and sent to the SAL asynchronously (either by
+ * timer callback or by UART interrupt) */
+
+
+/* routines for running the console in polling mode */
+
+static int hw_puts(const char *s, int len)
+{
+ /* looking at the PROM source code, putb calls the flush
+ * routine, so if we send characters in FIFO sized chunks, it
+ * should go out by the next time the timer gets called */
+ return ia64_sn_console_putb(s, len);
+}
+
+static int poll_getc(void)
+{
+ int ch;
+ ia64_sn_console_getc(&ch);
+ return ch;
+}
+
+static int poll_input_pending(void)
+{
+ int status, input;
+
+ status = ia64_sn_console_check(&input);
+ return !status && input;
+}
+
+static struct sn_sal_ops poll_ops = {
+ .puts = hw_puts,
+ .getc = poll_getc,
+ .input_pending = poll_input_pending
+};
+
+
+/* routines for running the console on the simulator */
+
+static int sim_puts(const char *str, int count)
+{
+ int counter = count;
+
+#ifdef FLAG_DIRECT_CONSOLE_WRITES
+ /* This is an easy way to pre-pend the output to know whether the output
+ * was done via sal or directly */
+ writeb('[', master_node_bedrock_address + (UART_TX << 3));
+ writeb('+', master_node_bedrock_address + (UART_TX << 3));
+ writeb(']', master_node_bedrock_address + (UART_TX << 3));
+ writeb(' ', master_node_bedrock_address + (UART_TX << 3));
+#endif /* FLAG_DIRECT_CONSOLE_WRITES */
+ while (counter > 0) {
+ writeb(*str, master_node_bedrock_address + (UART_TX << 3));
+ counter--;
+ str++;
+ }
+
+ return count;
+}
+
+static int sim_getc(void)
+{
+ return readb(master_node_bedrock_address + (UART_RX << 3));
+}
+
+static int sim_input_pending(void)
+{
+ return readb(master_node_bedrock_address + (UART_LSR << 3)) & UART_LSR_DR;
+}
+
+static struct sn_sal_ops sim_ops = {
+ .puts = sim_puts,
+ .getc = sim_getc,
+ .input_pending = sim_input_pending
+};
+
+
+/* routines for an interrupt driven console (normal) */
+
+static int intr_getc(void)
+{
+ return ia64_sn_console_readc();
+}
+
+static int intr_input_pending(void)
+{
+ return ia64_sn_console_intr_status() & SAL_CONSOLE_INTR_RECV;
+}
+
+static struct sn_sal_ops intr_ops = {
+ .puts = hw_puts,
+ .getc = intr_getc,
+ .input_pending = intr_input_pending,
+ .wakeup_transmit = intr_transmit_chars
+};
+
+extern void early_sn_setup(void);
+
+void
+early_printk_sn_sal(const char *s, unsigned count)
+{
+ if (!sn_sal_ops) {
+ if (IS_RUNNING_ON_SIMULATOR())
+ sn_sal_ops = &sim_ops;
+ else
+ sn_sal_ops = &poll_ops;
+
+ early_sn_setup();
+ }
+ sn_sal_ops->puts(s, count);
+}
+
+/* this is as "close to the metal" as we can get, used when the driver
+ * itself may be broken */
+int debug_printf(const char *fmt, ...)
+{
+ static char printk_buf[1024];
+ int printed_len;
+ va_list args;
+ va_start(args, fmt);
+ printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
+ early_printk_sn_sal(printk_buf, printed_len);
+ va_end(args);
+ return printed_len;
+}
+
+/*********************************************************************
+ * Interrupt handling routines.
+ */
+
+static void
+sn_sal_sched_event(int event)
+{
+ sn_sal_event |= (1 << event);
+ tasklet_schedule(&sn_sal_tasklet);
+}
+
+/* receive_chars can be called before sn_sal_tty is initialized. in
+ * that case, its only use is to trigger sysrq and kdb */
+static void
+receive_chars(struct pt_regs *regs)
+{
+ int ch;
+
+ while (sn_sal_ops->input_pending()) {
+ ch = sn_sal_ops->getc();
+ if (ch < 0) {
+ printk(KERN_ERR "sn_serial: An error occured while "
+ "obtaining data from the console (0x%0x)\n", ch);
+ break;
+ }
+#ifdef CONFIG_KDB
+ if (kdb_on) {
+ if (ch == *kdb_serial_ptr) {
+ if (!(*++kdb_serial_ptr)) {
+ if (!regs)
+ KDB_ENTER(); /* to get some registers */
+ else
+ kdb(KDB_REASON_KEYBOARD, 0, regs);
+ kdb_serial_ptr = kdb_serial_str;
+ break;
+ }
+ } else
+ kdb_serial_ptr = kdb_serial_str;
+ }
+#endif /* CONFIG_KDB */
+
+#if defined(CONFIG_SGI_L1_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+ if (sysrq_requested) {
+ unsigned long sysrq_timeout = sysrq_requested + HZ*5;
+ sysrq_requested = 0;
+ if (ch && time_before(jiffies, sysrq_timeout)) {
+ spin_unlock(&sn_sal_lock);
+ handle_sysrq(ch, regs, NULL, NULL);
+ spin_lock(&sn_sal_lock);
+ /* don't record this char */
+ continue;
+ }
+ }
+ if (ch == *sysrq_serial_ptr) {
+ if (!(*++sysrq_serial_ptr)) {
+ sysrq_requested = jiffies;
+ sysrq_serial_ptr = sysrq_serial_str;
+ }
+ } else
+ sysrq_serial_ptr = sysrq_serial_str;
+#endif /* CONFIG_SGI_L1_SERIAL_CONSOLE && CONFIG_MAGIC_SYSRQ */
+
+ /* record the character to pass up to the tty layer */
+ if (sn_sal_tty) {
+ *sn_sal_tty->flip.char_buf_ptr = ch;
+ sn_sal_tty->flip.char_buf_ptr++;
+ sn_sal_tty->flip.count++;
+ if (sn_sal_tty->flip.count == TTY_FLIPBUF_SIZE)
+ break;
+ }
+ rx_count++;
+ }
+
+ if (sn_sal_tty)
+ tty_flip_buffer_push(sn_sal_tty);
+}
+
+
+/* synch_flush_xmit must be called with sn_sal_lock */
+static void
+synch_flush_xmit(void)
+{
+ int xmit_count, tail, head, loops, ii;
+ int result;
+ char *start;
+
+ if (xmit.head == xmit.tail)
+ /* Nothing to do. */
+ return;
+
+ head = xmit.head;
+ tail = xmit.tail;
+ start = &xmit.buf[tail];
+
+ /* twice around gets the tail to the end of the buffer and
+ * then to the head, if needed */
+ loops = (head < tail) ? 2 : 1;
+
+ for (ii = 0; ii < loops; ii++) {
+ xmit_count = (head < tail) ?
+ (SN_SAL_BUFFER_SIZE - tail) : (head - tail);
+
+ if (xmit_count > 0) {
+ result = sn_sal_ops->puts(start, xmit_count);
+ if (!result)
+ debug_printf("\n*** synch_flush_xmit failed to flush\n");
+ if (result > 0) {
+ xmit_count -= result;
+ tx_count += result;
+ tail += result;
+ tail &= SN_SAL_BUFFER_SIZE - 1;
+ xmit.tail = tail;
+ start = &xmit.buf[tail];
+ }
+ }
+ }
+
+}
+
+/* must be called with a lock protecting the circular buffer and
+ * sn_sal_tty */
+static void
+poll_transmit_chars(void)
+{
+ int xmit_count, tail, head;
+ int result;
+ char *start;
+
+ BUG_ON(!sn_sal_is_asynch);
+
+ if (xmit.head == xmit.tail ||
+ (sn_sal_tty && (sn_sal_tty->stopped || sn_sal_tty->hw_stopped))) {
+ /* Nothing to do. */
+ return;
+ }
+
+ head = xmit.head;
+ tail = xmit.tail;
+ start = &xmit.buf[tail];
+
+ xmit_count = (head < tail) ?
+ (SN_SAL_BUFFER_SIZE - tail) : (head - tail);
+
+ if (xmit_count == 0)
+ debug_printf("\n*** empty xmit_count\n");
+
+ if (xmit_count > SN_SAL_UART_FIFO_DEPTH)
+ xmit_count = SN_SAL_UART_FIFO_DEPTH;
+
+ /* use the ops, as we could be on the simulator */
+ result = sn_sal_ops->puts(start, xmit_count);
+ if (!result)
+ debug_printf("\n*** error in synchronous puts\n");
+ /* XXX chadt clean this up */
+ if (result > 0) {
+ xmit_count -= result;
+ tx_count += result;
+ tail += result;
+ tail &= SN_SAL_BUFFER_SIZE - 1;
+ xmit.tail = tail;
+ start = &xmit.buf[tail];
+ }
+
+ /* if there's few enough characters left in the xmit buffer
+ * that we could stand for the upper layer to send us some
+ * more, ask for it. */
+ if (sn_sal_tty)
+ if (CIRC_CNT(xmit.head, xmit.tail, SN_SAL_BUFFER_SIZE) < WAKEUP_CHARS)
+ sn_sal_sched_event(SN_SAL_EVENT_WRITE_WAKEUP);
+}
+
+
+/* must be called with a lock protecting the circular buffer and
+ * sn_sal_tty */
+static void
+intr_transmit_chars(void)
+{
+ int xmit_count, tail, head, loops, ii;
+ int result;
+ char *start;
+
+ BUG_ON(!sn_sal_is_asynch);
+
+ if (xmit.head == xmit.tail ||
+ (sn_sal_tty && (sn_sal_tty->stopped || sn_sal_tty->hw_stopped))) {
+ /* Nothing to do. */
+ return;
+ }
+
+ head = xmit.head;
+ tail = xmit.tail;
+ start = &xmit.buf[tail];
+
+ /* twice around gets the tail to the end of the buffer and
+ * then to the head, if needed */
+ loops = (head < tail) ? 2 : 1;
+
+ for (ii = 0; ii < loops; ii++) {
+ xmit_count = (head < tail) ?
+ (SN_SAL_BUFFER_SIZE - tail) : (head - tail);
+
+ if (xmit_count > 0) {
+ result = ia64_sn_console_xmit_chars(start, xmit_count);
+#ifdef DEBUG
+ if (!result)
+ debug_printf("`");
+#endif
+ if (result > 0) {
+ xmit_count -= result;
+ tx_count += result;
+ tail += result;
+ tail &= SN_SAL_BUFFER_SIZE - 1;
+ xmit.tail = tail;
+ start = &xmit.buf[tail];
+ }
+ }
+ }
+
+ /* if there's few enough characters left in the xmit buffer
+ * that we could stand for the upper layer to send us some
+ * more, ask for it. */
+ if (sn_sal_tty)
+ if (CIRC_CNT(xmit.head, xmit.tail, SN_SAL_BUFFER_SIZE) < WAKEUP_CHARS)
+ sn_sal_sched_event(SN_SAL_EVENT_WRITE_WAKEUP);
+}
+
+
+static void
+sn_sal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ /* this call is necessary to pass the interrupt back to the
+ * SAL, since it doesn't intercept the UART interrupts
+ * itself */
+ int status = ia64_sn_console_intr_status();
+
+ spin_lock(&sn_sal_lock);
+ if (status & SAL_CONSOLE_INTR_RECV)
+ receive_chars(regs);
+ if (status & SAL_CONSOLE_INTR_XMIT)
+ intr_transmit_chars();
+ spin_unlock(&sn_sal_lock);
+}
+
+
+/* returns the console irq if interrupt is successfully registered,
+ * else 0 */
+static int
+sn_sal_connect_interrupt(void)
+{
+ cpuid_t intr_cpuid;
+ unsigned int intr_cpuloc;
+ nasid_t console_nasid;
+ unsigned int console_irq;
+ int result;
+
+ /* if it is an old prom, run in poll mode */
+ if ((sn_sal_rev_major() <= 1) && (sn_sal_rev_minor() <= 3)) {
+ /* before version 1.06 doesn't work */
+ printk(KERN_INFO "sn_serial: old prom version %x.%02x"
+ " - running in polled mode\n",
+ sn_sal_rev_major(), sn_sal_rev_minor());
+ return 0;
+ }
+
+ console_nasid = ia64_sn_get_console_nasid();
+ intr_cpuid = NODEPDA(NASID_TO_COMPACT_NODEID(console_nasid))
+ ->node_first_cpu;
+ intr_cpuloc = cpu_physical_id(intr_cpuid);
+ console_irq = CPU_VECTOR_TO_IRQ(intr_cpuloc, SGI_UART_VECTOR);
+
+ result = intr_connect_level(intr_cpuid, SGI_UART_VECTOR,
+ 0 /*not used*/, 0 /*not used*/);
+ BUG_ON(result != SGI_UART_VECTOR);
+
+ result = request_irq(console_irq, sn_sal_interrupt,
+ SA_INTERRUPT, "SAL console driver", &sn_sal_tty);
+ if (result >= 0)
+ return console_irq;
+
+ printk(KERN_INFO "sn_serial: console proceeding in polled mode\n");
+ return 0;
+}
+
+/*
+ * End of the interrupt routines.
+ *********************************************************************/
+
+
+static void
+sn_sal_tasklet_action(unsigned long data)
+{
+ unsigned long flags;
+
+ if (sn_sal_tty) {
+ spin_lock_irqsave(&sn_sal_lock, flags);
+ if (sn_sal_tty)
+ if (test_and_clear_bit(SN_SAL_EVENT_WRITE_WAKEUP, &sn_sal_event)) {
+ if ((sn_sal_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ sn_sal_tty->ldisc.write_wakeup)
+ (sn_sal_tty->ldisc.write_wakeup)(sn_sal_tty);
+ wake_up_interruptible(&sn_sal_tty->write_wait);
+ }
+ spin_unlock_irqrestore(&sn_sal_lock, flags);
+ }
+}
+
+
+/*
+ * This function handles polled mode.
+ */
+static void
+sn_sal_timer_poll(unsigned long dummy)
+{
+ if (!sn_sal_irq) {
+ spin_lock(&sn_sal_lock);
+ receive_chars(NULL);
+ poll_transmit_chars();
+ spin_unlock(&sn_sal_lock);
+ mod_timer(&sn_sal_timer, jiffies + interrupt_timeout);
+ }
+}
+
+static void
+sn_sal_timer_restart(unsigned long dummy)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ sn_sal_interrupt(0, NULL, NULL);
+ local_irq_restore(flags);
+ mod_timer(&sn_sal_timer, jiffies + interrupt_timeout);
+}
+
+/*
+ * End of "sofware interrupt" routines.
+ *********************************************************************/
+
+
+/*********************************************************************
+ * User-level console routines
+ */
+
+static int
+sn_sal_open(struct tty_struct *tty, struct file *filp)
+{
+ unsigned long flags;
+
+ DPRINTF("sn_sal_open: sn_sal_tty = %p, tty = %p, filp = %p\n",
+ sn_sal_tty, tty, filp);
+
+ spin_lock_irqsave(&sn_sal_lock, flags);
+ if (!sn_sal_tty)
+ sn_sal_tty = tty;
+ spin_unlock_irqrestore(&sn_sal_lock, flags);
+
+ return 0;
+}
+
+
+/* We're keeping all our resources. We're keeping interrupts turned
+ * on. Maybe just let the tty layer finish its stuff...? GMSH
+ */
+static void
+sn_sal_close(struct tty_struct *tty, struct file * filp)
+{
+ if (atomic_read(&tty->count) == 1) {
+ unsigned long flags;
+ tty->closing = 1;
+ if (tty->driver.flush_buffer)
+ tty->driver.flush_buffer(tty);
+ if (tty->ldisc.flush_buffer)
+ tty->ldisc.flush_buffer(tty);
+ tty->closing = 0;
+ spin_lock_irqsave(&sn_sal_lock, flags);
+ sn_sal_tty = NULL;
+ spin_unlock_irqrestore(&sn_sal_lock, flags);
+ }
+}
+
+
+static int
+sn_sal_write(struct tty_struct *tty, int from_user,
+ const unsigned char *buf, int count)
+{
+ int c, ret = 0;
+ unsigned long flags;
+
+ if (from_user) {
+ while (1) {
+ int c1;
+ c = CIRC_SPACE_TO_END(xmit.head, xmit.tail,
+ SN_SAL_BUFFER_SIZE);
+
+ if (count < c)
+ c = count;
+ if (c <= 0)
+ break;
+
+ c -= copy_from_user(sal_tmp_buffer, buf, c);
+ if (!c) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
+
+ /* Turn off interrupts and see if the xmit buffer has
+ * moved since the last time we looked.
+ */
+ spin_lock_irqsave(&sn_sal_lock, flags);
+ c1 = CIRC_SPACE_TO_END(xmit.head, xmit.tail,
+ SN_SAL_BUFFER_SIZE);
+
+ if (c1 < c)
+ c = c1;
+
+ memcpy(xmit.buf + xmit.head, sal_tmp_buffer, c);
+ xmit.head = ((xmit.head + c) & (SN_SAL_BUFFER_SIZE - 1));
+ spin_unlock_irqrestore(&sn_sal_lock, flags);
+
+ buf += c;
+ count -= c;
+ ret += c;
+ }
+ } else {
+ /* The buffer passed in isn't coming from userland,
+ * so cut out the middleman (sal_tmp_buffer).
+ */
+ spin_lock_irqsave(&sn_sal_lock, flags);
+ while (1) {
+ c = CIRC_SPACE_TO_END(xmit.head, xmit.tail,
+ SN_SAL_BUFFER_SIZE);
+
+ if (count < c)
+ c = count;
+ if (c <= 0) {
+ break;
+ }
+ memcpy(xmit.buf + xmit.head, buf, c);
+ xmit.head = ((xmit.head + c) & (SN_SAL_BUFFER_SIZE - 1));
+ buf += c;
+ count -= c;
+ ret += c;
+ }
+ spin_unlock_irqrestore(&sn_sal_lock, flags);
+ }
+
+ spin_lock_irqsave(&sn_sal_lock, flags);
+ if (xmit.head != xmit.tail &&
+ !(tty && (tty->stopped || tty->hw_stopped)))
+ if (sn_sal_ops->wakeup_transmit)
+ sn_sal_ops->wakeup_transmit();
+ spin_unlock_irqrestore(&sn_sal_lock, flags);
+
+ return ret;
+}
+
+
+static void
+sn_sal_put_char(struct tty_struct *tty, unsigned char ch)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&sn_sal_lock, flags);
+ if (CIRC_SPACE(xmit.head, xmit.tail, SN_SAL_BUFFER_SIZE) != 0) {
+ xmit.buf[xmit.head] = ch;
+ xmit.head = (xmit.head + 1) & (SN_SAL_BUFFER_SIZE-1);
+ sn_sal_ops->wakeup_transmit();
+ }
+ spin_unlock_irqrestore(&sn_sal_lock, flags);
+}
+
+
+static void
+sn_sal_flush_chars(struct tty_struct *tty)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&sn_sal_lock, flags);
+ if (CIRC_CNT(xmit.head, xmit.tail, SN_SAL_BUFFER_SIZE))
+ if (sn_sal_ops->wakeup_transmit)
+ sn_sal_ops->wakeup_transmit();
+ spin_unlock_irqrestore(&sn_sal_lock, flags);
+}
+
+
+static int
+sn_sal_write_room(struct tty_struct *tty)
+{
+ unsigned long flags;
+ int space;
+
+ spin_lock_irqsave(&sn_sal_lock, flags);
+ space = CIRC_SPACE(xmit.head, xmit.tail, SN_SAL_BUFFER_SIZE);
+ spin_unlock_irqrestore(&sn_sal_lock, flags);
+ return space;
+}
+
+
+static int
+sn_sal_chars_in_buffer(struct tty_struct *tty)
+{
+ unsigned long flags;
+ int space;
+
+ spin_lock_irqsave(&sn_sal_lock, flags);
+ space = CIRC_CNT(xmit.head, xmit.tail, SN_SAL_BUFFER_SIZE);
+ DPRINTF("<%d>", space);
+ spin_unlock_irqrestore(&sn_sal_lock, flags);
+ return space;
+}
+
+
+static int
+sn_sal_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ /* nothing supported */
+
+ return -ENOIOCTLCMD;
+}
+
+
+static void
+sn_sal_flush_buffer(struct tty_struct *tty)
+{
+ unsigned long flags;
+
+ /* drop everything */
+ spin_lock_irqsave(&sn_sal_lock, flags);
+ xmit.head = xmit.tail = 0;
+ spin_unlock_irqrestore(&sn_sal_lock, flags);
+
+ /* wake up tty level */
+ wake_up_interruptible(&tty->write_wait);
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup)(tty);
+}
+
+
+static void
+sn_sal_hangup(struct tty_struct *tty)
+{
+ sn_sal_flush_buffer(tty);
+}
+
+
+static void
+sn_sal_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+ /* this is SAL's problem */
+ DPRINTF("");
+}
+
+
+/*
+ * sn_sal_read_proc
+ *
+ * Console /proc interface
+ */
+
+static int
+sn_sal_read_proc(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+{
+ int len = 0;
+ off_t begin = 0;
+ extern nasid_t get_console_nasid(void);
+
+ len += sprintf(page, "sn_serial: revision:%s nasid:%d irq:%d tx:%d rx:%d\n",
+ serial_revdate, get_console_nasid(), sn_sal_irq,
+ tx_count, rx_count);
+ *eof = 1;
+
+ if (off >= len+begin)
+ return 0;
+ *start = page + (off-begin);
+
+ return count < begin+len-off ? count : begin+len-off;
+}
+
+
+static struct tty_driver sn_sal_driver = {
+ .magic = TTY_DRIVER_MAGIC,
+ .driver_name = "sn_serial",
+#if defined(CONFIG_DEVFS_FS)
+ .name = "tts/%d",
+#else
+ .name = "ttyS",
+#endif
+ .major = TTY_MAJOR,
+ .minor_start = SN_SAL_MINOR,
+ .num = 1,
+ .type = TTY_DRIVER_TYPE_SERIAL,
+ .subtype = SN_SAL_SUBTYPE,
+ .flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
+ .refcount = &sn_sal_refcount,
+ .table = &sn_sal_table,
+ .termios = &sn_sal_termios,
+ .termios_locked = &sn_sal_termios_locked,
+
+ .open = sn_sal_open,
+ .close = sn_sal_close,
+ .write = sn_sal_write,
+ .put_char = sn_sal_put_char,
+ .flush_chars = sn_sal_flush_chars,
+ .write_room = sn_sal_write_room,
+ .chars_in_buffer = sn_sal_chars_in_buffer,
+ .ioctl = sn_sal_ioctl,
+ .hangup = sn_sal_hangup,
+ .wait_until_sent = sn_sal_wait_until_sent,
+ .read_proc = sn_sal_read_proc,
+};
+
+/* sn_sal_init wishlist:
+ * - allocate sal_tmp_buffer
+ * - fix up the tty_driver struct
+ * - turn on receive interrupts
+ * - do any termios twiddling once and for all
+ */
+
+/*
+ * Boot-time initialization code
+ */
+
+static void __init
+sn_sal_switch_to_asynch(void)
+{
+ debug_printf("sn_serial: about to switch to asynchronous console\n");
+
+ /* without early_printk, we may be invoked late enough to race
+ * with other cpus doing console IO at this point, however
+ * console interrupts will never be enabled */
+ spin_lock(&sn_sal_lock);
+
+ /* early_printk invocation may have done this for us */
+ if (!sn_sal_ops) {
+ if (IS_RUNNING_ON_SIMULATOR())
+ sn_sal_ops = &sim_ops;
+ else
+ sn_sal_ops = &poll_ops;
+ }
+
+ /* we can't turn on the console interrupt (as request_irq
+ * calls kmalloc, which isn't set up yet), so we rely on a
+ * timer to poll for input and push data from the console
+ * buffer.
+ */
+ init_timer(&sn_sal_timer);
+ sn_sal_timer.function = sn_sal_timer_poll;
+
+ if (IS_RUNNING_ON_SIMULATOR())
+ interrupt_timeout = 6;
+ else
+ /* 960cps / 16 char FIFO = 60HZ
+ HZ / (SN_SAL_FIFO_SPEED_CPS / SN_SAL_FIFO_DEPTH) */
+ interrupt_timeout = HZ * SN_SAL_UART_FIFO_DEPTH /
+ SN_SAL_UART_FIFO_SPEED_CPS;
+
+ mod_timer(&sn_sal_timer, jiffies + interrupt_timeout);
+
+ sn_sal_is_asynch = 1;
+ spin_unlock(&sn_sal_lock);
+}
+
+static void __init
+sn_sal_switch_to_interrupts(void)
+{
+ int irq;
+
+ debug_printf("sn_serial: switching to interrupt driven console\n");
+
+ irq = sn_sal_connect_interrupt();
+ if (irq) {
+ unsigned long flags;
+ spin_lock_irqsave(&sn_sal_lock, flags);
+ /* sn_sal_irq is a global variable. When it's set to
+ * a non-zero value, we stop polling for input (since
+ * interrupts should now be enabled). */
+ sn_sal_irq = irq;
+ sn_sal_ops = &intr_ops;
+ /* turn on receive interrupts */
+ ia64_sn_console_intr_enable(SAL_CONSOLE_INTR_RECV);
+
+ /* the polling timer is already set up, we just change the
+ * frequency. if we've successfully enabled interrupts (and
+ * CONSOLE_RESTART isn't defined) the next timer expiration
+ * will be the last, otherwise we continue polling */
+ if (CONSOLE_RESTART) {
+ /* kick the console every once in a while in
+ * case we miss an interrupt */
+ interrupt_timeout = 20*HZ;
+ sn_sal_timer.function = sn_sal_timer_restart;
+ mod_timer(&sn_sal_timer, jiffies + interrupt_timeout);
+ }
+ spin_unlock_irqrestore(&sn_sal_lock, flags);
+ }
+}
+
+static int __init
+sn_sal_module_init(void)
+{
+ int retval;
+
+ printk("sn_serial: sn_sal_module_init\n");
+
+ if (!ia64_platform_is("sn2"))
+ return -ENODEV;
+
+ /* when this driver is compiled in, the console initialization
+ * will have already switched us into asynchronous operation
+ * before we get here through the module initcalls */
+ if (!sn_sal_is_asynch)
+ sn_sal_switch_to_asynch();
+
+ /* at this point (module_init) we can try to turn on
+ * interrupts */
+ if (!IS_RUNNING_ON_SIMULATOR())
+ sn_sal_switch_to_interrupts();
+
+ sn_sal_driver.init_termios = tty_std_termios;
+ sn_sal_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+
+ if ((retval = tty_register_driver(&sn_sal_driver))) {
+ printk(KERN_ERR "sn_serial: Unable to register tty driver\n");
+ return retval;
+ }
+
+ tty_register_devfs(&sn_sal_driver, 0, sn_sal_driver.minor_start);
+
+ return 0;
+}
+
+
+static void __exit
+sn_sal_module_exit(void)
+{
+ unsigned long flags;
+ int e;
+
+ del_timer_sync(&sn_sal_timer);
+ spin_lock_irqsave(&sn_sal_lock, flags);
+ if ((e = tty_unregister_driver(&sn_sal_driver)))
+ printk(KERN_ERR "sn_serial: failed to unregister driver (%d)\n", e);
+
+ spin_unlock_irqrestore(&sn_sal_lock, flags);
+}
+
+module_init(sn_sal_module_init);
+module_exit(sn_sal_module_exit);
+
+/*
+ * End of user-level console routines.
+ *********************************************************************/
+
+
+/*********************************************************************
+ * Kernel console definitions
+ */
+
+#ifdef CONFIG_SGI_L1_SERIAL_CONSOLE
+/*
+ * Print a string to the SAL console. The console_lock must be held
+ * when we get here.
+ */
+static void
+sn_sal_console_write(struct console *co, const char *s, unsigned count)
+{
+ BUG_ON(!sn_sal_is_asynch);
+
+ if (count > CIRC_SPACE_TO_END(xmit.head, xmit.tail,
+ SN_SAL_BUFFER_SIZE))
+ debug_printf("\n*** SN_SAL_BUFFER_SIZE too small, lost chars\n");
+
+ /* somebody really wants this output, might be an
+ * oops, kdb, panic, etc. make sure they get it. */
+ if (spin_is_locked(&sn_sal_lock)) {
+ synch_flush_xmit();
+ sn_sal_ops->puts(s, count);
+ } else if (in_interrupt()) {
+ spin_lock(&sn_sal_lock);
+ synch_flush_xmit();
+ spin_unlock(&sn_sal_lock);
+ sn_sal_ops->puts(s, count);
+ } else
+ sn_sal_write(NULL, 0, s, count);
+}
+
+static kdev_t
+sn_sal_console_device(struct console *c)
+{
+ return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+static int __init
+sn_sal_console_setup(struct console *co, char *options)
+{
+#ifdef CONFIG_KDB
+ /*
+ * Remember the line number of the first serial
+ * console. We'll make this the kdb serial console too.
+ */
+ if (kdb_serial_line == -1) {
+ kdb_serial_line = co->index;
+ }
+#endif /* CONFIG_KDB */
+
+ return 0;
+}
+
+
+static struct console sal_console = {
+ .name = "ttyS",
+ .write = sn_sal_console_write,
+ .device = sn_sal_console_device,
+ .setup = sn_sal_console_setup,
+ .index = -1
+};
+
+/*
+ * End of kernel console definitions.
+ *********************************************************************/
+
+
+void __init
+sn_sal_serial_console_init(void)
+{
+ if (ia64_platform_is("sn2")) {
+ sn_sal_switch_to_asynch();
+ register_console(&sal_console);
+ }
+}
+
+
+#ifdef CONFIG_KDB
+int
+l1_control_in_polled(int offset)
+{
+ int sal_call_status = 0, input;
+ int ret = 0;
+
+ if (IS_RUNNING_ON_SIMULATOR()) {
+ ret = readb((unsigned long)master_node_bedrock_address +
+ (offset<< 3));
+ return(ret);
+ }
+ if (offset == REG_LSR) {
+ ret = (LSR_XHRE | LSR_XSRE); /* can send anytime */
+ sal_call_status = ia64_sn_console_check(&input);
+ if (!sal_call_status && input) {
+ /* input pending */
+ ret |= LSR_RCA;
+ }
+ }
+ return ret;
+}
+
+int
+l1_serial_in_polled(void)
+{
+ int ch;
+
+ if (IS_RUNNING_ON_SIMULATOR()) {
+ return readb((unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
+ }
+
+ if (!ia64_sn_console_getc(&ch))
+ return ch;
+ else
+ return 0;
+}
+#endif /* CONFIG_KDB */
+
+#endif /* CONFIG_SGI_L1_SERIAL_CONSOLE */
diff -urN linux-2.4.22-bk4/drivers/char/tty_io.c linux-2.4.22-bk5/drivers/char/tty_io.c
--- linux-2.4.22-bk4/drivers/char/tty_io.c 2003-08-25 04:44:41.000000000 -0700
+++ linux-2.4.22-bk5/drivers/char/tty_io.c 2003-08-30 02:51:17.000000000 -0700
@@ -154,6 +154,7 @@
extern void rs285_console_init(void);
extern void sa1100_rs_console_init(void);
extern void sgi_serial_console_init(void);
+extern void sn_sal_serial_console_init(void);
extern void sci_console_init(void);
extern void dec_serial_console_init(void);
extern void tx3912_console_init(void);
@@ -2391,6 +2392,12 @@
kbd_init();
#endif
+#ifdef CONFIG_SGI_L1_SERIAL_CONSOLE
+ if (ia64_platform_is("sn2")) {
+ sn_sal_serial_console_init();
+ return; /* only one console right now for SN2 */
+ }
+#endif
#ifdef CONFIG_ESPSERIAL /* init ESP before rs, so rs doesn't see the port */
espserial_init();
#endif
diff -urN linux-2.4.22-bk4/drivers/scsi/scsi_scan.c linux-2.4.22-bk5/drivers/scsi/scsi_scan.c
--- linux-2.4.22-bk4/drivers/scsi/scsi_scan.c 2003-08-25 04:44:42.000000000 -0700
+++ linux-2.4.22-bk5/drivers/scsi/scsi_scan.c 2003-08-30 02:51:21.000000000 -0700
@@ -114,7 +114,8 @@
{"HP", "C2500A", "", BLIST_NOLUN}, /* scanjet iicx */
{"HP", "A6188A", "*", BLIST_SPARSELUN | BLIST_LARGELUN},/* HP Va7100 Array */
{"HP", "A6189A", "*", BLIST_SPARSELUN | BLIST_LARGELUN},/* HP Va7400 Array */
- {"HP", "A6189B", "*", BLIST_SPARSELUN | BLIST_LARGELUN},/* HP Va7410 Array */
+ {"HP", "A6189B", "*", BLIST_SPARSELUN | BLIST_LARGELUN},/* HP Va7110 Array */
+ {"HP", "A6218A", "*", BLIST_SPARSELUN | BLIST_LARGELUN},/* HP Va7410 Array */
{"YAMAHA", "CDR100", "1.00", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */
{"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* Locks up if polled for lun != 0
* extra reset */