diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-08-25 09:12:35 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-08-25 09:12:35 +0000 |
commit | c7fc24dc4420057f103afe8fc64524ebc25c5d37 (patch) | |
tree | 3682407a599b8f9f03fc096298134cafba1c9b2f /arch/m68k | |
parent | 1d793fade8b063fde3cf275bf1a5c2d381292cd9 (diff) |
o Merge with Linux 2.1.116.
o New Newport console code.
o New G364 console code.
Diffstat (limited to 'arch/m68k')
70 files changed, 5713 insertions, 2732 deletions
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile index 255a29a7b..9cd2d1838 100644 --- a/arch/m68k/Makefile +++ b/arch/m68k/Makefile @@ -64,6 +64,11 @@ CORE_FILES := $(CORE_FILES) arch/m68k/mac/mac.o SUBDIRS := $(SUBDIRS) arch/m68k/mac endif +ifdef CONFIG_HP300 +CORE_FILES := $(CORE_FILES) arch/m68k/hp300/hp300.o +SUBDIRS := $(SUBDIRS) arch/m68k/hp300 +endif + ifdef CONFIG_APOLLO CORE_FILES := $(CORE_FILES) arch/m68k/apollo/apollo.o SUBDIRS := $(SUBDIRS) arch/m68k/apollo @@ -74,6 +79,11 @@ CORE_FILES := $(CORE_FILES) arch/m68k/mvme16x/mvme16x.o SUBDIRS := $(SUBDIRS) arch/m68k/mvme16x endif +ifdef CONFIG_BVME6000 +CORE_FILES := $(CORE_FILES) arch/m68k/bvme6000/bvme6000.o +SUBDIRS := $(SUBDIRS) arch/m68k/bvme6000 +endif + ifdef CONFIG_M68040 CORE_FILES := $(CORE_FILES) arch/m68k/fpsp040/fpsp.o SUBDIRS := $(SUBDIRS) arch/m68k/fpsp040 @@ -107,4 +117,6 @@ endif archclean: rm -f vmlinux.gz +archmrproper: + archdep: diff --git a/arch/m68k/amiga/Makefile b/arch/m68k/amiga/Makefile index 91c835d54..b0211f3a7 100644 --- a/arch/m68k/amiga/Makefile +++ b/arch/m68k/amiga/Makefile @@ -8,7 +8,11 @@ # Note 2! The CFLAGS definitions are now in the main makefile... O_TARGET := amiga.o -O_OBJS := config.o amiints.o cia.o chipram.o amisound.o zorro.o +O_OBJS := config.o amiints.o cia.o chipram.o amisound.o OX_OBJS := amiga_ksyms.o +ifdef CONFIG_AMIGA_PCMCIA +O_OBJS := $(O_OBJS) pcmcia.o +endif + include $(TOPDIR)/Rules.make diff --git a/arch/m68k/amiga/amiga_ksyms.c b/arch/m68k/amiga/amiga_ksyms.c index 2b9c131d7..4de6e4167 100644 --- a/arch/m68k/amiga/amiga_ksyms.c +++ b/arch/m68k/amiga/amiga_ksyms.c @@ -1,7 +1,9 @@ +#include <linux/config.h> #include <linux/module.h> #include <linux/types.h> #include <linux/zorro.h> #include <asm/amigahw.h> +#include <asm/amipcmcia.h> extern volatile u_short amiga_audio_min_period; extern u_short amiga_audio_period; @@ -20,8 +22,11 @@ EXPORT_SYMBOL(amiga_chip_size); EXPORT_SYMBOL(amiga_audio_period); EXPORT_SYMBOL(amiga_audio_min_period); -EXPORT_SYMBOL(zorro_find); -EXPORT_SYMBOL(zorro_get_board); -EXPORT_SYMBOL(zorro_config_board); -EXPORT_SYMBOL(zorro_unconfig_board); -EXPORT_SYMBOL(zorro_unused_z2ram); +#ifdef CONFIG_AMIGA_PCMCIA + EXPORT_SYMBOL(pcmcia_reset); + EXPORT_SYMBOL(pcmcia_copy_tuple); + EXPORT_SYMBOL(pcmcia_program_voltage); + EXPORT_SYMBOL(pcmcia_access_speed); + EXPORT_SYMBOL(pcmcia_write_enable); + EXPORT_SYMBOL(pcmcia_write_disable); +#endif diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c index b7110188c..9aa47cf7c 100644 --- a/arch/m68k/amiga/amiints.c +++ b/arch/m68k/amiga/amiints.c @@ -32,6 +32,7 @@ #include <asm/traps.h> #include <asm/amigahw.h> #include <asm/amigaints.h> +#include <asm/amipcmcia.h> extern int cia_request_irq(struct ciabase *base,int irq, void (*handler)(int, void *, struct pt_regs *), @@ -89,6 +90,10 @@ __initfunc(void amiga_init_IRQ(void)) for (i = 0; i < AMI_IRQS; i++) ami_ablecount[i] = 0; + /* turn off PCMCIA interrupts */ + if (AMIGAHW_PRESENT(PCMCIA)) + pcmcia_disable_irq(); + /* turn off all interrupts and enable the master interrupt bit */ custom.intena = 0x7fff; custom.intreq = 0x7fff; diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c index ce52ad852..3c5dff56d 100644 --- a/arch/m68k/amiga/config.c +++ b/arch/m68k/amiga/config.c @@ -51,6 +51,7 @@ static void amiga_sched_init(void (*handler)(int, void *, struct pt_regs *)); /* amiga specific keyboard functions */ extern int amiga_keyb_init(void); extern int amiga_kbdrate (struct kbd_repeat *); +extern void amiga_kbd_reset_setup(char*, int); /* amiga specific irq functions */ extern void amiga_init_IRQ (void); extern void (*amiga_default_handler[]) (int, void *, struct pt_regs *); @@ -76,8 +77,6 @@ extern void amiga_floppy_setup(char *, int *); #endif static void amiga_reset (void); static int amiga_wait_key (struct console *co); -extern struct consw fb_con; -extern void zorro_init(void); extern void amiga_init_sound(void); static void amiga_savekmsg_init(void); static void amiga_mem_console_write(struct console *co, const char *b, @@ -343,6 +342,7 @@ __initfunc(void config_amiga(void)) mach_sched_init = amiga_sched_init; mach_keyb_init = amiga_keyb_init; mach_kbdrate = amiga_kbdrate; + kbd_reset_setup = amiga_kbd_reset_setup; mach_init_IRQ = amiga_init_IRQ; mach_default_handler = &amiga_default_handler; mach_request_irq = amiga_request_irq; @@ -376,7 +376,7 @@ __initfunc(void config_amiga(void)) mach_floppy_setup = amiga_floppy_setup; #endif mach_reset = amiga_reset; - conswitchp = &fb_con; + conswitchp = &dummy_con; kd_mksound = amiga_mksound; #ifdef CONFIG_MAGIC_SYSRQ mach_sysrq_key = 0x5f; /* HELP */ @@ -397,27 +397,6 @@ __initfunc(void config_amiga(void)) /* ensure that the DMA master bit is set */ custom.dmacon = DMAF_SETCLR | DMAF_MASTER; - /* don't use Z2 RAM as system memory on Z3 capable machines */ - if (AMIGAHW_PRESENT(ZORRO3)) { - int i, j; - unsigned long z2mem = 0; - for (i = 0; i < m68k_num_memory; i++) - if (m68k_memory[i].addr < 16*1024*1024) { - if (i == 0) { - /* don't cut off the branch we're sitting on */ - printk("Warning: kernel runs in Zorro II memory\n"); - continue; - } - z2mem += m68k_memory[i].size; - m68k_num_memory--; - for (j = i; j < m68k_num_memory; j++) - m68k_memory[j] = m68k_memory[j+1]; - } - if (z2mem) - printk("%ldK of Zorro II memory will not be used as system memory\n", - z2mem>>10); - } - /* initialize chipram allocator */ amiga_chip_init (); @@ -443,12 +422,8 @@ __initfunc(void config_amiga(void)) if (AMIGAHW_PRESENT(MAGIC_REKICK)) *(unsigned char *)ZTWO_VADDR(0xde0002) |= 0x80; - zorro_init(); #ifdef CONFIG_ZORRO - /* - * Identify all known AutoConfig Expansion Devices - */ - zorro_identify(); + zorro_init(); #endif } diff --git a/arch/m68k/amiga/pcmcia.c b/arch/m68k/amiga/pcmcia.c new file mode 100644 index 000000000..3faac7eda --- /dev/null +++ b/arch/m68k/amiga/pcmcia.c @@ -0,0 +1,112 @@ +/* +** asm-m68k/pcmcia.c -- Amiga Linux PCMCIA support +** most information was found by disassembling card.resource +** I'm still looking for an official doc ! +** +** Copyright 1997 by Alain Malek +** +** 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. +** +** Created: 12/10/97 by Alain Malek +*/ + +#include <linux/types.h> +#include <linux/sched.h> +#include <asm/amigayle.h> +#include <asm/amipcmcia.h> + +/* gayle config byte for program voltage and access speed */ +static u_char cfg_byte = GAYLE_CFG_0V|GAYLE_CFG_150NS; + +void pcmcia_reset(void) +{ + unsigned long reset_start_time = jiffies; + unsigned char b; + + gayle_reset = 0x00; + while (jiffies - reset_start_time < 1*HZ/100); + b = gayle_reset; +} + + +/* copy a tuple, including tuple header. return nb bytes copied */ +/* be carefull as this may trigger a GAYLE_IRQ_WR interrupt ! */ + +int pcmcia_copy_tuple(unsigned char tuple_id, void *tuple, int max_len) +{ + unsigned char id, *dest; + int cnt, pos, len; + + dest = tuple; + pos = 0; + + id = gayle_attribute[pos]; + + while((id != CISTPL_END) && (pos < 0x10000)) { + len = (int)gayle_attribute[pos+2] + 2; + if (id == tuple_id) { + len = (len > max_len)?max_len:len; + for (cnt = 0; cnt < len; cnt++) { + *dest++ = gayle_attribute[pos+(cnt<<1)]; + } + + return len; + } + pos += len<<1; + id = gayle_attribute[pos]; + } + + return 0; +} + +void pcmcia_program_voltage(int voltage) +{ + u_char v; + + switch (voltage) { + case PCMCIA_0V: + v = GAYLE_CFG_0V; + break; + case PCMCIA_5V: + v = GAYLE_CFG_5V; + break; + case PCMCIA_12V: + v = GAYLE_CFG_12V; + break; + default: + v = GAYLE_CFG_0V; + } + + cfg_byte = (cfg_byte & 0xfc) | v; + gayle.config = cfg_byte; + +} + +void pcmcia_access_speed(int speed) +{ + u_char s; + + if (speed <= PCMCIA_SPEED_100NS) + s = GAYLE_CFG_100NS; + else if (speed <= PCMCIA_SPEED_150NS) + s = GAYLE_CFG_150NS; + else if (speed <= PCMCIA_SPEED_250NS) + s = GAYLE_CFG_250NS; + else + s = GAYLE_CFG_720NS; + + cfg_byte = (cfg_byte & 0xf3) | s; + gayle.config = cfg_byte; +} + +void pcmcia_write_enable(void) +{ + gayle.cardstatus = GAYLE_CS_WR|GAYLE_CS_DA; +} + +void pcmcia_write_disable(void) +{ + gayle.cardstatus = 0; +} diff --git a/arch/m68k/amiga/zorro.c b/arch/m68k/amiga/zorro.c deleted file mode 100644 index 7f2cd8c47..000000000 --- a/arch/m68k/amiga/zorro.c +++ /dev/null @@ -1,1234 +0,0 @@ -/* - * linux/arch/m68k/amiga/zorro.c - * - * Copyright (C) 1995 Geert Uytterhoeven - * - * 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 <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <asm/setup.h> -#include <asm/bitops.h> -#include <asm/amigahw.h> -#include <linux/zorro.h> - - -#ifdef CONFIG_ZORRO - - /* - * Zorro Expansion Device Manufacturers and Products - */ - -struct Manufacturer { - const char *Name; - u_short Manuf; - u_short NumProd; - const struct Product *Products; -}; - -struct Product { - const char *Name; - u_char Class; - u_char Prod; -}; - -struct GVP_Product { - const char *Name; - u_char Class; - u_char EPC; -}; - - - /* - * Macro's to make life easier - */ - -#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x))) - -#define BEGIN_PROD(id) \ - static struct Product Prod_##id[] = { -#define PROD(name, class, id) \ - { name, ZORRO_CLASS_##class, ZORRO_PROD(ZORRO_PROD_##id) }, - -#define BEGIN_GVP_PROD \ - static struct GVP_Product Ext_Prod_GVP[] = { -#define GVP_PROD(name, class, id) \ - { name, ZORRO_CLASS_##class, ZORRO_EPC(ZORRO_PROD_##id) }, - -#define BEGIN_MANUF \ - static struct Manufacturer Manufacturers[] = { -#define MANUF(name, id) \ - { name, ZORRO_MANUF_##id, ARRAYSIZE(Prod_##id), Prod_##id }, - -#define END \ - }; - - - /* - * Recognized Zorro Expansion Devices - */ - -BEGIN_PROD(PACIFIC_PERIPHERALS) - PROD("SE 2000 A500", HD, PACIFIC_PERIPHERALS_SE_2000_A500) - PROD(NULL, SCSI, PACIFIC_PERIPHERALS_SCSI) -END - -BEGIN_PROD(MACROSYSTEMS_USA_2) - PROD("Warp Engine", TURBO_SCSI_RAM, MACROSYSTEMS_WARP_ENGINE) -END - -BEGIN_PROD(KUPKE_1) - PROD("Golem RAM Box 2MB", RAM, KUPKE_GOLEM_RAM_BOX_2MB) -END - -BEGIN_PROD(MEMPHIS) - PROD("Stormbringer", TURBO, MEMPHIS_STORMBRINGER) -END - -BEGIN_PROD(3_STATE) - PROD("Megamix 2000", RAM, 3_STATE_MEGAMIX_2000) -END - -BEGIN_PROD(COMMODORE_BRAUNSCHWEIG) - PROD("A2088 XT/A2286 AT", BRIDGE, CBM_A2088_A2286) - PROD("A2286 AT", BRIDGE, CBM_A2286) - PROD("A4091", SCSI, CBM_A4091_1) - PROD("A2386-SX", BRIDGE, CBM_A2386SX_1) -END - -BEGIN_PROD(COMMODORE_WEST_CHESTER_1) - PROD("A2090/A2090A", SCSI, CBM_A2090A) - PROD("A590/A2091", SCSI, CBM_A590_A2091_1) - PROD("A590/A2091", SCSI, CBM_A590_A2091_2) - PROD("A2090B 2090 Autoboot", SCSI, CBM_A2090B) - PROD("A2060", ARCNET, CBM_A2060) - PROD("A590/A2052/A2058/A2091", RAM, CBM_A590_A2052_A2058_A2091) - PROD("A560", RAM, CBM_A560_RAM) - PROD("A2232 Prototype", MULTIIO, CBM_A2232_PROTOTYPE) - PROD("A2232", MULTIIO, CBM_A2232) - PROD("A2620 68020/RAM", TURBO_RAM, CBM_A2620) - PROD("A2630 68030/RAM", TURBO_RAM, CBM_A2630) - PROD("A4091", SCSI, CBM_A4091_2) - PROD("A2065", ETHERNET, CBM_A2065_1) - PROD("Romulator Card", UNKNOWN, CBM_ROMULATOR) - PROD("A3000 Test Fixture", MISC, CBM_A3000_TEST_FIXTURE) - PROD("A2386-SX", BRIDGE, CBM_A2386SX_2) - PROD("A2065", ETHERNET, CBM_A2065_2) -END - -BEGIN_PROD(COMMODORE_WEST_CHESTER_2) - PROD("A2090/A2090A Combitec/MacroSystem", SCSI, CBM_A2090A_CM) -END - -BEGIN_PROD(PROGRESSIVE_PERIPHERALS_AND_SYSTEMS_2) - PROD("EXP8000", RAM, PPS_EXP8000) -END - -BEGIN_PROD(KOLFF_COMPUTER_SUPPLIES) - PROD("KCS Power PC Board", BRIDGE, KCS_POWER_PC_BOARD) -END - -BEGIN_PROD(CARDCO_1) - PROD("Kronos 2000", SCSI, CARDCO_KRONOS_2000_1) - PROD("A1000", SCSI, CARDCO_A1000_1) - PROD("Escort", SCSI, CARDCO_ESCORT) - PROD("A2410 HiRes", GFX, CARDCO_A2410) -END - -BEGIN_PROD(A_SQUARED) - PROD("Live! 2000", VIDEO, A_SQUARED_LIVE_2000) -END - -BEGIN_PROD(COMSPEC_COMMUNICATIONS) - PROD("AX2000", RAM, COMSPEC_COMMUNICATIONS_AX2000) -END - -BEGIN_PROD(ANAKIN_RESEARCH) - PROD("Easyl", TABLET, ANAKIN_RESEARCH_EASYL) -END - -BEGIN_PROD(MICROBOTICS) - PROD("StarBoard II", RAM, MICROBOTICS_STARBOARD_II) - PROD("StarDrive", SCSI, MICROBOTICS_STARDRIVE) - PROD("8-Up (Rev A)", RAM, MICROBOTICS_8_UP_A) - PROD("8-Up (Rev Z)", RAM, MICROBOTICS_8_UP_Z) - PROD("Delta", RAM, MICROBOTICS_DELTA_RAM) - PROD("8-Star", RAM, MICROBOTICS_8_STAR_RAM) - PROD("8-Star", MISC, MICROBOTICS_8_STAR) - PROD("VXL RAM*32", RAM, MICROBOTICS_VXL_RAM_32) - PROD("VXL-30", TURBO, MICROBOTICS_VXL_68030) - PROD("Delta", MISC, MICROBOTICS_DELTA) - PROD("MBX 1200/1200z", RAM, MICROBOTICS_MBX_1200_1200Z_RAM) - PROD("Hardframe 2000", SCSI, MICROBOTICS_HARDFRAME_2000_1) - PROD("Hardframe 2000", SCSI, MICROBOTICS_HARDFRAME_2000_2) - PROD("MBX 1200/1200z", MISC, MICROBOTICS_MBX_1200_1200Z) -END - -BEGIN_PROD(ACCESS_ASSOCIATES_ALEGRA) -END - -BEGIN_PROD(EXPANSION_TECHNOLOGIES) -END - -BEGIN_PROD(ASDG) - PROD(NULL, RAM, ASDG_MEMORY_1) - PROD(NULL, RAM, ASDG_MEMORY_2) - PROD("EB-920 Lan Rover", ETHERNET, ASDG_EB920_LAN_ROVER) - PROD("GPIB/Dual IEEE-488/Twin-X", MULTIIO, ASDG_GPIB_DUALIEEE488_TWIN_X) -END - -BEGIN_PROD(IMTRONICS_1) - PROD("Hurricane 2800", TURBO_RAM, IMTRONICS_HURRICANE_2800_1) - PROD("Hurricane 2800", TURBO_RAM, IMTRONICS_HURRICANE_2800_2) -END - -BEGIN_PROD(CBM_UNIVERSITY_OF_LOWELL) - PROD("A2410 HiRes", GFX, CBM_A2410) -END - -BEGIN_PROD(AMERISTAR) - PROD("A2065", ETHERNET, AMERISTAR_A2065) - PROD("A560", ARCNET, AMERISTAR_A560) - PROD("A4066", ETHERNET, AMERISTAR_A4066) -END - -BEGIN_PROD(SUPRA) - PROD("SupraDrive 4x4", SCSI, SUPRA_SUPRADRIVE_4x4) - PROD("1000", RAM, SUPRA_1000_RAM) - PROD("2000 DMA", SCSI, SUPRA_2000_DMA) - PROD("500", SCSI_RAM, SUPRA_500) - PROD("500", SCSI, SUPRA_500_SCSI) - PROD("500XP/2000", RAM, SUPRA_500XP_2000_RAM) - PROD("500RX/2000", RAM, SUPRA_500RX_2000_RAM) - PROD("2400zi", MODEM, SUPRA_2400ZI) - PROD("500XP/SupraDrive WordSync", SCSI, SUPRA_500XP_SUPRADRIVE_WORDSYNC) - PROD("SupraDrive WordSync II", SCSI, SUPRA_SUPRADRIVE_WORDSYNC_II) - PROD("2400zi+", MODEM, SUPRA_2400ZIPLUS) -END - -BEGIN_PROD(COMPUTER_SYSTEMS_ASSOCIATES) - PROD("Magnum 40", TURBO_SCSI, CSA_MAGNUM) - PROD("12 Gauge", SCSI, CSA_12_GAUGE) -END - -BEGIN_PROD(MARC_MICHAEL_GROTH) -END - -BEGIN_PROD(M_TECH) - PROD("AT500", RAM, MTEC_AT500_1) -END - -BEGIN_PROD(GREAT_VALLEY_PRODUCTS_1) - PROD("Impact Series I", SCSI_RAM, GVP_IMPACT_SERIES_I) -END - -BEGIN_PROD(BYTEBOX) - PROD("A500", UNKNOWN, BYTEBOX_A500) -END - -BEGIN_PROD(DKB_POWER_COMPUTING) - PROD("SecureKey", UNKNOWN, DKB_POWER_COMPUTING_SECUREKEY) - PROD("DKM 3128", RAM, DKB_POWER_COMPUTING_DKM_3128) - PROD("Rapid Fire", SCSI, DKB_POWER_COMPUTING_RAPID_FIRE) - PROD("DKM 1202", FPU_RAM, DKB_POWER_COMPUTING_DKM_1202) - PROD("Cobra/Viper II 68EC030", TURBO, DKB_POWER_COMPUTING_COBRA_VIPER_II_68EC030) - PROD("WildFire 060", TURBO, DKB_POWER_COMPUTING_WILDFIRE_060_1) - PROD("WildFire 060", TURBO, DKB_POWER_COMPUTING_WILDFIRE_060_2) -END - -BEGIN_PROD(GREAT_VALLEY_PRODUCTS_2) - PROD("Impact Series I (4K)", SCSI, GVP_IMPACT_SERIES_I_4K) - PROD("Impact Series I (16K/2)", SCSI, GVP_IMPACT_SERIES_I_16K_2) - PROD("Impact Series I (16K/2)", SCSI, GVP_IMPACT_SERIES_I_16K_3) - PROD("Impact 3001", IDE, GVP_IMPACT_3001_IDE_1) - PROD("Impact 3001", RAM, GVP_IMPACT_3001_RAM) - PROD("Impact Series II", RAM, GVP_IMPACT_SERIES_II_RAM_1) -/* PROD(NULL, UNKNOWN, GVP_EPC_BASE) */ - PROD("Impact 3001", IDE, GVP_IMPACT_3001_IDE_2) -/* PROD("A2000 030", TURBO, GVP_A2000_030) */ -/* PROD("GForce 040", TURBO_SCSI, GFORCE_040_SCSI_2) */ - PROD("GForce 040/060", TURBO_SCSI, GVP_GFORCE_040_060) - PROD("Impact Vision 24", GFX, GVP_IMPACT_VISION_24) - PROD("GForce 040", TURBO, GVP_GFORCE_040_2) -END - -BEGIN_GVP_PROD /* ZORRO_PROD_GVP_EPC_BASE */ - GVP_PROD("GForce 040", TURBO, GVP_GFORCE_040_1) - GVP_PROD("GForce 040", TURBO_SCSI, GVP_GFORCE_040_SCSI_1) - GVP_PROD("A1291", SCSI, GVP_A1291) - GVP_PROD("Combo 030 R4", TURBO, GVP_COMBO_030_R4) - GVP_PROD("Combo 030 R4", TURBO_SCSI, GVP_COMBO_030_R4_SCSI) - GVP_PROD("Phone Pak", UNKNOWN, GVP_PHONEPAK) - GVP_PROD("IO-Extender", MULTIIO, GVP_IO_EXTENDER) - GVP_PROD("GForce 030", TURBO, GVP_GFORCE_030) - GVP_PROD("GForce 030", TURBO_SCSI, GVP_GFORCE_030_SCSI) - GVP_PROD("A530", TURBO, GVP_A530) - GVP_PROD("A530", TURBO_SCSI, GVP_A530_SCSI) - GVP_PROD("Combo 030 R3", TURBO, GVP_COMBO_030_R3) - GVP_PROD("Combo 030 R3", TURBO_SCSI, GVP_COMBO_030_R3_SCSI) - GVP_PROD("Series-II", SCSI, GVP_SERIES_II) -END - -BEGIN_PROD(CALIFORNIA_ACCESS_SYNERGY) - PROD("Malibu", SCSI, CALIFORNIA_ACCESS_SYNERGY_MALIBU) -END - -BEGIN_PROD(XETEC) - PROD("FastCard", SCSI, XETEC_FASTCARD) - PROD("FastCard", RAM, XETEC_FASTCARD_RAM) - PROD("FastCard Plus", SCSI, XETEC_FASTCARD_PLUS) -END - -BEGIN_PROD(PROGRESSIVE_PERIPHERALS_AND_SYSTEMS) - PROD("Mercury", TURBO, PPS_MERCURY) - PROD("A3000 68040", TURBO, PPS_A3000_68040) - PROD("A2000 68040", TURBO, PPS_A2000_68040) - PROD("Zeus", TURBO_SCSI_RAM, PPS_ZEUS) - PROD("A500 68040", TURBO, PPS_A500_68040) -END - -BEGIN_PROD(XEBEC) -END - -BEGIN_PROD(SPIRIT_TECHNOLOGY) - PROD("Insider IN1000", RAM, SPIRIT_TECHNOLOGY_INSIDER_IN1000) - PROD("Insider IN500", RAM, SPIRIT_TECHNOLOGY_INSIDER_IN500) - PROD("SIN500", RAM, SPIRIT_TECHNOLOGY_SIN500) - PROD("HDA 506", HD, SPIRIT_TECHNOLOGY_HDA_506) - PROD("AX-S", MISC, SPIRIT_TECHNOLOGY_AX_S) - PROD("OctaByte", RAM, SPIRIT_TECHNOLOGY_OCTABYTE) - PROD("Inmate", SCSI_RAM, SPIRIT_TECHNOLOGY_INMATE) -END - -BEGIN_PROD(SPIRIT_TECHNOLOGY_2) -END - -BEGIN_PROD(BSC_ALFADATA_1) - PROD("ALF 3", SCSI, BSC_ALF_3_1) -END - -BEGIN_PROD(BSC_ALFADATA_2) - PROD("ALF 2", SCSI, BSC_ALF_2_1) - PROD("ALF 2", SCSI, BSC_ALF_2_2) - PROD("ALF 3", SCSI, BSC_ALF_3_2) -END - -BEGIN_PROD(CARDCO_2) - PROD("Kronos", SCSI, CARDCO_KRONOS_2000_2) - PROD("A1000", SCSI, CARDCO_A1000_2) -END - -BEGIN_PROD(JOCHHEIM) - PROD(NULL, RAM, JOCHHEIM_RAM) -END - -BEGIN_PROD(CHECKPOINT_TECHNOLOGIES) - PROD("Serial Solution", SERIAL, CHECKPOINT_TECHNOLOGIES_SERIAL_SOLUTION) -END - -BEGIN_PROD(EDOTRONIK) - PROD("IEEE-488 Interface Board", UNKNOWN, EDOTRONIK_IEEE_488) - PROD("CBM-8032 Board", UNKNOWN, EDOTRONIK_8032) - PROD(NULL, SERIAL, EDOTRONIK_MULTISERIAL) - PROD("24Bit Realtime Video Digitizer", UNKNOWN, EDOTRONIK_VIDEODIGITIZER) - PROD("32Bit Parallel I/O Interface", UNKNOWN, EDOTRONIK_PARALLEL_IO) - PROD("PIC Prototyping Board", UNKNOWN, EDOTRONIK_PIC_PROTOYPING) - PROD("16 Channel ADC Interface", UNKNOWN, EDOTRONIK_ADC) - PROD("VME-Bus Controller", UNKNOWN, EDOTRONIK_VME) - PROD("DSP96000 Realtime Data Acquisition", DSP, EDOTRONIK_DSP96000) -END - -BEGIN_PROD(NES_INC) - PROD(NULL, RAM, NES_INC_RAM) -END - -BEGIN_PROD(ICD) - PROD("Advantage 2000", SCSI, ICD_ADVANTAGE_2000_SCSI) - PROD("Advantage", IDE, ICD_ADVANTAGE_2000_SCSI) - PROD("Advantage 2080", RAM, ICD_ADVANTAGE_2080_RAM) -END - -BEGIN_PROD(KUPKE_2) - PROD("Omti", HD, KUPKE_OMTI) - PROD("Golem SCSI-II", SCSI, KUPKE_SCSI_II) - PROD("Golem Box", UNKNOWN, KUPKE_GOLEM_BOX) - PROD("030/882", TURBO, KUPKE_030_882) - PROD("Golem", SCSI, KUPKE_SCSI_AT) -END - -BEGIN_PROD(GREAT_VALLEY_PRODUCTS_3) - PROD("A2000-RAM8/2", MISC, GVP_A2000_RAM8) - PROD("Impact Series II", RAM, GVP_IMPACT_SERIES_II_RAM_2) -END - -BEGIN_PROD(INTERWORKS_NETWORK) -END - -BEGIN_PROD(HARDITAL_SYNTHESIS) - PROD("TQM 68030+68882", TURBO, HARDITAL_SYNTHESIS_TQM_68030_68882) -END - -BEGIN_PROD(APPLIED_ENGINEERING) - PROD("DL2000", MODEM, APPLIED_ENGINEERING_DL2000) - PROD("RAM Works", RAM, APPLIED_ENGINEERING_RAM_WORKS) -END - -BEGIN_PROD(BSC_ALFADATA_3) - PROD("Oktagon 2008", SCSI, BSC_OKTAGON_2008) - PROD("Tandem AT-2008/508", IDE, BSC_TANDEM_AT_2008_508) - PROD("Alpha RAM 1200", RAM, BSC_ALFA_RAM_1200) - PROD("Oktagon 2008", RAM, BSC_OKTAGON_2008_RAM) - PROD("MultiFace I", MULTIIO, BSC_MULTIFACE_I) - PROD("MultiFace II", MULTIIO, BSC_MULTIFACE_II) - PROD("MultiFace III", MULTIIO, BSC_MULTIFACE_III) - PROD("Framebuffer", MISC, BSC_FRAMEBUFFER) - PROD("Graffiti", GFXRAM, BSC_GRAFFITI_RAM) - PROD("Graffiti", GFX, BSC_GRAFFITI_REG) - PROD("ISDN MasterCard", ISDN, BSC_ISDN_MASTERCARD) - PROD("ISDN MasterCard II", ISDN, BSC_ISDN_MASTERCARD_II) -END - -BEGIN_PROD(PHOENIX) - PROD("ST506", HD, PHOENIX_ST506) - PROD(NULL, SCSI, PHOENIX_SCSI) - PROD(NULL, RAM, PHOENIX_RAM) -END - -BEGIN_PROD(ADVANCED_STORAGE_SYSTEMS) - PROD("Nexus", SCSI, ADVANCED_STORAGE_SYSTEMS_NEXUS) - PROD("Nexus", RAM, ADVANCED_STORAGE_SYSTEMS_NEXUS_RAM) -END - -BEGIN_PROD(IMPULSE) - PROD("FireCracker 24", GFX, IMPULSE_FIRECRACKER_24) -END - -BEGIN_PROD(IVS) - PROD("GrandSlam PIC 2", RAM, IVS_GRANDSLAM_PIC_2) - PROD("GrandSlam PIC 1", RAM, IVS_GRANDSLAM_PIC_1) - PROD("OverDrive", HD, IVS_OVERDRIVE) - PROD("TrumpCard Classic", SCSI, IVS_TRUMPCARD_CLASSIC) - PROD("TrumpCard Pro/GrandSlam", SCSI, IVS_TRUMPCARD_PRO_GRANDSLAM) - PROD("Meta-4", RAM, IVS_META_4) - PROD("Wavetools", AUDIO, IVS_WAVETOOLS) - PROD("Vector", SCSI, IVS_VECTOR_1) - PROD("Vector", SCSI, IVS_VECTOR_2) -END - -BEGIN_PROD(VECTOR_1) - PROD("Connection", MULTIIO, VECTOR_CONNECTION_1) -END - -BEGIN_PROD(XPERT_PRODEV) - PROD("Visiona", GFXRAM, XPERT_PRODEV_VISIONA_RAM) - PROD("Visiona", GFX, XPERT_PRODEV_VISIONA_REG) - PROD("Merlin", GFXRAM, XPERT_PRODEV_MERLIN_RAM) - PROD("Merlin", GFX, XPERT_PRODEV_MERLIN_REG_1) - PROD("Merlin", GFX, XPERT_PRODEV_MERLIN_REG_2) -END - -BEGIN_PROD(HYDRA_SYSTEMS) - PROD("Amiganet", ETHERNET, HYDRA_SYSTEMS_AMIGANET) -END - -BEGIN_PROD(SUNRIZE_INDUSTRIES) - PROD("AD1012", AUDIO, SUNRIZE_INDUSTRIES_AD1012) - PROD("AD516", AUDIO, SUNRIZE_INDUSTRIES_AD516) - PROD("DD512", AUDIO, SUNRIZE_INDUSTRIES_DD512) -END - -BEGIN_PROD(TRICERATOPS) - PROD(NULL, MULTIIO, TRICERATOPS_MULTI_IO) -END - -BEGIN_PROD(APPLIED_MAGIC) - PROD("DMI Resolver", GFX, APPLIED_MAGIC_DMI_RESOLVER) - PROD("Digital Broadcaster", VIDEO, APPLIED_MAGIC_DIGITAL_BROADCASTER) -END - -BEGIN_PROD(GFX_BASE) - PROD("GDA-1 VRAM", GFX, GFX_BASE_GDA_1_VRAM) - PROD("GDA-1", GFX, GFX_BASE_GDA_1) -END - -BEGIN_PROD(ROCTEC) - PROD("RH 800C", HD, ROCTEC_RH_800C) - PROD("RH 800C", RAM, ROCTEC_RH_800C_RAM) -END - -BEGIN_PROD(KATO) - PROD("Melody MPEG", AUDIO, KATO_MELODY) - PROD("Rainbow II", GFX, HELFRICH_RAINBOW_II) /* ID clash!! */ - PROD("Rainbow III", GFX, HELFRICH_RAINBOW_III) /* ID clash!! */ -END - -BEGIN_PROD(ATLANTIS) -END - -BEGIN_PROD(PROTAR) -END - -BEGIN_PROD(ACS) -END - -BEGIN_PROD(SOFTWARE_RESULTS_ENTERPRISES) - PROD("Golden Gate 2 Bus+", BRIDGE, SOFTWARE_RESULTS_ENTERPRISES_GOLDEN_GATE_2_BUS_PLUS) -END - -BEGIN_PROD(MASOBOSHI) - PROD("MasterCard SC201", RAM, MASOBOSHI_MASTER_CARD_SC201) - PROD("MasterCard MC702", SCSI_IDE, MASOBOSHI_MASTER_CARD_MC702) - PROD("MVD 819", UNKNOWN, MASOBOSHI_MVD_819) -END - -BEGIN_PROD(MAINHATTAN_DATA) - PROD(NULL, IDE, MAINHATTAN_DATA_IDE) -END - -BEGIN_PROD(VILLAGE_TRONIC) - PROD("Domino", GFXRAM, VILLAGE_TRONIC_DOMINO_RAM) - PROD("Domino", GFX, VILLAGE_TRONIC_DOMINO_REG) - PROD("Domino 16M Prototype", GFX, VILLAGE_TRONIC_DOMINO_16M_PROTOTYPE) - PROD("Picasso II/II+", GFXRAM, VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM) - PROD("Picasso II/II+", GFX, VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG) - PROD("Picasso II/II+ (Segmented Mode)", GFX, VILLAGE_TRONIC_PICASSO_II_II_PLUS_SEGMENTED_MODE) - PROD("Picasso IV Z2", GFXRAM, VILLAGE_TRONIC_PICASSO_IV_Z2_MEM1) - PROD("Picasso IV Z2", GFXRAM, VILLAGE_TRONIC_PICASSO_IV_Z2_MEM2) - PROD("Picasso IV Z2", GFX, VILLAGE_TRONIC_PICASSO_IV_Z2_REG) - PROD("Picasso IV Z3", GFX, VILLAGE_TRONIC_PICASSO_IV_Z3) - PROD("Ariadne", ETHERNET_PARALLEL, VILLAGE_TRONIC_ARIADNE) -END - -BEGIN_PROD(UTILITIES_UNLIMITED) - PROD("Emplant Deluxe", MACEMU, UTILITIES_UNLIMITED_EMPLANT_DELUXE) - PROD("Emplant Deluxe", MACEMU, UTILITIES_UNLIMITED_EMPLANT_DELUXE2) -END - -BEGIN_PROD(AMITRIX) - PROD(NULL, MULTIIO, AMITRIX_MULTI_IO) - PROD("CD-RAM", RAM, AMITRIX_CD_RAM) -END - -BEGIN_PROD(ARMAX) - PROD("OmniBus", GFX, ARMAX_OMNIBUS) -END - -BEGIN_PROD(NEWTEK) - PROD("VideoToaster", VIDEO, NEWTEK_VIDEOTOASTER) -END - -BEGIN_PROD(M_TECH_GERMANY) - PROD("AT500", IDE, MTEC_AT500_2) - PROD("68030", TURBO, MTEC_68030) - PROD("68020i", TURBO, MTEC_68020I) - PROD("A1200 T68030 RTC", TURBO, MTEC_A1200_T68030_RTC) - PROD("Viper Mk V/E-Matrix 530", TURBO_RAM, MTEC_VIPER_MK_V_E_MATRIX_530) - PROD("8MB", RAM, MTEC_8_MB_RAM) - PROD("Viper Mk V/E-Matrix 530 SCSI/IDE", SCSI_IDE, MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE) -END - -BEGIN_PROD(GREAT_VALLEY_PRODUCTS_4) - PROD("EGS 28/24 Spectrum", GFX, GVP_EGS_28_24_SPECTRUM_REG) - PROD("EGS 28/24 Spectrum", GFXRAM, GVP_EGS_28_24_SPECTRUM_RAM) -END - -BEGIN_PROD(APOLLO_1) - PROD("A1200", FPU_RAM, APOLLO_A1200) -END - -BEGIN_PROD(HELFRICH_2) - PROD("Piccolo", GFXRAM, HELFRICH_PICCOLO_RAM) - PROD("Piccolo", GFX, HELFRICH_PICCOLO_REG) - PROD("PeggyPlus MPEG", VIDEO, HELFRICH_PEGGY_PLUS_MPEG) - PROD("VideoCruncher", VIDEO, HELFRICH_VIDEOCRUNCHER) - PROD("Piccolo SD64", GFXRAM, HELFRICH_SD64_RAM) - PROD("Piccolo SD64", GFX, HELFRICH_SD64_REG) -END - -BEGIN_PROD(MACROSYSTEMS_USA) - PROD("Warp Engine 40xx", TURBO_SCSI_RAM, MACROSYSTEMS_WARP_ENGINE_40xx) -END - -BEGIN_PROD(ELBOX_COMPUTER) - PROD("1200/4", RAM, ELBOX_COMPUTER_1200_4) -END - -BEGIN_PROD(HARMS_PROFESSIONAL) - PROD("030 Plus", TURBO, HARMS_PROFESSIONAL_030_PLUS) - PROD("3500 Professional", TURBO_RAM, HARMS_PROFESSIONAL_3500) -END - -BEGIN_PROD(MICRONIK) - PROD("RCA 120", RAM, MICRONIK_RCA_120) -END - -BEGIN_PROD(MICRONIK2) - PROD("Z3i A1200 Zorro III + SCSI", SCSI, MICRONIK2_Z3I) -END - -BEGIN_PROD(MEGAMICRO) - PROD("SCRAM 500", SCSI, MEGAMICRO_SCRAM_500) - PROD("SCRAM 500", RAM, MEGAMICRO_SCRAM_500_RAM) -END - -BEGIN_PROD(IMTRONICS_2) - PROD("Hurricane 2800", TURBO_RAM, IMTRONICS_HURRICANE_2800_3) - PROD("Hurricane 2800", TURBO_RAM, IMTRONICS_HURRICANE_2800_4) -END - -BEGIN_PROD(INDIVIDUAL_COMPUTERS) - PROD("Buddha", IDE, INDIVIDUAL_COMPUTERS_BUDDHA) - PROD("Catweasel", IDE_FLOPPY, INDIVIDUAL_COMPUTERS_CATWEASEL) -END - -BEGIN_PROD(KUPKE_3) - PROD("Golem HD 3000", HD, KUPKE_GOLEM_HD_3000) -END - -BEGIN_PROD(ITH) - PROD("ISDN-Master II", ISDN, ITH_ISDN_MASTER_II) -END - -BEGIN_PROD(VMC) - PROD("ISDN Blaster Z2", ISDN, VMC_ISDN_BLASTER_Z2) - PROD("HyperCom 4", MULTIIO, VMC_HYPERCOM_4) -END - -BEGIN_PROD(INFORMATION) - PROD("ISDN Engine I", ISDN, INFORMATION_ISDN_ENGINE_I) -END - -BEGIN_PROD(VORTEX) - PROD("Golden Gate 80386SX", BRIDGE, VORTEX_GOLDEN_GATE_80386SX) - PROD("Golden Gate", RAM, VORTEX_GOLDEN_GATE_RAM) - PROD("Golden Gate 80486", BRIDGE, VORTEX_GOLDEN_GATE_80486) -END - -BEGIN_PROD(EXPANSION_SYSTEMS) - PROD("DataFlyer 4000SX", SCSI, EXPANSION_SYSTEMS_DATAFLYER_4000SX) - PROD("DataFlyer 4000SX", RAM, EXPANSION_SYSTEMS_DATAFLYER_4000SX_RAM) -END - -BEGIN_PROD(READYSOFT) - PROD("AMax II/IV", MACEMU, READYSOFT_AMAX_II_IV) -END - -BEGIN_PROD(PHASE5) - PROD("Blizzard", RAM, PHASE5_BLIZZARD_RAM) - PROD("Blizzard", TURBO, PHASE5_BLIZZARD) - PROD("Blizzard 1220-IV", TURBO, PHASE5_BLIZZARD_1220_IV) - PROD("FastLane Z3", RAM, PHASE5_FASTLANE_Z3_RAM) - PROD("Blizzard 1230-II/Fastlane Z3/CyberSCSI/CyberStorm060", TURBO_SCSI, PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060) - PROD("Blizzard 1220/CyberStorm", TURBO_SCSI, PHASE5_BLIZZARD_1220_CYBERSTORM) - PROD("Blizzard 1230", TURBO, PHASE5_BLIZZARD_1230) - PROD("Blizzard 1230-IV/1260", TURBO, PHASE5_BLIZZARD_1230_IV_1260) - PROD("Blizzard 2060", TURBO, PHASE5_BLIZZARD_2060) - PROD("CyberStorm Mk II", FLASHROM, PHASE5_CYBERSTORM_MK_II) - PROD("CyberVision64", GFX, PHASE5_CYBERVISION64) - PROD("CyberVision64-3D Prototype", GFX, PHASE5_CYBERVISION64_3D_PROTOTYPE) - PROD("CyberVision64-3D", GFX, PHASE5_CYBERVISION64_3D) - PROD("CyberStorm Mk III", TURBO_SCSI, PHASE5_CYBERSTORM_MK_III) -END - -BEGIN_PROD(DPS) - PROD("Personal Animation Recorder", VIDEO, DPS_PERSONAL_ANIMATION_RECORDER) -END - -BEGIN_PROD(APOLLO_2) - PROD("A620 68020", TURBO, APOLLO_A620_68020_1) - PROD("A620 68020", TURBO, APOLLO_A620_68020_2) -END - -BEGIN_PROD(APOLLO_3) - PROD("AT-Apollo", UNKNOWN, APOLLO_AT_APOLLO) - PROD("1230/1240/1260/2030/4040/4060", TURBO, APOLLO_1230_1240_1260_2030_4040_4060) -END - -BEGIN_PROD(PETSOFF_LP) - PROD("Delfina", AUDIO, PETSOFF_LP_DELFINA) - PROD("Delfina Lite", AUDIO, PETSOFF_LP_DELFINA_LITE) -END - -BEGIN_PROD(UWE_GERLACH) - PROD("RAM/ROM", MISC, UWE_GERLACH_RAM_ROM) -END - -BEGIN_PROD(MACROSYSTEMS_GERMANY) - PROD("Maestro", AUDIO, MACROSYSTEMS_MAESTRO) - PROD("VLab", VIDEO, MACROSYSTEMS_VLAB) - PROD("Maestro Pro", AUDIO, MACROSYSTEMS_MAESTRO_PRO) - PROD("Retina", GFX, MACROSYSTEMS_RETINA) - PROD("MultiEvolution", SCSI, MACROSYSTEMS_MULTI_EVOLUTION) - PROD("Toccata", AUDIO, MACROSYSTEMS_TOCCATA) - PROD("Retina Z3", GFX, MACROSYSTEMS_RETINA_Z3) - PROD("VLab Motion", VIDEO, MACROSYSTEMS_VLAB_MOTION) - PROD("Altais", GFX, MACROSYSTEMS_ALTAIS) - PROD("Falcon '040", TURBO, MACROSYSTEMS_FALCON_040) -END - -BEGIN_PROD(COMBITEC) -END - -BEGIN_PROD(SKI_PERIPHERALS) - PROD("MAST Fireball", SCSI, SKI_PERIPHERALS_MAST_FIREBALL) - PROD("SCSI/Dual Serial", SCSI_SERIAL, SKI_PERIPHERALS_SCSI_DUAL_SERIAL) -END - -BEGIN_PROD(REIS_WARE_2) - PROD("Scan King", SCANNER, REIS_WARE_SCAN_KING) -END - -BEGIN_PROD(CAMERON) - PROD("Personal A4", SCANNER, CAMERON_PERSONAL_A4) -END - -BEGIN_PROD(REIS_WARE) - PROD("Handyscanner", SCANNER, REIS_WARE_HANDYSCANNER) -END - -BEGIN_PROD(PHOENIX_2) - PROD("ST506", HD, PHOENIX_ST506_2) - PROD(NULL, SCSI, PHOENIX_SCSI_2) - PROD(NULL, RAM, PHOENIX_RAM_2) -END - -BEGIN_PROD(COMBITEC_2) - PROD(NULL, HD, COMBITEC_HD) - PROD("SRAM", RAM, COMBITEC_SRAM) -END - -BEGIN_PROD(HACKER) /* Unused */ -END - - -BEGIN_MANUF - MANUF("Pacific Peripherals", PACIFIC_PERIPHERALS) - MANUF("MacroSystems USA", MACROSYSTEMS_USA_2) - MANUF("Kupke", KUPKE_1) - MANUF("Memphis", MEMPHIS) - MANUF("3-State", 3_STATE) - MANUF("Commodore Braunschweig", COMMODORE_BRAUNSCHWEIG) - MANUF("Commodore West Chester", COMMODORE_WEST_CHESTER_1) - MANUF("Commodore West Chester", COMMODORE_WEST_CHESTER_2) - MANUF("Progressive Peripherals & Systems", PROGRESSIVE_PERIPHERALS_AND_SYSTEMS_2) - MANUF("Kolff Computer Supplies", KOLFF_COMPUTER_SUPPLIES) - MANUF("Cardco Ltd.", CARDCO_1) - MANUF("A-Squared", A_SQUARED) - MANUF("Comspec Communications", COMSPEC_COMMUNICATIONS) - MANUF("Anakin Research", ANAKIN_RESEARCH) - MANUF("Microbotics", MICROBOTICS) - MANUF("Access Associates Alegra", ACCESS_ASSOCIATES_ALEGRA) - MANUF("Expansion Technologies (Pacific Cypress)", EXPANSION_TECHNOLOGIES) - MANUF("ASDG", ASDG) - MANUF("Ronin/Imtronics", IMTRONICS_1) - MANUF("Commodore/University of Lowell", CBM_UNIVERSITY_OF_LOWELL) - MANUF("Ameristar", AMERISTAR) - MANUF("Supra", SUPRA) - MANUF("Computer Systems Assosiates", COMPUTER_SYSTEMS_ASSOCIATES) - MANUF("Marc Michael Groth", MARC_MICHAEL_GROTH) - MANUF("M-Tech", M_TECH) - MANUF("Great Valley Products", GREAT_VALLEY_PRODUCTS_1) - MANUF("ByteBox", BYTEBOX) - MANUF("DKB/Power Computing", DKB_POWER_COMPUTING) - MANUF("Great Valley Products", GREAT_VALLEY_PRODUCTS_2) - MANUF("California Access (Synergy)", CALIFORNIA_ACCESS_SYNERGY) - MANUF("Xetec", XETEC) - MANUF("Progressive Peripherals & Systems", PROGRESSIVE_PERIPHERALS_AND_SYSTEMS) - MANUF("Xebec", XEBEC) - MANUF("Spirit Technology", SPIRIT_TECHNOLOGY) - MANUF("Spirit Technology", SPIRIT_TECHNOLOGY_2) - MANUF("BSC/Alfadata", BSC_ALFADATA_1) - MANUF("BSC/Alfadata", BSC_ALFADATA_2) - MANUF("Cardco Ltd.", CARDCO_2) - MANUF("Jochheim", JOCHHEIM) - MANUF("Checkpoint Technologies", CHECKPOINT_TECHNOLOGIES) - MANUF("Edotronik", EDOTRONIK) - MANUF("NES Inc.", NES_INC) - MANUF("ICD", ICD) - MANUF("Kupke", KUPKE_2) - MANUF("Great Valley Products", GREAT_VALLEY_PRODUCTS_3) - MANUF("Interworks Network", INTERWORKS_NETWORK) - MANUF("Hardital Synthesis", HARDITAL_SYNTHESIS) - MANUF("Applied Engineering", APPLIED_ENGINEERING) - MANUF("BSC/Alfadata", BSC_ALFADATA_3) - MANUF("Phoenix", PHOENIX) - MANUF("Advanced Storage Systems", ADVANCED_STORAGE_SYSTEMS) - MANUF("Impulse", IMPULSE) - MANUF("IVS", IVS) - MANUF("Vector", VECTOR_1) - MANUF("XPert ProDev", XPERT_PRODEV) - MANUF("Hydra Systems", HYDRA_SYSTEMS) - MANUF("Sunrize Industries", SUNRIZE_INDUSTRIES) - MANUF("Triceratops", TRICERATOPS) - MANUF("Applied Magic Inc.", APPLIED_MAGIC) - MANUF("GFX-Base", GFX_BASE) - MANUF("RocTec", ROCTEC) - MANUF("Kato", KATO) - MANUF("Atlantis", ATLANTIS) - MANUF("Protar", PROTAR) - MANUF("ACS", ACS) - MANUF("Software Results Enterprises", SOFTWARE_RESULTS_ENTERPRISES) - MANUF("Masoboshi", MASOBOSHI) - MANUF("Mainhattan-Data (A-Team)", MAINHATTAN_DATA) - MANUF("Village Tronic", VILLAGE_TRONIC) - MANUF("Utilities Unlimited", UTILITIES_UNLIMITED) - MANUF("Amitrix", AMITRIX) - MANUF("ArMax", ARMAX) - MANUF("NewTek", NEWTEK) - MANUF("M-Tech Germany", M_TECH_GERMANY) - MANUF("Great Valley Products", GREAT_VALLEY_PRODUCTS_4) - MANUF("Apollo", APOLLO_1) - MANUF("Ingenieurbüro Helfrich", HELFRICH_2) - MANUF("MacroSystems USA", MACROSYSTEMS_USA) - MANUF("ElBox Computer", ELBOX_COMPUTER) - MANUF("Harms Professional", HARMS_PROFESSIONAL) - MANUF("Micronik", MICRONIK) - MANUF("Micronik", MICRONIK2) - MANUF("MegaMicro", MEGAMICRO) - MANUF("Ronin/Imtronics", IMTRONICS_2) - MANUF("Individual Computers", INDIVIDUAL_COMPUTERS) - MANUF("Kupke", KUPKE_3) - MANUF("ITH", ITH) - MANUF("VMC", VMC) - MANUF("Information", INFORMATION) - MANUF("Vortex", VORTEX) - MANUF("Expansion Systems", EXPANSION_SYSTEMS) - MANUF("ReadySoft", READYSOFT) - MANUF("Phase 5", PHASE5) - MANUF("DPS", DPS) - MANUF("Apollo", APOLLO_2) - MANUF("Apollo", APOLLO_3) - MANUF("Petsoff LP", PETSOFF_LP) - MANUF("Uwe Gerlach", UWE_GERLACH) - MANUF("MacroSystems Germany", MACROSYSTEMS_GERMANY) - MANUF("Combitec", COMBITEC) - MANUF("SKI Peripherals", SKI_PERIPHERALS) - MANUF("Reis-Ware", REIS_WARE_2) - MANUF("Cameron", CAMERON) - MANUF("Reis-Ware", REIS_WARE) - MANUF("Hacker Test Board", HACKER) /* Unused */ - MANUF("Phoenix", PHOENIX_2) - MANUF("Combitec", COMBITEC_2) -END - -#define NUM_MANUF (ARRAYSIZE(Manufacturers)) -#define NUM_GVP_PROD (ARRAYSIZE(Ext_Prod_GVP)) - - - /* - * Zorro product classes - * - * Make sure to keep these in sync with include/linux/zorro.h! - */ - -static const char *classnames[] = { - NULL, /* ZORRO_CLASS_UNKNOWN */ - "ArcNet Card", /* ZORRO_CLASS_ARCNET */ - "Audio Board", /* ZORRO_CLASS_AUDIO */ - "ISA Bus Bridge", /* ZORRO_CLASS_BRIDGE */ - "DSP Board", /* ZORRO_CLASS_DSP */ - "Ethernet Card", /* ZORRO_CLASS_ETHERNET */ - "Ethernet Card and Parallel Ports", /* ZORRO_CLASS_ETHERNET_PARALLEL */ - "Flash ROM", /* ZORRO_CLASS_FLASHROM */ - "FPU and RAM Expansion", /* ZORRO_CLASS_FPU_RAM */ - "Graphics Board", /* ZORRO_CLASS_GFX */ - "Graphics Board (RAM)", /* ZORRO_CLASS_GFXRAM */ - "HD Controller", /* ZORRO_CLASS_HD */ - "HD Controller and RAM Expansion", /* ZORRO_CLASS_HD_RAM */ - "IDE Interface", /* ZORRO_CLASS_IDE */ - "IDE Interface and RAM Expansion", /* ZORRO_CLASS_IDE_RAM */ - "IDE Interface and Floppy Controller", /* ZORRO_CLASS_IDE_FLOPPY */ - "ISDN Interface", /* ZORRO_CLASS_ISDN */ - "Macintosh Emulator", /* ZORRO_CLASS_MACEMU */ - "Miscellaneous Expansion Card", /* ZORRO_CLASS_MISC */ - "Modem", /* ZORRO_CLASS_MODEM */ - "Multi I/O", /* ZORRO_CLASS_MULTIIO */ - "RAM Expansion", /* ZORRO_CLASS_RAM */ - "Scanner Interface", /* ZORRO_CLASS_SCANNER */ - "SCSI Host Adapter", /* ZORRO_CLASS_SCSI */ - "SCSI Host Adapter and IDE Interface", /* ZORRO_CLASS_SCSI_IDE */ - "SCSI Host Adapter and RAM Expansion", /* ZORRO_CLASS_SCSI_RAM */ - "SCSI Host Adapter and Serial Card", /* ZORRO_CLASS_SCSI_SERIAL */ - "Multi Serial", /* ZORRO_CLASS_SERIAL */ - "Drawing Tablet Interface", /* ZORRO_CLASS_TABLET */ - "Accelerator", /* ZORRO_CLASS_TURBO */ - "Accelerator and RAM Expansion", /* ZORRO_CLASS_TURBO_RAM */ - "Accelerator and HD Controller", /* ZORRO_CLASS_TURBO_HD */ - "Accelerator and IDE Interface", /* ZORRO_CLASS_TURBO_IDE */ - "Accelerator and SCSI Host Adapter", /* ZORRO_CLASS_TURBO_SCSI */ - "Accelerator, SCSI Host Adapter and RAM Expansion", /* ZORRO_CLASS_TURBO_SCSI */ - "Video Board", /* ZORRO_CLASS_VIDEO */ -}; - -static inline const char *get_class_name(enum Zorro_Classes class) -{ - if (class < ARRAYSIZE(classnames)) - return(classnames[class]); - else - return("(**Illegal**)"); -} - -#endif /* CONFIG_ZORRO */ - - - /* - * Expansion Devices - */ - -u_int zorro_num_autocon; -struct ConfigDev zorro_autocon[ZORRO_NUM_AUTO]; -static u32 BoardPartFlags[ZORRO_NUM_AUTO] = { 0, }; - - - /* - * Find the key for the next unconfigured expansion device of a specific - * type. - * - * Part is a device specific number (0 <= part <= 31) to allow for the - * independent configuration of independent parts of an expansion board. - * Thanks to Jes Soerensen for this idea! - * - * Index is used to specify the first board in the autocon list - * to be tested. It was inserted in order to solve the problem - * with the GVP boards that uses the same product code, but - * it should help if there are other companies which use the same - * method as GVP. Drivers for boards which are not using this - * method do not need to think of this - just set index = 0. - * - * Example: - * - * while ((key = zorro_find(ZORRO_PROD_MY_BOARD, MY_PART, 0))) { - * cd = zorro_get_board(key); - * initialise_this_board; - * zorro_config_board(key, MY_PART); - * } - */ - -u_int zorro_find(zorro_id id, u_int part, u_int index) -{ - u_int manuf = ZORRO_MANUF(id); - u_int prod = ZORRO_PROD(id); - u_int epc = ZORRO_EPC(id); - u_int key; - const struct ConfigDev *cd; - u_long addr; - - if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO)) - return(0); - - if (part > 31) { - printk("zorro_find: bad part %d\n", part); - return(0); - } - - for (key = index + 1; key <= zorro_num_autocon; key++) { - cd = &zorro_autocon[key-1]; - addr = (u_long)cd->cd_BoardAddr; - if ((cd->cd_Rom.er_Manufacturer == manuf) && - (cd->cd_Rom.er_Product == prod) && - !(BoardPartFlags[key-1] & (1<<part)) && - (manuf != ZORRO_MANUF(ZORRO_PROD_GVP_EPC_BASE) || - prod != ZORRO_PROD(ZORRO_PROD_GVP_EPC_BASE) || - (*(u_short *)ZTWO_VADDR(addr+0x8000) & GVP_PRODMASK) == epc)) - break; - } - return(key <= zorro_num_autocon ? key : 0); -} - - - /* - * Get the board corresponding to a specific key - */ - -const struct ConfigDev *zorro_get_board(u_int key) -{ - const struct ConfigDev *cd = NULL; - - if ((key < 1) || (key > zorro_num_autocon)) - printk("zorro_get_board: bad key %d\n", key); - else - cd = &zorro_autocon[key-1]; - - return(cd); -} - - - /* - * Mark a part of a board as configured - */ - -void zorro_config_board(u_int key, u_int part) -{ - if ((key < 1) || (key > zorro_num_autocon)) - printk("zorro_config_board: bad key %d\n", key); - else if (part > 31) - printk("zorro_config_board: bad part %d\n", part); - else if (BoardPartFlags[key-1] & (1<<part)) - printk("zorro_config_board: key %d part %d is already configured\n", - key, part); - else - BoardPartFlags[key-1] |= 1<<part; -} - - - /* - * Mark a part of a board as unconfigured - * - * This function is mainly intended for the unloading of LKMs - */ - -void zorro_unconfig_board(u_int key, u_int part) -{ - if ((key < 1) || (key > zorro_num_autocon)) - printk("zorro_unconfig_board: bad key %d\n", key); - else if (part > 31) - printk("zorro_unconfig_board: bad part %d\n", part); - else if (!(BoardPartFlags[key-1] & (1<<part))) - printk("zorro_config_board: key %d part %d is not yet configured\n", - key, part); - else - BoardPartFlags[key-1] &= ~(1<<part); -} - - -#ifdef CONFIG_ZORRO - - /* - * Identify an AutoConfig Expansion Device - * - * If the board was configured by a Linux/m68k driver, an asterisk will - * be printed before the board address (except for unknown and `Hacker - * Test' boards). - */ - -static int identify(u_int devnum, char *buf, int verbose) -{ - const struct ConfigDev *cd = &zorro_autocon[devnum]; - u32 configured = BoardPartFlags[devnum]; - u_int manuf = cd->cd_Rom.er_Manufacturer; - u_int prod = cd->cd_Rom.er_Product; - u_int class = ZORRO_CLASS_UNKNOWN; - u_int epc = 0; - const char *manufname = "Unknown"; - const char *prodname = "Unknown"; - const char *classname; - u_int i, j, k, len = 0; - u_long addr = (u_long)cd->cd_BoardAddr; - u_long size = cd->cd_BoardSize; - char mag; - int identified = 0, gvp = 0; - - if (manuf != ZORRO_MANUF(ZORRO_PROD_GVP_EPC_BASE) || - prod != ZORRO_PROD(ZORRO_PROD_GVP_EPC_BASE)) { - for (i = 0; i < NUM_MANUF; i++) - if (Manufacturers[i].Manuf == manuf) { - manufname = Manufacturers[i].Name; - for (j = 0; j < Manufacturers[i].NumProd; j++) - if (Manufacturers[i].Products[j].Prod == prod) { - prodname = Manufacturers[i].Products[j].Name; - class = Manufacturers[i].Products[j].Class; - identified = 1; - break; - } - } - /* Put workarounds for ID clashes here */ - if (manuf == ZORRO_MANUF(ZORRO_PROD_HELFRICH_RAINBOW_III) && - prod == ZORRO_PROD(ZORRO_PROD_HELFRICH_RAINBOW_III)) - manufname = "Ingenieurbüro Helfrich"; - } else { - manufname = "Great Valley Products"; - gvp = 1; - epc = *(u_short *)ZTWO_VADDR(addr+0x8000) & GVP_PRODMASK; - for (k = 0; k < NUM_GVP_PROD; k++) - if (epc == Ext_Prod_GVP[k].EPC) { - prodname = Ext_Prod_GVP[k].Name; - class = Ext_Prod_GVP[k].Class; - identified = 1; - break; - } - } - classname = get_class_name(class); - if (size & 0xfffff) { - size >>= 10; - mag = 'K'; - } else { - size >>= 20; - mag = 'M'; - } - if (verbose) { - const char *zorro; - int is_mem = cd->cd_Rom.er_Type & ERTF_MEMLIST; - switch (cd->cd_Rom.er_Type & ERT_TYPEMASK) { - case ERT_ZORROII: - zorro = "Zorro II"; - break; - case ERT_ZORROIII: - zorro = "Zorro III"; - break; - default: - zorro = "Unknown Zorro"; - break; - } - if (!prodname) - prodname = "Unknown"; - if (!classname) - classname = "Unknown"; - len = sprintf(buf, " Device %d at 0x%08lx: ID=%04x:%02x", devnum, - addr, manuf, prod); - if (gvp) - len += sprintf(buf+len, ":%02x", epc); - len += sprintf(buf+len, ", %s, %ld%c", zorro, size, mag); - if (is_mem) - len += sprintf(buf+len, ", System RAM"); - else - len += sprintf(buf+len, ", Configured=%08x", configured); - len += sprintf(buf+len, "\n" - " Manufacturer: %s\n" - " Product Name: %s\n" - " Board Class : %s\n", - manufname, prodname, classname); - } else { - len = sprintf(buf, " %c%08lx: ", configured ? '*' : ' ', addr); - if (identified) { - len += sprintf(buf+len, "%s", manufname); - if (prodname) - len += sprintf(buf+len, " %s", prodname); - if (classname) - len += sprintf(buf+len, " %s", classname); - } else if (manuf == ZORRO_MANUF_HACKER) - len += sprintf(buf+len, "Hacker Test Board %02x", prod); - else if (gvp) - len += sprintf(buf+len, "[%04x:%02x:%02x] made by %s", manuf, prod, - epc, manufname); - else - len += sprintf(buf+len, "[%04x:%02x] made by %s", manuf, prod, - manufname); - len += sprintf(buf+len, " (%ld%c)\n", size, mag); - if (!identified && manuf != ZORRO_MANUF_HACKER) - len += sprintf(buf+len, " Please report this unknown device to " - "zorro@linux-m68k.org\n"); - } - return(len); -} - - - /* - * Identify all known AutoConfig Expansion Devices - */ - -void zorro_identify(void) -{ - u_int i; - char tmp[256]; - - if (!AMIGAHW_PRESENT(ZORRO)) - return; - - printk("Probing AutoConfig expansion device(s):\n"); - for (i = 0; i < zorro_num_autocon; i++) { - identify(i, tmp, 0); - printk(tmp); - } - if (!zorro_num_autocon) - printk("No AutoConfig expansion devices present.\n"); -} - - - /* - * Get the list of all AutoConfig Expansion Devices - */ - -int zorro_get_list(char *buffer) -{ - u_int i, len = 0, len2; - char tmp[256]; - - if (MACH_IS_AMIGA && AMIGAHW_PRESENT(ZORRO)) { - len = sprintf(buffer, "AutoConfig expansion devices:\n"); - for (i = 0; i < zorro_num_autocon; i++) { - len2 = identify(i, tmp, 1); - if (len+len2 >= 4075) { - len += sprintf(buffer+len, "4K limit reached!\n"); - break; - } - strcpy(buffer+len, tmp); - len += len2; - } - } - return(len); -} - -#endif /* CONFIG_ZORRO */ - - - /* - * Bitmask indicating portions of available Zorro II RAM that are unused - * by the system. Every bit represents a 64K chunk, for a maximum of 8MB - * (128 chunks, physical 0x00200000-0x009fffff). - * - * If you want to use (= allocate) portions of this RAM, you should clear - * the corresponding bits. - * - * Possible uses: - * - z2ram device - * - SCSI DMA bounce buffers - */ - -u32 zorro_unused_z2ram[4] = { 0, 0, 0, 0 }; - - -static void mark_region(u_long addr, u_long size, int flag) -{ - u_long start, end, chunk; - - if (flag) { - start = (addr+Z2RAM_CHUNKMASK) & ~Z2RAM_CHUNKMASK; - end = (addr+size) & ~Z2RAM_CHUNKMASK; - } else { - start = addr & ~Z2RAM_CHUNKMASK; - end = (addr+size+Z2RAM_CHUNKMASK) & ~Z2RAM_CHUNKMASK; - } - if (end <= Z2RAM_START || start >= Z2RAM_END) - return; - start = start < Z2RAM_START ? 0x00000000 : start-Z2RAM_START; - end = end > Z2RAM_END ? Z2RAM_SIZE : end-Z2RAM_START; - while (start < end) { - chunk = start>>Z2RAM_CHUNKSHIFT; - if (flag) - set_bit( chunk, zorro_unused_z2ram ); - else - clear_bit( chunk, zorro_unused_z2ram ); - start += Z2RAM_CHUNKSIZE; - } -} - - - /* - * Initialization - */ - -void zorro_init(void) -{ - u_int i; - const struct ConfigDev *cd; - - if (!AMIGAHW_PRESENT(ZORRO)) - return; - - /* Mark all available Zorro II memory */ - for (i = 0; i < zorro_num_autocon; i++) { - cd = &zorro_autocon[i]; - if (cd->cd_Rom.er_Type & ERTF_MEMLIST) - mark_region((u_long)cd->cd_BoardAddr, cd->cd_BoardSize, 1); - } - - /* Unmark all used Zorro II memory */ - for (i = 0; i < m68k_num_memory; i++) - mark_region(m68k_memory[i].addr, m68k_memory[i].size, 0); -} diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c index 2ad8f9c24..4c620f23e 100644 --- a/arch/m68k/apollo/config.c +++ b/arch/m68k/apollo/config.c @@ -14,7 +14,6 @@ #include <asm/irq.h> #include <asm/machdep.h> -extern struct consw fb_con; extern void dn_sched_init(void (*handler)(int,void *,struct pt_regs *)); extern int dn_keyb_init(void); extern int dn_dummy_kbdrate(struct kbd_repeat *); @@ -110,7 +109,9 @@ void config_apollo(void) { mach_floppy_setup = dn_dummy_floppy_setup; #endif mach_reset = dn_dummy_reset; /* */ - conswitchp = &fb_con; +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; +#endif #if 0 mach_fb_init = dn_fb_init; mach_video_setup = dn_dummy_video_setup; diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c index 61afbb50b..15e4c2d09 100644 --- a/arch/m68k/atari/ataints.c +++ b/arch/m68k/atari/ataints.c @@ -294,7 +294,7 @@ SYMBOL_NAME_STR(atari_fast_irq_handler) ": addql #8,%%sp addql #4,%%sp jbra "SYMBOL_NAME_STR(ret_from_interrupt) - : : "i" (&kstat.irqs), "n" (PT_OFF_FORMATVEC) + : : "i" (&kstat.irqs[0]), "n" (PT_OFF_FORMATVEC) ); } diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c index 8c512a714..e6535f6ff 100644 --- a/arch/m68k/atari/atakeyb.c +++ b/arch/m68k/atari/atakeyb.c @@ -28,11 +28,9 @@ #include <asm/atariints.h> #include <asm/atarihw.h> #include <asm/atarikb.h> -#include <asm/atari_mouse.h> #include <asm/atari_joystick.h> #include <asm/irq.h> -extern unsigned char mach_keyboard_type; static void atakeyb_rep( unsigned long ignore ); extern unsigned int keymap_count; @@ -193,7 +191,7 @@ static u_short ataalt_map[NR_KEYS] __initdata = { 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200 }; -static u_short atashift_alt_map[NR_KEYS] = { +static u_short atashift_alt_map[NR_KEYS] __initdata = { 0xf200, 0xf81b, 0xf821, 0xf840, 0xf823, 0xf824, 0xf825, 0xf85e, 0xf826, 0xf82a, 0xf828, 0xf829, 0xf85f, 0xf82b, 0xf808, 0xf809, 0xf851, 0xf857, 0xf845, 0xf852, 0xf854, 0xf859, 0xf855, 0xf849, @@ -767,19 +765,22 @@ void atari_kbd_leds (unsigned int leds) __initfunc(int atari_keyb_init(void)) { /* setup key map */ - memcpy(plain_map, ataplain_map, sizeof(plain_map)); - memcpy(shift_map, atashift_map, sizeof(shift_map)); + memcpy(key_maps[0], ataplain_map, sizeof(plain_map)); + memcpy(key_maps[1], atashift_map, sizeof(plain_map)); + memcpy(key_maps[4], atactrl_map, sizeof(plain_map)); + memcpy(key_maps[5], atashift_ctrl_map, sizeof(plain_map)); + memcpy(key_maps[8], ataalt_map, sizeof(plain_map)); + /* Atari doesn't have an altgr_map, so we can reuse its memory for + atashift_alt_map */ + memcpy(key_maps[2], atashift_alt_map, sizeof(plain_map)); + key_maps[9] = key_maps[2]; key_maps[2] = 0; /* ataaltgr_map */ - memcpy(ctrl_map, atactrl_map, sizeof(ctrl_map)); - memcpy(shift_ctrl_map, atashift_ctrl_map, sizeof(shift_ctrl_map)); - memcpy(alt_map, ataalt_map, sizeof(alt_map)); - key_maps[9] = atashift_alt_map; - memcpy(ctrl_alt_map, atactrl_alt_map, sizeof(ctrl_alt_map)); + memcpy(key_maps[12], atactrl_alt_map, sizeof(plain_map)); key_maps[13] = atashift_ctrl_alt_map; keymap_count = 8; /* say that we don't have an AltGr key */ - mach_keyboard_type = KB_84; + keyboard_type = KB_84; kb_state.state = KEYBOARD; kb_state.len = 0; @@ -860,3 +861,8 @@ int atari_kbdrate( struct kbd_repeat *k ) return( 0 ); } + +/* for "kbd-reset" cmdline param */ +__initfunc(void atari_kbd_reset_setup(char *str, int *ints)) +{ +} diff --git a/arch/m68k/atari/atasound.c b/arch/m68k/atari/atasound.c index 6b03b96fd..8223ce95c 100644 --- a/arch/m68k/atari/atasound.c +++ b/arch/m68k/atari/atasound.c @@ -10,6 +10,9 @@ * License. See the file COPYING in the main directory of this archive * for more details. * + * 1998-05-31 ++andreas: atari_mksound rewritten to always use the envelope, + * no timer, atari_nosound removed. + * */ @@ -31,22 +34,6 @@ * stuff from the old atasound.c */ - -static void atari_nosound (unsigned long ignored) -{ - unsigned char tmp; - unsigned long flags; - - /* turn off generator A in mixer control */ - save_flags(flags); - cli(); - sound_ym.rd_data_reg_sel = 7; - tmp = sound_ym.rd_data_reg_sel; - sound_ym.wd_data = tmp | 0x39; - restore_flags(flags); -} - - void atari_microwire_cmd (int cmd) { tt_microwire.mask = 0x7ff; @@ -58,90 +45,62 @@ void atari_microwire_cmd (int cmd) } -#define PC_FREQ 1192180 +/* PSG base frequency */ #define PSG_FREQ 125000 +/* PSG envelope base frequency times 10 */ +#define PSG_ENV_FREQ_10 78125 - -void atari_mksound (unsigned int count, unsigned int ticks) +void atari_mksound (unsigned int hz, unsigned int ticks) { - static struct timer_list sound_timer = { NULL, NULL, 0, 0, - atari_nosound }; - /* - * Generates sound of some count for some number of clock ticks - * [count = 1193180 / frequency] - */ + /* Generates sound of some frequency for some number of clock + ticks. */ unsigned long flags; unsigned char tmp; + int period; save_flags(flags); cli(); - if (count == 750 && ticks == HZ/8) { - /* Special case: These values are used by console.c to - * generate the console bell. They are cached here and the - * sound actually generated is somehow special: it uses the - * generator B and an envelope. No timer is needed therefore - * and the bell doesn't disturb an other ongoing sound. - */ + /* Convert from frequency value to PSG period value (base + frequency 125 kHz). */ + period = PSG_FREQ / hz; + + if (period > 0xfff) period = 0xfff; - /* set envelope duration to 492 ms */ + /* Disable generator A in mixer control. */ + sound_ym.rd_data_reg_sel = 7; + tmp = sound_ym.rd_data_reg_sel; + tmp |= 011; + sound_ym.wd_data = tmp; + /* Set generator A frequency to hz. */ + sound_ym.rd_data_reg_sel = 0; + sound_ym.wd_data = period & 0xff; + sound_ym.rd_data_reg_sel = 1; + sound_ym.wd_data = (period >> 8) & 0xf; + if (ticks) { + /* Set length of envelope (max 8 sec). */ + int length = (ticks * PSG_ENV_FREQ_10) / HZ / 10; + + if (length > 0xffff) length = 0xffff; sound_ym.rd_data_reg_sel = 11; - sound_ym.wd_data = 0; + sound_ym.wd_data = length & 0xff; sound_ym.rd_data_reg_sel = 12; - sound_ym.wd_data = 15; - /* envelope form: max -> min single */ + sound_ym.wd_data = length >> 8; + /* Envelope form: max -> min single. */ sound_ym.rd_data_reg_sel = 13; - sound_ym.wd_data = 9; - /* set generator B frequency to 2400 Hz */ - sound_ym.rd_data_reg_sel = 2; - sound_ym.wd_data = 52; - sound_ym.rd_data_reg_sel = 3; sound_ym.wd_data = 0; - /* set volume of generator B to envelope control */ - sound_ym.rd_data_reg_sel = 9; + /* Use envelope for generator A. */ + sound_ym.rd_data_reg_sel = 8; sound_ym.wd_data = 0x10; - /* enable generator B in the mixer control */ - sound_ym.rd_data_reg_sel = 7; - tmp = sound_ym.rd_data_reg_sel; - sound_ym.wd_data = (tmp & ~0x02) | 0x38; - - restore_flags(flags); - return; - } - - del_timer( &sound_timer ); - - if (!count) { - atari_nosound( 0 ); - } - else { - - /* convert from frequency value - * to PSG period value (base frequency 125 kHz). - */ - int period = PSG_FREQ / count; - - if (period > 0xfff) period = 0xfff; - - /* set generator A frequency to 0 */ - sound_ym.rd_data_reg_sel = 0; - sound_ym.wd_data = period & 0xff; - sound_ym.rd_data_reg_sel = 1; - sound_ym.wd_data = (period >> 8) & 0xf; - /* turn on generator A in mixer control (but not noise - * generator!) */ - sound_ym.rd_data_reg_sel = 7; - tmp = sound_ym.rd_data_reg_sel; - sound_ym.wd_data = (tmp & ~0x01) | 0x38; - /* set generator A level to maximum, no envelope */ + } else { + /* Set generator A level to maximum, no envelope. */ sound_ym.rd_data_reg_sel = 8; sound_ym.wd_data = 15; - - if (ticks) { - sound_timer.expires = jiffies + ticks; - add_timer( &sound_timer ); - } } + /* Turn on generator A in mixer control. */ + sound_ym.rd_data_reg_sel = 7; + tmp &= ~1; + sound_ym.wd_data = tmp; restore_flags(flags); } diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c index 9ea8a4fab..a63e71e08 100644 --- a/arch/m68k/atari/config.c +++ b/arch/m68k/atari/config.c @@ -38,6 +38,7 @@ #include <asm/atari_stram.h> #include <asm/system.h> #include <asm/machdep.h> +#include <asm/hwtest.h> u_long atari_mch_cookie; u_long atari_mch_type = 0; @@ -58,6 +59,7 @@ static int atari_get_hardware_list(char *buffer); extern int atari_keyb_init(void); extern int atari_kbdrate (struct kbd_repeat *); extern void atari_kbd_leds (unsigned int); +extern void atari_kbd_reset_setup(char*, int); /* atari specific irq functions */ extern void atari_init_IRQ (void); extern int atari_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *), @@ -70,7 +72,6 @@ extern void atari_mksound( unsigned int count, unsigned int ticks ); #ifdef CONFIG_HEARTBEAT static void atari_heartbeat( int on ); #endif -extern struct consw fb_con; /* atari specific timer functions (in time.c) */ extern void atari_sched_init(void (*)(int, void *, struct pt_regs *)); @@ -99,39 +100,15 @@ static char atari_sysrq_xlate[128] = extern void (*kd_mksound)(unsigned int, unsigned int); -/* This function tests for the presence of an address, specially a - * hardware register address. It is called very early in the kernel - * initialization process, when the VBR register isn't set up yet. On - * an Atari, it still points to address 0, which is unmapped. So a bus - * error would cause another bus error while fetching the exception - * vector, and the CPU would do nothing at all. So we needed to set up - * a temporary VBR and a vector table for the duration of the test. +/* I've moved hwreg_present() and hwreg_present_bywrite() out into + * mm/hwtest.c, to avoid having multiple copies of the same routine + * in the kernel [I wanted them in hp300 and they were already used + * in the nubus code. NB: I don't have an Atari so this might (just + * conceivably) break something. + * I've preserved the #if 0 version of hwreg_present_bywrite() here + * for posterity. + * -- Peter Maydell <pmaydell@chiark.greenend.org.uk>, 05/1998 */ - -__initfunc(static int hwreg_present( volatile void *regp )) -{ - int ret = 0; - long save_sp, save_vbr; - long tmp_vectors[3]; - - __asm__ __volatile__ - ( "movec %/vbr,%2\n\t" - "movel #Lberr1,%4@(8)\n\t" - "movec %4,%/vbr\n\t" - "movel %/sp,%1\n\t" - "moveq #0,%0\n\t" - "tstb %3@\n\t" - "nop\n\t" - "moveq #1,%0\n" - "Lberr1:\n\t" - "movel %1,%/sp\n\t" - "movec %2,%/vbr" - : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr) - : "a" (regp), "a" (tmp_vectors) - ); - - return( ret ); -} #if 0 __initfunc(static int @@ -164,35 +141,6 @@ hwreg_present_bywrite(volatile void *regp, unsigned char val)) } #endif -/* Basically the same, but writes a value into a word register, protected - * by a bus error handler */ - -__initfunc(static int hwreg_write( volatile void *regp, unsigned short val )) -{ - int ret; - long save_sp, save_vbr; - long tmp_vectors[3]; - - __asm__ __volatile__ - ( "movec %/vbr,%2\n\t" - "movel #Lberr2,%4@(8)\n\t" - "movec %4,%/vbr\n\t" - "movel %/sp,%1\n\t" - "moveq #0,%0\n\t" - "movew %5,%3@\n\t" - "nop \n\t" /* If this nop isn't present, 'ret' may already be - * loaded with 1 at the time the bus error - * happens! */ - "moveq #1,%0\n" - "Lberr2:\n\t" - "movel %1,%/sp\n\t" - "movec %2,%/vbr" - : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr) - : "a" (regp), "a" (tmp_vectors), "g" (val) - ); - - return( ret ); -} /* ++roman: This is a more elaborate test for an SCC chip, since the plain * Medusa board generates DTACK at the SCC's standard addresses, but a SCC @@ -302,6 +250,7 @@ __initfunc(void config_atari(void)) mach_keyb_init = atari_keyb_init; mach_kbdrate = atari_kbdrate; mach_kbd_leds = atari_kbd_leds; + kbd_reset_setup = atari_kbd_reset_setup; mach_init_IRQ = atari_init_IRQ; mach_request_irq = atari_request_irq; mach_free_irq = atari_free_irq; @@ -315,7 +264,9 @@ __initfunc(void config_atari(void)) #ifdef CONFIG_ATARI_FLOPPY mach_floppy_setup = atari_floppy_setup; #endif - conswitchp = &fb_con; +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; +#endif mach_max_dma_address = 0xffffff; kd_mksound = atari_mksound; #ifdef CONFIG_MAGIC_SYSRQ diff --git a/arch/m68k/atari/joystick.c b/arch/m68k/atari/joystick.c index 82eb85288..1deec9653 100644 --- a/arch/m68k/atari/joystick.c +++ b/arch/m68k/atari/joystick.c @@ -15,7 +15,6 @@ #include <asm/atarikb.h> #include <asm/atari_joystick.h> -#include <asm/atari_mouse.h> #include <asm/uaccess.h> #define MAJOR_NR JOYSTICK_MAJOR diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c index de9a96d03..02821ebaf 100644 --- a/arch/m68k/atari/stram.c +++ b/arch/m68k/atari/stram.c @@ -53,7 +53,7 @@ * ++roman: * * New version of ST-Ram buffer allocation. Instead of using the - * 1 MB - 4 KB that remain when the the ST-Ram chunk starts at $1000 + * 1 MB - 4 KB that remain when the ST-Ram chunk starts at $1000 * (1 MB granularity!), such buffers are reserved like this: * * - If the kernel resides in ST-Ram anyway, we can take the buffer @@ -826,18 +826,23 @@ static int unswap_process( struct mm_struct * mm, unsigned long entry, unsigned long page, int isswap ) { struct vm_area_struct* vma; + int retval = 0; /* * Go through process' page directory. */ if (!mm || mm == &init_mm) return 0; + down(&mm->mmap_sem); for( vma = mm->mmap; vma; vma = vma->vm_next ) { pgd_t * pgd = pgd_offset(mm, vma->vm_start); - if (unswap_vma( vma, pgd, entry, page, isswap )) - return 1; + if (unswap_vma( vma, pgd, entry, page, isswap )) { + retval = 1; + break; + } } - return 0; + up(&mm->mmap_sem); + return retval; } @@ -954,7 +959,7 @@ static int unswap_by_read( unsigned char *map, unsigned long max, return( -ENOMEM ); } DPRINTK( "unswap: reading swap page %lu to %08lx\n", i, page ); - read_swap_page( entry, (char *)page ); + rw_swap_page( READ, entry, (char *)page, 1 ); for_each_task(p) { if (unswap_process( p->mm, entry, page, 0 )) { @@ -1160,7 +1165,7 @@ static unsigned long find_free_region( unsigned long n_pages, /* setup parameters from command line */ -void stram_swap_setup( char *str, int *ints ) +__initfunc(void stram_swap_setup(char *str, int *ints)) { if (ints[0] >= 1) max_swap_size = ((ints[1] < 0 ? 0 : ints[1]) * 1024) & PAGE_MASK; @@ -1256,7 +1261,7 @@ static struct file_operations stram_fops = { block_fsync /* fsync */ }; -int stram_device_init( void ) +__initfunc(int stram_device_init(void)) { if (!MACH_IS_ATARI) diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c index 8a3921c8d..79c4f48f2 100644 --- a/arch/m68k/atari/time.c +++ b/arch/m68k/atari/time.c @@ -83,7 +83,7 @@ static void mste_write(struct MSTE_RTC *val) #define RTC_READ(reg) \ ({ unsigned char __val; \ - writeb(reg,&tt_rtc.regsel); \ + (void) writeb(reg,&tt_rtc.regsel); \ __val = tt_rtc.data; \ __val; \ }) diff --git a/arch/m68k/bvme6000/Makefile b/arch/m68k/bvme6000/Makefile new file mode 100644 index 000000000..e8670c60b --- /dev/null +++ b/arch/m68k/bvme6000/Makefile @@ -0,0 +1,14 @@ +# +# Makefile for Linux arch/m68k/bvme6000 source directory +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +O_TARGET := bvme6000.o +O_OBJS := config.o bvmeints.o rtc.o +#OX_OBJS = ksyms.o + +include $(TOPDIR)/Rules.make diff --git a/arch/m68k/bvme6000/bvmeints.c b/arch/m68k/bvme6000/bvmeints.c new file mode 100644 index 000000000..a79f5555d --- /dev/null +++ b/arch/m68k/bvme6000/bvmeints.c @@ -0,0 +1,154 @@ +/* + * arch/m68k/bvme6000/bvmeints.c + * + * Copyright (C) 1997 Richard Hirst [richard@sleepie.demon.co.uk] + * + * based on amiints.c -- Amiga Linux interrupt handling code + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file README.legal in the main directory of this archive + * for more details. + * + */ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/errno.h> + +#include <asm/ptrace.h> +#include <asm/system.h> +#include <asm/irq.h> +#include <asm/traps.h> + +static void bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp); + +/* + * This should ideally be 4 elements only, for speed. + */ + +static struct { + void (*handler)(int, void *, struct pt_regs *); + unsigned long flags; + void *dev_id; + const char *devname; + unsigned count; +} irq_tab[256]; + +/* + * void bvme6000_init_IRQ (void) + * + * Parameters: None + * + * Returns: Nothing + * + * This function is called during kernel startup to initialize + * the bvme6000 IRQ handling routines. + */ + +void bvme6000_init_IRQ (void) +{ + int i; + + for (i = 0; i < 256; i++) { + irq_tab[i].handler = bvme6000_defhand; + irq_tab[i].flags = IRQ_FLG_STD; + irq_tab[i].dev_id = NULL; + irq_tab[i].devname = NULL; + irq_tab[i].count = 0; + } +} + +int bvme6000_request_irq(unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long flags, const char *devname, void *dev_id) +{ + if (irq > 255) { + printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname); + return -ENXIO; + } +#if 0 + /* Nothing special about auto-vectored devices for the BVME6000, + * but treat it specially to avoid changes elsewhere. + */ + + if (irq >= VEC_INT1 && irq <= VEC_INT7) + return sys_request_irq(irq - VEC_SPUR, handler, flags, + devname, dev_id); +#endif + if (!(irq_tab[irq].flags & IRQ_FLG_STD)) { + if (irq_tab[irq].flags & IRQ_FLG_LOCK) { + printk("%s: IRQ %d from %s is not replaceable\n", + __FUNCTION__, irq, irq_tab[irq].devname); + return -EBUSY; + } + if (flags & IRQ_FLG_REPLACE) { + printk("%s: %s can't replace IRQ %d from %s\n", + __FUNCTION__, devname, irq, irq_tab[irq].devname); + return -EBUSY; + } + } + irq_tab[irq].handler = handler; + irq_tab[irq].flags = flags; + irq_tab[irq].dev_id = dev_id; + irq_tab[irq].devname = devname; + return 0; +} + +void bvme6000_free_irq(unsigned int irq, void *dev_id) +{ + if (irq > 255) { + printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); + return; + } +#if 0 + if (irq >= VEC_INT1 && irq <= VEC_INT7) { + sys_free_irq(irq - VEC_SPUR, dev_id); + return; + } +#endif + if (irq_tab[irq].dev_id != dev_id) + printk("%s: Removing probably wrong IRQ %d from %s\n", + __FUNCTION__, irq, irq_tab[irq].devname); + + irq_tab[irq].handler = bvme6000_defhand; + irq_tab[irq].flags = IRQ_FLG_STD; + irq_tab[irq].dev_id = NULL; + irq_tab[irq].devname = NULL; +} + +void bvme6000_process_int (unsigned long vec, struct pt_regs *fp) +{ + if (vec > 255) + panic ("bvme6000_process_int: Illegal vector %ld", vec); + irq_tab[vec].count++; + irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp); +} + +int bvme6000_get_irq_list (char *buf) +{ + int i, len = 0; + + for (i = 0; i < 256; i++) { + if (irq_tab[i].count) + len += sprintf (buf+len, "Vec 0x%02x: %8d %s\n", + i, irq_tab[i].count, + irq_tab[i].devname ? irq_tab[i].devname : "free"); + } + return len; +} + + +static void bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp) +{ + printk ("Unknown interrupt 0x%02x\n", irq); +} + +void bvme6000_enable_irq (unsigned int irq) +{ +} + + +void bvme6000_disable_irq (unsigned int irq) +{ +} + diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c new file mode 100644 index 000000000..74d15e995 --- /dev/null +++ b/arch/m68k/bvme6000/config.c @@ -0,0 +1,453 @@ +/* + * arch/m68k/bvme6000/config.c + * + * Copyright (C) 1997 Richard Hirst [richard@sleepie.demon.co.uk] + * + * Based on: + * + * linux/amiga/config.c + * + * Copyright (C) 1993 Hamish Macdonald + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file README.legal in the main directory of this archive + * for more details. + */ + +#include <stdarg.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/kd.h> +#include <linux/tty.h> +#include <linux/console.h> +#include <linux/linkage.h> +#include <linux/init.h> +#include <linux/major.h> + +#include <asm/system.h> +#include <asm/pgtable.h> +#include <asm/setup.h> +#include <asm/irq.h> +#include <asm/traps.h> +#include <asm/machdep.h> +#include <asm/bvme6000hw.h> + +extern void bvme6000_process_int (int level, struct pt_regs *regs); +extern void bvme6000_init_IRQ (void); +extern void bvme6000_free_irq (unsigned int, void *); +extern int bvme6000_get_irq_list (char *); +extern void bvme6000_enable_irq (unsigned int); +extern void bvme6000_disable_irq (unsigned int); +static void bvme6000_get_model(char *model); +static int bvme6000_get_hardware_list(char *buffer); +extern int bvme6000_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); +extern void bvme6000_sched_init(void (*handler)(int, void *, struct pt_regs *)); +extern int bvme6000_keyb_init(void); +extern int bvme6000_kbdrate (struct kbd_repeat *); +extern unsigned long bvme6000_gettimeoffset (void); +extern void bvme6000_gettod (int *year, int *mon, int *day, int *hour, + int *min, int *sec); +extern int bvme6000_hwclk (int, struct hwclk_time *); +extern int bvme6000_set_clock_mmss (unsigned long); +extern void bvme6000_check_partition (struct gendisk *hd, unsigned int dev); +extern void bvme6000_mksound( unsigned int count, unsigned int ticks ); +extern void bvme6000_reset (void); +extern void bvme6000_waitbut(void); +void bvme6000_set_vectors (void); + +static unsigned char bcd2bin (unsigned char b); +static unsigned char bin2bcd (unsigned char b); + +/* Save tick handler routine pointer, will point to do_timer() in + * kernel/sched.c, called via bvme6000_process_int() */ + +static void (*tick_handler)(int, void *, struct pt_regs *); + +int bvme6000_kbdrate (struct kbd_repeat *k) +{ + return 0; +} + +void bvme6000_mksound( unsigned int count, unsigned int ticks ) +{ +} + +void bvme6000_reset() +{ + volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE; + + printk ("\r\n\nCalled bvme6000_reset\r\n" + "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r"); + /* The string of returns is to delay the reset until the whole + * message is output. */ + /* Enable the watchdog, via PIT port C bit 4 */ + + pit->pcddr |= 0x10; /* WDOG enable */ + + while(1) + ; +} + +static void bvme6000_get_model(char *model) +{ + /* XXX Need to detect if BVME4000 or BVME6000 */ + sprintf(model, "BVME6000"); +} + + +/* No hardware options on BVME6000? */ + +static int bvme6000_get_hardware_list(char *buffer) +{ + *buffer = '\0'; + return 0; +} + + +__initfunc(void config_bvme6000(void)) +{ + volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE; + +#if 0 + /* Call bvme6000_set_vectors() so ABORT will work, along with BVMBug + * debugger. Note trap_init() will splat the abort vector, but + * bvme6000_init_IRQ() will put it back again. Hopefully. */ + + bvme6000_set_vectors(); +#endif + + mach_sched_init = bvme6000_sched_init; + mach_keyb_init = bvme6000_keyb_init; + mach_kbdrate = bvme6000_kbdrate; + mach_init_IRQ = bvme6000_init_IRQ; + mach_gettimeoffset = bvme6000_gettimeoffset; + mach_gettod = bvme6000_gettod; + mach_hwclk = bvme6000_hwclk; + mach_set_clock_mmss = bvme6000_set_clock_mmss; +/* mach_mksound = bvme6000_mksound; */ + mach_reset = bvme6000_reset; + mach_free_irq = bvme6000_free_irq; + mach_process_int = bvme6000_process_int; + mach_get_irq_list = bvme6000_get_irq_list; + mach_request_irq = bvme6000_request_irq; + enable_irq = bvme6000_enable_irq; + disable_irq = bvme6000_disable_irq; + mach_get_model = bvme6000_get_model; + mach_get_hardware_list = bvme6000_get_hardware_list; + + printk ("Board is %sconfigured as a System Controller\n", + *config_reg_ptr & BVME_CONFIG_SW1 ? "" : "not "); + + /* Now do the PIT configuration */ + + pit->pgcr = 0x00; /* Unidirectional 8 bit, no handshake for now */ + pit->psrr = 0x18; /* PIACK and PIRQ fucntions enabled */ + pit->pacr = 0x00; /* Sub Mode 00, H2 i/p, no DMA */ + pit->padr = 0x00; /* Just to be tidy! */ + pit->paddr = 0x00; /* All inputs for now (safest) */ + pit->pbcr = 0x80; /* Sub Mode 1x, H4 i/p, no DMA */ + pit->pbdr = 0xbc | (*config_reg_ptr & BVME_CONFIG_SW1 ? 0 : 0x40); + /* PRI, SYSCON?, Level3, SCC clks from xtal */ + pit->pbddr = 0xf3; /* Mostly outputs */ + pit->pcdr = 0x01; /* PA transceiver disabled */ + pit->pcddr = 0x03; /* WDOG disable */ +} + + +void bvme6000_abort_int (int irq, void *dev_id, struct pt_regs *fp) +{ + unsigned long *new = (unsigned long *)vectors; + unsigned long *old = (unsigned long *)0xf8000000;; + + /* Wait for button release */ + while (*config_reg_ptr & BVME_ABORT_STATUS) + ; + + *(new+4) = *(old+4); /* Illegal instruction */ + *(new+9) = *(old+9); /* Trace */ + *(new+47) = *(old+47); /* Trap #15 */ + *(new+0x1f) = *(old+0x1f); /* ABORT switch */ +} + + +static void bvme6000_timer_int (int irq, void *dev_id, struct pt_regs *fp) +{ + volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; + unsigned char msr = rtc->msr & 0xc0; + + rtc->msr = msr | 0x20; /* Ack the interrupt */ + + tick_handler(irq, dev_id, fp); +} + +/* + * Set up the RTC timer 1 to mode 2, so T1 output toggles every 5ms + * (40000 x 125ns). It will interrupt every 10ms, when T1 goes low. + * So, when reading the elapsed time, you should read timer1, + * subtract it from 39999, and then add 40000 if T1 is high. + * That gives you the number of 125ns ticks in to the 10ms period, + * so divide by 8 to get the microsecond result. + */ + +void bvme6000_sched_init (void (*timer_routine)(int, void *, struct pt_regs *)) +{ + volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; + unsigned char msr = rtc->msr & 0xc0; + + rtc->msr = 0; /* Ensure timer registers accessible */ + + tick_handler = timer_routine; + if (request_irq(BVME_IRQ_RTC, bvme6000_timer_int, 0, + "timer", bvme6000_timer_int)) + panic ("Couldn't register timer int"); + + rtc->t1cr_omr = 0x04; /* Mode 2, ext clk */ + rtc->t1msb = 39999 >> 8; + rtc->t1lsb = 39999 & 0xff; + rtc->irr_icr1 &= 0xef; /* Route timer 1 to INTR pin */ + rtc->msr = 0x40; /* Access int.cntrl, etc */ + rtc->pfr_icr0 = 0x80; /* Just timer 1 ints enabled */ + rtc->irr_icr1 = 0; + rtc->t1cr_omr = 0x0a; /* INTR+T1 active lo, push-pull */ + rtc->t0cr_rtmr &= 0xdf; /* Stop timers in standby */ + rtc->msr = 0; /* Access timer 1 control */ + rtc->t1cr_omr = 0x05; /* Mode 2, ext clk, GO */ + + rtc->msr = msr; + + if (request_irq(BVME_IRQ_ABORT, bvme6000_abort_int, 0, + "abort", bvme6000_abort_int)) + panic ("Couldn't register abort int"); +} + + +/* This is always executed with interrupts disabled. */ + +/* + * NOTE: Don't accept any readings within 5us of rollover, as + * the T1INT bit may be a little slow getting set. There is also + * a fault in the chip, meaning that reads may produce invalid + * results... + */ + +unsigned long bvme6000_gettimeoffset (void) +{ + volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; + volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE; + unsigned char msr = rtc->msr & 0xc0; + unsigned char t1int, t1op; + unsigned long v = 800000, ov; + + rtc->msr = 0; /* Ensure timer registers accessible */ + + do { + ov = v; + t1int = rtc->msr & 0x20; + t1op = pit->pcdr & 0x04; + rtc->t1cr_omr |= 0x40; /* Latch timer1 */ + v = rtc->t1msb << 8; /* Read timer1 */ + v |= rtc->t1lsb; /* Read timer1 */ + } while (t1int != (rtc->msr & 0x20) || + t1op != (pit->pcdr & 0x04) || + abs(ov-v) > 80 || + v > 39960); + + v = 39999 - v; + if (!t1op) /* If in second half cycle.. */ + v += 40000; + v /= 8; /* Convert ticks to microseconds */ + if (t1int) + v += 10000; /* Int pending, + 10ms */ + rtc->msr = msr; + + return v; +} + +extern void bvme6000_gettod (int *year, int *mon, int *day, int *hour, + int *min, int *sec) +{ + volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; + unsigned char msr = rtc->msr & 0xc0; + + rtc->msr = 0; /* Ensure clock accessible */ + + do { /* Loop until we get a reading with a stable seconds field */ + *sec = bcd2bin (rtc->bcd_sec); + *min = bcd2bin (rtc->bcd_min); + *hour = bcd2bin (rtc->bcd_hr); + *day = bcd2bin (rtc->bcd_dom); + *mon = bcd2bin (rtc->bcd_mth); + *year = bcd2bin (rtc->bcd_year); + } while (bcd2bin (rtc->bcd_sec) != *sec); + + rtc->msr = msr; +} + +static unsigned char bcd2bin (unsigned char b) +{ + return ((b>>4)*10 + (b&15)); +} + +static unsigned char bin2bcd (unsigned char b) +{ + return (((b/10)*16) + (b%10)); +} + + +/* + * Looks like op is non-zero for setting the clock, and zero for + * reading the clock. + * + * struct hwclk_time { + * unsigned sec; 0..59 + * unsigned min; 0..59 + * unsigned hour; 0..23 + * unsigned day; 1..31 + * unsigned mon; 0..11 + * unsigned year; 00... + * int wday; 0..6, 0 is Sunday, -1 means unknown/don't set + * }; + */ + +int bvme6000_hwclk(int op, struct hwclk_time *t) +{ + volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; + unsigned char msr = rtc->msr & 0xc0; + + rtc->msr = 0x40; /* Ensure clock and real-time-mode-register + * are accessible */ + if (op) + { /* Write.... */ + rtc->t0cr_rtmr = t->year%4; + rtc->bcd_tenms = 0; + rtc->bcd_sec = bin2bcd(t->sec); + rtc->bcd_min = bin2bcd(t->min); + rtc->bcd_hr = bin2bcd(t->hour); + rtc->bcd_dom = bin2bcd(t->day); + rtc->bcd_mth = bin2bcd(t->mon + 1); + rtc->bcd_year = bin2bcd(t->year%100); + if (t->wday >= 0) + rtc->bcd_dow = bin2bcd(t->wday+1); + rtc->t0cr_rtmr = t->year%4 | 0x08; + } + else + { /* Read.... */ + do { + t->sec = bcd2bin(rtc->bcd_sec); + t->min = bcd2bin(rtc->bcd_min); + t->hour = bcd2bin(rtc->bcd_hr); + t->day = bcd2bin(rtc->bcd_dom); + t->mon = bcd2bin(rtc->bcd_mth)-1; + t->year = bcd2bin(rtc->bcd_year); + if (t->year < 70) + t->year += 100; + t->wday = bcd2bin(rtc->bcd_dow)-1; + } while (t->sec != bcd2bin(rtc->bcd_sec)); + } + + rtc->msr = msr; + + return 0; +} + +/* + * Set the minutes and seconds from seconds value 'nowtime'. Fail if + * clock is out by > 30 minutes. Logic lifted from atari code. + * Algorithm is to wait for the 10ms register to change, and then to + * wait a short while, and then set it. + */ + +int bvme6000_set_clock_mmss (unsigned long nowtime) +{ + int retval = 0; + short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60; + unsigned char rtc_minutes, rtc_tenms; + volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; + unsigned char msr = rtc->msr & 0xc0; + unsigned long flags; + volatile int i; + + rtc->msr = 0; /* Ensure clock accessible */ + rtc_minutes = bcd2bin (rtc->bcd_min); + + if ((rtc_minutes < real_minutes + ? real_minutes - rtc_minutes + : rtc_minutes - real_minutes) < 30) + { + save_flags(flags); + cli(); + rtc_tenms = rtc->bcd_tenms; + while (rtc_tenms == rtc->bcd_tenms) + ; + for (i = 0; i < 1000; i++) + ; + rtc->bcd_min = bin2bcd(real_minutes); + rtc->bcd_sec = bin2bcd(real_seconds); + restore_flags(flags); + } + else + retval = -1; + + rtc->msr = msr; + + return retval; +} + + +int bvme6000_keyb_init (void) +{ + return 0; +} + +/*------------------- Serial console stuff ------------------------*/ + +static void bvme_scc_write(struct console *co, const char *str, unsigned cnt); + + +void bvme6000_init_console_port (struct console *co, int cflag) +{ + co->write = bvme_scc_write; +} + + +static void scc_delay (void) +{ + int n; + char i; + + for (n = 0; n < 20; n++) + i = *(volatile char *)0; +} + +static void scc_write (char ch) +{ + volatile char *p = (volatile char *)BVME_SCC_A_ADDR; + + do { + scc_delay(); + } + while (!(*p & 4)); + scc_delay(); + *p = 8; + scc_delay(); + *p = ch; +} + + +static void bvme_scc_write (struct console *co, const char *str, unsigned count) +{ + unsigned long flags; + + save_flags(flags); + cli(); + + while (count--) + { + if (*str == '\n') + scc_write ('\r'); + scc_write (*str++); + } + restore_flags(flags); +} + diff --git a/arch/m68k/bvme6000/rtc.c b/arch/m68k/bvme6000/rtc.c new file mode 100644 index 000000000..ca9f677f8 --- /dev/null +++ b/arch/m68k/bvme6000/rtc.c @@ -0,0 +1,175 @@ +/* + * Real Time Clock interface for Linux on the BVME6000 + * + * Based on the PC driver by Paul Gortmaker. + */ + +#define RTC_VERSION "1.00" + +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/miscdevice.h> +#include <linux/malloc.h> +#include <linux/ioport.h> +#include <linux/fcntl.h> +#include <linux/init.h> +#include <linux/poll.h> +#include <linux/mc146818rtc.h> /* For struct rtc_time and ioctls, etc */ +#include <asm/bvme6000hw.h> + +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/system.h> +#include <asm/setup.h> + +/* + * We sponge a minor off of the misc major. No need slurping + * up another valuable major dev number for this. If you add + * an ioctl, make sure you don't conflict with SPARC's RTC + * ioctls. + */ + +#define BCD2BIN(val) (((val)&15) + ((val)>>4)*10) +#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10) + +static unsigned char days_in_mo[] = +{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +static char rtc_status = 0; + +static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; + unsigned char msr; + unsigned long flags; + struct rtc_time wtime; + + switch (cmd) { + case RTC_RD_TIME: /* Read the time/date from RTC */ + { + save_flags(flags); + cli(); + /* Ensure clock and real-time-mode-register are accessible */ + msr = rtc->msr & 0xc0; + rtc->msr = 0x40; + do { + wtime.tm_sec = BCD2BIN(rtc->bcd_sec); + wtime.tm_min = BCD2BIN(rtc->bcd_min); + wtime.tm_hour = BCD2BIN(rtc->bcd_hr); + wtime.tm_mday = BCD2BIN(rtc->bcd_dom); + wtime.tm_mon = BCD2BIN(rtc->bcd_mth)-1; + wtime.tm_year = BCD2BIN(rtc->bcd_year); + if (wtime.tm_year < 70) + wtime.tm_year += 100; + wtime.tm_wday = BCD2BIN(rtc->bcd_dow)-1; + } while (wtime.tm_sec != BCD2BIN(rtc->bcd_sec)); + rtc->msr = msr; + restore_flags(flags); + return copy_to_user((void *)arg, &wtime, sizeof wtime) ? + -EFAULT : 0; + } + case RTC_SET_TIME: /* Set the RTC */ + { + unsigned char leap_yr; + struct rtc_time rtc_tm; + + if (!suser()) + return -EACCES; + + if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, + sizeof(struct rtc_time))) + return -EFAULT; + + leap_yr = ((!(rtc_tm.tm_year % 4) && (rtc_tm.tm_year % 100)) || !(rtc_tm.tm_year % 400)); + + if ((rtc_tm.tm_mon > 12) || (rtc_tm.tm_mday == 0)) + return -EINVAL; + + if (rtc_tm.tm_mday > (days_in_mo[rtc_tm.tm_mon] + ((rtc_tm.tm_mon == 2) && leap_yr))) + return -EINVAL; + + if ((rtc_tm.tm_hour >= 24) || (rtc_tm.tm_min >= 60) || (rtc_tm.tm_sec >= 60)) + return -EINVAL; + + save_flags(flags); + cli(); + /* Ensure clock and real-time-mode-register are accessible */ + msr = rtc->msr & 0xc0; + rtc->msr = 0x40; + + rtc->t0cr_rtmr = rtc_tm.tm_year%4; + rtc->bcd_tenms = 0; + rtc->bcd_sec = BIN2BCD(rtc_tm.tm_sec); + rtc->bcd_min = BIN2BCD(rtc_tm.tm_min); + rtc->bcd_hr = BIN2BCD(rtc_tm.tm_hour); + rtc->bcd_dom = BIN2BCD(rtc_tm.tm_mday); + rtc->bcd_mth = BIN2BCD(rtc_tm.tm_mon + 1); + rtc->bcd_year = BIN2BCD(rtc_tm.tm_year%100); + if (rtc_tm.tm_wday >= 0) + rtc->bcd_dow = BIN2BCD(rtc_tm.tm_wday+1); + rtc->t0cr_rtmr = rtc_tm.tm_year%4 | 0x08; + + rtc->msr = msr; + restore_flags(flags); + return 0; + } + default: + return -EINVAL; + } +} + +/* + * We enforce only one user at a time here with the open/close. + * Also clear the previous interrupt data on an open, and clean + * up things on a close. + */ + +static int rtc_open(struct inode *inode, struct file *file) +{ + if(rtc_status) + return -EBUSY; + + rtc_status = 1; + return 0; +} + +static int rtc_release(struct inode *inode, struct file *file) +{ + rtc_status = 0; + return 0; +} + +/* + * The various file operations we support. + */ + +static struct file_operations rtc_fops = { + NULL, + NULL, + NULL, /* No write */ + NULL, /* No readdir */ + NULL, + rtc_ioctl, + NULL, /* No mmap */ + rtc_open, + rtc_release +}; + +static struct miscdevice rtc_dev= +{ + RTC_MINOR, + "rtc", + &rtc_fops +}; + +__initfunc(int rtc_DP8570A_init(void)) +{ + if (!MACH_IS_BVME6000) + return -ENODEV; + + printk(KERN_INFO "DP8570A Real Time Clock Driver v%s\n", RTC_VERSION); + misc_register(&rtc_dev); + return 0; +} + diff --git a/arch/m68k/config.in b/arch/m68k/config.in index 8ad01e60b..33164f7bc 100644 --- a/arch/m68k/config.in +++ b/arch/m68k/config.in @@ -19,7 +19,7 @@ fi endmenu mainmenu_option next_comment -comment 'Platform dependant setup' +comment 'Platform dependent setup' bool 'Amiga support' CONFIG_AMIGA bool 'Atari support' CONFIG_ATARI @@ -30,13 +30,19 @@ if [ "$CONFIG_ATARI" = "y" ]; then fi fi bool 'Macintosh support' CONFIG_MAC +if [ "$CONFIG_MAC" = "y" ]; then + define_bool CONFIG_NUBUS y +fi bool 'Apollo support' CONFIG_APOLLO bool 'VME (Motorola and BVM) support' CONFIG_VME if [ "$CONFIG_VME" = "y" ]; then bool 'MVME162, 166 and 167 support' CONFIG_MVME16x -# bool 'BVME4000 and BVME6000 support' CONFIG_BVME6000 + bool 'BVME4000 and BVME6000 support' CONFIG_BVME6000 +fi +bool 'HP9000/300 support' CONFIG_HP300 +if [ "$CONFIG_HP300" = "y" ]; then + bool 'DIO bus support' CONFIG_DIO fi - if [ "$CONFIG_PCI" = "y" ]; then bool 'Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC fi @@ -54,9 +60,15 @@ if [ "$CONFIG_M68020" = "n" -a "$CONFIG_M68030" = "n" ]; then bool 'Use 68060 specific optimizations' CONFIG_OPTIMIZE_060 fi fi +if [ "$CONFIG_VME" = "y" -a "$CONFIG_M68060" = "y" ]; then + define_bool CONFIG_060_WRITETHROUGH y +fi bool 'Advanced processor options' CONFIG_ADVANCED_CPU if [ "$CONFIG_ADVANCED_CPU" = "y" ]; then bool 'Use read-modify-write instructions' CONFIG_RMW_INSNS + if [ "$CONFIG_M68060" = "y" -a "$CONFIG_VME" = "n" ]; then + bool 'Use write-through caching for 68060 supervisor accesses' CONFIG_060_WRITETHROUGH + fi fi endmenu @@ -72,12 +84,10 @@ tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC if [ "$CONFIG_AMIGA" = "y" ]; then - bool 'Amiga AutoConfig Identification' CONFIG_ZORRO -# bool 'Amiga GSP (TMS340x0) support' CONFIG_AMIGA_GSP -# if [ "$CONFIG_AMIGA_GSP" = "y" ]; then -# bool 'DMI Resolver support' CONFIG_GSP_RESOLVER -# bool 'A2410 support' CONFIG_GSP_A2410 -# fi + bool 'Amiga Zorro (AutoConfig) bus support' CONFIG_ZORRO + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool 'Amiga 1200/600 PCMCIA support' CONFIG_AMIGA_PCMCIA + fi fi if [ "$CONFIG_ATARI" = "y" ]; then bool 'Support for ST-RAM as swap space' CONFIG_STRAM_SWAP @@ -85,73 +95,17 @@ if [ "$CONFIG_ATARI" = "y" ]; then fi if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" ]; then bool 'Use power LED as a heartbeat' CONFIG_HEARTBEAT -fi -endmenu - -# -# Block device driver configuration -# -mainmenu_option next_comment -comment 'Floppy, IDE, and other block devices' - -if [ "$CONFIG_AMIGA" = "y" ]; then - tristate 'Amiga floppy support' CONFIG_AMIGA_FLOPPY -fi -if [ "$CONFIG_ATARI" = "y" ]; then - tristate 'Atari floppy support' CONFIG_ATARI_FLOPPY -fi -if [ "$CONFIG_MAC" = "y" ]; then - tristate 'Macintosh IWM floppy support' CONFIG_MAC_FLOPPY -fi -#Normal floppy disk support' CONFIG_BLK_DEV_FD - -tristate 'Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support' CONFIG_BLK_DEV_IDE -if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then - dep_tristate ' Include IDE/ATA-2 DISK support' CONFIG_BLK_DEV_IDEDISK $CONFIG_BLK_DEV_IDE - dep_tristate ' Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD $CONFIG_BLK_DEV_IDE - dep_tristate ' Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE $CONFIG_BLK_DEV_IDE - dep_tristate ' Include IDE/ATAPI FLOPPY support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_BLK_DEV_IDE - dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE - if [ "$CONFIG_AMIGA" = "y" ]; then - bool ' Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool ' Buddha/Catweasel IDE interface support' CONFIG_BLK_DEV_BUDDHA - bool ' Amiga IDE Doubler support' CONFIG_BLK_DEV_IDEDOUBLER $CONFIG_BLK_DEV_GAYLE - fi - fi - if [ "$CONFIG_ATARI" = "y" ]; then - bool ' Falcon IDE interface support' CONFIG_BLK_DEV_FALCON_IDE - fi -fi -if [ "$CONFIG_AMIGA" = "y" ]; then - tristate 'Amiga Zorro II ramdisk support' CONFIG_AMIGA_Z2RAM -fi -if [ "$CONFIG_ATARI" = "y" ]; then - tristate 'Atari ACSI support' CONFIG_ATARI_ACSI - if [ "$CONFIG_ATARI_ACSI" != "n" ]; then - comment 'Some devices (e.g. CD jukebox) support multiple LUNs' - bool 'Probe all LUNs on each ACSI device' CONFIG_ACSI_MULTI_LUN - dep_tristate 'Atari SLM laser printer support' CONFIG_ATARI_SLM $CONFIG_ATARI_ACSI +else + if [ "$CONFIG_HP300" = "y" ]; then +# We have a dedicated heartbeat LED. :-) + define_bool CONFIG_HEARTBEAT y fi fi - -comment 'Additional Block Devices' - -tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP -bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD -if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then - tristate ' Linear (append) mode' CONFIG_MD_LINEAR - tristate ' RAID-0 (striping) mode' CONFIG_MD_STRIPED -fi -if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_STRIPED" = "y" ]; then - bool ' Boot support (linear, striped)' CONFIG_MD_BOOT -fi -tristate 'RAM disk support' CONFIG_BLK_DEV_RAM -if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then - bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD -fi +bool '/proc/hardware support' CONFIG_PROC_HARDWARE endmenu +source drivers/block/Config.in + if [ "$CONFIG_NET" = "y" ]; then source net/Config.in fi @@ -185,26 +139,33 @@ comment 'SCSI low-level drivers' if [ "$CONFIG_AMIGA" = "y" ]; then tristate 'A3000 WD33C93A support' CONFIG_A3000_SCSI + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool 'A4000T SCSI support' CONFIG_A4000T_SCSI + fi +fi +if [ "$CONFIG_ZORRO" = "y" ]; then tristate 'A2091 WD33C93A support' CONFIG_A2091_SCSI tristate 'GVP Series II WD33C93A support' CONFIG_GVP11_SCSI bool 'CyberStorm SCSI support' CONFIG_CYBERSTORM_SCSI - bool 'CyberStorm SCSI Mk II support' CONFIG_CYBERSTORMII_SCSI + bool 'CyberStorm Mk II SCSI support' CONFIG_CYBERSTORMII_SCSI bool 'Blizzard 2060 SCSI support' CONFIG_BLZ2060_SCSI bool 'Blizzard 1230IV/1260 SCSI support' CONFIG_BLZ1230_SCSI bool 'Fastlane SCSI support' CONFIG_FASTLANE_SCSI if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool 'A4000T SCSI support' CONFIG_A4000T_SCSI bool 'A4091 SCSI support' CONFIG_A4091_SCSI bool 'WarpEngine SCSI support' CONFIG_WARPENGINE_SCSI -# bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI + bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI # bool 'GVP Turbo 040/060 SCSI support' CONFIG_GVP_TURBO_SCSI fi fi if [ "$CONFIG_ATARI" = "y" ]; then dep_tristate 'Atari native SCSI support' CONFIG_ATARI_SCSI $CONFIG_SCSI - bool 'Long delays for Toshiba CD-ROMs' CONFIG_ATARI_SCSI_TOSHIBA_DELAY - if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_HADES" = "y" ]; then - bool 'Hades SCSI DMA emulator (EXPERIMENTAL)' CONFIG_TT_DMA_EMUL + if [ "$CONFIG_ATARI_SCSI" != "n" ]; then + bool ' Long delays for Toshiba CD-ROMs' CONFIG_ATARI_SCSI_TOSHIBA_DELAY + bool ' Reset SCSI-devices at boottime' CONFIG_ATARI_SCSI_RESET_BOOT + if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_HADES" = "y" ]; then + bool ' Hades SCSI DMA emulator (EXPERIMENTAL)' CONFIG_TT_DMA_EMUL + fi fi fi if [ "$CONFIG_MAC" = "y" ]; then @@ -216,6 +177,10 @@ if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME16x" = "y" ]; then bool 'NCR53C710 SCSI driver for MVME16x' CONFIG_MVME16x_SCSI fi +if [ "$CONFIG_VME" = "y" -a "$CONFIG_BVME6000" = "y" ]; then + bool 'NCR53C710 SCSI driver for BVME6000' CONFIG_BVME6000_SCSI +fi + endmenu fi @@ -243,14 +208,26 @@ if [ ! "$CONFIG_PPP" = "n" ]; then comment 'CCP compressors for PPP are only built as modules.' fi tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER -if [ "$CONFIG_AMIGA" = "y" ]; then +if [ "$CONFIG_ZORRO" = "y" ]; then tristate 'Ariadne support' CONFIG_ARIADNE tristate 'A2065 support' CONFIG_A2065 tristate 'Hydra support' CONFIG_HYDRA fi +if [ "$CONFIG_AMIGA_PCMCIA" = "y" ]; then + tristate 'PCMCIA NE2000 support' CONFIG_APNE +fi if [ "$CONFIG_APOLLO" = "y" ] ; then tristate 'Apollo 3c505 support' CONFIG_APOLLO_ELPLUS fi +if [ "$CONFIG_MAC" = "y" ]; then + bool 'Mac NS 8390 based ethernet cards' CONFIG_DAYNAPORT +fi +if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME16x" = "y" ]; then + bool 'MVME16x Ethernet support' CONFIG_MVME16x_NET +fi +if [ "$CONFIG_VME" = "y" -a "$CONFIG_BVME6000" = "y" ]; then + bool 'BVME6000 Ethernet support' CONFIG_BVME6000_NET +fi if [ "$CONFIG_ATARI" = "y" ]; then tristate 'Atari Lance support' CONFIG_ATARILANCE if [ "$CONFIG_ATARI_ACSI" != "n" ]; then @@ -258,12 +235,6 @@ if [ "$CONFIG_ATARI" = "y" ]; then tristate 'PAMsNet support' CONFIG_ATARI_PAMSNET fi fi -if [ "$CONFIG_MAC" = "y" ]; then - bool 'Mac NS 8390 based ethernet cards' CONFIG_DAYNAPORT -fi -if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME16x" = "y" ]; then - bool 'MVME16x Ethernet support' CONFIG_APRICOT -fi fi endmenu @@ -273,7 +244,10 @@ source fs/Config.in if [ "$CONFIG_VME" = "n" ]; then define_bool CONFIG_FB y + mainmenu_option next_comment + comment 'Console drivers' source drivers/video/Config.in + endmenu fi source fs/nls/Config.in @@ -286,16 +260,17 @@ if [ "$CONFIG_VME" = "n" ]; then if [ "$CONFIG_VT" = "y" ]; then bool 'Support for console on virtual terminal' CONFIG_VT_CONSOLE fi - define_bool CONFIG_FB_CONSOLE y fi if [ "$CONFIG_ATARI" = "y" ]; then define_bool CONFIG_NVRAM y fi -tristate 'Parallel printer support' CONFIG_PRINTER -if [ "$CONFIG_AMIGA" = "y" ]; then +tristate 'Parallel printer support' CONFIG_M68K_PRINTER +if [ "$CONFIG_ZORRO" = "y" ]; then dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_PRINTER +fi +if [ "$CONFIG_AMIGA" = "y" ]; then tristate 'Amiga mouse support' CONFIG_AMIGAMOUSE fi if [ "$CONFIG_ATARI" = "y" ]; then @@ -317,26 +292,39 @@ if [ "$CONFIG_ATARI" = "y" ]; then fi if [ "$CONFIG_AMIGA" = "y" ]; then tristate 'Amiga builtin serial support' CONFIG_AMIGA_BUILTIN_SERIAL + bool 'Hisoft Whippet PCMCIA serial support' CONFIG_WHIPPET +fi +if [ "$CONFIG_ZORRO" = "y" ]; then tristate 'GVP IO-Extender support' CONFIG_GVPIOEXT dep_tristate 'GVP IO-Extender parallel printer support' CONFIG_GVPIOEXT_LP $CONFIG_GVPIOEXT dep_tristate 'GVP IO-Extender PLIP support' CONFIG_GVPIOEXT_PLIP $CONFIG_GVPIOEXT tristate 'Multiface Card III serial support' CONFIG_MULTIFACE_III_TTY - bool 'Hisoft Whippet PCMCIA serial support' CONFIG_WHIPPET fi -if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" ]; then +if [ "$CONFIG_MAC" = "y" ]; then + bool 'Mac SCC serial support' CONFIG_MAC_SCC +fi +if [ "$CONFIG_HP300" = "y" -a "$CONFIG_DIO" = "y" ]; then + tristate 'HP DCA serial support' CONFIG_HPDCA +fi +if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" -o \ + "$CONFIG_MAC" = "y" -o "$CONFIG_HP300" = "y" ]; then if [ "$CONFIG_ATARI_MFPSER" = "y" -o "$CONFIG_ATARI_SCC" = "y" -o \ - "$CONFIG_ATARI_MIDI" = "y" -o "$CONFIG_AMIGA_BUILTIN_SERIAL" = "y" -o \ - "$CONFIG_GVPIOEXT" = "y" -o "$CONFIG_MULTIFACE_III_TTY" = "y" ]; then + "$CONFIG_ATARI_MIDI" = "y" -o "$CONFIG_MAC_SCC" = "y" -o \ + "$CONFIG_AMIGA_BUILTIN_SERIAL" = "y" -o \ + "$CONFIG_GVPIOEXT" = "y" -o "$CONFIG_MULTIFACE_III_TTY" = "y" -o \ + "$CONFIG_HPDCA" = "y" ]; then bool 'Support for serial port console' CONFIG_SERIAL_CONSOLE fi fi -if [ "$CONFIG_MAC" = "y" ]; then - bool 'Mac SCC serial support' CONFIG_MAC_SCC -fi if [ "$CONFIG_VME" = "y" ]; then define_bool CONFIG_SERIAL_CONSOLE y - bool 'CD2401 support for MVME166/7 serial ports' CONFIG_SERIAL167 - bool 'SCC support for MVME162 serial ports' CONFIG_MVME162_SCC + if [ "$CONFIG_MVME16x" = "y" ]; then + bool 'CD2401 support for MVME166/7 serial ports' CONFIG_SERIAL167 + bool 'SCC support for MVME162 serial ports' CONFIG_MVME162_SCC + fi + if [ "$CONFIG_BVME6000" = "y" ]; then + bool 'SCC support for BVME6000 serial ports' CONFIG_BVME6000_SCC + fi fi if [ "$CONFIG_APOLLO" = "y" ]; then bool 'Support for DN serial port (dummy)' CONFIG_SERIAL @@ -348,9 +336,10 @@ if [ "$CONFIG_WATCHDOG" != "n" ]; then bool ' Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT bool ' Software Watchdog' CONFIG_SOFT_WATCHDOG fi -bool 'Support for user misc device modules' CONFIG_UMISC -if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" ]; then - define_bool CONFIG_ABSTRACT_CONSOLE y +if [ "$CONFIG_VME" = "y" ]; then + define_bool CONFIG_UMISC y +else + bool 'Support for user misc device modules' CONFIG_UMISC fi if [ "$CONFIG_ATARI" = "y" ]; then bool 'Enhanced Real Time Clock Support' CONFIG_RTC @@ -370,10 +359,6 @@ mainmenu_option next_comment comment 'Kernel hacking' #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC -bool 'Kernel profiling support' CONFIG_PROFILE -if [ "$CONFIG_PROFILE" = "y" ]; then - int ' Profile shift count' CONFIG_PROFILE_SHIFT 2 -fi bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ bool 'Remote debugging support' CONFIG_KGDB endmenu diff --git a/arch/m68k/defconfig b/arch/m68k/defconfig index 6ce3991d4..e866b5dd3 100644 --- a/arch/m68k/defconfig +++ b/arch/m68k/defconfig @@ -45,6 +45,9 @@ CONFIG_ZORRO=y # CONFIG_AMIGA_GSP is not set # CONFIG_GSP_RESOLVER is not set # CONFIG_GSP_A2410 is not set +# CONFIG_AMIGA_PCMCIA is not set +# CONFIG_HEARTBEAT is not set +CONFIG_PROC_HARDWARE=y # # Block device driver configuration @@ -133,6 +136,8 @@ CONFIG_GVP11_SCSI=y # CONFIG_A4091_SCSI is not set # CONFIG_WARPENGINE_SCSI is not set CONFIG_ATARI_SCSI=y +# CONFIG_ATARI_SCSI_TOSHIBA_DELAY is not set +# CONFIG_ATARI_SCSI_RESET_BOOT is not set # # Network device support @@ -144,6 +149,7 @@ CONFIG_NETDEVICES=y # CONFIG_ARIADNE is not set # CONFIG_A2065 is not set # CONFIG_HYDRA is not set +# CONFIG_APNE is not set # CONFIG_ATARILANCE is not set # CONFIG_ATARI_BIONET is not set # CONFIG_ATARI_PAMSNET is not set @@ -190,7 +196,7 @@ CONFIG_NLS_CODEPAGE_437=y # CONFIG_VT=y CONFIG_VT_CONSOLE=y -# CONFIG_PRINTER is not set +# CONFIG_M68K_PRINTER is not set CONFIG_AMIGAMOUSE=y CONFIG_ATARIMOUSE=y CONFIG_AMIGA_BUILTIN_SERIAL=y @@ -211,5 +217,4 @@ CONFIG_AMIGA_BUILTIN_SERIAL=y # # Kernel hacking # -# CONFIG_PROFILE is not set CONFIG_SCSI_CONSTANTS=y diff --git a/arch/m68k/fpsp040/res_func.S b/arch/m68k/fpsp040/res_func.S index 9a81bde1d..66e42d749 100644 --- a/arch/m68k/fpsp040/res_func.S +++ b/arch/m68k/fpsp040/res_func.S @@ -1889,7 +1889,7 @@ dp_over: | | Input: a0 points to a normalized number in internal extended format | d0 is the round precision (=1 for sgl; =2 for dbl) -| d1 is the the single precision or double precision +| d1 is the single precision or double precision | denorm threshold | | Output: (In the format for dest_sgl or dest_dbl) diff --git a/arch/m68k/fpsp040/skeleton.S b/arch/m68k/fpsp040/skeleton.S index 719bcc9ce..1e4d0cf72 100644 --- a/arch/m68k/fpsp040/skeleton.S +++ b/arch/m68k/fpsp040/skeleton.S @@ -378,14 +378,12 @@ fpsp_done: beq Lnotkern rte Lnotkern: - tstl SYMBOL_NAME(need_resched) - bne Lmustsched - rte -Lmustsched: SAVE_ALL_INT GET_CURRENT(%d0) - bral SYMBOL_NAME(ret_from_exception) | deliver signals, reschedule etc.. - + tstl %curptr@(LTASK_NEEDRESCHED) + jne SYMBOL_NAME(ret_from_exception) | deliver signals, + | reschedule etc.. + RESTORE_ALL | | mem_write --- write to user or supervisor address space diff --git a/arch/m68k/fpsp040/slogn.S b/arch/m68k/fpsp040/slogn.S index b660acd0d..20c5bae9f 100644 --- a/arch/m68k/fpsp040/slogn.S +++ b/arch/m68k/fpsp040/slogn.S @@ -17,7 +17,7 @@ | result is provably monotonic in double precision. | | Speed: The program slogn takes approximately 190 cycles for input -| argument X such that |X-1| >= 1/16, which is the the usual +| argument X such that |X-1| >= 1/16, which is the usual | situation. For those arguments, slognp1 takes approximately | 210 cycles. For the less common arguments, the program will | run no worse than 10% slower. diff --git a/arch/m68k/fpsp040/ssin.S b/arch/m68k/fpsp040/ssin.S index 978941f4e..96e0e7141 100644 --- a/arch/m68k/fpsp040/ssin.S +++ b/arch/m68k/fpsp040/ssin.S @@ -21,7 +21,7 @@ | result is provably monotonic in double precision. | | Speed: The programs sSIN and sCOS take approximately 150 cycles for -| input argument X such that |X| < 15Pi, which is the the usual +| input argument X such that |X| < 15Pi, which is the usual | situation. The speed for sSINCOS is approximately 190 cycles. | | Algorithm: diff --git a/arch/m68k/fpsp040/stan.S b/arch/m68k/fpsp040/stan.S index b7a880a2a..6bd2dda60 100644 --- a/arch/m68k/fpsp040/stan.S +++ b/arch/m68k/fpsp040/stan.S @@ -16,7 +16,7 @@ | result is provably monotonic in double precision. | | Speed: The program sTAN takes approximately 170 cycles for -| input argument X such that |X| < 15Pi, which is the the usual +| input argument X such that |X| < 15Pi, which is the usual | situation. | | Algorithm: diff --git a/arch/m68k/fpsp040/sto_res.S b/arch/m68k/fpsp040/sto_res.S index 634b10855..6be6dd5ac 100644 --- a/arch/m68k/fpsp040/sto_res.S +++ b/arch/m68k/fpsp040/sto_res.S @@ -3,7 +3,7 @@ | | Takes the result and puts it in where the user expects it. | Library functions return result in fp0. If fp0 is not the -| users destination register then fp0 is moved to the the +| users destination register then fp0 is moved to the | correct floating-point destination register. fp0 and fp1 | are then restored to the original contents. | diff --git a/arch/m68k/hp300/Makefile b/arch/m68k/hp300/Makefile new file mode 100644 index 000000000..a59cede94 --- /dev/null +++ b/arch/m68k/hp300/Makefile @@ -0,0 +1,13 @@ +# +# Makefile for Linux arch/m68k/hp300 source directory +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +O_TARGET := hp300.o +O_OBJS := ksyms.o config.o ints.o time.o reboot.o hil.o + +include $(TOPDIR)/Rules.make diff --git a/arch/m68k/hp300/README.hp300 b/arch/m68k/hp300/README.hp300 new file mode 100644 index 000000000..47073fbd4 --- /dev/null +++ b/arch/m68k/hp300/README.hp300 @@ -0,0 +1,14 @@ +HP300 notes +----------- + +The Linux/HP web page is at <http://www.tazenda.demon.co.uk/phil/linux-hp/> + +Currently only 9000/340 machines have been tested. Any amount of RAM should +work now but I've only tried 16MB and 12MB. + +The serial console is probably broken at the moment but the Topcat/HIL keyboard +combination seems to work for me. Your mileage may vary. + +The LANCE driver works after a fashion but only if you reset the chip before +every packet. This doesn't make for very speedy operation. + diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c new file mode 100644 index 000000000..065430ca5 --- /dev/null +++ b/arch/m68k/hp300/config.c @@ -0,0 +1,78 @@ +/* + * linux/arch/m68k/hp300/config.c + * + * Copyright (C) 1998 Philip Blundell <philb@gnu.org> + * + * This file contains the HP300-specific initialisation code. It gets + * called by setup.c. + */ + +#include <linux/config.h> +#include <linux/types.h> +#include <linux/mm.h> +#include <linux/kd.h> +#include <linux/tty.h> +#include <linux/console.h> +#include <linux/interrupt.h> +#include <linux/init.h> +#include <asm/machdep.h> +#include <asm/blinken.h> +#include <asm/io.h> /* readb() and writeb() */ +#include <asm/hwtest.h> /* hwreg_present() */ + +#include "ints.h" +#include "time.h" + +extern void hp300_reset(void); +extern void hp300_hil_init(void); + +#ifdef CONFIG_HEARTBEAT +static void hp300_pulse(int x) +{ + if (x) + blinken_leds(0xfe); + else + blinken_leds(0xff); +} +#endif + +static int hp300_kbdrate(struct kbd_repeat *k) +{ + return 0; +} + +static void hp300_kbd_leds(unsigned int leds) +{ +} + +__initfunc(void config_hp300(void)) +{ + mach_sched_init = hp300_sched_init; + mach_keyb_init = hp300_hil_init; + mach_kbdrate = hp300_kbdrate; + mach_kbd_leds = hp300_kbd_leds; + mach_init_IRQ = hp300_init_IRQ; + mach_request_irq = hp300_request_irq; + mach_free_irq = hp300_free_irq; +#if 0 + mach_get_model = hp300_get_model; + mach_get_irq_list = hp300_get_irq_list; +#endif + mach_gettimeoffset = hp300_gettimeoffset; +#if 0 + mach_gettod = hp300_gettod; +#endif + mach_reset = hp300_reset; +#ifdef CONFIG_HEARTBEAT + mach_heartbeat = hp300_pulse; +#endif +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; +#endif + mach_max_dma_address = 0xffffffff; +} + +/* for "kbd-reset" cmdline param */ +__initfunc(void kbd_reset_setup(char *str, int *ints)) +{ +} diff --git a/arch/m68k/hp300/hil.c b/arch/m68k/hp300/hil.c new file mode 100644 index 000000000..76d45b4d1 --- /dev/null +++ b/arch/m68k/hp300/hil.c @@ -0,0 +1,250 @@ +/* + * linux/arch/m68k/hp300/hil.c + * + * Copyright (C) 1998 Philip Blundell <philb@gnu.org> + * + * HP300 Human Interface Loop driver. This handles the keyboard and mouse. + */ + +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/init.h> +#include <linux/keyboard.h> +#include <linux/kbd_ll.h> +#include <asm/io.h> +#include <asm/hwtest.h> +#include <asm/ptrace.h> +#include <asm/irq.h> +#include <asm/system.h> + +#define HILBASE 0xf0428000 +#define HIL_DATA 0x1 +#define HIL_CMD 0x3 + +#define HIL_BUSY 0x02 +#define HIL_DATA_RDY 0x01 + +#define hil_busy() (readb(HILBASE + HIL_CMD) & HIL_BUSY) +#define hil_data_available() (readb(HILBASE + HIL_CMD) & HIL_DATA_RDY) +#define hil_status() (readb(HILBASE + HIL_CMD)) +#define hil_command(x) do { writeb((x), HILBASE + HIL_CMD); } while (0) +#define hil_read_data() (readb(HILBASE + HIL_DATA)) +#define hil_write_data(x) do { writeb((x), HILBASE + HIL_DATA); } while (0) + +#define HIL_SETARD 0xA0 /* set auto-repeat delay */ +#define HIL_SETARR 0xA2 /* set auto-repeat rate */ +#define HIL_SETTONE 0xA3 /* set tone generator */ +#define HIL_CNMT 0xB2 /* clear nmi */ +#define HIL_INTON 0x5C /* Turn on interrupts. */ +#define HIL_INTOFF 0x5D /* Turn off interrupts. */ +#define HIL_TRIGGER 0xC5 /* trigger command */ +#define HIL_STARTCMD 0xE0 /* start loop command */ +#define HIL_TIMEOUT 0xFE /* timeout */ +#define HIL_READTIME 0x13 /* Read real time register */ + +#define HIL_READBUSY 0x02 /* internal "busy" register */ +#define HIL_READKBDLANG 0x12 /* read keyboard language code */ +#define HIL_READKBDSADR 0xF9 +#define HIL_WRITEKBDSADR 0xE9 +#define HIL_READLPSTAT 0xFA +#define HIL_WRITELPSTAT 0xEA +#define HIL_READLPCTRL 0xFB +#define HIL_WRITELPCTRL 0xEB + +#define HIL_IRQ 1 + +static u_short hp_plain_map[NR_KEYS] __initdata = { + 0xf200, 0xf01b, 0xf20e, 0xf700, 0xf700, 0xf700, 0xf702, 0xf036, + 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf009, + 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, + 0xfb62, 0xfb76, 0xf063, 0xfb78, 0xfb7a, 0xf702, 0xfb61, 0xfb73, + 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b, + 0xfb68, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb61, 0xfb63, 0xfb76, + 0xfb75, 0xfb79, 0xfb74, 0xfb72, 0xfb65, 0xfb77, 0xfb71, 0xf200, + 0xf037, 0xf036, 0xf035, 0xf034, 0xf033, 0xf032, 0xf031, 0xf104, + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114, + 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200, + 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf038, 0xf039, 0xf030, 0xf200, 0xf200, 0xf008, 0xf200, 0xf200, + 0xfb69, 0xfb6f, 0xfb70, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307, + 0xfb6a, 0xfb6b, 0xfb6c, 0xf305, 0xf306, 0xf00d, 0xf302, 0xf303, + 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfb6e, 0xf020, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200 +}; + +static u_short hp_shift_map[NR_KEYS] __initdata = { + 0xf200, 0xf01b, 0xf20e, 0xf700, 0xf700, 0xf700, 0xf002, 0xf036, + 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf009, + 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, + 0xfb62, 0xfb76, 0xf063, 0xfb78, 0xfb7a, 0xf702, 0xfb61, 0xfb73, + 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b, + 0xfb68, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb61, 0xfb63, 0xfb76, + 0xfb75, 0xfb79, 0xfb74, 0xfb72, 0xfb65, 0xfb77, 0xfb71, 0xf200, + 0xf037, 0xf036, 0xf035, 0xf034, 0xf033, 0xf032, 0xf031, 0xf104, + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114, + 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200, + 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf038, 0xf039, 0xf030, 0xf200, 0xf200, 0xf008, 0xf200, 0xf200, + 0xfb69, 0xfb6f, 0xfb70, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307, + 0xfb6a, 0xfb6b, 0xfb6c, 0xf305, 0xf306, 0xf00d, 0xf302, 0xf303, + 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfb6e, 0xf020, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200 +}; + +static u_short hp_ctrl_map[NR_KEYS] __initdata = { + 0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e, + 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200, + 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, + 0xf00f, 0xf010, 0xf003, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013, + 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200, + 0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016, + 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf07f, 0xf700, 0xf200, + 0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114, + 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200, + 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf1ff, 0xf202, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307, + 0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303, + 0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200 +}; + +struct { + unsigned char s, c; + int valid; +} hil_last; + +#define hil_getlast(s,c) do { s = hil_last.s; c = hil_last.c; hil_last.valid = 0; } while (0) + +struct { + unsigned char data[16]; + unsigned int ptr; +} poll; + +unsigned char curdev = 0; + +static void poll_finished(void) +{ + switch (poll.data[0]) + { + case 0x40: + { + unsigned char scode = (poll.data[1] >> 1) | ((poll.data[1] & 1)?0x80:0); +#if 0 + if (scode & 0x80) + printk("[%02x]", scode & 0x7f); +#endif + handle_scancode(scode); + } + break; + } + curdev = 0; +} + +static inline void handle_status(unsigned char s, unsigned char c) +{ + if (c & 0x8) { + /* End of block */ + if (c & 0x10) + poll_finished(); + } else { + if (c & 0x10) { + if (curdev) + poll_finished(); /* just in case */ + curdev = c & 7; + poll.ptr = 0; + } + } +} + +static inline void handle_data(unsigned char s, unsigned char c) +{ + if (curdev) + poll.data[poll.ptr++] = c; +} + +/* + * Handle HIL interrupts. + */ + +static void hil_interrupt(int irq, void *handle, struct pt_regs *regs) +{ + unsigned char s, c; + s = hil_status(); c = hil_read_data(); + switch (s >> 4) + { + case 0x5: + handle_status(s, c); + break; + case 0x6: + handle_data(s, c); + break; + case 0x4: + hil_last.s = s; + hil_last.c = c; + mb(); + hil_last.valid = 1; + break; + } +} + +/* + * Send a command to the HIL + */ + +static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len) +{ + unsigned long flags; + save_flags(flags); cli(); + while (hil_busy()); + hil_command(cmd); + while (len--) { + while (hil_busy()); + hil_write_data(*(data++)); + } + restore_flags(flags); +} + +/* + * Initialise HIL. + */ + +__initfunc(void hp300_hil_init(void)) +{ + unsigned char s, c, kbid; + unsigned int n = 0; + + memcpy(key_maps[0], hp_plain_map, sizeof(plain_map)); + memcpy(key_maps[1], hp_shift_map, sizeof(plain_map)); + memcpy(key_maps[4], hp_ctrl_map, sizeof(plain_map)); + + if (!hwreg_present((void *)(HILBASE + HIL_DATA))) + return; /* maybe this can happen */ + + request_irq(HIL_IRQ, hil_interrupt, 0, "HIL", NULL); + + /* Turn on interrupts */ + hil_do(HIL_INTON, NULL, 0); + + /* Look for keyboards */ + hil_do(HIL_READKBDSADR, NULL, 0); + while (!hil_last.valid) { + if (n++ > 1000) { + printk("HIL: timed out, assuming no keyboard present.\n"); + return; + } + mb(); + } + hil_getlast(s, c); + if (c == 0) { + printk("HIL: no keyboard present.\n"); + return; + } + for (kbid = 0; (kbid < 8) && ((c & (1<<kbid)) == 0); kbid++); + printk("HIL: keyboard found at id %d\n", kbid); + /* set it to raw mode */ + c = 0; + hil_do(HIL_WRITEKBDSADR, &c, 1); +} diff --git a/arch/m68k/hp300/ints.c b/arch/m68k/hp300/ints.c new file mode 100644 index 000000000..9f1a1a6a5 --- /dev/null +++ b/arch/m68k/hp300/ints.c @@ -0,0 +1,47 @@ +/* + * linux/arch/m68k/hp300/ints.c + * + * Copyright (C) 1998 Philip Blundell <philb@gnu.org> + * + * This file contains the HP300-specific interrupt handling. There + * isn't much here -- we only use the autovector interrupts and at the + * moment everything difficult is handled by the generic code. + */ + +#include <asm/ptrace.h> +#include <linux/types.h> +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/kernel_stat.h> +#include <linux/interrupt.h> +#include <asm/machdep.h> +#include <asm/irq.h> +#include <asm/io.h> +#include <asm/system.h> +#include <asm/traps.h> +#include "ints.h" + +static void hp300_nmi_handler(int irq, void *dev_id, struct pt_regs *fp) +{ + extern void hp300_reset(void); + printk("RESET pressed - self destruct sequence initiated.\n"); + hp300_reset(); +} + +int hp300_request_irq(unsigned int irq, + void (*handler) (int, void *, struct pt_regs *), + unsigned long flags, const char *devname, void *dev_id) +{ + return sys_request_irq(irq, handler, flags, devname, dev_id); +} + +void hp300_free_irq(unsigned int irq, void *dev_id) +{ + sys_free_irq(irq, dev_id); +} + +__initfunc(void hp300_init_IRQ(void)) +{ + /* IPL6 - NMI (keyboard reset) */ + sys_request_irq(7, hp300_nmi_handler, IRQ_FLG_STD, "NMI", hp300_nmi_handler); +} diff --git a/arch/m68k/hp300/ints.h b/arch/m68k/hp300/ints.h new file mode 100644 index 000000000..38b62b61b --- /dev/null +++ b/arch/m68k/hp300/ints.h @@ -0,0 +1,6 @@ +extern void hp300_init_IRQ(void); +extern void (*hp300_handlers[8])(int, void *, struct pt_regs *); +extern void hp300_free_irq(unsigned int irq, void *dev_id); +extern int hp300_request_irq(unsigned int irq, + void (*handler) (int, void *, struct pt_regs *), + unsigned long flags, const char *devname, void *dev_id); diff --git a/arch/m68k/hp300/ksyms.c b/arch/m68k/hp300/ksyms.c new file mode 100644 index 000000000..820283076 --- /dev/null +++ b/arch/m68k/hp300/ksyms.c @@ -0,0 +1,9 @@ +/* + * linux/arch/m68k/hp300/ksyms.c + * + * Copyright (C) 1998 Philip Blundell <philb@gnu.org> + * + * This file contains the HP300-specific kernel symbols. None yet. :-) + */ + +#include <linux/module.h> diff --git a/arch/m68k/hp300/reboot.S b/arch/m68k/hp300/reboot.S new file mode 100644 index 000000000..aaecdbda2 --- /dev/null +++ b/arch/m68k/hp300/reboot.S @@ -0,0 +1,35 @@ +/* + * linux/arch/m68k/hp300/reboot.S + * + * Copyright (C) 1998 Philip Blundell <philb@gnu.org> + * + * Do the dirty work of rebooting the machine. Basically we need to undo all the + * good stuff that head.S did when we started up. The caches and MMU must be + * disabled and then we jump back to the PROM. This is a bit gruesome but we put + * a brave face on it. + */ + +/* XXX Doesn't work yet. Not sure why and can't be bothered to fix it at the moment. */ + + .globl hp300_reset +hp300_reset: + .chip 68030 + oriw #0x0700,%sr /* cli() */ + movel hp300_phys_ram_base, %d1 + movel #0, %d0 + movec %d0, %vbr /* reset vector table */ + lea zero, %a0 + lea 1f, %a1 + add %d1, %a0 + add %d1, %a1 + pmove %tc, %a0@ + bclr #7, %a0@ + pmove %a0@, %tc /* goodbye MMU */ + jmp %a1@ +1: movel #0x808, %d0 + movec %d0, %cacr /* cache off */ + moveb #0, 0x1ffff + movel #0x1a4, %a0 + jmp %a0@ + +zero: .quad 0 diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c new file mode 100644 index 000000000..2a60c5621 --- /dev/null +++ b/arch/m68k/hp300/time.c @@ -0,0 +1,62 @@ +/* + * linux/arch/m68k/hp300/time.c + * + * Copyright (C) 1998 Philip Blundell <philb@gnu.org> + * + * This file contains the HP300-specific time handling code. + */ + +#include <asm/ptrace.h> +#include <linux/types.h> +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/kernel_stat.h> +#include <linux/interrupt.h> +#include <asm/machdep.h> +#include <asm/irq.h> +#include <asm/io.h> +#include <asm/system.h> +#include <asm/traps.h> +#include "ints.h" + +/* Clock hardware definitions */ + +#define CLOCKBASE 0xf05f8000 + +#define CLKCR1 0x1 +#define CLKCR2 0x3 +#define CLKCR3 CLKCR1 +#define CLKSR CLKCR2 +#define CLKMSB1 0x5 +#define CLKMSB2 0x9 +#define CLKMSB3 0xD + +unsigned long hp300_gettimeoffset (void) +{ + return 0L; +} + +static void hp300_tick(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long tmp; + void (*vector)(int, void *, struct pt_regs *) = dev_id; + readb(CLOCKBASE + CLKSR); + asm volatile ("movpw %1@(5),%0" : "=r" (tmp) : "a" (CLOCKBASE)); + vector(irq, NULL, regs); +} + +__initfunc(void hp300_sched_init(void (*vector)(int, void *, struct pt_regs *))) +{ + unsigned int intval = (10000 / 4) - 1; + + writeb(0x1, CLOCKBASE + CLKCR2); /* select CR1 */ + writeb(0x1, CLOCKBASE + CLKCR1); /* reset */ + + asm volatile(" movpw %0,%1@(5)" : : "d" (intval), "a" (CLOCKBASE)); + + sys_request_irq(6, hp300_tick, IRQ_FLG_STD, "timer tick", vector); + + writeb(0x1, CLOCKBASE + CLKCR2); /* select CR1 */ + writeb(0x40, CLOCKBASE + CLKCR1); /* enable irq */ +} + diff --git a/arch/m68k/hp300/time.h b/arch/m68k/hp300/time.h new file mode 100644 index 000000000..a081903ee --- /dev/null +++ b/arch/m68k/hp300/time.h @@ -0,0 +1,4 @@ +extern void hp300_sched_init(void (*vector)(int, void *, struct pt_regs *)); +extern unsigned long hp300_gettimeoffset (void); + + diff --git a/arch/m68k/ifpsp060/iskeleton.S b/arch/m68k/ifpsp060/iskeleton.S index 629208409..cde14e120 100644 --- a/arch/m68k/ifpsp060/iskeleton.S +++ b/arch/m68k/ifpsp060/iskeleton.S @@ -72,14 +72,12 @@ _060_isp_done: beq Lnotkern rte Lnotkern: - tstl SYMBOL_NAME(need_resched) - bne Lmustsched - rte -Lmustsched: SAVE_ALL_INT - GET_CURRENT(%d0) - bral SYMBOL_NAME(ret_from_exception) | deliver signals, reschedule etc.. + tstl %curptr@(LTASK_NEEDRESCHED) + jne SYMBOL_NAME(ret_from_exception) | deliver signals, + | reschedule etc.. + RESTORE_ALL | | _060_real_chk(): diff --git a/arch/m68k/kernel/bios32.c b/arch/m68k/kernel/bios32.c index a1dc77f33..b1322261a 100644 --- a/arch/m68k/kernel/bios32.c +++ b/arch/m68k/kernel/bios32.c @@ -33,7 +33,6 @@ * been removed in this version. */ -#include <linux/bios32.h> #include <linux/pci.h> #include <linux/malloc.h> #include <linux/mm.h> @@ -49,7 +48,7 @@ #define GB (1024*MB) #define MAJOR_REV 0 -#define MINOR_REV 0 +#define MINOR_REV 1 /* * Base addresses of the PCI memory and I/O areas on the Hades. @@ -264,12 +263,14 @@ __initfunc(static void disable_dev(struct pci_dev *dev)) #define MAX(val1, val2) ( ((val1) > (val2)) ? val1 : val2) -__initfunc(static void layout_dev(struct pci_dev *dev)) +__initfunc(static void layout_dev(struct pci_dev *dev, unsigned long pci_mem_base, + unsigned long pci_io_base)) { struct pci_bus *bus; unsigned short cmd; unsigned int base, mask, size, reg; unsigned int alignto; + int i; /* * Skip video cards for the time being. @@ -283,7 +284,7 @@ __initfunc(static void layout_dev(struct pci_dev *dev)) bus = dev->bus; pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd); - for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) + for (reg = PCI_BASE_ADDRESS_0, i = 0; reg <= PCI_BASE_ADDRESS_5; reg += 4, i++) { /* * Figure out how much space and of what type this @@ -297,6 +298,7 @@ __initfunc(static void layout_dev(struct pci_dev *dev)) if (!base) { /* this base-address register is unused */ + dev->base_address[i] = 0; continue; } @@ -322,6 +324,7 @@ __initfunc(static void layout_dev(struct pci_dev *dev)) io_base = base + size; pcibios_write_config_dword(bus->number, dev->devfn, reg, base | 0x1); + dev->base_address[i] = (pci_io_base + base) | 1; DBG_DEVS(("layout_dev: IO address: %lX\n", base)); } else @@ -369,6 +372,7 @@ __initfunc(static void layout_dev(struct pci_dev *dev)) mem_base = base + size; pcibios_write_config_dword(bus->number, dev->devfn, reg, base); + dev->base_address[i] = pci_mem_base + base; } } @@ -396,7 +400,8 @@ __initfunc(static void layout_dev(struct pci_dev *dev)) bus->number, PCI_SLOT(dev->devfn), dev->vendor, dev->device, dev->class)); } -__initfunc(static void layout_bus(struct pci_bus *bus)) +__initfunc(static void layout_bus(struct pci_bus *bus, unsigned long pci_mem_base, + unsigned long pci_io_base)) { struct pci_dev *dev; @@ -438,7 +443,7 @@ __initfunc(static void layout_bus(struct pci_bus *bus)) for (dev = bus->devices; dev; dev = dev->sibling) { if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) - layout_dev(dev); + layout_dev(dev, pci_mem_base, pci_io_base); } } @@ -507,8 +512,7 @@ int pcibios_present(void) return 0; } -__initfunc(unsigned long pcibios_init(unsigned long mem_start, - unsigned long mem_end)) +__initfunc(void pcibios_init(void)) { printk("Linux/m68k PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV); @@ -516,7 +520,8 @@ __initfunc(unsigned long pcibios_init(unsigned long mem_start, printk("...NOT modifying existing PCI configuration\n"); #endif - return mem_start; + pci_mem_base = 0x80000000; + pci_io_base = 0xB0000000; } /* @@ -555,26 +560,39 @@ __initfunc(static inline void hades_fixup(void)) } } -__initfunc(unsigned long pcibios_fixup(unsigned long mem_start, - unsigned long mem_end)) +__initfunc(void pcibios_fixup(void)) { #if PCI_MODIFY + unsigned long orig_mem_base, orig_io_base; + + orig_mem_base = pci_mem_base; + orig_io_base = pci_io_base; + pci_mem_base = 0; + pci_io_base = 0; + /* * Scan the tree, allocating PCI memory and I/O space. */ - layout_bus(&pci_root); -#endif + layout_bus(&pci_root, orig_mem_base, orig_io_base); - pci_mem_base = 0x80000000; - pci_io_base = 0xB0000000; + pci_mem_base = orig_mem_base; + pci_io_base = orig_io_base; +#endif /* * Now is the time to do all those dirty little deeds... */ hades_fixup(); +} + +__initfunc(void pcibios_fixup_bus(struct pci_bus *bus)) +{ +} - return mem_start; +__initfunc(char *pcibios_setup(char *str)) +{ + return str; } #endif /* CONFIG_PCI */ diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 1c157c26a..eba9842cf 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S @@ -114,7 +114,7 @@ SYMBOL_NAME_LABEL(ret_from_exception) | kernel stack, otherwise stack overflow can occur during | heavy interupt load andw #ALLOWINT,%sr - tstl SYMBOL_NAME(need_resched) + tstl %curptr@(LTASK_NEEDRESCHED) jne SYMBOL_NAME(reschedule) cmpl #SYMBOL_NAME(task),%curptr | task[0] cannot have signals jeq 2f @@ -579,6 +579,14 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_pread) /* 180 */ .long SYMBOL_NAME(sys_pwrite) .long SYMBOL_NAME(sys_lchown); + .long SYMBOL_NAME(sys_getcwd) + .long SYMBOL_NAME(sys_capget) + .long SYMBOL_NAME(sys_capset) /* 185 */ + .long SYMBOL_NAME(sys_sigaltstack) + .long SYMBOL_NAME(sys_sendfile) + .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */ + .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */ + .rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4 .long SYMBOL_NAME(sys_ni_syscall) .endr diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S index 1f3795a7c..e98f39fa8 100644 --- a/arch/m68k/kernel/head.S +++ b/arch/m68k/kernel/head.S @@ -17,6 +17,7 @@ ** 95/11/18 Richard Hirst: Added MVME166 support ** 96/04/26 Guenther Kelleter: fixed identity mapping for Falcon with ** Magnum- and FX-alternate ram +** 98/04/25 Phil Blundell: added HP300 support ** ** This file is subject to the terms and conditions of the GNU General Public ** License. See the file README.legal in the main directory of this archive @@ -73,10 +74,25 @@ #include <asm/pgtable.h> .globl SYMBOL_NAME(kernel_pg_dir), SYMBOL_NAME(kpt) -.globl SYMBOL_NAME(availmem), SYMBOL_NAME(mvme_bdid_ptr) +.globl SYMBOL_NAME(availmem) .globl SYMBOL_NAME(m68k_pgtable_cachemode) .globl SYMBOL_NAME(kernel_pmd_table), SYMBOL_NAME(swapper_pg_dir) +#if defined(CONFIG_MVME16x) +.globl SYMBOL_NAME(mvme_bdid_ptr) +#endif + +/* + * Added m68k_supervisor_cachemode for 68060 boards where some drivers + * need writethrough caching for supervisor accesses. Drivers known to + * be effected are 53c7xx.c and apricot.c (when used on VME boards). + * Richard Hirst. + */ + +#ifdef CONFIG_060_WRITETHROUGH +.globl SYMBOL_NAME(m68k_supervisor_cachemode) +#endif + D6B_0460 = 16 /* indicates 680[46]0 in d6 */ D6B_060 = 17 /* indicates 68060 in d6 */ D6F_040 = 1<<D6B_0460 @@ -146,12 +162,23 @@ TABLENR_16MB = 64 /* same for 16 MB */ #define is_not_amiga(lab) moveq &MACH_AMIGA,%d7; cmpl %d4,%d7; jne lab #define is_not_atari(lab) moveq &MACH_ATARI,%d7; cmpl %d4,%d7; jne lab #define is_not_mvme16x(lab) moveq &MACH_MVME16x,%d7; cmpl %d4,%d7; jne lab +#define is_not_bvme6000(lab) moveq &MACH_BVME6000,%d7; cmpl %d4,%d7; jne lab +#define is_not_hp300(lab) moveq &MACH_HP300,%d7 ; cmpl %d4,%d7; jne lab #define is_040_or_060(lab) btst &D6B_0460,%d6; jne lab #define is_not_040_or_060(lab) btst &D6B_0460,%d6; jeq lab #define is_060(lab) btst &D6B_060,%d6; jne lab #define is_not_060(lab) btst &D6B_060,%d6; jeq lab +/* On the HP300 we use the on-board LEDs for debug output before + the console is running. Writing a 1 bit turns the corresponding LED + _off_ - on the 340 bit 7 is towards the back panel of the machine. */ +#ifdef CONFIG_HP300 +#define leds(x) is_not_hp300(42f) ; moveb #(x),%d7 ; jbsr Lset_leds; 42: +#else +#define leds(x) +#endif + .text ENTRY(_stext) /* @@ -164,6 +191,7 @@ ENTRY(_stext) .long MACH_AMIGA, AMIGA_BOOTI_VERSION .long MACH_ATARI, ATARI_BOOTI_VERSION .long MACH_MVME16x, MVME16x_BOOTI_VERSION + .long MACH_BVME6000, BVME6000_BOOTI_VERSION .long 0 1: jra SYMBOL_NAME(_start) @@ -224,6 +252,22 @@ ENTRY(_start) movew %d6,%d0 movel %d0,%a0@ /* save cache mode for page tables */ + /* + * If this is a 68060 board using drivers with cache coherency + * problems, then supervisor memory accesses need to be write-through + * also; otherwise, we want copyback. + */ + +#if defined(CONFIG_060_WRITETHROUGH) + is_not_060(Lset_norm) + jra 1f +Lset_norm: + move.w #_PAGE_CACHE040,%d0 +1: + lea %pc@(SYMBOL_NAME(m68k_supervisor_cachemode)),%a0 + movel %d0,%a0@ +#endif + /* * raise interrupt level */ @@ -386,7 +430,12 @@ Lnotypetest: movel %a3,%a0 movel %d5,%a1 - addw #_PAGE_GLOBAL040+_PAGE_CACHE040+_PAGE_PRESENT+_PAGE_ACCESSED,%a1 +#if defined(CONFIG_060_WRITETHROUGH) + addw #_PAGE_GLOBAL040+_PAGE_PRESENT+_PAGE_ACCESSED,%a1 + addl m68k_supervisor_cachemode,%a1 +#else + addw #_PAGE_GLOBAL040+_PAGE_CACHE040+_PAGE_PRESENT+_PAGE_ACCESSED,%a1 +#endif movew #(PAGE_TABLE_SIZE*TABLENR_4MB)-1,%d1 movel #PAGESIZE,%d2 1: movel %a1,%a0@+ @@ -424,6 +473,9 @@ Lnotypetest: * of %a2 are forgotten. */ Lnot040: + + leds(0x4) + /* * Do any machine specific page table initializations. */ @@ -615,6 +667,21 @@ Lspata68040: Lnotatari: #endif +#ifdef CONFIG_HP300 + is_not_hp300(Lnothp300) + +/* On the HP300, we map the ROM, INTIO and DIO regions (phys. 0x00xxxxxx) + by mapping 32MB from 0xf0xxxxxx -> 0x00xxxxxx) using an 030 early + termination page descriptor. The ROM mapping is needed because the LEDs + are mapped there too. */ + + movel #_PAGE_NOCACHE030+_PAGE_PRESENT+_PAGE_ACCESSED,%d0 + movel %d0,%a5@(0x78<<2) + +Lnothp300: + +#endif + #if defined(CONFIG_MVME16x) is_not_mvme16x(Lnot16x) @@ -639,6 +706,25 @@ Lnotatari: Lnot16x: #endif +#if defined(CONFIG_BVME6000) + is_not_bvme6000(Lnotbvm) + + /* + * On BVME6000 we have already created kernel page tables for + * 4MB of RAM at address 0, so now need to do a transparent + * mapping of the top of memory space. Make it 0.5GByte for now. + */ + + movel #0xe01f0000,%d2 /* logical address base */ + orw #0xa040,%d2 /* add in magic bits */ + .long 0x4e7b2005 /* movec d2,ittr1 */ + .long 0x4e7b2007 /* movec d2,dttr1 */ + .long 0x4e7b2004 /* movec d2,ittr0 */ + .long 0x4e7b2006 /* movec d2,dttr0 */ + +Lnotbvm: +#endif + /* * Setup a transparent mapping of the physical memory we are executing in. * @@ -647,6 +733,7 @@ Lnot16x: */ Lmapphys: putc('J') + leds(0x8) #ifdef CONFIG_AMIGA is_not_amiga(Lmapphysnotamiga) @@ -853,6 +940,80 @@ Lmapphysnot16x: #endif +#if defined(CONFIG_HP300) + is_not_hp300(Lmapphysnothp300) + +/* + * Physical RAM is at 0xff000000. We want to map the kernel at 0x00000000. + * In order to avoid disaster when we enable the MMU we need to make a + * transparent mapping of the RAM we're executing out of as well. + */ + /* + * save physaddr of phys mem in register a3 + */ + + .chip 68030 + lea %pc@(Lmmu),%a3 + movel %d5,%d0 + andl #0xff000000,%d0 /* logical address base */ + orw #TTR_ENABLE+TTR_CI+TTR_RWM+TTR_FCB2+TTR_FCM1+TTR_FCM0,%d0 + movel %d0,%a3@ + pmove %a3@,%tt0 + /* no limit, 4byte descriptors */ + movel #0x80000002,%a3@ + movel %a5,%a3@(4) + pmove %a3@,%srp + pmove %a3@,%crp + pflusha + /* + * enable,super root enable,4096 byte pages,7 bit root index, + * 7 bit pointer index, 6 bit page table index. + */ + movel #0x82c07760,%a3@ + pmove %a3@,%tc /* enable the MMU */ + jmp 1f +1: + .chip 68k + + /* + * Fix up the custom register to point to the new location of the LEDs. + */ + lea %pc@(Lcustom),%a1 + movel #0xf0000000,%a1@ + + /* + * Energise the FPU and caches. + */ + orl #0x64, 0xf05f400c + +Lmapphysnothp300: + +#endif + +#if defined(CONFIG_BVME6000) + is_not_bvme6000(Lmapphysnotbvm) + /* + * save physaddr of phys mem in register a3 + */ + moveq #'L',%d7 + jbsr Lserial_putc + + .word 0xf4d8 /* CINVA I/D */ + .word 0xf518 /* pflusha */ + .long 0x4e7bd807 /* movec a5,srp */ + .long 0x4e7bd806 /* movec a5,urp */ + movel #(TC_ENABLE+TC_PAGE4K),%d0 + /* + * this value is also ok for the 68060, we don`t use the cache + * mode/protection defaults + */ + .long 0x4e7b0003 /* movec d0,tc (enable the MMU) */ + jra LdoneMMUenable /* branch to continuation of startup */ + +Lmapphysnotbvm: + +#endif + LdoneMMUenable: /* @@ -861,6 +1022,7 @@ LdoneMMUenable: */ putc('M') + leds(0x10) /* * d5 contains physaddr of kernel start @@ -917,6 +1079,7 @@ Lcache68060: /* jump to the kernel start */ putr() + leds(0x55) subl %a6,%a6 /* clear a6 for gdb */ jbsr SYMBOL_NAME(start_kernel) @@ -998,6 +1161,11 @@ LMFP_UDR = 0xfffa2f #endif #endif +#if defined (CONFIG_BVME6000) +BVME_SCC_CTRL_A = 0xffb0000b +BVME_SCC_DATA_A = 0xffb0000f +#endif + /* * Serial port output support. */ @@ -1062,6 +1230,17 @@ Lserial_init: 9: rts +#ifdef CONFIG_HP300 +/* Set LEDs to %d7 */ + .even +Lset_leds: + moveml %a0/%a1,%sp@- + movel %pc@(Lcustom),%a1 + moveb %d7,%a1@(0x1ffff) + moveml %sp@+,%a0/%a1 + rts +#endif + /* * Output character in d7 on serial port. * d7 thrashed. @@ -1073,6 +1252,16 @@ Lserial_putc: jne 2f moveb %d7,%sp@- .long 0x4e4f0020 + jra 9f +2: +#endif +#ifdef CONFIG_BVME6000 + cmpil #MACH_BVME6000,%d4 + jne 2f +1: btst #2,BVME_SCC_CTRL_A + jeq 1b + moveb %d7,BVME_SCC_DATA_A + jra 9f 2: #endif #ifdef CONFIG_AMIGA @@ -1199,5 +1388,11 @@ SYMBOL_NAME_LABEL(availmem) .long 0 SYMBOL_NAME_LABEL(m68k_pgtable_cachemode) .long 0 +#ifdef CONFIG_060_WRITETHROUGH +SYMBOL_NAME_LABEL(m68k_supervisor_cachemode) + .long 0 +#endif +#if defined(CONFIG_MVME16x) SYMBOL_NAME_LABEL(mvme_bdid_ptr) .long 0 +#endif diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index a9109ab0a..20e39f17f 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -31,6 +31,7 @@ #include <linux/errno.h> #include <linux/init.h> +#include <asm/setup.h> #include <asm/system.h> #include <asm/irq.h> #include <asm/traps.h> @@ -212,7 +213,7 @@ static void dummy_free_irq(unsigned int irq, void *dev_id) asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) { - if (vec >= VEC_INT1 && vec <= VEC_INT7) { + if (vec >= VEC_INT1 && vec <= VEC_INT7 && !MACH_IS_BVME6000) { vec -= VEC_SPUR; kstat.irqs[0][vec]++; irq_list[vec].handler(vec, irq_list[vec].dev_id, fp); diff --git a/arch/m68k/kernel/kgdb.c b/arch/m68k/kernel/kgdb.c new file mode 100644 index 000000000..cdbd250cd --- /dev/null +++ b/arch/m68k/kernel/kgdb.c @@ -0,0 +1,1194 @@ +/* + * arch/m68k/kernel/kgdb.c -- Stub for GDB remote debugging protocol + * + * Originally written by Glenn Engel, Lake Stevens Instrument Division + * + * Contributed by HP Systems + * + * Modified for SPARC by Stu Grossman, Cygnus Support. + * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse + * Modified and extended for Linux/68k by Roman Hodek + * + * Send complaints, suggestions etc. to + * <Roman.Hodek@informatik.uni-erlangen.de> + * + * Copyright (C) 1996-97 Roman Hodek + */ + +/* + * kgdb usage notes: + * ----------------- + * + * If you select CONFIG_KGDB in the configuration, the kernel will be built + * with different gccc flags: "-g" is added to get debug infos, and + * "-fomit-frame-pointer" is omitted to make debugging easier. Since the + * resulting kernel will be quite big (approx. > 7 MB), it will be stripped + * before compresion. Such a kernel will behave just as usually, except if + * given a "debug=<device>" command line option. (Only serial devices are + * allowed for <device>, i.e. no printers or the like; possible values are + * machine depedend and are the same as for the usual debug device, the one + * for logging kernel messages.) If that option is given and the device can be + * initialized, the kernel will connect to the remote gdb in trap_init(). The + * serial parameters are fixed to 8N1 and 9600bps, for easyness of + * implementation. + * + * Of course, you need a remote machine a suitable gdb there. I.e., it must + * have support for a m68k-linux target built in. If the remote machine + * doesn't run Linux/68k itself, you have to build a cross gdb. This is done + * by + * ./configure --target=m68k-linux + * in the gdb source directory. Until gdb comes with m68k-linux support by + * default, you have to apply some patches before. The remote debugging + * protocol itself is always built into gdb anyway, so you don't have to take + * special care about it. + * + * To start a debugging session, start that gdb with the debugging kernel + * image (the one with the symbols, vmlinux.debug) named on the command line. + * This file will be used by gdb to get symbol and debugging infos about the + * kernel. Next, select remote debug mode by + * target remote <device> + * where <device> is the name of the serial device over which the debugged + * machine is connected. Maybe you have to adjust the baud rate by + * set remotebaud <rate> + * or also other parameters with stty: + * shell stty ... </dev/... + * If the kernel to debug has already booted, it waited for gdb and now + * connects, and you'll see a breakpoint being reported. If the kernel isn't + * running yet, start it now. The order of gdb and the kernel doesn't matter. + * Another thing worth knowing about in the getting-started phase is how to + * debug the remote protocol itself. This is activated with + * set remotedebug 1 + * gdb will then print out each packet sent or received. You'll also get some + * messages about the gdb stub on the console of the debugged machine. + * + * If all that works, you can use lots of the usual debugging techniques on + * the kernel, e.g. inspecting and changing variables/memory, setting + * breakpoints, single stepping and so on. It's also possible to interrupt the + * debugged kernel by pressing C-c in gdb. Have fun! :-) + * + * The gdb stub is entered (and thus the remote gdb gets control) in the + * following situations: + * + * - If breakpoint() is called. This is just after kgdb initialization, or if + * a breakpoint() call has been put somewhere into the kernel source. + * (Breakpoints can of course also be set the usual way in gdb.) + * + * - If there is a kernel exception, i.e. bad_super_trap() or die_if_kernel() + * are entered. All the CPU exceptions are mapped to (more or less..., see + * the hard_trap_info array below) appropriate signal, which are reported + * to gdb. die_if_kernel() is usually called after some kind of access + * error and thus is reported as SIGSEGV. + * + * - When panic() is called. This is reported as SIGABRT. + * + * - If C-c is received over the serial line, which is treated as + * SIGINT. + * + * Of course, all these signals are just faked for gdb, since there is no + * signal concept as such for the kernel. It also isn't possible --obviously-- + * to set signal handlers from inside gdb, or restart the kernel with a + * signal. + * + * Current limitations: + * + * - While the kernel is stopped, interrupts are disabled for safety reasons + * (i.e., variables not changing magically or the like). But this also + * means that the clock isn't running anymore, and that interrupts from the + * hardware may get lost/not be served in time. This can cause some device + * errors... + * + * - When single-stepping, only one instruction of the current thread is + * executed, but interrupts are allowed for that time and will be serviced + * if pending. Be prepared for that. + * + * - All debugging happens in kernel virtual address space. There's no way to + * access physical memory not mapped in kernel space, or to access user + * space. A way to work around this is using get_user_long & Co. in gdb + * expressions, but only for the current process. + * + * - Interrupting the kernel only works if interrupts are currently allowed, + * and the interrupt of the serial line isn't blocked by some other means + * (IPL too high, disabled, ...) + * + * - The gdb stub is currently not reentrant, i.e. errors that happen therein + * (e.g. accesing invalid memory) may not be caught correctly. This could + * be removed in future by introducing a stack of struct registers. + * + */ + +/* + * To enable debugger support, two things need to happen. One, a + * call to kgdb_init() is necessary in order to allow any breakpoints + * or error conditions to be properly intercepted and reported to gdb. + * (Linux/68k note: Due to the current design, kgdb has to be initialized + * after traps and interrupts.) + * Two, a breakpoint needs to be generated to begin communication. This + * is most easily accomplished by a call to breakpoint(). Breakpoint() + * simulates a breakpoint by executing a TRAP #15 instruction. + * + * + * The following gdb commands are supported: + * + * command function Return value + * + * g return the value of the CPU registers hex data or ENN + * G set the value of the CPU registers OK or ENN + * + * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN + * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN + * + * c Resume at current address SNN ( signal NN) + * cAA..AA Continue at address AA..AA SNN + * + * s Step one instruction SNN + * sAA..AA Step one instruction from AA..AA SNN + * + * k kill + * + * ? What was the last sigval ? SNN (signal NN) + * + * bBB..BB Set baud rate to BB..BB OK or BNN, then sets + * baud rate + * + * All commands and responses are sent with a packet which includes a + * checksum. A packet consists of + * + * $<packet info>#<checksum>. + * + * where + * <packet info> :: <characters representing the command or response> + * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>> + * + * When a packet is received, it is first acknowledged with either '+' or '-'. + * '+' indicates a successful transfer. '-' indicates a failed transfer. + * + * Example: + * + * Host: Reply: + * $m0,10#2a +$00010203040506070809101112131415#42 + * + */ + +#include <linux/config.h> +#include <linux/string.h> +#include <linux/signal.h> +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/linkage.h> + +#include <asm/setup.h> +#include <asm/ptrace.h> +#include <asm/traps.h> +#include <asm/machdep.h> +#include <asm/kgdb.h> +#ifdef CONFIG_ATARI +#include <asm/atarihw.h> +#include <asm/atariints.h> +#endif +#ifdef CONFIG_AMIGA +#include <asm/amigahw.h> +#include <asm/amigaints.h> +#endif + + +#undef DEBUG + +/* + * global variable: register structure + */ + +struct gdb_regs kgdb_registers; + +/* + * serial i/o functions + */ + +static int (*serial_out)( unsigned char c ); +static unsigned char (*serial_in)( void ); +static unsigned char (*serial_intr)( void ); + +#define putDebugChar(c) serial_out(c) +#define getDebugChar() serial_in() + + +/***************************** Prototypes *****************************/ + +static int hex( unsigned char ch); +static void getpacket( char *buffer); +static void putpacket( char *buffer, int expect_ack); +static inline unsigned long *get_vbr( void ); +static int protected_read( char *p, unsigned long *vbr ); +static int protected_write( char *p, char val, unsigned long *vbr ); +static unsigned char *mem2hex( char *mem, char *buf, int count, int + may_fault); +static char *hex2mem( char *buf, char *mem, int count, int may_fault); +static int computeSignal( int tt); +static int hexToInt( char **ptr, int *intValue); +extern asmlinkage void kgdb_intr( int intno, void *data, struct pt_regs *fp ); +static asmlinkage void handle_exception( void ); +static void show_gdbregs( void ); +#ifdef CONFIG_ATARI +static int atari_mfp_out( unsigned char c ); +static unsigned char atari_mfp_in( void ); +static unsigned char atari_mfp_intr( void ); +static int atari_scc_out( unsigned char c ); +static unsigned char atari_scc_in( void ); +static unsigned char atari_scc_intr( void ); +#endif +#ifdef CONFIG_AMIGA +extern int amiga_ser_out( unsigned char c ); +extern unsigned char amiga_ser_in( void ); +#endif + +/************************* End of Prototypes **************************/ + + +int kgdb_initialized = 0; /* !0 means we've been initialized */ + +/* + * BUFMAX defines the maximum number of characters in inbound/outbound buffers + * at least NUMREGBYTES*2 are needed for register packets + */ +#define BUFMAX 2048 + +static char input_buffer[BUFMAX]; +static char output_buffer[BUFMAX]; +static const char hexchars[]="0123456789abcdef"; +/* debug > 0 prints ill-formed commands in valid packets & checksum errors */ +static int remote_debug = 0; + +/* sizes (in bytes) of CPU stack frames */ +static int frame_sizes[16] = { + 8, 8, 12, 12, /* $0..$3 */ + 16, 8, 8, 60, /* $4..$7 */ + 8, 20, 32, 92, /* $8..$B */ + 12, 4, 4, 4 /* $C..$F */ +}; + +/* + * Convert ch from a hex digit to an int + */ +static int hex(unsigned char ch) +{ + if (ch >= 'a' && ch <= 'f') + return ch-'a'+10; + if (ch >= '0' && ch <= '9') + return ch-'0'; + if (ch >= 'A' && ch <= 'F') + return ch-'A'+10; + return -1; +} + +/* + * scan for the sequence $<data>#<checksum> + */ +static void getpacket(char *buffer) +{ + unsigned char checksum; + unsigned char xmitcsum; + int i; + int count; + unsigned char ch; + + do { + /* + * wait around for the start character, + * ignore all other characters + */ + while ((ch = (getDebugChar() & 0x7f)) != '$') ; + + checksum = 0; + xmitcsum = -1; + count = 0; + + /* + * now, read until a # or end of buffer is found + */ + while (count < BUFMAX) { + ch = getDebugChar() & 0x7f; + if (ch == '#') + break; + checksum = checksum + ch; + buffer[count] = ch; + count = count + 1; + } + + if (count >= BUFMAX) + continue; + + buffer[count] = 0; +#ifdef DEBUG + printk( "kgdb: received packet %s\n", buffer ); +#endif + + if (ch == '#') { + xmitcsum = hex(getDebugChar() & 0x7f) << 4; + xmitcsum |= hex(getDebugChar() & 0x7f); + + if (checksum != xmitcsum) { + if (remote_debug) + printk( "kgdb: bad checksum. count = 0x%x sent=0x%x " + "buf=%s\n", checksum, xmitcsum, buffer ); + putDebugChar('-'); /* failed checksum */ + } + else { + putDebugChar('+'); /* successful transfer */ + + /* + * if a sequence char is present, + * reply the sequence ID + */ + if (buffer[2] == ':') { + putDebugChar(buffer[0]); + putDebugChar(buffer[1]); + + /* + * remove sequence chars from buffer + */ + count = strlen(buffer); + for (i=3; i <= count; i++) + buffer[i-3] = buffer[i]; + } + } + } + } + while (checksum != xmitcsum); +} + +/* + * send the packet in buffer. + */ +static void putpacket(char *buffer, int expect_ack) +{ + unsigned char checksum; + int count; + unsigned char ch; + + /* + * $<packet info>#<checksum>. + */ + +#ifdef DEBUG + printk( "kgdb: sending packet %s\n", buffer ); +#endif + do { + putDebugChar('$'); + checksum = 0; + count = 0; + + while ((ch = buffer[count]) != 0) { + if (!(putDebugChar(ch))) + return; + checksum += ch; + count += 1; + } + + putDebugChar('#'); + putDebugChar(hexchars[checksum >> 4]); + putDebugChar(hexchars[checksum & 0xf]); + + } + while (expect_ack && (getDebugChar() & 0x7f) != '+'); +} + + +static inline unsigned long *get_vbr( void ) + +{ unsigned long *vbr; + + __asm__ __volatile__ ( "movec %/vbr,%0" : "=d" (vbr) : ); + return( vbr ); +} + +static int protected_read( char *p, unsigned long *vbr ) + +{ unsigned char val; + int rv; + + __asm__ __volatile__ + ( "movel %3@(8),%/a0\n\t" + "movel #Lberr1,%3@(8)\n\t" + "movel %/sp,%/a1\n\t" + "moveq #1,%1\n\t" + "moveb %2@,%0\n" + "nop \n\t" + "moveq #0,%1\n\t" + "Lberr1:\t" + "movel %/a1,%/sp\n\t" + "movel %/a0,%3@(8)" + : "=&d" (val), "=&r" (rv) + : "a" (p), "a" (vbr) + : "a0", "a1" ); + + return( rv ? -1 : val ); +} + +static int protected_write( char *p, char val, unsigned long *vbr ) + +{ int rv; + + __asm__ __volatile__ + ( "movel %3@(8),%/a0\n\t" + "movel #Lberr2,%3@(8)\n\t" + "movel %/sp,%/a1\n\t" + "moveq #1,%0\n\t" + "moveb %2,%1@\n" + "nop \n\t" + "moveq #0,%0\n\t" + "Lberr2:\t" + "movel %/a1,%/sp\n\t" + "movel %/a0,%3@(8)" + : "=&r" (rv) + : "a" (p), "d" (val), "a" (vbr) + : "a0", "a1" ); + + return( rv ); +} + +/* + * Convert the memory pointed to by mem into hex, placing result in buf. + * Return a pointer to the last char put in buf (null), in case of mem fault, + * return 0. + * If MAY_FAULT is non-zero, then we will handle memory faults by returning + * a 0, else treat a fault like any other fault in the stub. + */ +static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault) +{ + int ch; + unsigned long *vbr = get_vbr(); + + for( ; count-- > 0; ++mem ) { + if ((ch = protected_read( mem, vbr )) < 0) { + /* bus error happened */ + if (may_fault) + return 0; + else { + /* ignore, but print a warning */ + printk( "Bus error on read from %p\n", mem ); + ch = 0; + } + } + *buf++ = hexchars[(ch >> 4) & 0xf]; + *buf++ = hexchars[ch & 0xf]; + } + + *buf = 0; + + return buf; +} + +/* + * convert the hex array pointed to by buf into binary to be placed in mem + * return a pointer to the character AFTER the last byte written + */ +static char *hex2mem(char *buf, char *mem, int count, int may_fault) +{ + int i; + unsigned char ch; + unsigned long *vbr = get_vbr(); + + for( i = 0; i < count; i++, mem++ ) { + ch = hex(*buf++) << 4; + ch |= hex(*buf++); + if (protected_write( mem, ch, vbr )) { + /* bus error happened */ + if (may_fault) + return 0; + else + /* ignore, but print a warning */ + printk( "Bus error on write to %p\n", mem ); + } + } + + return mem; +} + +/* + * This table contains the mapping between SPARC hardware trap types, and + * signals, which are primarily what GDB understands. It also indicates + * which hardware traps we need to commandeer when initializing the stub. + */ +static struct hard_trap_info +{ + unsigned char tt; /* Trap type code for MIPS R3xxx and R4xxx */ + unsigned char signo; /* Signal that we map this trap into */ +} hard_trap_info[] = { + { 1, SIGINT }, /* excep. 1 is used to fake SIGINT */ + { VEC_BUSERR, SIGSEGV }, /* bus/access error */ + { VEC_ADDRERR, SIGBUS }, /* address error */ + { VEC_ILLEGAL, SIGILL }, /* illegal insn */ + { VEC_ZERODIV, SIGFPE }, /* (integer) divison by zero */ + { VEC_CHK, SIGILL }, /* CHK insn */ + { VEC_TRAP, SIGFPE }, /* [F]TRAPcc insn */ + { VEC_PRIV, SIGILL }, /* priviledge violation (cannot happen) */ + { VEC_TRACE, SIGTRAP }, /* trace trap (single-stepping) */ + { VEC_LINE10, SIGILL }, /* A-line insn */ + { VEC_LINE11, SIGILL }, /* F-line insn */ + { VEC_COPROC, SIGIOT }, /* coprocessor protocol error */ + { VEC_FORMAT, SIGIOT }, /* frame format error */ + { VEC_UNINT, SIGIOT }, /* uninitialized intr. (should not happen) */ + { VEC_SYS, SIGILL }, /* TRAP #0 = system call (illegal in kernel) */ + { VEC_TRAP1, SIGILL }, /* TRAP #1 */ + { VEC_TRAP2, SIGILL }, /* TRAP #2 */ + { VEC_TRAP3, SIGILL }, /* TRAP #3 */ + { VEC_TRAP4, SIGILL }, /* TRAP #4 */ + { VEC_TRAP5, SIGILL }, /* TRAP #5 */ + { VEC_TRAP6, SIGILL }, /* TRAP #6 */ + { VEC_TRAP7, SIGILL }, /* TRAP #7 */ + { VEC_TRAP8, SIGILL }, /* TRAP #8 */ + { VEC_TRAP9, SIGILL }, /* TRAP #9 */ + { VEC_TRAP10, SIGILL }, /* TRAP #10 */ + { VEC_TRAP11, SIGILL }, /* TRAP #11 */ + { VEC_TRAP12, SIGILL }, /* TRAP #12 */ + { VEC_TRAP13, SIGILL }, /* TRAP #13 */ + { VEC_TRAP14, SIGABRT }, /* TRAP #14 (used by kgdb_abort) */ + { VEC_TRAP15, SIGTRAP }, /* TRAP #15 (breakpoint) */ + { VEC_FPBRUC, SIGFPE }, /* FPU */ + { VEC_FPIR, SIGFPE }, /* FPU */ + { VEC_FPDIVZ, SIGFPE }, /* FPU */ + { VEC_FPUNDER, SIGFPE }, /* FPU */ + { VEC_FPOE, SIGFPE }, /* FPU */ + { VEC_FPOVER, SIGFPE }, /* FPU */ + { VEC_FPNAN, SIGFPE }, /* FPU */ + { VEC_FPUNSUP, SIGFPE }, /* FPU */ + { VEC_UNIMPEA, SIGILL }, /* unimpl. effective address */ + { VEC_UNIMPII, SIGILL }, /* unimpl. integer insn */ + + { 0, 0 } /* Must be last */ +}; + + +/* + * Set up exception handlers for tracing and breakpoints + */ +void kgdb_init(void) +{ + extern char m68k_debug_device[]; + + /* fake usage to avoid gcc warnings about unused stuff (they're used in + * assembler code) The local variables will be optimized away... */ + void (*fake1)(void) = handle_exception; + int *fake2 = frame_sizes; + (void)fake1; (void)fake2; + + /* We don't modify the real exception vectors here for the m68k. + * handle_exception() will be called from bad_kernel_trap() or + * die_if_kernel() as needed. */ + + /* + * Initialize the serial port (name in 'm68k_debug_device') + */ + + serial_in = NULL; + serial_out = NULL; + serial_intr = NULL; + +#ifdef CONFIG_ATARI + if (MACH_IS_ATARI) { + if (!strcmp( m68k_debug_device, "ser" )) { + /* defaults to ser2 for a Falcon and ser1 otherwise */ + strcpy( m68k_debug_device, + ((atari_mch_cookie>>16) == ATARI_MCH_FALCON) ? + "ser2" : "ser1" ); + } + + if (!strcmp( m68k_debug_device, "ser1" )) { + /* ST-MFP Modem1 serial port init */ + mfp.trn_stat &= ~0x01; /* disable TX */ + mfp.rcv_stat &= ~0x01; /* disable RX */ + mfp.usart_ctr = 0x88; /* clk 1:16, 8N1 */ + mfp.tim_ct_cd &= 0x70; /* stop timer D */ + mfp.tim_dt_d = 2; /* 9600 bps */ + mfp.tim_ct_cd |= 0x01; /* start timer D, 1:4 */ + mfp.trn_stat |= 0x01; /* enable TX */ + mfp.rcv_stat |= 0x01; /* enable RX */ + + /* set function pointers */ + serial_in = atari_mfp_in; + serial_out = atari_mfp_out; + serial_intr = atari_mfp_intr; + + /* allocate interrupt */ + request_irq( IRQ_MFP_RECFULL, kgdb_intr, IRQ_TYPE_FAST, "kgdb", + NULL ); + } + else if (!strcmp( m68k_debug_device, "ser2" )) { + extern int atari_SCC_reset_done; + + /* SCC Modem2 serial port init */ + static unsigned char *p, scc_table[] = { + 9, 0xc0, /* Reset */ + 4, 0x44, /* x16, 1 stopbit, no parity */ + 3, 0xc0, /* receiver: 8 bpc */ + 5, 0xe2, /* transmitter: 8 bpc, assert dtr/rts */ + 2, 0x60, /* base int vector */ + 9, 0x09, /* int enab, with status low */ + 10, 0, /* NRZ */ + 11, 0x50, /* use baud rate generator */ + 12, 24, 13, 0, /* 9600 baud */ + 14, 2, 14, 3, /* use master clock for BRG, enable */ + 3, 0xc1, /* enable receiver */ + 5, 0xea, /* enable transmitter */ + 15, 0, /* no stat ints */ + 1, 0x10, /* Rx int every char, other ints off */ + 0 + }; + + (void)scc.cha_b_ctrl; /* reset reg pointer */ + MFPDELAY(); + for( p = scc_table; *p != 0; ) { + scc.cha_b_ctrl = *p++; + MFPDELAY(); + scc.cha_b_ctrl = *p++; + MFPDELAY(); + if (p[-2] == 9) + udelay(40); /* extra delay after WR9 access */ + } + /* avoid that atari_SCC.c resets the whole SCC again */ + atari_SCC_reset_done = 1; + + /* set function pointers */ + serial_in = atari_scc_in; + serial_out = atari_scc_out; + serial_intr = atari_scc_intr; + + /* allocate rx and spcond ints */ + request_irq( IRQ_SCCB_RX, kgdb_intr, IRQ_TYPE_FAST, "kgdb", NULL ); + request_irq( IRQ_SCCB_SPCOND, kgdb_intr, IRQ_TYPE_FAST, "kgdb", + NULL ); + } + } +#endif + +#ifdef CONFIG_AMIGA + if (MACH_IS_AMIGA) { + /* always use built-in serial port, no init required */ + serial_in = amiga_ser_in; + serial_out = amiga_ser_out; + } +#endif + +#ifdef CONFIG_ATARI + if (!serial_in || !serial_out) { + if (*m68k_debug_device) + printk( "kgdb_init failed: no valid serial device!\n" ); + else + printk( "kgdb not enabled\n" ); + return; + } +#endif + + /* + * In case GDB is started before us, ack any packets + * (presumably "$?#xx") sitting there. + */ + + putDebugChar ('+'); + kgdb_initialized = 1; + printk( KERN_INFO "kgdb initialized.\n" ); +} + + +/* + * Convert the MIPS hardware trap type code to a unix signal number. + */ +static int computeSignal(int tt) +{ + struct hard_trap_info *ht; + + for (ht = hard_trap_info; ht->tt && ht->signo; ht++) + if (ht->tt == tt) + return ht->signo; + + return SIGHUP; /* default for things we don't know about */ +} + +/* + * While we find nice hex chars, build an int. + * Return number of chars processed. + */ +static int hexToInt(char **ptr, int *intValue) +{ + int numChars = 0; + int hexValue; + + *intValue = 0; + + while (**ptr) + { + hexValue = hex(**ptr); + if (hexValue < 0) + break; + + *intValue = (*intValue << 4) | hexValue; + numChars ++; + + (*ptr)++; + } + + return (numChars); +} + + +/* + * This assembler stuff copies a struct frame (passed as argument) into struct + * gdb_regs registers and then calls handle_exception. After return from + * there, register and the like are restored from 'registers', the stack is + * set up and execution is continued where registers->pc tells us. + */ + +/* offsets in struct frame */ +#define FRAMEOFF_D1 "0" /* d1..d5 */ +#define FRAMEOFF_A0 "5*4" /* a0..a2 */ +#define FRAMEOFF_D0 "8*4" +#define FRAMEOFF_SR "11*4" +#define FRAMEOFF_PC "11*4+2" +#define FRAMEOFF_VECTOR "12*4+2" + +/* offsets in struct gdb_regs */ +#define GDBOFF_D0 "0" +#define GDBOFF_D1 "1*4" +#define GDBOFF_D6 "6*4" +#define GDBOFF_A0 "8*4" +#define GDBOFF_A3 "11*4" +#define GDBOFF_A7 "15*4" +#define GDBOFF_VECTOR "16*4" +#define GDBOFF_SR "16*4+2" +#define GDBOFF_PC "17*4" +#define GDBOFF_FP0 "18*4" +#define GDBOFF_FPCTL "42*4" + +__asm__ +( " .globl " SYMBOL_NAME_STR(enter_kgdb) "\n" + SYMBOL_NAME_STR(enter_kgdb) ":\n" + /* return if not initialized */ + " tstl "SYMBOL_NAME_STR(kgdb_initialized)"\n" + " bne 1f\n" + " rts \n" + "1: orw #0x700,%sr\n" /* disable interrupts while in stub */ + " tstl %sp@+\n" /* pop off return address */ + " movel %sp@+,%a0\n" /* get pointer to fp->ptregs (param) */ + " movel #"SYMBOL_NAME_STR(kgdb_registers)",%a1\n" /* destination */ + /* copy d0-d5/a0-a1 into gdb_regs */ + " movel %a0@("FRAMEOFF_D0"),%a1@("GDBOFF_D0")\n" + " moveml %a0@("FRAMEOFF_D1"),%d1-%d5\n" + " moveml %d1-%d5,%a1@("GDBOFF_D1")\n" + " moveml %a0@("FRAMEOFF_A0"),%d0-%d2\n" + " moveml %d0-%d2,%a1@("GDBOFF_A0")\n" + /* copy sr and pc */ + " movel %a0@("FRAMEOFF_PC"),%a1@("GDBOFF_PC")\n" + " movew %a0@("FRAMEOFF_SR"),%a1@("GDBOFF_SR")\n" + /* copy format/vector word */ + " movew %a0@("FRAMEOFF_VECTOR"),%a1@("GDBOFF_VECTOR")\n" + /* save FPU regs */ + " fmovemx %fp0-%fp7,%a1@("GDBOFF_FP0")\n" + " fmoveml %fpcr/%fpsr/%fpiar,%a1@("GDBOFF_FPCTL")\n" + + /* set stack to CPU frame */ + " addl #"FRAMEOFF_SR",%a0\n" + " movel %a0,%sp\n" + " movew %sp@(6),%d0\n" + " andl #0xf000,%d0\n" + " lsrl #8,%d0\n" + " lsrl #2,%d0\n" /* get frame format << 2 */ + " lea "SYMBOL_NAME_STR(frame_sizes)",%a2\n" + " addl %a2@(%d0),%sp\n" + " movel %sp,%a1@("GDBOFF_A7")\n" /* save a7 now */ + + /* call handle_exception() now that the stack is set up */ + "Lcall_handle_excp:" + " jsr "SYMBOL_NAME_STR(handle_exception)"\n" + + /* after return, first restore FPU registers */ + " movel #"SYMBOL_NAME_STR(kgdb_registers)",%a0\n" /* source */ + " fmovemx %a0@("GDBOFF_FP0"),%fp0-%fp7\n" + " fmoveml %a0@("GDBOFF_FPCTL"),%fpcr/%fpsr/%fpiar\n" + /* set new stack pointer */ + " movel %a0@("GDBOFF_A7"),%sp\n" + " clrw %sp@-\n" /* fake format $0 frame */ + " movel %a0@("GDBOFF_PC"),%sp@-\n" /* new PC into frame */ + " movew %a0@("GDBOFF_SR"),%sp@-\n" /* new SR into frame */ + /* restore general registers */ + " moveml %a0@("GDBOFF_D0"),%d0-%d7/%a0-%a6\n" + /* and jump to new PC */ + " rte" + ); + + +/* + * This is the entry point for the serial interrupt handler. It calls the + * machine specific function pointer 'serial_intr' to get the char that + * interrupted. If that was C-c, the stub is entered as above, but based on + * just a struct intframe, not a struct frame. + */ + +__asm__ +( SYMBOL_NAME_STR(kgdb_intr) ":\n" + /* return if not initialized */ + " tstl "SYMBOL_NAME_STR(kgdb_initialized)"\n" + " bne 1f\n" + "2: rts \n" + "1: movel "SYMBOL_NAME_STR(serial_intr)",%a0\n" + " jsr (%a0)\n" /* get char from serial */ + " cmpb #3,%d0\n" /* is it C-c ? */ + " bne 2b\n" /* no -> just ignore */ + " orw #0x700,%sr\n" /* disable interrupts */ + " subql #1,"SYMBOL_NAME_STR(local_irq_count)"\n" + " movel %sp@(12),%sp\n" /* revert stack to where 'inthandler' set + * it up */ + /* restore regs from frame */ + " moveml %sp@+,%d1-%d5/%a0-%a2\n" + " movel %sp@+,%d0\n" + " addql #8,%sp\n" /* throw away orig_d0 and stkadj */ + /* save them into 'registers' */ + " moveml %d0-%d7/%a0-%a6,"SYMBOL_NAME_STR(kgdb_registers)"\n" + " movel #"SYMBOL_NAME_STR(kgdb_registers)",%a1\n" /* destination */ + /* copy sr and pc */ + " movel %sp@(2),%a1@("GDBOFF_PC")\n" + " movew %sp@,%a1@("GDBOFF_SR")\n" + /* fake format 0 and vector 1 (translated to SIGINT) */ + " movew #4,%a1@("GDBOFF_VECTOR")\n" + /* save FPU regs */ + " fmovemx %fp0-%fp7,%a1@("GDBOFF_FP0")\n" + " fmoveml %fpcr/%fpsr/%fpiar,%a1@("GDBOFF_FPCTL")\n" + /* pop off the CPU stack frame */ + " addql #8,%sp\n" + " movel %sp,%a1@("GDBOFF_A7")\n" /* save a7 now */ + /* proceed as in enter_kgdb */ + " jbra Lcall_handle_excp\n" + ); + +/* + * This function does all command processing for interfacing to gdb. It + * returns 1 if you should skip the instruction at the trap address, 0 + * otherwise. + */ +static asmlinkage void handle_exception( void ) +{ + int trap; /* Trap type */ + int sigval; + int addr; + int length; + char *ptr; + + trap = kgdb_registers.vector >> 2; + sigval = computeSignal(trap); + /* clear upper half of vector/sr word */ + kgdb_registers.vector = 0; + kgdb_registers.format = 0; + +#ifndef DEBUG + if (remote_debug) { +#endif + printk("in handle_exception() trap=%d sigval=%d\n", trap, sigval ); + show_gdbregs(); +#ifndef DEBUG + } +#endif + + /* + * reply to host that an exception has occurred + */ + ptr = output_buffer; + + /* + * Send trap type (converted to signal) + */ + *ptr++ = 'T'; + *ptr++ = hexchars[sigval >> 4]; + *ptr++ = hexchars[sigval & 0xf]; + + /* + * Send Error PC + */ + *ptr++ = hexchars[GDBREG_PC >> 4]; + *ptr++ = hexchars[GDBREG_PC & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((char *)&kgdb_registers.pc, ptr, 4, 0); + *ptr++ = ';'; + + /* + * Send frame pointer + */ + *ptr++ = hexchars[GDBREG_A6 >> 4]; + *ptr++ = hexchars[GDBREG_A6 & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((char *)&kgdb_registers.regs[GDBREG_A6], ptr, 4, 0); + *ptr++ = ';'; + + /* + * Send stack pointer + */ + *ptr++ = hexchars[GDBREG_SP >> 4]; + *ptr++ = hexchars[GDBREG_SP & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((char *)&kgdb_registers.regs[GDBREG_SP], ptr, 4, 0); + *ptr++ = ';'; + + *ptr++ = 0; + putpacket(output_buffer,1); /* send it off... */ + + /* + * Wait for input from remote GDB + */ + for(;;) { + output_buffer[0] = 0; + getpacket(input_buffer); + + switch (input_buffer[0]) { + case '?': + output_buffer[0] = 'S'; + output_buffer[1] = hexchars[sigval >> 4]; + output_buffer[2] = hexchars[sigval & 0xf]; + output_buffer[3] = 0; + break; + + case 'd': + /* toggle debug flag */ + remote_debug = !remote_debug; + break; + + /* + * Return the value of the CPU registers + */ + case 'g': + ptr = output_buffer; + ptr = mem2hex((char *)&kgdb_registers, ptr, NUMREGSBYTES, 0); + break; + + /* + * set the value of the CPU registers - return OK + */ + case 'G': + ptr = &input_buffer[1]; + ptr = hex2mem(ptr, (char *)&kgdb_registers, NUMREGSBYTES, 0); + strcpy(output_buffer,"OK"); + break; + + /* + * Pn...=r... Write register n + */ + case 'P': + ptr = &input_buffer[1]; + if (hexToInt(&ptr, &addr) && *ptr++ == '=') { + if (addr >= 0 && addr <= GDBREG_PC) + hex2mem(ptr, (char *)&kgdb_registers.regs[addr], 4, 0); + else if (addr >= GDBREG_FP0 && addr <= GDBREG_FP7) + hex2mem(ptr, (char *)&kgdb_registers.fpregs[addr-GDBREG_FP0], + 12, 0); + else if (addr >= GDBREG_FPCR && addr <= GDBREG_FPIAR) + hex2mem(ptr, (char *)&kgdb_registers.fpcntl[addr-GDBREG_FPCR], + 4, 0); + } + else + strcpy(output_buffer,"E01"); + break; + + /* + * mAA..AA,LLLL Read LLLL bytes at address AA..AA + */ + case 'm': + ptr = &input_buffer[1]; + + if (hexToInt(&ptr, &addr) + && *ptr++ == ',' + && hexToInt(&ptr, &length)) { + if (mem2hex((char *)addr, output_buffer, length, 1)) + break; + strcpy (output_buffer, "E03"); + } else + strcpy(output_buffer,"E01"); + break; + + /* + * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK + */ + case 'M': + ptr = &input_buffer[1]; + + if (hexToInt(&ptr, &addr) + && *ptr++ == ',' + && hexToInt(&ptr, &length) + && *ptr++ == ':') { + if (hex2mem(ptr, (char *)addr, length, 1)) + strcpy(output_buffer, "OK"); + else + strcpy(output_buffer, "E03"); + } + else + strcpy(output_buffer, "E02"); + break; + + /* + * cAA..AA Continue at address AA..AA(optional) + * sAA..AA Step one instruction from AA..AA(optional) + */ + case 'c': + case 's': + /* try to read optional parameter, pc unchanged if no parm */ + + ptr = &input_buffer[1]; + if (hexToInt(&ptr, &addr)) + kgdb_registers.pc = addr; + + kgdb_registers.sr &= 0x7fff; /* clear Trace bit */ + if (input_buffer[0] == 's') + kgdb_registers.sr |= 0x8000; /* set it if step command */ + + if (remote_debug) + printk( "cont; new PC=0x%08lx SR=0x%04x\n", + kgdb_registers.pc, kgdb_registers.sr ); + + /* + * Need to flush the instruction cache here, as we may + * have deposited a breakpoint, and the icache probably + * has no way of knowing that a data ref to some location + * may have changed something that is in the instruction + * cache. + */ + + if (m68k_is040or060) + __asm__ __volatile__ + ( ".word 0xf4f8\n\t" /* CPUSHA I/D */ + ".word 0xf498" /* CINVA I */ + ); + else + __asm__ __volatile__ + ( "movec %/cacr,%/d0\n\t" + "oriw #0x0008,%/d0\n\t" + "movec %/d0,%/cacr" + : : : "d0" ); + + return; + + /* + * kill the program means reset the machine + */ + case 'k' : + case 'r': + if (mach_reset) { + /* reply OK before actual reset */ + strcpy(output_buffer,"OK"); + putpacket(output_buffer,0); + mach_reset(); + } + else + strcpy(output_buffer,"E01"); + break; + + /* + * Set baud rate (bBB) + * FIXME: Needs to be written (in gdb, too...) + */ + case 'b': + strcpy(output_buffer,"E01"); + break; + + } /* switch */ + + /* + * reply to the request + */ + + putpacket(output_buffer,1); + + } +} + + +/* + * Print registers (on target console) + * Used only to debug the stub... + */ +static void show_gdbregs( void ) +{ + printk( "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", + kgdb_registers.regs[0], kgdb_registers.regs[1], + kgdb_registers.regs[2], kgdb_registers.regs[3] ); + printk( "d4: %08lx d5: %08lx d6: %08lx d7: %08lx\n", + kgdb_registers.regs[4], kgdb_registers.regs[5], + kgdb_registers.regs[6], kgdb_registers.regs[7] ); + printk( "a0: %08lx a1: %08lx a2: %08lx a3: %08lx\n", + kgdb_registers.regs[8], kgdb_registers.regs[9], + kgdb_registers.regs[10], kgdb_registers.regs[11] ); + printk( "a4: %08lx a5: %08lx a6: %08lx a7: %08lx\n", + kgdb_registers.regs[12], kgdb_registers.regs[13], + kgdb_registers.regs[14], kgdb_registers.regs[15] ); + printk( "pc: %08lx sr: %04x\n", kgdb_registers.pc, kgdb_registers.sr ); +} + + +/* -------------------- Atari serial I/O -------------------- */ + +#ifdef CONFIG_ATARI + +static int atari_mfp_out( unsigned char c ) + +{ + while( !(mfp.trn_stat & 0x80) ) /* wait for tx buf empty */ + barrier(); + mfp.usart_dta = c; + return( 1 ); +} + + +static unsigned char atari_mfp_in( void ) + +{ + while( !(mfp.rcv_stat & 0x80) ) /* wait for rx buf filled */ + barrier(); + return( mfp.usart_dta ); +} + + +static unsigned char atari_mfp_intr( void ) + +{ + return( mfp.usart_dta ); +} + + +static int atari_scc_out( unsigned char c ) + +{ + do { + MFPDELAY(); + } while( !(scc.cha_b_ctrl & 0x04) ); /* wait for tx buf empty */ + MFPDELAY(); + scc.cha_b_data = c; + return( 1 ); +} + + +static unsigned char atari_scc_in( void ) + +{ + do { + MFPDELAY(); + } while( !(scc.cha_b_ctrl & 0x01) ); /* wait for rx buf filled */ + MFPDELAY(); + return( scc.cha_b_data ); +} + + +static unsigned char atari_scc_intr( void ) + +{ unsigned char c, stat; + + MFPDELAY(); + scc.cha_b_ctrl = 1; /* RR1 */ + MFPDELAY(); + stat = scc.cha_b_ctrl; + MFPDELAY(); + c = scc.cha_b_data; + MFPDELAY(); + if (stat & 0x30) { + scc.cha_b_ctrl = 0x30; /* error reset for overrun and parity */ + MFPDELAY(); + } + scc.cha_b_ctrl = 0x38; /* reset highest IUS */ + MFPDELAY(); + return( c ); +} + +#endif diff --git a/arch/m68k/kernel/m68k_defs.h b/arch/m68k/kernel/m68k_defs.h new file mode 100644 index 000000000..992d390c7 --- /dev/null +++ b/arch/m68k/kernel/m68k_defs.h @@ -0,0 +1,8 @@ +/* + * WARNING! This file is automatically generated - DO NOT EDIT! + */ + +#define TS_MAGICKEY 0x5a5a5a5a +#define TS_TSS 478 +#define TS_ESP0 498 +#define TS_FPU 502 diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c index 025e11c0f..ee73b3ff2 100644 --- a/arch/m68k/kernel/m68k_ksyms.c +++ b/arch/m68k/kernel/m68k_ksyms.c @@ -1,4 +1,3 @@ -#include <linux/config.h> #include <linux/module.h> #include <linux/linkage.h> #include <linux/sched.h> @@ -8,7 +7,6 @@ #include <linux/elfcore.h> #include <linux/in6.h> #include <linux/interrupt.h> -#include <linux/pci.h> #include <asm/setup.h> #include <asm/machdep.h> @@ -44,6 +42,8 @@ EXPORT_SYMBOL(strrchr); EXPORT_SYMBOL(strstr); EXPORT_SYMBOL(local_irq_count); EXPORT_SYMBOL(local_bh_count); +EXPORT_SYMBOL(enable_irq); +EXPORT_SYMBOL(disable_irq); /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy); @@ -60,7 +60,3 @@ EXPORT_SYMBOL_NOVERS(memcmp); EXPORT_SYMBOL_NOVERS(__down_failed); EXPORT_SYMBOL_NOVERS(__down_failed_interruptible); EXPORT_SYMBOL_NOVERS(__up_wakeup); - -#ifdef CONFIG_PCI -EXPORT_SYMBOL(pci_devices); -#endif diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index a6fbd5718..dac2bfcc8 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -66,13 +66,14 @@ asmlinkage int sys_idle(void) current->priority = -100; current->counter = -100; for (;;){ - if (!need_resched) + if (!current->need_resched) #if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC) /* block out HSYNC on the atari (falcon) */ __asm__("stop #0x2200" : : : "cc"); #else /* portable version */ __asm__("stop #0x2000" : : : "cc"); #endif /* machine compilation types */ + check_pgt_cache(); run_task_queue(&tq_scheduler); schedule(); } diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index 4a2a95f4b..da91d32de 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c @@ -347,9 +347,13 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) goto out; child->flags |= PF_PTRACED; if (child->p_pptr != current) { + unsigned long flags; + + write_lock_irqsave(&tasklist_lock, flags); REMOVE_LINKS(child); child->p_pptr = current; SET_LINKS(child); + write_unlock_irqrestore(&tasklist_lock, flags); } send_sig(SIGSTOP, child, 1); ret = 0; @@ -491,6 +495,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) } case PTRACE_DETACH: { /* detach a process that was attached. */ + unsigned long flags; long tmp; ret = -EIO; @@ -499,9 +504,11 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) child->flags &= ~(PF_PTRACED|PF_TRACESYS); wake_up_process(child); child->exit_code = data; + write_lock_irqsave(&tasklist_lock, flags); REMOVE_LINKS(child); child->p_pptr = child->p_opptr; SET_LINKS(child); + write_unlock_irqrestore(&tasklist_lock, flags); /* make sure the single step bit is not set. */ tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); put_reg(child, PT_SR, tmp); diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c index fccf8b4cf..6df005fb4 100644 --- a/arch/m68k/kernel/setup.c +++ b/arch/m68k/kernel/setup.c @@ -61,6 +61,8 @@ void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) __initd int (*mach_keyb_init) (void) __initdata; int (*mach_kbdrate) (struct kbd_repeat *) = NULL; void (*mach_kbd_leds) (unsigned int) = NULL; +/* machine dependent "kbd-reset" setup function */ +void (*kbd_reset_setup) (char *, int) __initdata = NULL; /* machine dependent irq functions */ void (*mach_init_IRQ) (void) __initdata; void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL; @@ -102,6 +104,8 @@ extern void config_mac(void); extern void config_sun3(void); extern void config_apollo(void); extern void config_mvme16x(void); +extern void config_bvme6000(void); +extern void config_hp300(void); #define MASK_256K 0xfffc0000 @@ -250,6 +254,16 @@ __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p, config_mvme16x(); break; #endif +#ifdef CONFIG_BVME6000 + case MACH_BVME6000: + config_bvme6000(); + break; +#endif +#ifdef CONFIG_HP300 + case MACH_HP300: + config_hp300(); + break; +#endif default: panic ("No configuration setup"); } diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index 97809d382..03214a42f 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c @@ -147,6 +147,12 @@ sys_sigaction(int sig, const struct old_sigaction *act, return ret; } +asmlinkage int +sys_sigaltstack(const stack_t *uss, stack_t *uoss) +{ + return do_sigaltstack(uss, uoss, rdusp()); +} + /* * Do a signal return; undo the signal stack. @@ -177,31 +183,33 @@ struct rt_sigframe static unsigned char fpu_version = 0; /* version number of fpu, set by setup_frame */ -static inline void restore_fpu_state(struct sigcontext *sc) +static inline int restore_fpu_state(struct sigcontext *sc) { + int err = 1; + if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { /* Verify the frame format. */ if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version)) - goto badframe; + goto out; if (CPU_IS_020_OR_030) { if (m68k_fputype & FPU_68881 && !(sc->sc_fpstate[1] == 0x18 || sc->sc_fpstate[1] == 0xb4)) - goto badframe; + goto out; if (m68k_fputype & FPU_68882 && !(sc->sc_fpstate[1] == 0x38 || sc->sc_fpstate[1] == 0xd4)) - goto badframe; + goto out; } else if (CPU_IS_040) { if (!(sc->sc_fpstate[1] == 0x00 || sc->sc_fpstate[1] == 0x28 || sc->sc_fpstate[1] == 0x60)) - goto badframe; + goto out; } else if (CPU_IS_060) { if (!(sc->sc_fpstate[3] == 0x00 || sc->sc_fpstate[3] == 0x60 || sc->sc_fpstate[3] == 0xe0)) - goto badframe; + goto out; } else - goto badframe; + goto out; __asm__ volatile (".chip 68k/68881\n\t" "fmovemx %0,%/fp0-%/fp1\n\t" @@ -213,10 +221,10 @@ static inline void restore_fpu_state(struct sigcontext *sc) __asm__ volatile (".chip 68k/68881\n\t" "frestore %0\n\t" ".chip 68k" : : "m" (*sc->sc_fpstate)); - return; + err = 0; -badframe: - do_exit(SIGSEGV); +out: + return err; } #define FPCONTEXT_SIZE 216 @@ -224,42 +232,43 @@ badframe: #define uc_formatvec uc_filler[FPCONTEXT_SIZE/4] #define uc_extra uc_filler[FPCONTEXT_SIZE/4+1] -static inline void rt_restore_fpu_state(struct ucontext *uc) +static inline int rt_restore_fpu_state(struct ucontext *uc) { unsigned char fpstate[FPCONTEXT_SIZE]; int context_size = CPU_IS_060 ? 8 : 0; fpregset_t fpregs; + int err = 1; if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate)) - goto badframe; + goto out; if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { if (!CPU_IS_060) context_size = fpstate[1]; /* Verify the frame format. */ if (!CPU_IS_060 && (fpstate[0] != fpu_version)) - goto badframe; + goto out; if (CPU_IS_020_OR_030) { if (m68k_fputype & FPU_68881 && !(context_size == 0x18 || context_size == 0xb4)) - goto badframe; + goto out; if (m68k_fputype & FPU_68882 && !(context_size == 0x38 || context_size == 0xd4)) - goto badframe; + goto out; } else if (CPU_IS_040) { if (!(context_size == 0x00 || context_size == 0x28 || context_size == 0x60)) - goto badframe; + goto out; } else if (CPU_IS_060) { if (!(fpstate[3] == 0x00 || fpstate[3] == 0x60 || fpstate[3] == 0xe0)) - goto badframe; + goto out; } else - goto badframe; + goto out; if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs, sizeof(fpregs))) - goto badframe; + goto out; __asm__ volatile (".chip 68k/68881\n\t" "fmovemx %0,%/fp0-%/fp7\n\t" "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t" @@ -271,21 +280,23 @@ static inline void rt_restore_fpu_state(struct ucontext *uc) if (context_size && __copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1, context_size)) - goto badframe; + goto out; __asm__ volatile (".chip 68k/68881\n\t" "frestore %0\n\t" ".chip 68k" : : "m" (*fpstate)); - return; + err = 0; -badframe: - do_exit(SIGSEGV); +out: + return err; } static inline int -restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp) +restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp, + int *pd0) { int fsize, formatvec; struct sigcontext context; + int err; /* get previous context */ if (copy_from_user(&context, usc, sizeof(context))) @@ -303,7 +314,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp) regs->format = formatvec >> 12; regs->vector = formatvec & 0xfff; - restore_fpu_state(&context); + err = restore_fpu_state(&context); fsize = frame_extra_sizes[regs->format]; if (fsize < 0) { @@ -356,49 +367,55 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp) goto badframe; } - return context.sc_d0; + *pd0 = context.sc_d0; + return err; badframe: - do_exit(SIGSEGV); + return 1; } static inline int rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, - struct ucontext *uc) + struct ucontext *uc, int *pd0) { int fsize, temp; greg_t *gregs = uc->uc_mcontext.gregs; + unsigned long usp; + int err; - __get_user(temp, &uc->uc_mcontext.version); + err = __get_user(temp, &uc->uc_mcontext.version); if (temp != MCONTEXT_VERSION) goto badframe; /* restore passed registers */ - __get_user(regs->d0, &gregs[0]); - __get_user(regs->d1, &gregs[1]); - __get_user(regs->d2, &gregs[2]); - __get_user(regs->d3, &gregs[3]); - __get_user(regs->d4, &gregs[4]); - __get_user(regs->d5, &gregs[5]); - __get_user(sw->d6, &gregs[6]); - __get_user(sw->d7, &gregs[7]); - __get_user(regs->a0, &gregs[8]); - __get_user(regs->a1, &gregs[9]); - __get_user(regs->a2, &gregs[10]); - __get_user(sw->a3, &gregs[11]); - __get_user(sw->a4, &gregs[12]); - __get_user(sw->a5, &gregs[13]); - __get_user(sw->a6, &gregs[14]); - __get_user(temp, &gregs[15]); - wrusp(temp); - __get_user(regs->pc, &gregs[16]); - __get_user(temp, &gregs[17]); + err |= __get_user(regs->d0, &gregs[0]); + err |= __get_user(regs->d1, &gregs[1]); + err |= __get_user(regs->d2, &gregs[2]); + err |= __get_user(regs->d3, &gregs[3]); + err |= __get_user(regs->d4, &gregs[4]); + err |= __get_user(regs->d5, &gregs[5]); + err |= __get_user(sw->d6, &gregs[6]); + err |= __get_user(sw->d7, &gregs[7]); + err |= __get_user(regs->a0, &gregs[8]); + err |= __get_user(regs->a1, &gregs[9]); + err |= __get_user(regs->a2, &gregs[10]); + err |= __get_user(sw->a3, &gregs[11]); + err |= __get_user(sw->a4, &gregs[12]); + err |= __get_user(sw->a5, &gregs[13]); + err |= __get_user(sw->a6, &gregs[14]); + err |= __get_user(usp, &gregs[15]); + wrusp(usp); + err |= __get_user(regs->pc, &gregs[16]); + err |= __get_user(temp, &gregs[17]); regs->sr = (regs->sr & 0xff00) | (temp & 0xff); regs->orig_d0 = -1; /* disable syscall checks */ - __get_user(temp, &uc->uc_formatvec); + err |= __get_user(temp, &uc->uc_formatvec); regs->format = temp >> 12; regs->vector = temp & 0xfff; - rt_restore_fpu_state(uc); + err |= rt_restore_fpu_state(uc); + + if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT) + goto badframe; fsize = frame_extra_sizes[regs->format]; if (fsize < 0) { @@ -449,10 +466,11 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, goto badframe; } - return regs->d0; + *pd0 = regs->d0; + return err; badframe: - do_exit(SIGSEGV); + return 1; } asmlinkage int do_sigreturn(unsigned long __unused) @@ -462,6 +480,7 @@ asmlinkage int do_sigreturn(unsigned long __unused) unsigned long usp = rdusp(); struct sigframe *frame = (struct sigframe *)(usp - 24); sigset_t set; + int d0; if (verify_area(VERIFY_READ, frame, sizeof(*frame))) goto badframe; @@ -475,10 +494,13 @@ asmlinkage int do_sigreturn(unsigned long __unused) current->blocked = set; recalc_sigpending(current); - return restore_sigcontext(regs, &frame->sc, frame + 1); + if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0)) + goto badframe; + return d0; badframe: - do_exit(SIGSEGV); + force_sig(SIGSEGV, current); + return 0; } asmlinkage int do_rt_sigreturn(unsigned long __unused) @@ -488,6 +510,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused) unsigned long usp = rdusp(); struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4); sigset_t set; + int d0; if (verify_area(VERIFY_READ, frame, sizeof(*frame))) goto badframe; @@ -498,10 +521,13 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused) current->blocked = set; recalc_sigpending(current); - return rt_restore_ucontext(regs, sw, &frame->uc); + if (rt_restore_ucontext(regs, sw, &frame->uc, &d0)) + goto badframe; + return d0; badframe: - do_exit(SIGSEGV); + force_sig(SIGSEGV, current); + return 0; } /* @@ -535,17 +561,18 @@ static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs) } } -static inline void rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs) +static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs) { unsigned char fpstate[FPCONTEXT_SIZE]; int context_size = CPU_IS_060 ? 8 : 0; + int err = 0; __asm__ volatile (".chip 68k/68881\n\t" "fsave %0\n\t" ".chip 68k" : : "m" (*fpstate) : "memory"); - __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate); + err |= __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate); if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { fpregset_t fpregs; if (!CPU_IS_060) @@ -566,11 +593,13 @@ static inline void rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs) : "m" (*fpregs.f_fpregs), "m" (fpregs.f_pcr) : "memory"); - copy_to_user(&uc->uc_mcontext.fpregs, &fpregs, sizeof(fpregs)); + err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs, + sizeof(fpregs)); } if (context_size) - copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4, - context_size); + err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4, + context_size); + return err; } static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, @@ -588,32 +617,34 @@ static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, save_fpu_state(sc, regs); } -static inline void rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs) +static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs) { struct switch_stack *sw = (struct switch_stack *)regs - 1; greg_t *gregs = uc->uc_mcontext.gregs; - - __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version); - __put_user(regs->d0, &gregs[0]); - __put_user(regs->d1, &gregs[1]); - __put_user(regs->d2, &gregs[2]); - __put_user(regs->d3, &gregs[3]); - __put_user(regs->d4, &gregs[4]); - __put_user(regs->d5, &gregs[5]); - __put_user(sw->d6, &gregs[6]); - __put_user(sw->d7, &gregs[7]); - __put_user(regs->a0, &gregs[8]); - __put_user(regs->a1, &gregs[9]); - __put_user(regs->a2, &gregs[10]); - __put_user(sw->a3, &gregs[11]); - __put_user(sw->a4, &gregs[12]); - __put_user(sw->a5, &gregs[13]); - __put_user(sw->a6, &gregs[14]); - __put_user(rdusp(), &gregs[15]); - __put_user(regs->pc, &gregs[16]); - __put_user(regs->sr, &gregs[17]); - __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec); - rt_save_fpu_state(uc, regs); + int err = 0; + + err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version); + err |= __put_user(regs->d0, &gregs[0]); + err |= __put_user(regs->d1, &gregs[1]); + err |= __put_user(regs->d2, &gregs[2]); + err |= __put_user(regs->d3, &gregs[3]); + err |= __put_user(regs->d4, &gregs[4]); + err |= __put_user(regs->d5, &gregs[5]); + err |= __put_user(sw->d6, &gregs[6]); + err |= __put_user(sw->d7, &gregs[7]); + err |= __put_user(regs->a0, &gregs[8]); + err |= __put_user(regs->a1, &gregs[9]); + err |= __put_user(regs->a2, &gregs[10]); + err |= __put_user(sw->a3, &gregs[11]); + err |= __put_user(sw->a4, &gregs[12]); + err |= __put_user(sw->a5, &gregs[13]); + err |= __put_user(sw->a6, &gregs[14]); + err |= __put_user(rdusp(), &gregs[15]); + err |= __put_user(regs->pc, &gregs[16]); + err |= __put_user(regs->sr, &gregs[17]); + err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec); + err |= rt_save_fpu_state(uc, regs); + return err; } static inline void push_cache (unsigned long vaddr) @@ -708,60 +739,72 @@ static inline void push_cache (unsigned long vaddr) } } +static inline void * +get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) +{ + unsigned long usp; + + /* Default to using normal stack. */ + usp = rdusp(); + + /* This is the X/Open sanctioned signal stack switching. */ + if (ka->sa.sa_flags & SA_ONSTACK) { + if (!on_sig_stack(usp)) + usp = current->sas_ss_sp + current->sas_ss_size; + } + return (void *)((usp - frame_size) & -8UL); +} + static void setup_frame (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs) { struct sigframe *frame; int fsize = frame_extra_sizes[regs->format]; struct sigcontext context; + int err = 0; if (fsize < 0) { #ifdef DEBUG printk ("setup_frame: Unknown frame format %#x\n", regs->format); #endif - goto segv_and_exit; + goto give_sigsegv; } - frame = (struct sigframe *)((rdusp() - sizeof(*frame) - fsize) & -8); - - if (!(current->flags & PF_ONSIGSTK) && (ka->sa.sa_flags & SA_ONSTACK)) { - frame = (struct sigframe *)(((unsigned long)ka->sa.sa_restorer - - sizeof(*frame) - fsize) & -8); - current->flags |= PF_ONSIGSTK; - } + frame = get_sigframe(ka, regs, sizeof(*frame) + fsize); if (fsize) { - if (copy_to_user (frame + 1, regs + 1, fsize)) - goto segv_and_exit; + err |= copy_to_user (frame + 1, regs + 1, fsize); regs->stkadj = fsize; } - __put_user((current->exec_domain - && current->exec_domain->signal_invmap - && sig < 32 - ? current->exec_domain->signal_invmap[sig] - : sig), - &frame->sig); + err |= __put_user((current->exec_domain + && current->exec_domain->signal_invmap + && sig < 32 + ? current->exec_domain->signal_invmap[sig] + : sig), + &frame->sig); - __put_user(regs->vector, &frame->code); - __put_user(&frame->sc, &frame->psc); + err |= __put_user(regs->vector, &frame->code); + err |= __put_user(&frame->sc, &frame->psc); if (_NSIG_WORDS > 1) - copy_to_user(frame->extramask, &set->sig[1], - sizeof(frame->extramask)); + err |= copy_to_user(frame->extramask, &set->sig[1], + sizeof(frame->extramask)); setup_sigcontext(&context, regs, set->sig[0]); - if (copy_to_user (&frame->sc, &context, sizeof(context))) - goto segv_and_exit; + err |= copy_to_user (&frame->sc, &context, sizeof(context)); /* Set up to return from userspace. */ - __put_user(frame->retcode, &frame->pretcode); + err |= __put_user(frame->retcode, &frame->pretcode); /* addaw #20,sp */ - __put_user(0xdefc0014, (long *)(frame->retcode + 0)); + err |= __put_user(0xdefc0014, (long *)(frame->retcode + 0)); /* moveq #,d0; trap #0 */ - __put_user(0x70004e40 + (__NR_sigreturn << 16), - (long *)(frame->retcode + 4)); + err |= __put_user(0x70004e40 + (__NR_sigreturn << 16), + (long *)(frame->retcode + 4)); + + if (err) + goto give_sigsegv; push_cache ((unsigned long) &frame->retcode); @@ -791,8 +834,10 @@ static void setup_frame (int sig, struct k_sigaction *ka, } return; -segv_and_exit: - do_exit(SIGSEGV); +give_sigsegv: + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); } static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, @@ -800,48 +845,53 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, { struct rt_sigframe *frame; int fsize = frame_extra_sizes[regs->format]; + int err = 0; if (fsize < 0) { #ifdef DEBUG printk ("setup_frame: Unknown frame format %#x\n", regs->format); #endif - goto segv_and_exit; + goto give_sigsegv; } - frame = (struct rt_sigframe *)((rdusp() - sizeof(*frame)) & -8); - - /* XXX: Check here if we need to switch stacks.. */ + frame = get_sigframe(ka, regs, sizeof(*frame)); if (fsize) { - if (copy_to_user (&frame->uc.uc_extra, regs + 1, fsize)) - goto segv_and_exit; + err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize); regs->stkadj = fsize; } - __put_user((current->exec_domain - && current->exec_domain->signal_invmap - && sig < 32 - ? current->exec_domain->signal_invmap[sig] - : sig), - &frame->sig); - __put_user(&frame->info, &frame->pinfo); - __put_user(&frame->uc, &frame->puc); - __copy_to_user(&frame->info, info, sizeof(*info)); - - /* Clear all the bits of the ucontext we don't use. */ - clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); - - rt_setup_ucontext(&frame->uc, regs); - if (copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set))) - goto segv_and_exit; + err |= __put_user((current->exec_domain + && current->exec_domain->signal_invmap + && sig < 32 + ? current->exec_domain->signal_invmap[sig] + : sig), + &frame->sig); + err |= __put_user(&frame->info, &frame->pinfo); + err |= __put_user(&frame->uc, &frame->puc); + err |= __copy_to_user(&frame->info, info, sizeof(*info)); + + /* Create the ucontext. */ + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user((void *)current->sas_ss_sp, + &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(rdusp()), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= rt_setup_ucontext(&frame->uc, regs); + err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set)); /* Set up to return from userspace. */ - __put_user(frame->retcode, &frame->pretcode); + err |= __put_user(frame->retcode, &frame->pretcode); /* movel #,d0; trap #0 */ - __put_user(0x203c, (short *)(frame->retcode + 0)); - __put_user(__NR_rt_sigreturn, (long *)(frame->retcode + 2)); - __put_user(0x4e40, (short *)(frame->retcode + 6)); + err |= __put_user(0x203c, (short *)(frame->retcode + 0)); + err |= __put_user(__NR_rt_sigreturn, (long *)(frame->retcode + 2)); + err |= __put_user(0x4e40, (short *)(frame->retcode + 6)); + + if (err) + goto give_sigsegv; push_cache ((unsigned long) &frame->retcode); @@ -871,8 +921,34 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, } return; -segv_and_exit: - do_exit(SIGSEGV); +give_sigsegv: + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); +} + +static inline void +handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) +{ + switch (regs->d0) { + case -ERESTARTNOHAND: + if (!has_handler) + goto do_restart; + regs->d0 = -EINTR; + break; + + case -ERESTARTSYS: + if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) { + regs->d0 = -EINTR; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: + do_restart: + regs->d0 = regs->orig_d0; + regs->pc -= 2; + break; + } } /* @@ -883,24 +959,9 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { /* are we from a system call? */ - if (regs->orig_d0 >= 0) { + if (regs->orig_d0 >= 0) /* If so, check system call restarting.. */ - switch (regs->d0) { - case -ERESTARTNOHAND: - regs->d0 = -EINTR; - break; - - case -ERESTARTSYS: - if (!(ka->sa.sa_flags & SA_RESTART)) { - regs->d0 = -EINTR; - break; - } - /* fallthrough */ - case -ERESTARTNOINTR: - regs->d0 = regs->orig_d0; - regs->pc -= 2; - } - } + handle_restart(regs, ka, 1); /* set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) @@ -952,13 +1013,14 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) /* Did we come from a system call? */ if (regs->orig_d0 >= 0) { - /* Restart the system call */ - if (regs->d0 == -ERESTARTNOHAND || - regs->d0 == -ERESTARTSYS || - regs->d0 == -ERESTARTNOINTR) { - regs->d0 = regs->orig_d0; - regs->pc -= 2; - } + /* Restart the system call the same way as + if the process were not traced. */ + struct k_sigaction *ka = + ¤t->sig->action[signr-1]; + int has_handler = + (ka->sa.sa_handler != SIG_IGN && + ka->sa.sa_handler != SIG_DFL); + handle_restart(regs, ka, has_handler); } notify_parent(current, SIGCHLD); schedule(); @@ -1052,15 +1114,9 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) } /* Did we come from a system call? */ - if (regs->orig_d0 >= 0) { + if (regs->orig_d0 >= 0) /* Restart the system call - no handlers present */ - if (regs->d0 == -ERESTARTNOHAND || - regs->d0 == -ERESTARTSYS || - regs->d0 == -ERESTARTNOINTR) { - regs->d0 = regs->orig_d0; - regs->pc -= 2; - } - } + handle_restart(regs, NULL, 0); /* If we are about to discard some frame stuff we must copy over the remaining frame. */ diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c index 50d564134..75da52541 100644 --- a/arch/m68k/kernel/sys_m68k.c +++ b/arch/m68k/kernel/sys_m68k.c @@ -66,20 +66,25 @@ asmlinkage int old_mmap(struct mmap_arg_struct *arg) struct file * file = NULL; struct mmap_arg_struct a; - lock_kernel(); - error = -EFAULT; if (copy_from_user(&a, arg, sizeof(a))) - goto out; + return -EFAULT; + down(¤t->mm->mmap_sem); + lock_kernel(); if (!(a.flags & MAP_ANONYMOUS)) { error = -EBADF; - if (a.fd >= NR_OPEN || !(file = current->files->fd[a.fd])) + file = fget(a.fd); + if (!file) goto out; } a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset); + if (file) + fput(file); out: unlock_kernel(); + up(¤t->mm->mmap_sem); return error; } diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c index 51359f046..8f11a00d8 100644 --- a/arch/m68k/kernel/time.c +++ b/arch/m68k/kernel/time.c @@ -38,7 +38,7 @@ static inline void do_profile (unsigned long pc) ++prof_buffer[pc]; else /* - * Dont ignore out-of-bounds PC values silently, + * Don't ignore out-of-bounds PC values silently, * put them into the last histogram slot, so if * present, they will show up as a sharp peak. */ diff --git a/arch/m68k/mac/Makefile b/arch/m68k/mac/Makefile index 458a01f44..cfd63295a 100644 --- a/arch/m68k/mac/Makefile +++ b/arch/m68k/mac/Makefile @@ -10,7 +10,8 @@ EXTRA_CFLAGS := -Wa,-m68020 O_TARGET := mac.o -O_OBJS := config.o ksyms.o bootparse.o macints.o via6522.o \ +O_OBJS := config.o bootparse.o macints.o via6522.o \ mackeyb.o adb-bus.o macboing.o debug.o +OX_OBJS := mac_ksyms.o include $(TOPDIR)/Rules.make diff --git a/arch/m68k/mac/adb-bus.c b/arch/m68k/mac/adb-bus.c index ddd5176c4..0f41bc6aa 100644 --- a/arch/m68k/mac/adb-bus.c +++ b/arch/m68k/mac/adb-bus.c @@ -6,9 +6,11 @@ * Copyright (C) 1996 Paul Mackerras. * * MSch (9/97) Partial rewrite of interrupt handler to MacII style - * ADB handshake, based on: - * - Guide to Mac Hardware - * - Guido Koerber's session with a logic analyzer + * ADB handshake, based on: + * - Guide to Mac Hardware + * - Guido Koerber's session with a logic analyzer + * + * MSch (1/98) Integrated start of IIsi driver by Robert Thompson */ #include <stdarg.h> @@ -63,6 +65,9 @@ #define SR_DATA 0x08 /* Shift register data */ #define SR_CLOCK 0x10 /* Shift register clock */ +/* JRT */ +#define ADB_DELAY 150 + static struct adb_handler { void (*handler)(unsigned char *, int, struct pt_regs *); } adb_handler[16]; @@ -88,6 +93,9 @@ static int prefix_len; static int status = ST_IDLE|TREQ; static int last_status; + +static int driver_running = 0; + /*static int adb_delay;*/ int in_keybinit = 1; @@ -98,12 +106,19 @@ extern void adb_clock_interrupt(int irq, void *arg, struct pt_regs *regs); extern void adb_data_interrupt(int irq, void *arg, struct pt_regs *regs); static void adb_input(unsigned char *buf, int nb, struct pt_regs *regs); +static void adb_hw_setup_IIsi(void); +static void adb_hw_setup_cuda(void); + /* - * Misc. defines for testing + * debug level 10 required for ADB logging (should be && debug_adb, ideally) */ extern int console_loglevel; +/* + * Misc. defines for testing - should go to header :-( + */ + #define ADBDEBUG_STATUS (1) #define ADBDEBUG_STATE (2) #define ADBDEBUG_READ (4) @@ -118,11 +133,13 @@ extern int console_loglevel; #define ADBDEBUG_INPUT (2048) #define ADBDEBUG_DEVICE (4096) +#define ADBDEBUG_IISI (8192) + -#define DEBUG_ADB +/*#define DEBUG_ADB*/ #ifdef DEBUG_ADB -#define ADBDEBUG (ADBDEBUG_READ | ADBDEBUG_START | ADBDEBUG_WRITE | ADBDEBUG_SRQ | ADBDEBUG_REQUEST) +#define ADBDEBUG (ADBDEBUG_INPUT | ADBDEBUG_READ | ADBDEBUG_START | ADBDEBUG_WRITE | ADBDEBUG_SRQ | ADBDEBUG_REQUEST) #else #define ADBDEBUG (0) #endif @@ -132,7 +149,7 @@ extern int console_loglevel; void adb_bus_init(void) { unsigned long flags; - unsigned char c; + unsigned char c, i; save_flags(flags); cli(); @@ -174,31 +191,7 @@ void adb_bus_init(void) via_write(via1, vIER, IER_SET|SR_INT); /* This clears the interrupt bit */ via_write(via1, vIFR, SR_INT); -#if 0 - ct=1000; - while( ct-- && (via_read(via1, vBufB)&TREQ)) - udelay(1000); - if(ct<0) - printk("No sync occured\n"); - ct=1000; - while( ct-- && !(via_read(via1, vIFR)&SR_INT)) - udelay(1000); - if(ct<0) - printk("No sync 2 occured\n"); - via_read(via1, vSR); - via_write(via1, vBufB, via_read(via1, vBufB)|TACK); - while( ct-- && !(via_read(via1, vBufB)&TREQ)) - udelay(1000); - if(ct<0) - printk("No sync 3 occured\n"); - ct=1000; - while( ct-- && !(via_read(via1, vIFR)&SR_INT)) - udelay(1000); - if(ct<0) - printk("No sync 4 occured\n"); - via_read(via1, vSR); - via_write(via1, vBufB, via_read(via1, vBufB)|TIP); -#endif + /* * Ok we probably ;) have a ready to use adb bus. Its also * hopefully idle (Im assuming the mac didnt leave a half @@ -214,20 +207,58 @@ void adb_bus_init(void) */ case MAC_ADB_CUDA: printk("adb: CUDA interface.\n"); -#ifdef TRY_CUDA +#if 0 /* don't know what to set up here ... */ adb_state = idle; /* Set the lines up. We want TREQ as input TACK|TIP as output */ via_write(via1, vDirB, ((via_read(via1,vDirB)|TACK|TIP)&~TREQ)); +#endif + adb_hw_setup_cuda(); + adb_state = idle; request_irq(IRQ_MAC_ADB, adb_cuda_interrupt, IRQ_FLG_LOCK, "adb CUDA interrupt", adb_cuda_interrupt); break; -#else - goto nosupp; -#endif case MAC_ADB_IISI: printk("adb: Using IIsi hardware.\n"); - goto nosupp; + printk("\tDEBUG_JRT\n"); + /* Set the lines up. We want TREQ as input TACK|TIP as output */ + via_write(via1, vDirB, ((via_read(via1,vDirB)|TACK|TIP)&~TREQ)); + + /* + * MSch: I'm pretty sure the setup is mildly wrong + * for the IIsi. + */ + /* Initial state: idle (clear state bits) */ + via_write(via1, vBufB, (via_read(via1, vBufB) & ~(TIP|TACK)) ); + last_status = (via_read(via1, vBufB)&~ST_MASK); + /* Shift register on input */ + c=via_read(via1, vACR); + c&=~SR_CTRL; /* Clear shift register bits */ + c|=SR_EXT; /* Shift on external clock; out or in? */ + via_write(via1, vACR, c); + /* Wipe any pending data and int */ + via_read(via1, vSR); + + /* This is interrupts on enable SR for keyboard */ + via_write(via1, vIER, IER_SET|SR_INT); + /* This clears the interrupt bit */ + via_write(via1, vIFR, SR_INT); + + /* get those pesky clock ticks we missed while booting */ + for ( i = 0; i < 30; i++) { + udelay(ADB_DELAY); + adb_hw_setup_IIsi(); + udelay(ADB_DELAY); + if (via_read(via1, vBufB) & TREQ) + break; + } + /* + * Ok we probably ;) have a ready to use adb bus. Its also + */ + request_irq(IRQ_MAC_ADB, adb_cuda_interrupt, IRQ_FLG_LOCK, + "adb interrupt", adb_cuda_interrupt); + adb_state = idle; + break; default: printk("adb: Unknown hardware interface.\n"); nosupp: @@ -255,6 +286,171 @@ void adb_bus_init(void) restore_flags(flags); } +void adb_hw_setup_cuda(void) +{ + int x; + unsigned long flags; + + printk("CUDA: HW Setup:"); + + save_flags(flags); + cli(); + + if (console_loglevel == 10) + printk(" 1,"); + + /* Set the direction of the cuda signals, TIP+TACK are output TREQ is an input */ + via_write( via1, vDirB, via_read( via1, vDirB ) | TIP | TACK ); + via_write( via1, vDirB, via_read( via1, vDirB ) & ~TREQ ); + + if (console_loglevel == 10) + printk("2,"); + + /* Set the clock control. Set to shift data in by external clock CB1 */ + via_write( via1, vACR, ( via_read(via1, vACR ) | SR_EXT ) & ~SR_OUT ); + + if (console_loglevel == 10) + printk("3,"); + + /* Clear any possible Cuda interrupt */ + x = via_read( via1, vSR ); + + if (console_loglevel == 10) + printk("4,"); + + /* Terminate transaction and set idle state */ + via_write( via1, vBufB, via_read( via1, vBufB ) | TIP | TACK ); + + if (console_loglevel == 10) + printk("5,"); + + /* Delay 4 mS for ADB reset to complete */ + udelay(4000); + + if (console_loglevel == 10) + printk("6,"); + + /* Clear pending interrupts... */ + x = via_read( via1, vSR ); + + if (console_loglevel == 10) + printk("7,"); + /* Issue a sync transaction, TACK asserted while TIP negated */ + via_write( via1, vBufB, via_read( via1, vBufB ) & ~TACK ); + + if (console_loglevel == 10) + printk("8,"); + + /* Wait for the sync acknowledgement, Cuda to assert TREQ */ + while( ( via_read( via1, vBufB ) & TREQ ) != 0 ) + barrier(); + + if (console_loglevel == 10) + printk("9,"); + + /* Wait for the sync acknowledment interrupt */ + while( ( via_read( via1, vIFR ) & SR_INT ) == 0 ) + barrier(); + + if (console_loglevel == 10) + printk("10,"); + + /* Clear pending interrupts... */ + x = via_read( via1, vSR ); + + if (console_loglevel == 10) + printk("11,"); + + /* Terminate the sync cycle by negating TACK */ + via_write( via1, vBufB, via_read( via1, vBufB ) | TACK ); + + if (console_loglevel == 10) + printk("12,"); + + /* Wait for the sync termination acknowledgement, Cuda to negate TREQ */ + while( ( via_read( via1, vBufB ) & TREQ ) == 0 ) + barrier(); + + if (console_loglevel == 10) + printk("13,"); + + /* Wait for the sync termination acknowledment interrupt */ + while( ( via_read( via1, vIFR ) & SR_INT ) == 0 ) + barrier(); + + if (console_loglevel == 10) + printk("14,"); + + /* Terminate transaction and set idle state, TIP+TACK negate */ + via_write( via1, vBufB, via_read( via1, vBufB ) | TIP ); + + if (console_loglevel == 10) + printk("15 !"); + + /* Clear pending interrupts... */ + x = via_read( via1, vSR ); + + restore_flags(flags); + + printk("\nCUDA: HW Setup done!\n"); +} + +void adb_hw_setup_IIsi(void) +{ + int dummy; + long poll_timeout; + + printk("adb_IIsi: cleanup!\n"); + + /* ??? */ + udelay(ADB_DELAY); + + /* disable SR int. */ + via_write(via1, vIER, IER_CLR|SR_INT); + /* set SR to shift in */ + via_write(via1, vACR, via_read(via1, vACR ) & ~SR_OUT); + + /* this is required, especially on faster machines */ + udelay(ADB_DELAY); + + if (!(via_read(via1, vBufB) & TREQ)) { /* IRQ on */ + /* start frame */ + via_write(via1, vBufB,via_read(via1,vBufB) | TIP); + + while (1) { + /* poll for ADB interrupt and watch for timeout */ + /* if time out, keep going in hopes of not hanging the + * ADB chip - I think */ + poll_timeout = ADB_DELAY * 5; + while ( !(via_read(via1, vIFR) & SR_INT) + && (poll_timeout-- > 0) ) + dummy = via_read(via1, vBufB); + + dummy = via_read(via1, vSR); /* reset interrupt flag */ + + /* perhaps put in a check here that ignores all data + * after the first ADB_MAX_MSG_LENGTH bytes ??? */ + + /* end of frame reached ?? */ + if (via_read(via1, vBufB) & TREQ) + break; + + /* set ACK */ + via_write(via1,vBufB,via_read(via1, vBufB) | TACK); + /* delay */ + udelay(ADB_DELAY); + /* clear ACK */ + via_write(via1,vBufB,via_read(via1, vBufB) & ~TACK); + } + /* end frame */ + via_write(via1, vBufB,via_read(via1,vBufB) & ~TIP); + /* probably don't need to delay this long */ + udelay(ADB_DELAY); + } + /* re-enable SR int. */ + via_write(via1, vIER, IER_SET|SR_INT); +} + #define WAIT_FOR(cond, what) \ do { \ for (x = 1000; !(cond); --x) { \ @@ -288,7 +484,7 @@ int adb_request(struct adb_request *req, void (*done)(struct adb_request *), /* * skip first byte if not CUDA */ - if (macintosh_config->adb_type != MAC_ADB_CUDA) { + if (macintosh_config->adb_type == MAC_ADB_II) { start = va_arg(list, int); nbytes--; } @@ -390,8 +586,12 @@ void adb_queue_poll(void) printk("adb: Polling %d\n",pod); #endif - /* XXX: that's a TALK, register 0, MacII version */ - adb_build_request(&r,NULL, 1, (pod<<4|0xC)); + if (macintosh_config->adb_type == MAC_ADB_II) + /* XXX: that's a TALK, register 0, MacII version */ + adb_build_request(&r,NULL, 1, (pod<<4|0xC)); + else + /* CUDA etc. version */ + adb_build_request(&r,NULL, 2, 0, (pod<<4|0xC)); r.reply_expected=0; r.done=NULL; @@ -545,7 +745,7 @@ static void adb_start(void) * IRQ signaled ?? (means ADB controller wants to send, or might * be end of packet if we were reading) */ - if ((via_read(via1, vBufB)& TREQ) == 0) + if ((via_read(via1, vBufB) & TREQ) == 0) { switch(macintosh_config->adb_type) { @@ -560,7 +760,12 @@ static void adb_start(void) /* printk("device busy - fail\n"); */ restore_flags(flags); /* a byte is coming in from the CUDA */ - return; + return; + case MAC_ADB_IISI: + printk("adb_start: device busy - fail\n"); + retry_req = req; + restore_flags(flags); + return; case MAC_ADB_II: /* * if the interrupt handler set the need_poll @@ -635,6 +840,19 @@ static void adb_start(void) via_write(via1, vSR, req->data[0]); via_write(via1, vBufB, via_read(via1, vBufB)&~TIP); break; + case MAC_ADB_IISI: + /* store command byte (first byte is 'type' byte) */ + command_byte = req->data[1]; + /* set ADB state to 'active' */ + via_write(via1, vBufB, via_read(via1, vBufB) | TIP); + /* switch ACK off (in case it was left on) */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* set the shift register to shift out and send a byte */ + via_write(via1, vACR, via_read(via1, vACR) | SR_OUT); + via_write(via1, vSR, req->data[0]); + /* signal 'byte ready' */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + break; case MAC_ADB_II: /* store command byte */ command_byte = req->data[0]; @@ -653,14 +871,14 @@ static void adb_start(void) #endif break; } + adb_state = sent_first_byte; + data_index = 1; #if (ADBDEBUG & ADBDEBUG_START) if (console_loglevel == 10) printk("sent first byte of %d: %x, (%x %x) ... ", req->nbytes, req->data[0], adb_state, (via_read(via1, vBufB) & (ST_MASK|TREQ)) ); #endif - adb_state = sent_first_byte; - data_index = 1; restore_flags(flags); } @@ -748,16 +966,34 @@ void adb_data_interrupt(int irq, void *arg, struct pt_regs *regs) * and retransmit (Talk to the last active device). Cleanup of code and * testing of the CUDA functionality is required, though. * Note2: As of 13/12/97, CUDA support is definitely broken ... + * Note3: As of 21/12/97, CUDA works on a P475. What was broken? The assumption + * that Q700 and Q800 use CUDA :-( + * + * 27/01/98: IIsi driver implemented (thanks to Robert Thompson for the + * initial bits). See adb_cuda_interrupts ... + * * Next TODO: implementation of IIsi ADB protocol (maybe the USE_ORIG * conditionals can be a start?) */ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) { int x, adbdir; + unsigned long flags; struct adb_request *req; last_status = status; + /* prevent races due to SCSI enabling ints */ + save_flags(flags); + cli(); + + if (driver_running) { + restore_flags(flags); + return; + } + + driver_running = 1; + #ifdef USE_ORIG status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT); #else @@ -774,7 +1010,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) adb_state, status, last_status, adbdir); #endif - switch (adb_state) { case idle: @@ -786,6 +1021,26 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) x = via_read(via1, vSR); via_write(via1, vBufB, via_read(via1,vBufB)&~TIP); } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + udelay(150); + /* set SR to IN (??? no byte received else) */ + via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT); + /* signal start of frame */ + via_write(via1, vBufB, via_read(via1, vBufB) | TIP); + /* read first byte */ + x = via_read(via1, vSR); + first_byte = x; +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_macIIsi : receiving unsol. packet: %x (%x %x) ", + x, adb_state, status); +#endif + /* ACK adb chip */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + udelay(150); + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + } else if(macintosh_config->adb_type==MAC_ADB_II) { #if (ADBDEBUG & ADBDEBUG_STATUS) @@ -801,12 +1056,8 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) printk("adb_macII: receiving unsol. packet: %x (%x %x) ", x, adb_state, status); #endif -#ifdef USE_ORIG - via_write(via1, vBufB, via_read(via1, vBufB)&~(TIP|TACK)); -#else /* set ADB state = even for first data byte */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN); -#endif } adb_state = reading; reply_ptr = cuda_rbuf; @@ -831,7 +1082,34 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) x = via_read(via1, vSR); via_write(via1,vBufB, via_read(via1, vBufB)&~TIP); - } else if(macintosh_config->adb_type==MAC_ADB_II) { + } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + /* set SR to IN */ + via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT); + /* signal start of frame */ + via_write(via1, vBufB, via_read(via1, vBufB) | TIP); + /* read first byte */ + x = via_read(via1, vSR); + first_byte = x; +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_macIIsi: reading reply: %x (%x %x) ", + x, adb_state, status); +#endif +#if 0 + if( via_read(via1,vBufB) & TREQ) + ending = 1; + else + ending = 0; +#endif + /* ACK adb chip */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + udelay(150); + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + } + else if(macintosh_config->adb_type==MAC_ADB_II) + { /* handshake etc. for II ?? */ x = via_read(via1, vSR); first_byte = x; @@ -840,12 +1118,8 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) printk("adb_macII: reading reply: %x (%x %x) ", x, adb_state, status); #endif -#ifdef USE_ORIG - via_write(via1, vBufB, via_read(via1, vBufB)&~(TIP|TACK)); -#else /* set ADB state = even for first data byte */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN); -#endif } adb_state = reading; reply_ptr = current_req->reply; @@ -862,6 +1136,11 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) break; case sent_first_byte: +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk(" sending: %x (%x %x) ", + current_req->data[1], adb_state, status); +#endif if(macintosh_config->adb_type==MAC_ADB_CUDA) { if (status == TREQ + TIP + SR_OUT) @@ -886,14 +1165,45 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) adb_state = sending; } } - else if(macintosh_config->adb_type==MAC_ADB_II) + else if(macintosh_config->adb_type==MAC_ADB_IISI) { - /* how to detect a collision here ?? */ + /* switch ACK off */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + if ( !(via_read(via1, vBufB) & TREQ) ) + { + /* collision */ #if (ADBDEBUG & ADBDEBUG_WRITE) - if (console_loglevel == 10) - printk(" sending: %x (%x %x) ", - current_req->data[1], adb_state, status); + if (console_loglevel == 10) + printk("adb_macIIsi: send collison, aborting!\n"); +#endif + /* set shift in */ + via_write(via1, vACR, + via_read(via1, vACR)&~SR_OUT); + /* clear SR int. */ + x = via_read(via1, vSR); + /* set ADB state to 'idle' */ + via_write(via1, vBufB, + via_read(via1,vBufB) & ~(TIP|TACK)); + adb_state = idle; + } + else + { + /* delay */ + udelay(ADB_DELAY); + /* set the shift register to shift out and send a byte */ +#if 0 + via_write(via1, vACR, via_read(via1, vACR) | SR_OUT); #endif + via_write(via1, vSR, current_req->data[1]); + /* signal 'byte ready' */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + data_index=2; + adb_state = sending; + } + } + else if(macintosh_config->adb_type==MAC_ADB_II) + { + /* how to detect a collision here ?? */ /* maybe we're already done (Talk, or Poll)? */ if (data_index >= current_req->nbytes) { @@ -934,14 +1244,9 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) via_write(via1, vACR, via_read(via1, vACR) & ~SR_OUT); x=via_read(via1, vSR); -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)|TACK|TIP); -#else /* set ADB state idle - might get SRQ */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE); -#endif break; } #if (ADBDEBUG & ADBDEBUG_STATUS) @@ -951,14 +1256,9 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) #endif /* SR already set to shift out; send byte */ via_write(via1, vSR, current_req->data[1]); -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)^TACK); -#else /* set state to ST_EVEN (first byte was: ST_CMD) */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN); -#endif data_index=2; adb_state = sending; } @@ -968,6 +1268,11 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) req = current_req; if (data_index >= req->nbytes) { +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk(" -> end (%d of %d) (%x %x)!\n", + data_index-1, req->nbytes, adb_state, status); +#endif /* end of packet */ if(macintosh_config->adb_type==MAC_ADB_CUDA) { @@ -977,29 +1282,34 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) via_write(via1, vBufB, via_read(via1,vBufB)|TACK|TIP); } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + /* XXX maybe clear ACK here ??? */ + /* switch ACK off */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* delay */ + udelay(ADB_DELAY); + /* set the shift register to shift in */ + via_write(via1, vACR, via_read(via1, vACR)|SR_OUT); + /* clear SR int. */ + x = via_read(via1, vSR); + /* set ADB state 'idle' (end of frame) */ + via_write(via1, vBufB, + via_read(via1,vBufB) & ~(TACK|TIP)); + } else if(macintosh_config->adb_type==MAC_ADB_II) { /* * XXX Not sure: maybe only switch to * input mode on Talk ?? */ -#if (ADBDEBUG & ADBDEBUG_WRITE) - if (console_loglevel == 10) - printk(" -> end (%d of %d) (%x %x)!\n", - data_index-1, req->nbytes, adb_state, status); -#endif /* set to shift in */ via_write(via1, vACR, via_read(via1, vACR) & ~SR_OUT); x=via_read(via1, vSR); -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)|TACK|TIP); -#else /* set ADB state idle - might get SRQ */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE); -#endif } req->sent = 1; if (req->reply_expected) @@ -1008,7 +1318,12 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) * maybe fake a reply here on Listen ?? * Otherwise, a Listen hangs on success */ - if ( ((req->data[0]&0xc) == 0xc) ) + if ( macintosh_config->adb_type==MAC_ADB_II + && ((req->data[0]&0xc) == 0xc) ) + adb_state = awaiting_reply; + else if ( macintosh_config->adb_type != MAC_ADB_II + && ( req->data[0] == 0x0) + && ((req->data[1]&0xc) == 0xc) ) adb_state = awaiting_reply; else { /* @@ -1063,34 +1378,46 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) } else { +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk(" %x (%x %x) ", + req->data[data_index], adb_state, status); +#endif if(macintosh_config->adb_type==MAC_ADB_CUDA) { via_write(via1, vSR, req->data[data_index++]); via_write(via1, vBufB, via_read(via1, vBufB)^TACK); } - else if(macintosh_config->adb_type==MAC_ADB_II) + else if(macintosh_config->adb_type==MAC_ADB_IISI) { -#if (ADBDEBUG & ADBDEBUG_WRITE) - if (console_loglevel == 10) - printk(" %x (%x %x) ", - req->data[data_index], adb_state, status); + /* switch ACK off */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* delay */ + udelay(ADB_DELAY); + /* XXX: need to check for collision?? */ + /* set the shift register to shift out and send a byte */ +#if 0 + via_write(via1, vACR, via_read(via1, vACR)|SR_OUT); #endif via_write(via1, vSR, req->data[data_index++]); -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)^TACK); -#else + /* signal 'byte ready' */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + } + else if(macintosh_config->adb_type==MAC_ADB_II) + { + via_write(via1, vSR, req->data[data_index++]); /* invert state bits, toggle ODD/EVEN */ x = via_read(via1, vBufB); via_write(via1, vBufB, (x&~ST_MASK)|~(x&ST_MASK)); -#endif } } break; case reading: + + /* timeout / SRQ handling for II hw */ #ifdef POLL_ON_TIMEOUT if((reply_len-prefix_len)==3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0) #else @@ -1128,16 +1455,12 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) x, adb_state, status); #endif -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)|TACK|TIP); -#else #if 0 /* XXX leave status unchanged!! - need to check this again! */ + /* XXX Only touch status on II !!! */ /* set ADB state to idle (required by adb_start()) */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE); #endif -#endif /* * What if the timeout happens on reading a @@ -1206,6 +1529,7 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) */ break; } + /* end timeout / SRQ handling for II hw. */ if((reply_len-prefix_len)>3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0) { /* SRQ tacked on data packet */ @@ -1241,7 +1565,7 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) reply_len++; } /* The usual handshake ... */ - if(macintosh_config->adb_type==MAC_ADB_CUDA) + if (macintosh_config->adb_type==MAC_ADB_CUDA) { if (status == TIP) { @@ -1259,7 +1583,27 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) via_read(via1, vBufB)^TACK); } } - if(macintosh_config->adb_type==MAC_ADB_II) + else if (macintosh_config->adb_type==MAC_ADB_IISI) + { + /* ACK adb chip (maybe check for end first?) */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + udelay(150); + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* end of frame?? */ + if (status & TREQ) + { +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_IIsi: end of frame!\n"); +#endif + /* that's all folks */ + via_write(via1, vBufB, + via_read(via1, vBufB) & ~(TACK|TIP)); + adb_state = read_done; + /* maybe process read_done here?? Handshake anyway?? */ + } + } + else if (macintosh_config->adb_type==MAC_ADB_II) { /* * NetBSD hints that the next to last byte @@ -1277,10 +1621,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) if (console_loglevel == 10) printk(" -> read done!\n"); #endif -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)|TACK|TIP); -#else #if 0 /* XXX: we take one more byte (why?), so handshake! */ /* set ADB state to idle */ via_write(via1, vBufB, @@ -1291,7 +1631,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) via_write(via1, vBufB, (x&~ST_MASK)|~(x&ST_MASK)); #endif -#endif /* adjust packet length */ reply_len--; reply_ptr--; @@ -1303,10 +1642,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) if(status!=TIP+TREQ) printk("macII_adb: state=reading status=%x\n", status); #endif -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)^TACK); -#else /* not caught: ST_CMD */ /* required for re-entry 'reading'! */ if ((status&ST_MASK) == ST_IDLE) { @@ -1319,7 +1654,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) via_write(via1, vBufB, (x&~ST_MASK)|~(x&ST_MASK)); } -#endif } } break; @@ -1352,7 +1686,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) last_reply = command_byte; last_active = (command_byte&0xf0)>>4; - /* * Assert status = ST_IDLE ?? */ @@ -1374,15 +1707,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) break; } -#ifdef USE_ORIG - /* - * This will fail - TREQ is active low -> 0 is IRQ !! - */ - if (status == TREQ) - { - via_write(via1, vBufB, - via_read(via1, vBufB)|~TIP); -#else /* * /IRQ seen, so the ADB controller has data for us */ @@ -1391,7 +1715,7 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) /* set ADB state to idle */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE); -#endif + adb_state = reading; reply_ptr = cuda_rbuf; reply_len = 0; @@ -1422,35 +1746,81 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) printk("adb_interrupt: unknown adb_state %d?\n", adb_state); #endif } + /* reset mutex and interrupts */ + driver_running = 0; + restore_flags(flags); } /* * Restart of CUDA support: please modify this interrupt handler while * working at the Quadra etc. ADB driver. We can try to merge them later, or * remove the CUDA stuff from the MacII handler + * + * MSch 27/01/98: Implemented IIsi driver based on initial code by Robert + * Thompson and hints from the NetBSD driver. CUDA and IIsi seem more closely + * related than to the MacII code, so merging all three might be a bad + * idea. */ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) { int x, status; struct adb_request *req; + unsigned long flags; + + save_flags(flags); + cli(); - status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT); + if(macintosh_config->adb_type==MAC_ADB_CUDA) + status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT); + else + status = via_read(via1, vBufB) & (TIP|TREQ); + +#if (ADBDEBUG & ADBDEBUG_INT) if (console_loglevel == 10) printk("adb_interrupt: state=%d status=%x\n", adb_state, status); +#endif switch (adb_state) { case idle: + first_byte = 0; if(macintosh_config->adb_type==MAC_ADB_CUDA) { +#if (ADBDEBUG & ADBDEBUG_STATUS) /* CUDA has sent us the first byte of data - unsolicited */ if (status != TREQ) printk("cuda: state=idle, status=%x want=%x\n", status, TREQ); +#endif x = via_read(via1, vSR); +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_cuda: receiving unsol. packet: %x (%x %x) ", + x, adb_state, status); +#endif via_write(via1, vBufB, via_read(via1,vBufB)&~TIP); } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + udelay(150); + /* set SR to IN */ + via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT); + /* signal start of frame */ + via_write(via1, vBufB, via_read(via1, vBufB) | TIP); + /* read first byte */ + x = via_read(via1, vSR); + first_byte = x; +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_IIsi : receiving unsol. packet: %x (%x %x) ", + x, adb_state, status); +#endif + /* ACK adb chip */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + udelay(150); + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + } else if(macintosh_config->adb_type==MAC_ADB_II) { if (status != TREQ) @@ -1469,13 +1839,46 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) if(macintosh_config->adb_type==MAC_ADB_CUDA) { /* CUDA has sent us the first byte of data of a reply */ +#if (ADBDEBUG & ADBDEBUG_STATUS) if (status != TREQ) printk("cuda: state=awaiting_reply, status=%x want=%x\n", status, TREQ); +#endif x = via_read(via1, vSR); +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_cuda: reading reply: %x (%x %x) ", + x, adb_state, status); +#endif via_write(via1,vBufB, via_read(via1, vBufB)&~TIP); } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + /* udelay(150);*/ + /* set SR to IN */ + via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT); + /* signal start of frame */ + via_write(via1, vBufB, via_read(via1, vBufB) | TIP); + /* read first byte */ + x = via_read(via1, vSR); + first_byte = x; +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_IIsi: reading reply: %x (%x %x) ", + x, adb_state, status); +#endif +#if 0 + if( via_read(via1,vBufB) & TREQ) + ending = 1; + else + ending = 0; +#endif + /* ACK adb chip */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + udelay(150); + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + } adb_state = reading; reply_ptr = current_req->reply; reading_reply = 1; @@ -1485,11 +1888,16 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) case sent_first_byte: if(macintosh_config->adb_type==MAC_ADB_CUDA) { +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk(" sending: %x (%x %x) ", + current_req->data[1], adb_state, status); +#endif if (status == TREQ + TIP + SR_OUT) { /* collision */ if (console_loglevel == 10) - printk("cuda: send collision!\n"); + printk("adb_cuda: send collision!\n"); via_write(via1, vACR, via_read(via1, vACR)&~SR_OUT); x = via_read(via1, vSR); @@ -1500,9 +1908,11 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) else { /* assert status == TIP + SR_OUT */ +#if (ADBDEBUG & ADBDEBUG_STATUS) if (status != TIP + SR_OUT) - printk("cuda: state=sent_first_byte status=%x want=%x\n", + printk("adb_cuda: state=sent_first_byte status=%x want=%x\n", status, TIP + SR_OUT); +#endif via_write(via1,vSR,current_req->data[1]); via_write(via1, vBufB, via_read(via1, vBufB)^TACK); @@ -1510,6 +1920,42 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) adb_state = sending; } } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + /* switch ACK off */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + if ( !(via_read(via1, vBufB) & TREQ) ) + { + /* collision */ +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk("adb_macIIsi: send collison, aborting!\n"); +#endif + /* set shift in */ + via_write(via1, vACR, + via_read(via1, vACR)&~SR_OUT); + /* clear SR int. */ + x = via_read(via1, vSR); + /* set ADB state to 'idle' */ + via_write(via1, vBufB, + via_read(via1,vBufB) & ~(TIP|TACK)); + adb_state = idle; + } + else + { + /* delay */ + udelay(ADB_DELAY); + /* set the shift register to shift out and send a byte */ +#if 0 + via_write(via1, vACR, via_read(via1, vACR) | SR_OUT); +#endif + via_write(via1, vSR, current_req->data[1]); + /* signal 'byte ready' */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + data_index=2; + adb_state = sending; + } + } else if(macintosh_config->adb_type==MAC_ADB_II) { if(status!=TIP+SR_OUT) @@ -1527,6 +1973,11 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) req = current_req; if (data_index >= req->nbytes) { +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk(" -> end (%d of %d) (%x %x)!\n", + data_index-1, req->nbytes, adb_state, status); +#endif if(macintosh_config->adb_type==MAC_ADB_CUDA) { via_write(via1, vACR, @@ -1535,6 +1986,21 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) via_write(via1, vBufB, via_read(via1,vBufB)|TACK|TIP); } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + /* XXX maybe clear ACK here ??? */ + /* switch ACK off */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* delay */ + udelay(ADB_DELAY); + /* set the shift register to shift in */ + via_write(via1, vACR, via_read(via1, vACR)|SR_OUT); + /* clear SR int. */ + x = via_read(via1, vSR); + /* set ADB state 'idle' (end of frame) */ + via_write(via1, vBufB, + via_read(via1,vBufB) & ~(TACK|TIP)); + } else if(macintosh_config->adb_type==MAC_ADB_II) { via_write(via1, vACR, @@ -1546,7 +2012,40 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) req->sent = 1; if (req->reply_expected) { - adb_state = awaiting_reply; + /* + * maybe fake a reply here on Listen ?? + * Otherwise, a Listen hangs on success + * CUDA+IIsi: only ADB Talk considered + * RTC/PRAM read (0x1 0x3) to follow. + */ + if ( (req->data[0] == 0x0) && ((req->data[1]&0xc) == 0xc) ) + adb_state = awaiting_reply; + else { + /* + * Reply expected, but none + * possible -> fake reply. + */ +#if (ADBDEBUG & ADBDEBUG_PROT) + printk("ADB: reply expected on Listen, faking reply\n"); +#endif + /* make it look weird */ + /* XXX: return reply_len -1? */ + /* XXX: fake ADB header? */ + req->reply[0] = req->reply[1] = req->reply[2] = 0xFF; + req->reply_len = 3; + req->got_reply = 1; + current_req = req->next; + if (req->done) + (*req->done)(req); + /* + * ready with this one, run + * next command ! + */ + /* set state to idle !! */ + adb_state = idle; + if (current_req || retry_req) + adb_start(); + } } else { @@ -1560,12 +2059,32 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) } else { +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk(" %x (%x %x) ", + req->data[data_index], adb_state, status); +#endif if(macintosh_config->adb_type==MAC_ADB_CUDA) { via_write(via1, vSR, req->data[data_index++]); via_write(via1, vBufB, via_read(via1, vBufB)^TACK); } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + /* switch ACK off */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* delay */ + udelay(ADB_DELAY); + /* XXX: need to check for collision?? */ + /* set the shift register to shift out and send a byte */ +#if 0 + via_write(via1, vACR, via_read(via1, vACR)|SR_OUT); +#endif + via_write(via1, vSR, req->data[data_index++]); + /* signal 'byte ready' */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + } else if(macintosh_config->adb_type==MAC_ADB_II) { via_write(via1, vSR, req->data[data_index++]); @@ -1579,14 +2098,17 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) if(reply_len==3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0) { /* Terminate the SRQ packet */ - printk("CUDA: Got an SRQ\n"); +#if (ADBDEBUG & ADBDEBUG_SRQ) + if (console_loglevel == 10) + printk("adb: Got an SRQ\n"); +#endif adb_state = idle; adb_queue_poll(); break; } /* Sanity check - botched in orig. code! */ if(reply_len>15) { - printk("CUDA: reply buffer overrun!\n"); + printk("adb_cuda: reply buffer overrun!\n"); /* wrap buffer */ reply_len=0; if (reading_reply) @@ -1595,9 +2117,11 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) reply_ptr = cuda_rbuf; } *reply_ptr = via_read(via1, vSR); +#if (ADBDEBUG & ADBDEBUG_READ) if (console_loglevel == 10) - printk(" %p-> %x (%x %x) ", - reply_ptr, *reply_ptr, adb_state, status); + printk(" %x (%x %x) ", + *reply_ptr, adb_state, status); +#endif reply_ptr++; reply_len++; if(macintosh_config->adb_type==MAC_ADB_CUDA) @@ -1612,13 +2136,36 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) else { /* assert status == TIP | TREQ */ +#if (ADBDEBUG & ADBDEBUG_STATUS) if (status != TIP + TREQ) printk("cuda: state=reading status=%x want=%x\n", status, TIP + TREQ); +#endif via_write(via1, vBufB, via_read(via1, vBufB)^TACK); } } + else if (macintosh_config->adb_type==MAC_ADB_IISI) + { + /* ACK adb chip (maybe check for end first?) */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + udelay(150); + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* end of frame?? */ + if (status & TREQ) + { +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_IIsi: end of frame!\n"); +#endif + /* that's all folks */ + via_write(via1, vBufB, + via_read(via1, vBufB) & ~(TACK|TIP)); + adb_state = read_done; + /* XXX maybe process read_done here?? + Handshake anyway?? */ + } + } if(macintosh_config->adb_type==MAC_ADB_II) { if( status == TIP) @@ -1629,16 +2176,26 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) } else { +#if (ADBDEBUG & ADBDEBUG_STATUS) if(status!=TIP+TREQ) printk("macII_adb: state=reading status=%x\n", status); +#endif via_write(via1, vBufB, via_read(via1, vBufB)^TACK); } } - break; + /* fall through for IIsi on end of frame */ + if (macintosh_config->adb_type != MAC_ADB_IISI + || adb_state != read_done) + break; case read_done: x = via_read(via1, vSR); +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb: read done: %x (%x %x)!\n", + x, adb_state, status); +#endif if (reading_reply) { req = current_req; @@ -1653,10 +2210,21 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) adb_input(cuda_rbuf, reply_ptr - cuda_rbuf, regs); } - if (status == TREQ) + if (macintosh_config->adb_type==MAC_ADB_CUDA + && status & TREQ) + { + via_write(via1, vBufB, + via_read(via1, vBufB)&~TIP); + adb_state = reading; + reply_ptr = cuda_rbuf; + reading_reply = 0; + } + else if (macintosh_config->adb_type==MAC_ADB_IISI + && !(status & TREQ)) { + udelay(150); via_write(via1, vBufB, - via_read(via1, vBufB)|~TIP); + via_read(via1, vBufB) | TIP); adb_state = reading; reply_ptr = cuda_rbuf; reading_reply = 0; @@ -1669,8 +2237,11 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) break; default: - printk("adb_interrupt: unknown adb_state %d?\n", adb_state); + printk("adb_cuda_interrupt: unknown adb_state %d?\n", adb_state); } + + restore_flags(flags); + } /* diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index d711dd7b3..fe77ded05 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c @@ -35,20 +35,16 @@ #include <asm/macintosh.h> #include <asm/macints.h> +#include <asm/machw.h> #include "via6522.h" -/* old bootinfo stuff */ +/* Mac bootinfo struct */ struct mac_booter_data mac_bi_data = {0,}; int mac_bisize = sizeof mac_bi_data; -struct compat_bootinfo compat_boot_info ={0,}; -int compat_bisize = sizeof compat_boot_info; - -int compat_bi = 0; - -/* New bootinfo stuff */ +/* New m68k bootinfo stuff and videobase */ extern int m68k_num_memory; extern struct mem_info m68k_memory[NUM_MEMINFO]; @@ -59,42 +55,67 @@ extern char m68k_command_line[CL_SIZE]; void *mac_env; /* Loaded by the boot asm */ +/* The logical video addr. determined by head.S - testing */ +extern unsigned long mac_videobase; + +/* The phys. video addr. - might be bogus on some machines */ +unsigned long mac_orig_videoaddr; + +/* Mac specific keyboard functions */ extern int mac_keyb_init(void); extern int mac_kbdrate(struct kbd_repeat *k); extern void mac_kbd_leds(unsigned int leds); +extern void mac_kbd_reset_setup(char*, int); + +/* Mac specific irq functions */ +extern void mac_init_IRQ (void); +extern void (*mac_handlers[]) (int, void *, struct pt_regs *); +extern int mac_request_irq (unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long flags, const char *devname, + void *dev_id); +extern void mac_free_irq (unsigned int irq, void *dev_id); +extern void mac_enable_irq (unsigned int); +extern void mac_disable_irq (unsigned int); +static void mac_get_model(char *model); +/*static int mac_get_hardware_list(char *buffer);*/ +extern int mac_get_irq_list (char *); + +/* Mac specific timer functions */ +extern unsigned long mac_gettimeoffset (void); +extern void mac_gettod (int *, int *, int *, int *, int *, int *); +extern int mac_hwclk (int, struct hwclk_time *); +extern int mac_set_clock_mmss (unsigned long); +extern void via_init_clock(void (*func)(int, void *, struct pt_regs *)); extern void (*kd_mksound)(unsigned int, unsigned int); extern void mac_mksound(unsigned int, unsigned int); extern int mac_floppy_init(void); extern void mac_floppy_setup(char *,int *); -extern void mac_gettod (int *, int *, int *, int *, int *, int *); - extern void nubus_sweep_video(void); -extern void via_init_clock(void (*func)(int, void *, struct pt_regs *)); -extern void mac_debugging_long(int, long); /* Mac specific debug functions (in debug.c) */ extern void mac_debug_init(void); +extern void mac_debugging_long(int, long); #ifdef CONFIG_MAGIC_SYSRQ + +/* XXX FIXME: Atari scancodes still */ static char mac_sysrq_xlate[128] = - "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ - "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ - "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ - "bnm,./\000\000\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ + "bnm,./\000\000\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ "\206\207\210\211\212\000\000\000\000\000-\000\000\000+\000"/* 0x40 - 0x4f */ "\000\000\000\177\000\000\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ - "\000\000\000()/*789456123" /* 0x60 - 0x6f */ + "\000\000\000()/*789456123" /* 0x60 - 0x6f */ "0.\r\000\000\000\000\000\000\000\000\000\000\000\000\000"; /* 0x70 - 0x7f */ #endif extern void (*kd_mksound)(unsigned int, unsigned int); -void mac_get_model(char *str) -{ - strcpy(str,"Macintosh"); -} +static void mac_get_model(char *str); void mac_bang(int irq, void *vector, struct pt_regs *p) { @@ -107,27 +128,22 @@ void mac_sched_init(void (*vector)(int, void *, struct pt_regs *)) via_init_clock(vector); } -unsigned long mac_gettimeoffset (void) -{ - return 0L; -} - extern int console_loglevel; +/* + * This function translates the boot timeval into a proper date, to initialize + * the system time. + */ + void mac_gettod (int *yearp, int *monp, int *dayp, int *hourp, int *minp, int *secp) { unsigned long time; int leap, oldleap, isleap; - int mon_days[14] = { -1, 31, 27, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, -1 }; + int mon_days[14] = { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, -1 }; time = mac_bi_data.boottime - 60*mac_bi_data.gmtbias; /* seconds */ -#if 0 - printk("mac_gettod: boottime 0x%lx gmtbias %ld \n", - mac_bi_data.boottime, mac_bi_data.gmtbias); -#endif - *minp = time / 60; *secp = time - (*minp * 60); time = *minp; /* minutes now */ @@ -143,7 +159,7 @@ void mac_gettod (int *yearp, int *monp, int *dayp, /* for leap day calculation */ *yearp = (time / 365) + 1970; /* approx. year */ - /* leap year calculation - there's an easier way, I bet */ + /* leap year calculation - there's an easier way, I bet. And it's broken :-( */ /* calculate leap days up to previous year */ oldleap = (*yearp-1)/4 - (*yearp-1)/100 + (*yearp-1)/400; /* calculate leap days incl. this year */ @@ -161,7 +177,7 @@ void mac_gettod (int *yearp, int *monp, int *dayp, time = *dayp; if (isleap) /* add leap day ?? */ - mon_days[2] = 28; + mon_days[2] += 1; /* count the months */ for (*monp = 1; time > mon_days[*monp]; (*monp)++) @@ -169,15 +185,29 @@ void mac_gettod (int *yearp, int *monp, int *dayp, *dayp = time; -#if 1 - printk("mac_gettod: %d-%d-%d %d:%d.%d GMT (GMT offset %d)\n", - *yearp, *monp, *dayp, *hourp, *minp, *secp, - (signed long) mac_bi_data.gmtbias); -#endif - return; } +/* + * TBI: read and write hwclock + */ + +int mac_hwclk( int op, struct hwclk_time *t ) +{ + return 0; +} + +/* + * TBI: set minutes/seconds in hwclock + */ + +int mac_set_clock_mmss (unsigned long nowtime) +{ + short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60; + + return 0; +} + void mac_waitbut (void) { ; @@ -187,11 +217,6 @@ extern struct consw fb_con; extern struct fb_info *mac_fb_init(long *); extern void mac_video_setup(char *, int *); -void mac_debug_init (void) -{ - ; -} - void (*mac_handlers[8])(int, void *, struct pt_regs *)= { mac_default_handler, @@ -213,15 +238,14 @@ __initfunc(int mac_parse_bootinfo(const struct bi_record *record)) int unknown = 0; const u_long *data = record->data; - if (compat_bi) - return(unknown); - switch (record->tag) { case BI_MAC_MODEL: mac_bi_data.id = *data; break; case BI_MAC_VADDR: - mac_bi_data.videoaddr = *data; + /* save booter supplied videobase; use the one mapped in head.S! */ + mac_orig_videoaddr = *data; + mac_bi_data.videoaddr = mac_videobase; break; case BI_MAC_VDEPTH: mac_bi_data.videodepth = *data; @@ -256,39 +280,6 @@ __initfunc(int mac_parse_bootinfo(const struct bi_record *record)) return(unknown); } -__initfunc(void mac_copy_compat(void)) -{ - int i; - - compat_bi = 1; - - for (i=0; i<compat_boot_info.num_memory; i++) { - m68k_memory[m68k_num_memory].addr = compat_boot_info.memory[i].addr; - m68k_memory[m68k_num_memory].size = compat_boot_info.memory[i].size; - m68k_num_memory++; - } - - m68k_ramdisk.addr = compat_boot_info.ramdisk_addr; - m68k_ramdisk.size = compat_boot_info.ramdisk_size; - - strncpy(m68k_command_line, (const char *)compat_boot_info.command_line, - CL_SIZE); - m68k_command_line[CL_SIZE-1] = '\0'; - - mac_bi_data.id = compat_boot_info.bi_mac.id; - mac_bi_data.videoaddr = compat_boot_info.bi_mac.videoaddr; - mac_bi_data.videodepth = compat_boot_info.bi_mac.videodepth; - mac_bi_data.videorow = compat_boot_info.bi_mac.videorow; - mac_bi_data.dimensions = compat_boot_info.bi_mac.dimensions; - mac_bi_data.videological = compat_boot_info.bi_mac.videological; - mac_bi_data.sccbase = compat_boot_info.bi_mac.sccbase; - mac_bi_data.boottime = compat_boot_info.bi_mac.boottime; - mac_bi_data.gmtbias = compat_boot_info.bi_mac.gmtbias; - mac_bi_data.memsize = compat_boot_info.bi_mac.memsize; - mac_bi_data.cpuid = compat_boot_info.bi_mac.cpuid; - -} - __initfunc(void config_mac(void)) { @@ -296,14 +287,13 @@ __initfunc(void config_mac(void)) printk("ERROR: no Mac, but config_mac() called!! \n"); } - mac_debugging_penguin(5); - mac_debug_init(); mach_sched_init = mac_sched_init; mach_keyb_init = mac_keyb_init; mach_kbdrate = mac_kbdrate; mach_kbd_leds = mac_kbd_leds; + kbd_reset_setup = mac_kbd_reset_setup; mach_init_IRQ = mac_init_IRQ; mach_request_irq = mac_request_irq; mach_free_irq = mac_free_irq; @@ -316,15 +306,13 @@ __initfunc(void config_mac(void)) mach_get_irq_list = mac_get_irq_list; mach_gettimeoffset = mac_gettimeoffset; mach_gettod = mac_gettod; + mach_hwclk = mac_hwclk; + mach_set_clock_mmss = mac_set_clock_mmss; #if 0 mach_mksound = mac_mksound; #endif mach_reset = mac_reset; -#ifdef CONFIG_BLK_DEV_FD - mach_floppy_init = mac_floppy_init; - mach_floppy_setup = mac_floppy_setup; -#endif - conswitchp = &fb_con; + conswitchp = &dummy_con; mach_max_dma_address = 0xffffffff; #if 0 mach_debug_init = mac_debug_init; @@ -361,11 +349,20 @@ __initfunc(void config_mac(void)) */ nubus_sweep_video(); + } /* - * Macintosh Table + * Macintosh Table: hardcoded model configuration data. + * + * Much of this was defined by Alan, based on who knows what docs. + * I've added a lot more, and some of that was pure guesswork based + * on hardware pages present on the Mac web site. Possibly wildly + * inaccurate, so look here if a new Mac model won't run. Example: if + * a Mac crashes immediately after the VIA1 registers have been dumped + * to the screen, it probably died attempting to read DirB on a RBV. + * Meaning it should have MAC_VIA_IIci here :-) */ struct mac_model *macintosh_config; @@ -389,10 +386,11 @@ static struct mac_model mac_data_table[]= * * The IIfx apparently has different ADB hardware, and stuff * so zany nobody knows how to drive it. + * Even so, with Marten's help we'll try to deal with it :-) */ { MAC_MODEL_IICI, "IIci", MAC_ADB_II, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_IIFX, "IIfx", MAC_ADB_NONE, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_IIFX, "IIfx", MAC_ADB_II, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_IISI, "IIsi", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_IIVI, "IIvi", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_IIVX, "IIvx", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, @@ -405,9 +403,10 @@ static struct mac_model mac_data_table[]= { MAC_MODEL_CCL, "Color Classic", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, /* - * Some Mac LC machines. Basically the same as the IIci + * Some Mac LC machines. Basically the same as the IIci, ADB like IIsi */ + { MAC_MODEL_LC, "LC", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_LCII, "LC II", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_LCIII,"LC III", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, @@ -416,75 +415,74 @@ static struct mac_model mac_data_table[]= * 0xF9000000, via is like a MacII. We label it differently as some of the * stuff connected to VIA2 seems different. Better SCSI chip and ???? onboard ethernet * in all cases using a NatSemi SONIC. The 700, 900 and 950 have some I/O chips in the wrong - * place to confuse us. The 840 seems to have a scsi location of its own + * place to confuse us. The 840AV seems to have a scsi location of its own */ - { MAC_MODEL_Q605, "Quadra 605", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, - { MAC_MODEL_Q610, "Quadra 610", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, - { MAC_MODEL_Q630, "Quadra 630", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, - { MAC_MODEL_Q650, "Quadra 650", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q605, "Quadra 605", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q610, "Quadra 610", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q630, "Quadra 630", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_QUADRA, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q650, "Quadra 650", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, /* The Q700 does have a NS Sonic */ -#if 0 - { MAC_MODEL_Q700, "Quadra 700", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS}, - { MAC_MODEL_Q800, "Quadra 800", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, -#else - { MAC_MODEL_Q700, "Quadra 700", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS}, - { MAC_MODEL_Q800, "Quadra 800", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, -#endif - /* Does the 840 have ethernet ??? documents seem to indicate its not quite a + { MAC_MODEL_Q700, "Quadra 700", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q800, "Quadra 800", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, + /* Does the 840AV have ethernet ??? documents seem to indicate its not quite a Quadra in this respect ? */ - { MAC_MODEL_Q840, "Quadra 840", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_Q900, "Quadra 900", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS}, - { MAC_MODEL_Q950, "Quadra 950", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q840, "Quadra 840AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + /* These might have IOP problems */ + { MAC_MODEL_Q900, "Quadra 900", MAC_ADB_IISI, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_IOP, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q950, "Quadra 950", MAC_ADB_IISI, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_IOP, MAC_ETHER_SONIC, MAC_NUBUS}, /* * Performa - more LC type machines */ - { MAC_MODEL_P460, "Performa 460", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_P475, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_P520, "Performa 520", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_P550, "Performa 550", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_P575, "Performa 575", MAC_ADB_CUDA, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_TV, "TV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P460, "Performa 460", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P475, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P475F, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P520, "Performa 520", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P550, "Performa 550", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P575, "Performa 575", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P588, "Performa 588", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_TV, "TV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P600, "Performa 600", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, #if 0 /* other sources seem to suggest the P630/Q630/LC630 is more like LCIII */ - { MAC_MODEL_P630, "Performa 630", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P630, "Performa 630", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, #endif /* * Centris - just guessing again; maybe like Quadra */ - { MAC_MODEL_C610, "Centris 610", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_C650, "Centris 650", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_C660, "Centris 660AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_C610, "Centris 610", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_C650, "Centris 650", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_C660, "Centris 660AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, /* * Power books - seem similar to early Quadras ? (most have 030 though) */ - { MAC_MODEL_PB140, "PowerBook 140", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB145, "PowerBook 145", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB140, "PowerBook 140", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB145, "PowerBook 145", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, /* The PB150 has IDE, and IIci style VIA */ - { MAC_MODEL_PB150, "PowerBook 150", MAC_ADB_CUDA, MAC_VIA_IIci, MAC_SCSI_QUADRA, MAC_IDE_PB, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB160, "PowerBook 160", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB165, "PowerBook 165", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB165C, "PowerBook 165c", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB170, "PowerBook 170", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB180, "PowerBook 180", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB180C, "PowerBook 180c", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB190, "PowerBook 190cs", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB520, "PowerBook 520", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB150, "PowerBook 150", MAC_ADB_PB1, MAC_VIA_IIci, MAC_SCSI_QUADRA, MAC_IDE_PB, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB160, "PowerBook 160", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB165, "PowerBook 165", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB165C, "PowerBook 165c", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB170, "PowerBook 170", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB180, "PowerBook 180", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB180C, "PowerBook 180c", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB190, "PowerBook 190cs", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_PB, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB520, "PowerBook 520", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, /* * Power book Duos - similar to Power books, I hope */ - { MAC_MODEL_PB210, "PowerBook Duo 210", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB230, "PowerBook Duo 230", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB250, "PowerBook Duo 250", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB270C, "PowerBook Duo 270c", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB280, "PowerBook Duo 280", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB280C, "PowerBook Duo 280c", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB210, "PowerBook Duo 210", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB230, "PowerBook Duo 230", MAC_ADB_PB2, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB250, "PowerBook Duo 250", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB270C, "PowerBook Duo 270c", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB280, "PowerBook Duo 280", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB280C, "PowerBook Duo 280c", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, /* * Other stuff ?? @@ -517,8 +515,6 @@ void mac_identify(void) { printk("\nUnknown macintosh model %d, probably unsupported.\n", model); - mac_debugging_long(1, (long) 0x55555555); - mac_debugging_long(1, (long) model); model = MAC_MODEL_Q800; printk("Defaulting to: Quadra800, model id %d\n", model); printk("Please report this case to linux-mac68k@wave.lm.com\n"); @@ -536,19 +532,22 @@ void mac_identify(void) /* * Report booter data: */ - printk (" Penguin (bootinfo version %d) data:\n", 2-compat_bi); - printk (" Video: addr 0x%lx row 0x%lx depth %lx dimensions %d x %d\n", + printk (" Penguin bootinfo data:\n"); + printk (" Video: addr 0x%lx row 0x%lx depth %lx dimensions %ld x %ld\n", mac_bi_data.videoaddr, mac_bi_data.videorow, - mac_bi_data.videodepth, mac_bi_data.dimensions & 0xFFFF, - mac_bi_data.dimensions >> 16); + mac_bi_data.videodepth, (int) (mac_bi_data.dimensions & 0xFFFF), + (int) (mac_bi_data.dimensions >> 16)); + printk (" Videological 0x%lx phys. 0x%lx, SCC at 0x%lx \n", + mac_bi_data.videological, mac_orig_videoaddr, + mac_bi_data.sccbase); printk (" Boottime: 0x%lx GMTBias: 0x%lx \n", mac_bi_data.boottime, mac_bi_data.gmtbias); - printk (" Videological 0x%lx, SCC at 0x%lx \n", - mac_bi_data.videological, mac_bi_data.sccbase); printk (" Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n", mac_bi_data.id, mac_bi_data.cpuid, mac_bi_data.memsize); +#if 0 printk ("Ramdisk: addr 0x%lx size 0x%lx\n", m68k_ramdisk.addr, m68k_ramdisk.size); +#endif /* * Save the pointer @@ -559,6 +558,25 @@ void mac_identify(void) /* * TODO: set the various fields in macintosh_config->hw_present here! */ + switch (macintosh_config->scsi_type) { + case MAC_SCSI_OLD: + MACHW_SET(MAC_SCSI_80); + break; + case MAC_SCSI_QUADRA: + case MAC_SCSI_QUADRA2: + case MAC_SCSI_QUADRA3: + MACHW_SET(MAC_SCSI_96); + if ((macintosh_config->ident == MAC_MODEL_Q900) || + (macintosh_config->ident == MAC_MODEL_Q950)) + MACHW_SET(MAC_SCSI_96_2); + break; + default: + printk("config.c: wtf: unknown scsi, using 53c80\n"); + MACHW_SET(MAC_SCSI_80); + break; + + } + } @@ -567,6 +585,12 @@ void mac_report_hardware(void) printk("Apple Macintosh %s\n", macintosh_config->name); } +static void mac_get_model(char *str) +{ + strcpy(str,"Macintosh "); + strcat(str, macintosh_config->name); +} + /* * Local variables: * c-indent-level: 4 diff --git a/arch/m68k/mac/debug.c b/arch/m68k/mac/debug.c index cc6f491fb..6fc3ac52d 100644 --- a/arch/m68k/mac/debug.c +++ b/arch/m68k/mac/debug.c @@ -16,6 +16,7 @@ #include <linux/config.h> #include <linux/types.h> +#include <linux/sched.h> #include <linux/tty.h> #include <linux/console.h> #include <linux/init.h> @@ -35,6 +36,9 @@ extern unsigned long mac_videobase; extern unsigned long mac_videodepth; extern unsigned long mac_rowbytes; +#define DEBUG_SCREEN +#define DEBUG_SERIAL + /* * These two auxiliary debug functions should go away ASAP. Only usage: * before the console output is up (after head.S come some other crucial @@ -45,21 +49,30 @@ extern unsigned long mac_rowbytes; * The 'pos' argument now simply means 'linefeed after print' ... */ +#ifdef DEBUG_SCREEN static int peng=0, line=0; +#endif void mac_debugging_short(int pos, short num) { +#ifdef DEBUG_SCREEN unsigned char *pengoffset; unsigned char *pptr; int i; +#endif + +#ifdef DEBUG_SERIAL + printk("debug: %d !\n", num); +#endif +#ifdef DEBUG_SCREEN if (!MACH_IS_MAC) { /* printk("debug: %d !\n", num); */ return; } /* calculate current offset */ - pengoffset=(unsigned char *)(mac_videobase+(20+line*2)*mac_rowbytes) + pengoffset=(unsigned char *)(mac_videobase+(150+line*2)*mac_rowbytes) +80*peng; pptr=pengoffset; @@ -76,20 +89,28 @@ void mac_debugging_short(int pos, short num) line++; peng = 0; } +#endif } void mac_debugging_long(int pos, long addr) { +#ifdef DEBUG_SCREEN unsigned char *pengoffset; unsigned char *pptr; int i; +#endif +#ifdef DEBUG_SERIAL + printk("debug: #%ld !\n", addr); +#endif + +#ifdef DEBUG_SCREEN if (!MACH_IS_MAC) { /* printk("debug: #%ld !\n", addr); */ return; } - pengoffset=(unsigned char *)(mac_videobase+(20+line*2)*mac_rowbytes) + pengoffset=(unsigned char *)(mac_videobase+(150+line*2)*mac_rowbytes) +80*peng; pptr=pengoffset; @@ -105,6 +126,7 @@ void mac_debugging_long(int pos, long addr) line++; peng = 0; } +#endif } /* @@ -114,24 +136,33 @@ char that_penguin[]={ #include "that_penguin.h" }; +#ifdef DEBUG_SCREEN /* * B/W version of penguin, unfinished - any takers?? */ static char bw_penguin[]={ #include "bw_penguin.h" }; +#endif void mac_debugging_penguin(int peng) { +#ifdef DEBUG_SCREEN unsigned char *pengoffset; unsigned char *pptr; unsigned char *bwpdptr=bw_penguin; int i; +#endif +#ifdef DEBUG_SERIAL + printk("Penguin: #%d !\n", peng); +#endif + +#ifdef DEBUG_SCREEN if (!MACH_IS_MAC) return; - if (compat_boot_info.bi_mac.videodepth ==1) + if (mac_videodepth ==1) pengoffset=(unsigned char *)(mac_videobase+80*mac_rowbytes) +5*peng; else @@ -146,15 +177,19 @@ void mac_debugging_penguin(int peng) bwpdptr+=4; pptr+=mac_rowbytes; } +#endif } +#ifdef DEBUG_SCREEN /* * B/W version of flaming Mac, unfinished (see above). */ static char bw_kaboom_map[]={ #include "bw_mac.h" }; +#endif +#ifdef DEBUG_SCREEN static void mac_boom_boom(void) { static unsigned char *boomoffset=NULL; @@ -162,14 +197,21 @@ static void mac_boom_boom(void) unsigned char *bwpdptr=bw_kaboom_map; int i; +#ifdef DEBUG_SERIAL + printk("BOOM !\n"); +#endif + + if (!MACH_IS_MAC) + return; + if(!boomoffset) - if (compat_boot_info.bi_mac.videodepth == 1) { + if (mac_videodepth == 1) { boomoffset=(unsigned char *)(mac_videobase+160*mac_rowbytes); } else { boomoffset=(unsigned char *)(mac_videobase+256*mac_rowbytes); } else - if (compat_boot_info.bi_mac.videodepth == 1) + if (mac_videodepth == 1) boomoffset+=5; else boomoffset+=32; @@ -183,25 +225,43 @@ static void mac_boom_boom(void) pptr+=mac_rowbytes; } } +#endif void mac_boom(int booms) { +#ifdef DEBUG_SCREEN int i; +#endif if (!MACH_IS_MAC) return; +#ifdef DEBUG_SCREEN for(i=0;i<booms;i++) mac_boom_boom(); while(1); +#endif } -#if 0 +#ifdef DEBUG_SERIAL /* * TODO: serial debug code */ +#define SCC_BAS (0x50F04000) +struct SCC + { + u_char cha_b_ctrl; + u_char char_dummy1; + u_char cha_a_ctrl; + u_char char_dummy2; + u_char cha_b_data; + u_char char_dummy3; + u_char cha_a_data; + }; +# define scc ((*(volatile struct SCC*)SCC_BAS)) + /* Flag that serial port is already initialized and used */ int mac_SCC_init_done = 0; /* Can be set somewhere, if a SCC master reset has already be done and should @@ -224,54 +284,113 @@ static struct console mac_console_driver = { static int scc_port; -static inline void mac_scc_out (char c) +/* Mac: loops_per_sec min. 1900000 ^= .5 us; MFPDELAY was 0.6 us*/ + +#define US 1 + +static inline void mac_sccb_out (char c) { + int i; do { - MFPDELAY(); + for( i = US; i > 0; --i ) + barrier(); } while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */ - MFPDELAY(); + for( i = US; i > 0; --i ) + barrier(); scc.cha_b_data = c; } -void mac_scc_console_write (struct console *co, const char *str, +static inline void mac_scca_out (char c) +{ + int i; + do { + for( i = US; i > 0; --i ) + barrier(); + } while (!(scc.cha_a_ctrl & 0x04)); /* wait for tx buf empty */ + for( i = US; i > 0; --i ) + barrier(); + scc.cha_a_data = c; +} + +void mac_sccb_console_write (struct console *co, const char *str, unsigned int count) { while (count--) { if (*str == '\n') - mac_scc_out( '\r' ); - mac_scc_out( *str++ ); + mac_sccb_out( '\r' ); + mac_sccb_out( *str++ ); + } +} + +void mac_scca_console_write (struct console *co, const char *str, + unsigned int count) +{ + while (count--) { + if (*str == '\n') + mac_scca_out( '\r' ); + mac_scca_out( *str++ ); } } #ifdef CONFIG_SERIAL_CONSOLE -int mac_scc_console_wait_key(struct console *co) +int mac_sccb_console_wait_key(struct console *co) { + int i; do { - MFPDELAY(); + for( i = US; i > 0; --i ) + barrier(); } while( !(scc.cha_b_ctrl & 0x01) ); /* wait for rx buf filled */ - MFPDELAY(); + for( i = US; i > 0; --i ) + barrier(); return( scc.cha_b_data ); } + +int mac_scca_console_wait_key(struct console *co) +{ + int i; + do { + for( i = US; i > 0; --i ) + barrier(); + } while( !(scc.cha_a_ctrl & 0x01) ); /* wait for rx buf filled */ + for( i = US; i > 0; --i ) + barrier(); + return( scc.cha_a_data ); +} #endif /* The following two functions do a quick'n'dirty initialization of the MFP or * SCC serial ports. They're used by the debugging interface, kgdb, and the * serial console code. */ -#define SCC_WRITE(reg,val) \ +#define SCCB_WRITE(reg,val) \ do { \ + int i; \ scc.cha_b_ctrl = (reg); \ - MFPDELAY(); \ + for( i = US; i > 0; --i ) \ + barrier(); \ scc.cha_b_ctrl = (val); \ - MFPDELAY(); \ + for( i = US; i > 0; --i ) \ + barrier(); \ + } while(0) + +#define SCCA_WRITE(reg,val) \ + do { \ + int i; \ + scc.cha_a_ctrl = (reg); \ + for( i = US; i > 0; --i ) \ + barrier(); \ + scc.cha_a_ctrl = (val); \ + for( i = US; i > 0; --i ) \ + barrier(); \ } while(0) /* loops_per_sec isn't initialized yet, so we can't use udelay(). This does a * delay of ~ 60us. */ +/* Mac: loops_per_sec min. 1900000 ^= .5 us; MFPDELAY was 0.6 us*/ #define LONG_DELAY() \ do { \ int i; \ - for( i = 100; i > 0; --i ) \ - MFPDELAY(); \ + for( i = 60*US; i > 0; --i ) \ + barrier(); \ } while(0) #ifndef CONFIG_SERIAL_CONSOLE @@ -309,30 +428,56 @@ void mac_init_scc_port( int cflag, int port ) reg3 = (cflag & CSIZE) == CS8 ? 0xc0 : 0x40; reg5 = (cflag & CSIZE) == CS8 ? 0x60 : 0x20 | 0x82 /* assert DTR/RTS */; - - (void)scc.cha_b_ctrl; /* reset reg pointer */ - SCC_WRITE( 9, 0xc0 ); /* reset */ - LONG_DELAY(); /* extra delay after WR9 access */ - SCC_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 | - 0x04 /* 1 stopbit */ | - clkmode ); - SCC_WRITE( 3, reg3 ); - SCC_WRITE( 5, reg5 ); - SCC_WRITE( 9, 0 ); /* no interrupts */ - LONG_DELAY(); /* extra delay after WR9 access */ - SCC_WRITE( 10, 0 ); /* NRZ mode */ - SCC_WRITE( 11, clksrc ); /* main clock source */ - SCC_WRITE( 12, div ); /* BRG value */ - SCC_WRITE( 13, 0 ); /* BRG high byte */ - SCC_WRITE( 14, brgsrc_table[baud] ); - SCC_WRITE( 14, brgsrc_table[baud] | (div ? 1 : 0) ); - SCC_WRITE( 3, reg3 | 1 ); - SCC_WRITE( 5, reg5 | 8 ); - + +#if 0 + if (port) { +#endif + (void)scc.cha_b_ctrl; /* reset reg pointer */ + SCCB_WRITE( 9, 0xc0 ); /* reset */ + LONG_DELAY(); /* extra delay after WR9 access */ + SCCB_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 | + 0x04 /* 1 stopbit */ | + clkmode ); + SCCB_WRITE( 3, reg3 ); + SCCB_WRITE( 5, reg5 ); + SCCB_WRITE( 9, 0 ); /* no interrupts */ + LONG_DELAY(); /* extra delay after WR9 access */ + SCCB_WRITE( 10, 0 ); /* NRZ mode */ + SCCB_WRITE( 11, clksrc ); /* main clock source */ + SCCB_WRITE( 12, div ); /* BRG value */ + SCCB_WRITE( 13, 0 ); /* BRG high byte */ + SCCB_WRITE( 14, brgsrc_table[baud] ); + SCCB_WRITE( 14, brgsrc_table[baud] | (div ? 1 : 0) ); + SCCB_WRITE( 3, reg3 | 1 ); + SCCB_WRITE( 5, reg5 | 8 ); +#if 0 + } else { +#endif + (void)scc.cha_a_ctrl; /* reset reg pointer */ + SCCA_WRITE( 9, 0xc0 ); /* reset */ + LONG_DELAY(); /* extra delay after WR9 access */ + SCCA_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 | + 0x04 /* 1 stopbit */ | + clkmode ); + SCCA_WRITE( 3, reg3 ); + SCCA_WRITE( 5, reg5 ); + SCCA_WRITE( 9, 0 ); /* no interrupts */ + LONG_DELAY(); /* extra delay after WR9 access */ + SCCA_WRITE( 10, 0 ); /* NRZ mode */ + SCCA_WRITE( 11, clksrc ); /* main clock source */ + SCCA_WRITE( 12, div ); /* BRG value */ + SCCA_WRITE( 13, 0 ); /* BRG high byte */ + SCCA_WRITE( 14, brgsrc_table[baud] ); + SCCA_WRITE( 14, brgsrc_table[baud] | (div ? 1 : 0) ); + SCCA_WRITE( 3, reg3 | 1 ); + SCCA_WRITE( 5, reg5 | 8 ); +#if 0 + } +#endif mac_SCC_reset_done = 1; mac_SCC_init_done = 1; } - +#endif /* DEBUG_SERIAL */ __initfunc(void mac_debug_init(void)) { @@ -340,23 +485,24 @@ __initfunc(void mac_debug_init(void)) /* the m68k_debug_device is used by the GDB stub, do nothing here */ return; #endif +#ifdef DEBUG_SERIAL if (!strcmp( m68k_debug_device, "ser" )) { strcpy( m68k_debug_device, "ser1" ); } if (!strcmp( m68k_debug_device, "ser1" )) { /* ST-MFP Modem1 serial port */ mac_init_scc_port( B9600|CS8, 0 ); - mac_console_driver.write = mac_scc_console_write; + mac_console_driver.write = mac_scca_console_write; } else if (!strcmp( m68k_debug_device, "ser2" )) { /* SCC Modem2 serial port */ mac_init_scc_port( B9600|CS8, 1 ); - mac_console_driver.write = mac_scc_console_write; + mac_console_driver.write = mac_sccb_console_write; } if (mac_console_driver.write) register_console(&mac_console_driver); -} #endif +} /* * Local variables: diff --git a/arch/m68k/mac/ksyms.c b/arch/m68k/mac/mac_ksyms.c index 05373b04e..05373b04e 100644 --- a/arch/m68k/mac/ksyms.c +++ b/arch/m68k/mac/mac_ksyms.c diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c index b9c3331e9..d2ea26e05 100644 --- a/arch/m68k/mac/macints.c +++ b/arch/m68k/mac/macints.c @@ -28,6 +28,12 @@ * * 7 - Debug output * + * AV Macs only, handled by PSC: + * + * 3 - MACE ethernet IRQ (DMA complete on level 4) + * + * 5 - DSP ?? + * * Using the autovector irq numbers for Linux/m68k hardware interrupts without * the IRQ_MACHSPEC bit set would interfere with the general m68k interrupt * handling in kernel versions 2.0.x, so the following strategy is used: @@ -57,13 +63,19 @@ * should be sufficient to use the same numbers (everything > 7 is assumed * to be machspec, according to Jes!). * + * TODO: + * - integrate Nubus interrupts in request/free_irq + * + * - */ +#include <linux/config.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/kernel_stat.h> #include <linux/interrupt.h> /* for intr_count */ +#include <linux/delay.h> #include <asm/system.h> #include <asm/irq.h> @@ -98,7 +110,10 @@ struct irqflags { static struct irqhandler via1_handler[8]; static struct irqhandler via2_handler[8]; static struct irqhandler rbv_handler[8]; +static struct irqhandler psc3_handler[8]; static struct irqhandler scc_handler[8]; +static struct irqhandler psc5_handler[8]; +static struct irqhandler psc6_handler[8]; static struct irqhandler nubus_handler[8]; static struct irqhandler *handler_table[8]; @@ -111,7 +126,10 @@ static struct irqhandler *handler_table[8]; static struct irqparam via1_param[8]; static struct irqparam via2_param[8]; static struct irqparam rbv_param[8]; +static struct irqparam psc3_param[8]; static struct irqparam scc_param[8]; +static struct irqparam psc5_param[8]; +static struct irqparam psc6_param[8]; static struct irqparam nubus_param[8]; static struct irqparam *param_table[8]; @@ -125,27 +143,57 @@ static struct irqflags irq_flags[8]; /* * This array holds the pointers to the various VIA or other interrupt - * controllers + * controllers, indexed by interrupt level */ static volatile unsigned char *via_table[8]; -#ifdef VIABASE_WEIRDNESS /* - * VIA2 / RBV default base address + * Arrays with irq statistics */ +static unsigned long via1_irqs[8]; +static unsigned long via2_irqs[8]; +static unsigned long rbv_irqs[8]; +static unsigned long psc3_irqs[8]; +static unsigned long scc_irqs[8]; +static unsigned long psc5_irqs[8]; +static unsigned long psc6_irqs[8]; +static unsigned long nubus_irqs[8]; -volatile unsigned char *via2_regp = ((volatile unsigned char *)VIA2_BAS); -volatile unsigned char *rbv_regp = ((volatile unsigned char *)VIA2_BAS_IIci); -#endif +static unsigned long *mac_irqs[8]; + +/* + * VIA2 / RBV register base pointers + */ + +volatile unsigned char *via2_regp=(volatile unsigned char *)VIA2_BAS; +volatile unsigned char *rbv_regp=(volatile unsigned char *)VIA2_BAS_IIci; +volatile unsigned char *oss_regp=(volatile unsigned char *)OSS_BAS; +volatile unsigned char *psc_regp=(volatile unsigned char *)PSC_BAS; /* * Flags to control via2 / rbv behaviour */ static int via2_is_rbv = 0; +static int via2_is_oss = 0; static int rbv_clear = 0; +/* fake VIA2 to OSS bit mapping */ +static int oss_map[8] = {2, 7, 0, 1, 3, 4, 5}; + +void oss_irq(int irq, void *dev_id, struct pt_regs *regs); +static void oss_do_nubus(int irq, void *dev_id, struct pt_regs *regs); + +/* PSC ints */ +void psc_irq(int irq, void *dev_id, struct pt_regs *regs); + +/* + * PSC hooks + */ + +extern void psc_init(void); + /* * console_loglevel determines NMI handler function */ @@ -174,11 +222,13 @@ void mac_init_IRQ(void) { int i; - mac_debugging_penguin(6); - #ifdef DEBUG_MACINTS printk("Mac interrupt stuff initializing ...\n"); #endif + + via2_regp = (unsigned char *)VIA2_BAS; + rbv_regp = (unsigned char *)VIA2_BAS_IIci; + /* initialize the hardwired (primary, autovector) IRQs */ /* level 1 IRQ: VIA1, always present */ @@ -186,17 +236,33 @@ void mac_init_IRQ(void) /* via2 or rbv?? */ if (macintosh_config->via_type == MAC_VIA_IIci) { - /* VIA2 is part of the RBV: different base, other offsets */ - via2_is_rbv = 1; - /* LC III weirdness: IFR seems to behave like VIA2 */ - /* FIXME: maybe also for LC II ?? */ - if (macintosh_config->ident == MAC_MODEL_LCIII) { - rbv_clear = 0x0; + /* + * A word of caution: the definitions here only affect interrupt + * handling, see via6522.c for yet another file to change + * base addresses and RBV flags + */ + + /* yes, this is messy - the IIfx deserves a class of his own */ + if (macintosh_config->ident == MAC_MODEL_IIFX) { + /* no real VIA2, the OSS seems _very_different */ + via2_is_oss = 1; + /* IIfx has OSS, at a different base address than RBV */ + rbv_regp = (unsigned char *) OSS_BAS; + sys_request_irq(2, oss_irq, IRQ_FLG_LOCK, "oss", oss_irq); } else { - rbv_clear = 0x80; + /* VIA2 is part of the RBV: different base, other offsets */ + via2_is_rbv = 1; + + /* LC III weirdness: IFR seems to behave like VIA2 */ + /* FIXME: maybe also for LC II ?? */ + if (macintosh_config->ident == MAC_MODEL_LCIII) { + rbv_clear = 0x0; + } else { + rbv_clear = 0x80; + } + /* level 2 IRQ: RBV/OSS; we only care about RBV for now */ + sys_request_irq(2, rbv_irq, IRQ_FLG_LOCK, "rbv", rbv_irq); } - /* level 2 IRQ: RBV/OSS; we only care about RBV for now */ - sys_request_irq(2, rbv_irq, IRQ_FLG_LOCK, "rbv", rbv_irq); } else /* level 2 IRQ: VIA2 */ sys_request_irq(2, via2_irq, IRQ_FLG_LOCK, "via2", via2_irq); @@ -207,7 +273,7 @@ void mac_init_IRQ(void) * Currently, one interrupt per channel is used, solely * to pass the correct async_info as parameter! */ -#if 0 /* doesn't seem to work yet */ +#if 0 /* want to install debug/SCC shutup routine until SCC init */ sys_request_irq(4, mac_SCC_handler, IRQ_FLG_STD, "INT4", mac_SCC_handler); #else sys_request_irq(4, mac_debug_handler, IRQ_FLG_STD, "INT4", mac_debug_handler); @@ -255,26 +321,65 @@ void mac_init_IRQ(void) via_table[0] = via1_regp; handler_table[0] = &via1_handler[0]; param_table[0] = &via1_param[0]; + mac_irqs[0] = &via1_irqs[0]; - if (via2_is_rbv) { + if (via2_is_rbv || via2_is_oss) { via_table[1] = rbv_regp; handler_table[1] = &rbv_handler[0]; param_table[1] = &rbv_param[0]; + mac_irqs[1] = &rbv_irqs[0]; } else { via_table[1] = via2_regp; handler_table[1] = &via2_handler[0]; param_table[1] = &via2_param[0]; + mac_irqs[1] = &via2_irqs[0]; } via_table[2] = NULL; via_table[3] = NULL; handler_table[2] = &rbv_handler[0]; - handler_table[3] = &nubus_handler[0]; + handler_table[3] = &scc_handler[0]; + handler_table[4] = NULL; + handler_table[5] = NULL; + handler_table[6] = NULL; + handler_table[7] = &nubus_handler[0]; param_table[2] = &rbv_param[0]; - param_table[3] = &nubus_param[0]; + param_table[3] = &scc_param[0]; + param_table[7] = &nubus_param[0]; + + mac_irqs[2] = &rbv_irqs[0]; + mac_irqs[3] = &scc_irqs[0]; + mac_irqs[7] = &nubus_irqs[0]; + + /* + * AV Macs: shutup the PSC ints + */ + if (macintosh_config->ident == MAC_MODEL_C660 + || macintosh_config->ident == MAC_MODEL_Q840) { + psc_init(); + + handler_table[2] = &psc3_handler[0]; + /* handler_table[3] = &psc4_handler[0]; */ + handler_table[4] = &psc5_handler[0]; + handler_table[5] = &psc6_handler[0]; + + param_table[2] = &psc3_param[0]; + /* param_table[3] = &psc4_param[0]; */ + param_table[4] = &psc5_param[0]; + param_table[5] = &psc6_param[0]; + + mac_irqs[2] = &psc3_irqs[0]; + /* mac_irqs[3] = &psc4_irqs[0]; */ + mac_irqs[4] = &psc5_irqs[0]; + mac_irqs[5] = &psc6_irqs[0]; + + sys_request_irq(3, psc_irq, IRQ_FLG_STD, "PSC3", psc_irq); + sys_request_irq(4, psc_irq, IRQ_FLG_STD, "PSC4", psc_irq); + sys_request_irq(5, psc_irq, IRQ_FLG_STD, "PSC5", psc_irq); + sys_request_irq(6, psc_irq, IRQ_FLG_STD, "PSC6", psc_irq); + } - mac_debugging_penguin(7); #ifdef DEBUG_MACINTS printk("Mac interrupt init done!\n"); #endif @@ -284,7 +389,7 @@ void mac_init_IRQ(void) * We have no machine specific interrupts on a macintoy * Yet, we need to register/unregister interrupts ... :-) * Currently unimplemented: Test for valid irq number, chained irqs, - * Nubus interrupts. + * Nubus interrupts (use nubus_request_irq!). */ int mac_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *), @@ -315,8 +420,8 @@ int mac_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_re return -EINVAL; } - /* figure out if SCC pseudo-irq */ - if (irq >= IRQ_IDX(IRQ_SCC) && irq < IRQ_IDX(IRQ_NUBUS_1)) { + /* figure out if SCC pseudo-irq (redundant ??) */ + if (irq >= IRQ_IDX(IRQ_SCC) && irq < IRQ_IDX(IRQ_PSC5_0)) { /* set specific SCC handler */ scc_handler[irqidx].handler = handler; scc_handler[irqidx].dev_id = dev_id; @@ -326,6 +431,8 @@ int mac_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_re return 0; } + /* add similar hack for Nubus pseudo-irq here - hide nubus_request_irq */ + via = (volatile unsigned char *) via_table[srcidx]; if (!via) return -EINVAL; @@ -341,9 +448,11 @@ int mac_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_re via_param[irqidx].flags = flags; via_param[irqidx].devname = devname; - /* and turn it on ... */ + /* and turn it on ... careful, that's VIA only ... */ if (srcidx == SRC_VIA2 && via2_is_rbv) via_write(via, rIER, via_read(via, rIER)|0x80|(1<<(irqidx))); + else if (srcidx == SRC_VIA2 && via2_is_oss) + via_write(oss_regp, oss_map[irqidx]+8, 2); else via_write(via, vIER, via_read(via, vIER)|0x80|(1<<(irqidx))); @@ -351,8 +460,18 @@ int mac_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_re if (irq == IRQ_IDX(IRQ_MAC_SCSI)) { /* * Set vPCR for SCSI interrupts. (what about RBV here?) + * 980429 MS: RBV is ok, OSS seems to be differentt */ - via_write(via, vPCR, 0x66); + if (!via2_is_oss) + /* CB2 (IRQ) indep. interrupt input, positive edge */ + /* CA2 (DRQ) indep. interrupt input, positive edge */ + via_write(via, vPCR, 0x66); +#if 0 + else + /* CB2 (IRQ) indep. interrupt input, negative edge */ + /* CA2 (DRQ) indep. interrupt input, negative edge */ + via_write(via, vPCR, 0x22); +#endif } return 0; @@ -382,7 +501,7 @@ void mac_free_irq (unsigned int irq, void *dev_id) cli(); /* figure out if SCC pseudo-irq */ - if (irq >= IRQ_IDX(IRQ_SCC) && irq < IRQ_IDX(IRQ_NUBUS_1)) { + if (irq >= IRQ_IDX(IRQ_SCC) && irq < IRQ_IDX(IRQ_PSC5_0)) { /* clear specific SCC handler */ scc_handler[irqidx].handler = mac_default_handler; scc_handler[irqidx].dev_id = NULL; @@ -411,6 +530,8 @@ void mac_free_irq (unsigned int irq, void *dev_id) /* and turn it off */ if (srcidx == SRC_VIA2 && via2_is_rbv) via_write(via, rIER, (via_read(via, rIER)&(1<<irqidx))); + else if (srcidx == SRC_VIA2 && via2_is_oss) + via_write(oss_regp, oss_map[irqidx]+8, 0); else via_write(via, vIER, (via_read(via, vIER)&(1<<irqidx))); @@ -453,8 +574,8 @@ not_found: void mac_enable_irq (unsigned int irq) { - int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; - int irqidx = (irq & IRQ_IDX_MASK); + int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; + int irqidx = (irq & IRQ_IDX_MASK); irq_flags[srcidx].disabled &= ~(1<<irqidx); /* @@ -468,8 +589,8 @@ void mac_enable_irq (unsigned int irq) void mac_disable_irq (unsigned int irq) { - int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; - int irqidx = (irq & IRQ_IDX_MASK); + int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; + int irqidx = (irq & IRQ_IDX_MASK); irq_flags[srcidx].disabled |= (1<<irqidx); } @@ -481,8 +602,8 @@ void mac_disable_irq (unsigned int irq) void mac_turnon_irq( unsigned int irq ) { - int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; - int irqidx = (irq & IRQ_IDX_MASK); + int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; + int irqidx = (irq & IRQ_IDX_MASK); volatile unsigned char *via; via = (volatile unsigned char *) via_table[srcidx]; @@ -491,6 +612,11 @@ void mac_turnon_irq( unsigned int irq ) if (srcidx == SRC_VIA2 && via2_is_rbv) via_write(via, rIER, via_read(via, rIER)|0x80|(1<<(irqidx))); + else if (srcidx == SRC_VIA2 && via2_is_oss) + via_write(oss_regp, oss_map[irqidx]+8, 2); + else if (srcidx >= SRC_VIA2) + via_write(via, (0x104 + 0x10*srcidx), + via_read(via, (0x104 + 0x10*srcidx))|0x80|(1<<(irqidx))); else via_write(via, vIER, via_read(via, vIER)|0x80|(1<<(irqidx))); @@ -498,8 +624,8 @@ void mac_turnon_irq( unsigned int irq ) void mac_turnoff_irq( unsigned int irq ) { - int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; - int irqidx = (irq & IRQ_IDX_MASK); + int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; + int irqidx = (irq & IRQ_IDX_MASK); volatile unsigned char *via; via = (volatile unsigned char *) via_table[srcidx]; @@ -508,6 +634,11 @@ void mac_turnoff_irq( unsigned int irq ) if (srcidx == SRC_VIA2 && via2_is_rbv) via_write(via, rIER, (via_read(via, rIER)&(1<<irqidx))); + else if (srcidx == SRC_VIA2 && via2_is_oss) + via_write(oss_regp, oss_map[irqidx]+8, 0); + else if (srcidx >= SRC_VIA2) + via_write(via, (0x104 + 0x10*srcidx), + via_read(via, (0x104 + 0x10*srcidx))|(1<<(irqidx))); else via_write(via, vIER, (via_read(via, vIER)&(1<<irqidx))); } @@ -522,23 +653,109 @@ void mac_turnoff_irq( unsigned int irq ) void mac_clear_pending_irq( unsigned int irq ) { - int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; - int irqidx = (irq & IRQ_IDX_MASK); + int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; + int irqidx = (irq & IRQ_IDX_MASK); irq_flags[srcidx].pending &= ~(1<<irqidx); } int mac_irq_pending( unsigned int irq ) { - int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; - int irqidx = (irq & IRQ_IDX_MASK); + int pending = 0; + volatile unsigned char *via; + + int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; + int irqidx = (irq & IRQ_IDX_MASK); - return (irq_flags[srcidx].pending & (1<<irqidx)); + pending = irq_flags[srcidx].pending & (1<<irqidx); + + via = (volatile unsigned char *) via_table[srcidx]; + if (!via) + return (pending); + + if (srcidx == SRC_VIA2 && via2_is_rbv) + pending |= via_read(via, rIFR)&(1<<irqidx); + else if (srcidx == SRC_VIA2 && via2_is_oss) + pending |= via_read(via, oIFR)&0x03&(1<<oss_map[irqidx]); + else if (srcidx >= SRC_VIA2) + pending |= via_read(via, (0x100 + 0x10*srcidx))&(1<<irqidx); + else + pending |= via_read(via, vIFR)&(1<<irqidx); + + return (pending); } int mac_get_irq_list (char *buf) { - return 0; + int i, len = 0; + int srcidx, irqidx; + + for (i = VIA1_SOURCE_BASE; i < NUM_MAC_SOURCES+8; ++i) { + srcidx = ((i & IRQ_SRC_MASK)>>3) - 1; + irqidx = (i & IRQ_IDX_MASK); + + /* + * Not present: skip + */ + + if (mac_irqs[srcidx] == NULL) + continue; + + /* + * never used by VIAs, unused by others so far, counts + * the magic 'nothing pending' cases ... + */ + if (irqidx == 7 && mac_irqs[srcidx][irqidx]) { + len += sprintf(buf+len, "Level %01d: %10lu (spurious) \n", + srcidx, + mac_irqs[srcidx][irqidx]); + continue; + } + + /* + * Nothing registered for this IPL: skip + */ + + if (handler_table[srcidx] == NULL) + continue; + + /* + * No handler installed: skip + */ + + if (handler_table[srcidx][irqidx].handler == mac_default_handler || + handler_table[srcidx][irqidx].handler == nubus_wtf) + continue; + + + if (i < VIA2_SOURCE_BASE) + len += sprintf(buf+len, "via1 %01d: %10lu ", + irqidx, + mac_irqs[srcidx][irqidx]); + else if (i < RBV_SOURCE_BASE) + len += sprintf(buf+len, "via2 %01d: %10lu ", + irqidx, + mac_irqs[srcidx][irqidx]); + else if (i < MAC_SCC_SOURCE_BASE) + len += sprintf(buf+len, "rbv %01d: %10lu ", + irqidx, + mac_irqs[srcidx][irqidx]); + else if (i < NUBUS_SOURCE_BASE) + len += sprintf(buf+len, "scc %01d: %10lu ", + irqidx, + mac_irqs[srcidx][irqidx]); + else /* Nubus */ + len += sprintf(buf+len, "nubus %01d: %10lu ", + irqidx, + mac_irqs[srcidx][irqidx]); + + len += sprintf(buf+len, "%s\n", + param_table[srcidx][irqidx].devname); + + } + if (num_spurious) + len += sprintf(buf+len, "spurio.: %10u\n", num_spurious); + return len; } void via_scsi_clear(void) @@ -547,6 +764,9 @@ void via_scsi_clear(void) if (via2_is_rbv) { via_write(rbv_regp, rIFR, (1<<3)|(1<<0)|0x80); deep_magic = via_read(rbv_regp, rBufB); + } else if (via2_is_oss) { + /* nothing */ + /* via_write(oss_regp, 9, 0) */; } else deep_magic = via_read(via2_regp, vBufB); mac_enable_irq( IRQ_IDX(IRQ_MAC_SCSI) ); @@ -570,12 +790,45 @@ void mac_debug_handler(int irq, void *dev_id, struct pt_regs *regs) } } +void scsi_mac_debug(void); +void scsi_mac_polled(void); + +static int in_nmi = 0; +static volatile int nmi_hold = 0; + void mac_nmi_handler(int irq, void *dev_id, struct pt_regs *fp) { + int i; /* * generate debug output on NMI switch if 'debug' kernel option given * (only works with Penguin!) */ + + in_nmi++; +#if 0 + scsi_mac_debug(); + printk("PC: %08lx\nSR: %04x SP: %p\n", fp->pc, fp->sr, fp); +#endif + for (i=0; i<100; i++) + udelay(1000); + + if (in_nmi == 1) { + nmi_hold = 1; + printk("... pausing, press NMI to resume ..."); + } else { + printk(" ok!\n"); + nmi_hold = 0; + } + + barrier(); + + while (nmi_hold == 1) + udelay(1000); + +#if 0 + scsi_mac_polled(); +#endif + if ( console_loglevel >= 8 ) { #if 0 show_state(); @@ -595,6 +848,7 @@ void mac_nmi_handler(int irq, void *dev_id, struct pt_regs *fp) /* printk("NMI "); */ #endif } + in_nmi--; } /* @@ -610,6 +864,7 @@ static void via_irq(unsigned char *via, int *viaidx, struct pt_regs *regs) int ct = 0; struct irqhandler *via_handler = handler_table[*viaidx]; struct irqparam *via_param = param_table[*viaidx]; + unsigned long *via_irqs = mac_irqs[*viaidx]; /* to be changed, possibly: for each non'masked', enabled IRQ, read * flag bit, ack and call handler ... @@ -626,7 +881,12 @@ static void via_irq(unsigned char *via, int *viaidx, struct pt_regs *regs) if(events==0) { - printk("via_irq: nothing pending!\n"); +#ifdef DEBUG_VIA + /* should go away; mostly missing timer ticks and ADB events */ + printk("via%d_irq: nothing pending, flags %x mask %x!\n", + *viaidx + 1, via_read(via, vIFR), via_read(via,vIER)); +#endif + via_irqs[7]++; return; } @@ -661,9 +921,12 @@ static void via_irq(unsigned char *via, int *viaidx, struct pt_regs *regs) /* call corresponding handlers */ if (events&(1<<i)) { if (irq_flags[*viaidx].disabled & (1<<i)) { + if (!irq_flags[*viaidx].pending&(1<<i)) + via_irqs[i]++; /* irq disabled -> mark pending */ irq_flags[*viaidx].pending |= (1<<i); } else { + via_irqs[i]++; /* irq enabled -> call handler */ (via_handler[i].handler)(irq, via, regs); } @@ -686,7 +949,9 @@ static void via_irq(unsigned char *via, int *viaidx, struct pt_regs *regs) ct++; if(events && ct>8) { +#ifdef DEBUG_VIA printk("via%d: stuck events %x\n", (*viaidx)+1, events); +#endif break; } } @@ -743,6 +1008,23 @@ void rbv_irq(int irq, void *dev_id, struct pt_regs *regs) struct irqhandler *via_handler = handler_table[srcidx]; struct irqparam *via_param = param_table[srcidx]; + /* shouldn't we disable interrupts here ?? */ + + + /* + * Shouldnt happen + */ + + if(events==0) + { +#ifdef DEBUG_VIA + printk("rbv_irq: nothing pending, flags %x mask %x!\n", + via_read(via, rIFR), via_read(via,rIER)); +#endif + rbv_irqs[7]++; + return; + } + #ifdef DEBUG_VIA /* * limited verbosity for RBV interrupts (add more if needed) @@ -757,19 +1039,6 @@ void rbv_irq(int irq, void *dev_id, struct pt_regs *regs) * If ack for masked IRQ required: keep 'pending' info separate. */ - /* shouldn't we disable interrupts here ?? */ - - - /* - * Shouldnt happen - */ - - if(events==0) - { - printk("rbv_irq: nothing pending!\n"); - return; - } - do { /* * Clear the pending flag @@ -787,12 +1056,16 @@ void rbv_irq(int irq, void *dev_id, struct pt_regs *regs) int irq = (srcidx+1)* 8 + i; /* call corresponding handlers */ if (events&(1<<i)) { - if (irq_flags[srcidx].disabled & (1<<i)) + if (irq_flags[srcidx].disabled & (1<<i)) { + if (!irq_flags[srcidx].pending&(1<<i)) + rbv_irqs[i]++; /* irq disabled -> mark pending */ irq_flags[srcidx].pending |= (1<<i); - else + } else { + rbv_irqs[i]++; /* irq enabled -> call handler */ (via_handler[i].handler)(irq, via, regs); + } } /* and call handlers for pending irqs - first ?? */ if ( (irq_flags[srcidx].pending & (1<<i)) @@ -803,7 +1076,7 @@ void rbv_irq(int irq, void *dev_id, struct pt_regs *regs) irq_flags[srcidx].pending &= ~(1<<i); } } - + /* * And done ... check for more punishment! */ @@ -843,24 +1116,277 @@ void via_wtf(int slot, void *via, struct pt_regs *regs) #endif } +/* + * Nubus / SCSI interrupts; OSS style + * The OSS is even more different than the RBV. OSS appears to stand for + * Obscenely Screwed Silicon ... + * + * Latest NetBSD sources suggest the OSS should behave like a RBV, but + * that's probably true for the 0x203 offset (Nubus/ADB-SWIM IOP) at best + */ + +void oss_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + int srcidx = IRQ_IDX(irq) - 1; /* MUST be 1 !! */ + volatile unsigned char *via = oss_regp; + unsigned char events=(via_read(via, oIFR))&0x03; + unsigned char nub_ev=(via_read(via, nIFR))&0x4F; + unsigned char adb_ev; + int i; + int ct = 0; + struct irqhandler *via_handler = handler_table[srcidx]; + struct irqparam *via_param = param_table[srcidx]; + + /* shouldn't we disable interrupts here ?? */ + + adb_ev = nub_ev & 0x40; + nub_ev &= 0x3F; + + /* + * Shouldnt happen + */ + + if (events==0 && adb_ev==0 && nub_ev==0) + { + printk("oss_irq: nothing pending, flags %x %x!\n", + via_read(via, oIFR), via_read(via, nIFR)); + rbv_irqs[7]++; + return; + } + +#ifdef DEBUG_VIA + /* + * limited verbosity for RBV interrupts (add more if needed) + */ + if ( events != 1<<3 ) /* SCSI IRQ */ + printk("oss_irq: irq %d events %x %x %x !\n", irq, srcidx+1, + events, adb_ev, nub_ev); +#endif + + /* + * OSS priorities: call ADB handler first if registered, other events, + * then Nubus + * ADB: yet to be implemented! + */ + + /* + * ADB: try to shutup the IOP + */ + if (adb_ev) { + printk("Hands off ! Don't press this button ever again !!!\n"); + via_write(via, 6, 0); + } + + do { + /* + * Clear the pending flags + * How exactly is that supposed to work ?? + */ + + /* + * Now see what bits are raised + */ + + for(i=0;i<7;i++) + { + /* HACK HACK: map to bit number in OSS register */ + int irqidx = oss_map[i]; + /* determine machspec. irq no. */ + int irq = (srcidx+1)* 8 + i; + /* call corresponding handlers */ + if ( (events&(1<<irqidx)) && /* bit set*/ + (via_read(via, irqidx+8)&0x7) ) { /* irq enabled */ + if (irq_flags[srcidx].disabled & (1<<i)) { + if (!irq_flags[srcidx].pending&(1<<i)) + rbv_irqs[i]++; + /* irq disabled -> mark pending */ + irq_flags[srcidx].pending |= (1<<i); + } else { + rbv_irqs[i]++; + /* irq enabled -> call handler */ + (via_handler[i].handler)(irq, via, regs); + } + } + /* and call handlers for pending irqs - first ?? */ + if ( (irq_flags[srcidx].pending & (1<<i)) + && !(irq_flags[srcidx].disabled & (1<<i)) ) { + /* call handler for re-enabled irq */ + (via_handler[i].handler)(irq, via, regs); + /* and clear pending flag :-) */ + irq_flags[srcidx].pending &= ~(1<<i); + } + } + + /* + * And done ... check for more punishment! + */ + + events=(via_read(via, oIFR)/*&via_read(via,rIER)*/)&0x03; + ct++; + if(events && ct>8) + { + printk("oss: stuck events %x\n",events); + for(i=0;i<7;i++) + { + if(events&(1<<i)) + { + printk("oss - bashing source %d\n", + i); + /* that should disable it */ + via_write(via, 8+i, 0); + } + } + break; + } + } + while(events); +#if 0 + scsi_mac_polled(); +#endif + + if (nub_ev) + oss_do_nubus(irq, via, regs); + +} + +/* + * Unexpected slot interrupt + */ + void nubus_wtf(int slot, void *via, struct pt_regs *regs) { -#ifdef DEBUG_VIA +#ifdef DEBUG_VIA_NUBUS printk("Unexpected interrupt on nubus slot %d\n",slot); #endif } +/* + * SCC master interrupt handler; sole purpose: pass the registered + * async struct to the SCC handler proper. + */ + void mac_SCC_handler(int irq, void *dev_id, struct pt_regs *regs) { int i; - - for (i = 0; i < 8; i++) + /* 1+2: compatibility with PSC ! */ + for (i = 1; i < 3; i++) /* currently only these two used */ if (scc_handler[i].handler != mac_default_handler) (scc_handler[i].handler)(i, scc_handler[i].dev_id, regs); } /* + * PSC interrupt handler + */ + +void psc_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + int srcidx = IRQ_IDX(irq) - 1; + volatile unsigned char *via = psc_regp; + unsigned int pIFR = 0x100 + 0x10*srcidx; + unsigned int pIER = 0x104 + 0x10*srcidx; + unsigned char events=(via_read(via, pIFR)&via_read(via,pIER))&0xF; + int i; + int ct = 0; + struct irqhandler *via_handler = handler_table[srcidx]; + struct irqparam *via_param = param_table[srcidx]; + + /* shouldn't we disable interrupts here ?? */ + + + /* + * Shouldnt happen + */ + + if(events==0) + { +#ifdef DEBUG_VIA + printk("rbv_irq: nothing pending, flags %x mask %x!\n", + via_read(via, pIFR), via_read(via,pIER)); +#endif + mac_irqs[srcidx][7]++; + return; + } + +#ifdef DEBUG_VIA + /* + * limited verbosity for RBV interrupts (add more if needed) + */ + if ( srcidx == 1 && events != 1<<3 && events != 1<<1 ) /* SCSI IRQ */ + printk("psc_irq: irq %d events %x !\n", irq, srcidx+1, events); +#endif + + /* to be changed, possibly: for each non'masked', enabled IRQ, read + * flag bit, ack and call handler ... + * Currently: all pending irqs ack'ed en bloc. + * If ack for masked IRQ required: keep 'pending' info separate. + */ + + do { + /* + * Clear the pending flag + */ + + /* via_write(via, pIFR, events); */ + + /* + * Now see what bits are raised + */ + + for(i=0;i<7;i++) + { + /* determine machspec. irq no. */ + int irq = (srcidx+1)* 8 + i; + /* call corresponding handlers */ + if (events&(1<<i)) { + if (irq_flags[srcidx].disabled & (1<<i)) { + if (!irq_flags[srcidx].pending&(1<<i)) + mac_irqs[srcidx][i]++; + /* irq disabled -> mark pending */ + irq_flags[srcidx].pending |= (1<<i); + } else { + mac_irqs[srcidx][i]++; + /* irq enabled -> call handler */ + (via_handler[i].handler)(irq, via, regs); + } + } + /* and call handlers for pending irqs - first ?? */ + if ( (irq_flags[srcidx].pending & (1<<i)) + && !(irq_flags[srcidx].disabled & (1<<i)) ) { + /* call handler for re-enabled irq */ + (via_handler[i].handler)(irq, via, regs); + /* and clear pending flag :-) */ + irq_flags[srcidx].pending &= ~(1<<i); + } + } + + /* + * And done ... check for more punishment! + */ + + events=(via_read(via,pIFR)&via_read(via,pIER))&0x7F; + ct++; + if(events && ct>8) + { + printk("psc: stuck events %x\n",events); + for(i=0;i<7;i++) + { + if(events&(1<<i)) + { + printk("psc - bashing source %d\n", + i); + via_write(via, pIER, 1<<i); + /* via_write(via, pIFR, (1<<i)); */ + } + } + break; + } + } + while(events); +} + + +/* * Nubus handling * Caution: slot numbers are currently 'hardcoded' to the range 9-15! * In general, the same request_irq() functions as above can be used if @@ -869,25 +1395,26 @@ void mac_SCC_handler(int irq, void *dev_id, struct pt_regs *regs) static int nubus_active=0; -int nubus_request_irq(int slot, void (*handler)(int,void *,struct pt_regs *)) +int nubus_request_irq(int slot, void *dev_id, void (*handler)(int,void *,struct pt_regs *)) { slot-=9; /* printk("Nubus request irq for slot %d\n",slot);*/ if(nubus_handler[slot].handler!=nubus_wtf) return -EBUSY; nubus_handler[slot].handler=handler; - nubus_handler[slot].dev_id =handler; + nubus_handler[slot].dev_id =dev_id; nubus_param[slot].flags = IRQ_FLG_LOCK; - nubus_param[slot].devname = "nubus"; + nubus_param[slot].devname = "nubus slot"; /* * if no nubus int. was active previously: register the main nubus irq * handler now! */ - if (!nubus_active) - request_irq(IRQ_MAC_NUBUS, via_do_nubus, IRQ_FLG_LOCK, - "nubus dispatch", via_do_nubus); + if (!nubus_active && !via2_is_oss) { + request_irq(IRQ_MAC_NUBUS, via_do_nubus, IRQ_FLG_LOCK, + "nubus dispatch", via_do_nubus); + } nubus_active|=1<<slot; /* printk("program slot %d\n",slot);*/ @@ -897,7 +1424,9 @@ int nubus_request_irq(int slot, void (*handler)(int,void *,struct pt_regs *)) via_read(via2, vDirA)|(1<<slot)); via_write(via2, vBufA, 0); #endif - if (!via2_is_rbv) { + if (via2_is_oss) + via_write(oss_regp, slot, 2); + else if (!via2_is_rbv) { /* Make sure the bit is an input */ via_write(via2_regp, vDirA, via_read(via2_regp, vDirA)&~(1<<slot)); @@ -917,6 +1446,8 @@ int nubus_free_irq(int slot) if (via2_is_rbv) via_write(rbv_regp, rBufA, 1<<slot); + else if (via2_is_oss) + via_write(oss_regp, slot, 0); else { via_write(via2_regp, vDirA, via_read(via2_regp, vDirA)|(1<<slot)); @@ -927,6 +1458,16 @@ int nubus_free_irq(int slot) return 0; } +#ifdef CONFIG_BLK_DEV_MAC_IDE +/* + * IDE interrupt hook + */ +extern void (*mac_ide_intr_hook)(int, void *, struct pt_regs *); +#endif + +/* + * Nubus dispatch handler - VIA/RBV style + */ static void via_do_nubus(int slot, void *via, struct pt_regs *regs) { unsigned char map; @@ -941,6 +1482,14 @@ static void via_do_nubus(int slot, void *via, struct pt_regs *regs) else via_write(via2_regp, vIFR, 0x82); +#ifdef CONFIG_BLK_DEV_MAC_IDE + /* IDE hack */ + if (mac_ide_intr_hook) + /* 'slot' is lacking the machspec bit in 2.0 */ + /* need to pass proper dev_id = hwgroup here */ + mac_ide_intr_hook(IRQ_MAC_NUBUS, via, regs); +#endif + while(1) { if (via2_is_rbv) @@ -948,15 +1497,23 @@ static void via_do_nubus(int slot, void *via, struct pt_regs *regs) else map = ~via_read(via2_regp, vBufA); -#ifdef DEBUG_VIA - printk("nubus_irq: map %x mask %x\n", map, nubus_active); + if( (map = (map&nubus_active)) ==0 ) { +#ifdef DEBUG_NUBUS_INT + printk("nubus_irq: nothing pending, map %x mask %x\n", + map, nubus_active); #endif - if( (map = (map&nubus_active)) ==0 ) + nubus_irqs[7]++; break; + } +#ifdef DEBUG_NUBUS_INT + printk("nubus_irq: map %x mask %x\n", map, nubus_active); +#endif if(ct++>2) { +#ifdef DEBUG_NUBUS_INT printk("nubus stuck events - %d/%d\n", map, nubus_active); +#endif return; } @@ -964,7 +1521,8 @@ static void via_do_nubus(int slot, void *via, struct pt_regs *regs) { if(map&(1<<i)) { - (nubus_handler[i].handler)(i+9, via, regs); + nubus_irqs[i]++; + (nubus_handler[i].handler)(i+9, nubus_handler[i].dev_id, regs); } } /* clear it */ @@ -977,3 +1535,76 @@ static void via_do_nubus(int slot, void *via, struct pt_regs *regs) /* And done */ } + +/* + * Nubus dispatch handler - OSS style + */ +static void oss_do_nubus(int slot, void *via, struct pt_regs *regs) +{ + unsigned char map; + int i; + int ct=0; + +/* printk("nubus interrupt\n");*/ + +#if 0 + /* lock the nubus interrupt */ + if (via2_is_rbv) + via_write(rbv_regp, rIFR, 0x82); + else + via_write(via2_regp, vIFR, 0x82); +#endif + + /* IDE hack for Quadra: uses Nubus interrupt without any slot bit set */ +#ifdef CONFIG_BLK_DEV_MAC_IDE + if (mac_ide_intr_hook) + mac_ide_intr_hook(IRQ_MAC_NUBUS, via, regs); +#endif + + while(1) + { + /* pending events */ + map=(via_read(via, nIFR))&0x3F; + +#ifdef DEBUG_VIA_NUBUS + printk("nubus_irq: map %x mask %x\n", map, nubus_active); +#endif + if( (map = (map&nubus_active)) ==0 ) { +#ifdef CONFIG_BLK_DEV_MAC_IDE + if (!mac_ide_intr_hook) + printk("nubus_irq: nothing pending, map %x mask %x\n", + map, nubus_active); +#endif + nubus_irqs[7]++; + break; + } + + if(ct++>2) + { +#if 0 + printk("nubus stuck events - %d/%d\n", map, nubus_active); +#endif + return; + } + + for(i=0;i<7;i++) + { + if(map&(1<<i)) + { + nubus_irqs[i]++; + /* call handler */ + (nubus_handler[i].handler)((i+9), nubus_handler[i].dev_id, regs); + /* clear interrupt ?? */ +#if 0 + via_write(oss_regp, i, 0); +#endif + } + } + /* clear it */ +#if 0 + via_write(oss_regp, nIFR, map); +#endif + } + + /* And done */ +} diff --git a/arch/m68k/mac/mackeyb.c b/arch/m68k/mac/mackeyb.c index f338253f3..5946a9e8b 100644 --- a/arch/m68k/mac/mackeyb.c +++ b/arch/m68k/mac/mackeyb.c @@ -600,13 +600,13 @@ __initfunc(int mac_keyb_init(void)) volatile int ct; /* setup key map */ - memcpy (plain_map, mac_plain_map, sizeof(plain_map)); - memcpy(shift_map, mac_shift_map, sizeof(shift_map)); - memcpy(altgr_map, mac_altgr_map, sizeof(altgr_map)); - memcpy(ctrl_map, mac_ctrl_map, sizeof(ctrl_map)); - memcpy(shift_ctrl_map, mac_shift_ctrl_map, sizeof(shift_ctrl_map)); - memcpy(alt_map, mac_alt_map, sizeof(alt_map)); - memcpy(ctrl_alt_map, mac_ctrl_alt_map, sizeof(ctrl_alt_map)); + memcpy(key_maps[0], mac_plain_map, sizeof(plain_map)); + memcpy(key_maps[1], mac_shift_map, sizeof(plain_map)); + memcpy(key_maps[2], mac_altgr_map, sizeof(plain_map)); + memcpy(key_maps[4], mac_ctrl_map, sizeof(plain_map)); + memcpy(key_maps[5], mac_shift_ctrl_map, sizeof(plain_map)); + memcpy(key_maps[8], mac_alt_map, sizeof(plain_map)); + memcpy(key_maps[12], mac_ctrl_alt_map, sizeof(plain_map)); /* initialize mouse interrupt hook */ mac_mouse_interrupt_hook = NULL; @@ -642,11 +642,12 @@ __initfunc(int mac_keyb_init(void)) ct=0; while (!autopoll_req.got_reply && ++ct<1000) { - adb_poll(); udelay(10); } - if(ct==1000) + if(ct==1000) { printk("Keyboard timed out.\n"); + autopoll_req.got_reply = 1; + } } /* @@ -654,7 +655,7 @@ __initfunc(int mac_keyb_init(void)) * care of that for other Macs. */ - printk("Configuring keyboard\n"); + printk("Configuring keyboard:\n"); /* * turn on all leds - the keyboard driver will turn them back off @@ -668,17 +669,17 @@ __initfunc(int mac_keyb_init(void)) * The polling stuff should go away as soon as the ADB driver is stable */ ct = 0; - adb_poll(); while (!led_request.got_reply && ++ct<1000) { - adb_poll(); udelay(10); } - if(ct==1000) - printk("Keyboard timed out.\n"); + if(ct==1000) { + printk("keyboard timed out.\n"); + led_request.got_reply = 1; + } #if 1 - printk("Configuring coding mode ...\n"); + printk("configuring coding mode ...\n"); /* * get the keyboard to send separate codes for @@ -688,14 +689,14 @@ __initfunc(int mac_keyb_init(void)) ADB_WRITEREG(ADB_KEYBOARD, 3), 0, 3); ct=0; - adb_poll(); while (!confcod_req.got_reply && ++ct<1000) { - adb_poll(); udelay(10); } - if(ct==1000) - printk("Keyboard timed out.\n"); + if(ct==1000) { + printk("keyboard timed out.\n"); + confcod_req.got_reply = 1; + } #endif #if 0 /* seems to hurt, at least Geert's Mac */ @@ -710,10 +711,8 @@ __initfunc(int mac_keyb_init(void)) ADB_WRITEREG(ADB_MOUSE, 3), 0x23, 4 ); ct=0; - adb_poll(); while (!mouse_req.got_reply && ++ct<1000) { - adb_poll(); udelay(10); } if(ct==1000) @@ -734,19 +733,18 @@ __initfunc(int mac_keyb_init(void)) ADB_READREG(ADB_KEYBOARD, KEYB_KEYREG)); #endif - /* - * fake 'request done' for the driver if requests timed out - */ - - autopoll_req.got_reply = 1; -#if 0 - /* XXX: results in race and hang with mac_kbd_leds and serial (why ?) */ - led_request.got_reply = 1; -#endif - confcod_req.got_reply = 1; - in_keybinit = 0; - printk("Keyboard init done\n"); + printk("keyboard init done\n"); return 0; } + +/* for "kbd-reset" cmdline param */ +__initfunc(void mac_kbd_reset_setup(char *str, int *ints)) +{ +} + +/* for "kbd-reset" cmdline param */ +__initfunc(void mac_kbd_reset_setup(char *str, int *ints)) +{ +} diff --git a/arch/m68k/mac/psc.h b/arch/m68k/mac/psc.h new file mode 100644 index 000000000..964f6547c --- /dev/null +++ b/arch/m68k/mac/psc.h @@ -0,0 +1,18 @@ +/* + * Apple Peripheral System Controller (PSC) + * + * The PSC is used on the AV Macs to control IO functions not handled + * by the VIAs (Ethernet, DSP, SCC). + */ + +#define PSCBASE 0x50F31000 + +#define pIFR3 0x130 +#define pIFR4 0x140 +#define pIFR5 0x150 +#define pIFR6 0x160 + +#define pIER3 0x134 +#define pIER4 0x144 +#define pIER5 0x154 +#define pIER6 0x164 diff --git a/arch/m68k/mac/via6522.c b/arch/m68k/mac/via6522.c index d2a25ab13..c867bc96d 100644 --- a/arch/m68k/mac/via6522.c +++ b/arch/m68k/mac/via6522.c @@ -1,4 +1,3 @@ - /* * 6522 Versatile Interface Adapter (VIA) * @@ -13,75 +12,27 @@ #include <asm/macintosh.h> #include <asm/macints.h> #include "via6522.h" +#include "psc.h" volatile unsigned char *via1=(unsigned char *)VIABASE; volatile unsigned char *via2=(unsigned char *)VIABASE2; +volatile unsigned char *psc=(unsigned char *)PSCBASE; unsigned char via1_clock, via1_datab; static int rbv=0; +static int oss=0; + +extern void adb_interrupt(int slot, void *via, struct pt_regs *regs); /* - * Debugging the VBL ints + * hardware reset vector */ - -extern int console_loglevel; +static void (*rom_reset)(void); /* - * VIA1 - hardwired vectors + * Timer defs. */ - -#if 0 /* gone to macints.[ch] */ -extern void via_wtf(int slot, void *via, struct pt_regs *regs); -static void via_do_nubus(int slot, volatile void *via, struct pt_regs *regs); - -extern void adb_interrupt(int slot, void *via, struct pt_regs *regs); - -static struct via_irq_tab via1_func_tab= -{ - { - via_wtf, /* One second interrupt */ - via_wtf, /* Vblank */ - via_wtf, /* ADB data ready */ - via_wtf, /* ADB data */ - via_wtf, /* ADB clock */ - via_wtf, - via_wtf, /* Slot 6 is replaced by the timer */ - via_wtf - } -}; - -static struct via_irq_tab via2_func_tab= -{ - { - via_wtf, - via_do_nubus, - via_wtf, - via_wtf, - via_wtf, - via_wtf, - via_wtf, - via_wtf - } -}; - -static struct via_irq_tab nubus_func_tab= -{ - { - via_wtf, - via_wtf, - via_wtf, - via_wtf, - via_wtf, - via_wtf, - via_wtf, - via_wtf - } -}; -#endif - -extern void adb_interrupt(int slot, void *via, struct pt_regs *regs); - #define MAC_CLOCK_TICK (783300/HZ) /* ticks per HZ */ #define MAC_CLOCK_LOW (MAC_CLOCK_TICK&0xFF) #define MAC_CLOCK_HIGH (MAC_CLOCK_TICK>>8) @@ -91,8 +42,6 @@ void via_init_clock(void (*func)(int, void *, struct pt_regs *)) { unsigned char c; -/* mac_debugging_penguin(6);*/ - switch(macintosh_config->via_type) { /* @@ -102,6 +51,10 @@ void via_init_clock(void (*func)(int, void *, struct pt_regs *)) via1=(void *)0x50F00000; via2=(void *)0x50F26000; rbv=1; + if (macintosh_config->ident == MAC_MODEL_IIFX) { + via2=(void *)0x50F1A000; + oss=1; + } break; /* * Quadra and early MacIIs agree on the VIA locations @@ -162,7 +115,7 @@ void via_init_clock(void (*func)(int, void *, struct pt_regs *)) via_write(via2,vT2CH,0); via_write(via2,vIER, 0x7F); } - else + else if (oss==0) { /* * Init the RBV chip a bit @@ -201,30 +154,18 @@ void via_init_clock(void (*func)(int, void *, struct pt_regs *)) request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func); -/* mac_debugging_penguin(7);*/ - /* * SE/30: disable video int. * XXX: testing for SE/30 VBL */ - if (macintosh_config->ident == MAC_MODEL_SE30 - && console_loglevel != 10) { + if (macintosh_config->ident == MAC_MODEL_SE30) { c = via_read(via1, vBufB); via_write(via1, vBufB, c|(0x40)); c = via_read(via1, vDirB); via_write(via1, vDirB, c|(0x40)); } - /* - * XXX: use positive edge - */ - - if (console_loglevel == 10) { - c = via_read(via1, vPCR); - via_write(via1, vPCR, c|(0x1)); - } - #if 0 /* gone to mac_init_IRQ */ /* * Set vPCR for SCSI interrupts. @@ -237,172 +178,55 @@ void via_init_clock(void (*func)(int, void *, struct pt_regs *)) } -#if 0 /* moved to macints.c */ - -static void via_irq(volatile unsigned char *via, struct via_irq_tab *irqtab, - struct pt_regs *regs) -{ - unsigned char events=(via_read(via, vIFR)&via_read(via,vIER))&0x7F; - int i; - int ct=0; - - /* - * Shouldnt happen - */ - - if(events==0) - { - printk("via_irq: nothing pending!\n"); - return; - } - - do { - /* - * Clear the pending flag - */ - - /* HACK HACK - FIXME !!! - just testing some keyboard ideas */ - - /* events&=~(1<<4); */ - via_write(via, vIFR, events); - - /* - * Now see what bits are raised - */ - - for(i=0;i<7;i++) - { - if(events&(1<<i)) - (irqtab->vector[i])(i, via, regs); - } - - /* - * And done.. - */ - events=(via_read(via, vIFR)&via_read(via,vIER))&0x7F; - ct++; - if(events && ct>8) - { - printk("via: stuck events %x\n",events); - break; - } - } - while(events); - - scsi_mac_polled(); -} - /* - * - * The RBV is different. RBV appears to stand for randomly broken - * VIA. + * get time offset between scheduling timer ticks + * Code stolen from arch/m68k/atari/time.c; underflow check probably + * wrong. */ - -static void rbv_irq(volatile unsigned char *via, struct via_irq_tab *irqtab, - struct pt_regs *regs) +#define TICK_SIZE 10000 + +/* This is always executed with interrupts disabled. */ +unsigned long mac_gettimeoffset (void) { - unsigned char events=(via_read(via, rIFR)&via_read(via,rIER))&0x7F; - int i; - int ct=0; - - /* - * Shouldnt happen - */ - - if(events==0) - { - printk("rbv_irq: nothing pending!\n"); - return; - } - - do { - /* - * Clear the pending flag - */ - - /* HACK HACK - FIXME !!! - just testing some keyboard ideas */ - - /* events&=~(1<<4); */ - via_write(via, rIFR, events); - - /* - * Now see what bits are raised - */ - - for(i=0;i<7;i++) - { - if(events&(1<<i)) - (irqtab->vector[i])(i, via, regs); - } - - /* - * And done.. - */ - events=(via_read(via, rIFR)&via_read(via,rIER))&0x7F; - ct++; - if(events && ct>8) - { - printk("rbv: stuck events %x\n",events); - for(i=0;i<7;i++) - { - if(events&(1<<i)) - { - printk("rbv - bashing source %d\n", - i); - via_write(via, rIER, i); - via_write(via, rIFR, i); - } - } - break; - } - } - while(events); -} + unsigned long ticks, offset = 0; -/* - * System interrupts - */ + /* read VIA1 timer 2 current value */ + ticks = via_read(via1, vT1CL) + (via_read(via1, vT1CH)<<8); + /* The probability of underflow is less than 2% */ + if (ticks > MAC_CLOCK_TICK - MAC_CLOCK_TICK / 50) + /* Check for pending timer interrupt in VIA1 IFR */ + if (via_read(via1, vIFR) & 0x40) + offset = TICK_SIZE; -void via1_irq(int irq, void *dev_id, struct pt_regs *regs) -{ - via_irq(via1, &via1_func_tab, regs); -} + ticks = MAC_CLOCK_TICK - ticks; + ticks = ticks * 10000L / MAC_CLOCK_TICK; -/* - * Nubus interrupts - */ - -void via2_irq(int irq, void *dev_id, struct pt_regs *regs) -{ -/* printk("via2 interrupt\n");*/ - if(rbv) - rbv_irq(via2, &via2_func_tab, regs); - else - via_irq(via2, &via2_func_tab, regs); + return ticks + offset; } /* - * Unexpected via interrupt + * PSC (AV Macs; level 3-6): initialize interrupt enable registers */ - -void via_wtf(int slot, volatile void *via, struct pt_regs *regs) -{ - printk("Unexpected event %d on via %p\n",slot,via); -} -void nubus_wtf(int slot, volatile void *via, struct pt_regs *regs) +void psc_init(void) { - printk("Unexpected interrupt on nubus slot %d\n",slot); + via_write(psc, pIER3, 0x01); + via_write(psc, pIER4, 0x09); + via_write(psc, pIER4, 0x86); + via_write(psc, pIER5, 0x03); + via_write(psc, pIER6, 0x07); } -#endif - /* * The power switch - yes its software! */ -void mac_reset(void) +void mac_poweroff(void) { +#if 0 + /* + * Powerdown, for the Macs that support it + */ if(rbv) { via_write(via2, rBufB, via_read(via2, rBufB)&~0x04); } else { @@ -411,7 +235,38 @@ void mac_reset(void) /* Send a value of 0 on that line */ via_write(via2,vBufB,via_read(via2,vBufB)&~0x04); } +#endif + /* We should never make it this far... */ + /* XXX - delay do we need to spin here ? */ + while(1); /* Just in case .. */ +} + +/* + * Not all Macs support software power down; for the rest, just + * try the ROM reset vector ... + */ +void mac_reset(void) +{ + unsigned long flags; + unsigned long *reset_hook; + + save_flags(flags); + cli(); + +#if 0 /* need ROMBASE in booter */ +#if 0 /* works on some */ + rom_reset = (boot_info.bi_mac.rombase + 0xa); +#else /* testing, doesn't work on SE/30 either */ + reset_hook = (unsigned long *) (boot_info.bi_mac.rombase + 0x4); + printk("ROM reset hook: %p\n", *reset_hook); + rom_reset = *reset_hook; +#endif + rom_reset(); +#endif + restore_flags(flags); + /* We never make it this far... */ + printk(" reboot failed, reboot manually!\n"); /* XXX - delay do we need to spin here ? */ while(1); /* Just in case .. */ } @@ -442,140 +297,13 @@ void via1_set_head(int head) via_write(via1, vBufA, via_read(via1, vBufA)|0x20); } -#if 0 /* moved to macints.c */ - - -/* - * Set up the SCSI - */ - -void via_scsi_disable(void) -{ - if (rbv) - via_write(via2, rIER, (1<<3)|(1<<0)); - else - via_write(via2, vIER, (1<<3)|(1<<0)); -} - -void via_scsi_enable(void) -{ - if (rbv) - via_write(via2, rIER, (1<<3)|(1<<0)|0x80); - else - via_write(via2, vIER, (1<<3)|(1<<0)|0x80); -} - -void via_scsi_clear(void) -{ - if (rbv) - via_write(via2, rIFR, (1<<3)|(1<<0)|0x80); - volatile unsigned char deep_magic=via_read(via2, vBufB); - via_scsi_enable(); -} - -void via_setup_scsi(void (*handler)(int,volatile void *,struct pt_regs *)) -{ - via2_func_tab.vector[0]=handler; /* SCSI DRQ */ - via2_func_tab.vector[3]=handler; /* SCSI IRQ */ - via_write(via2, vPCR, 0x66); /* Edge direction! */ - via_scsi_enable(); -} - -/* - * Nubus handling - */ - -static int nubus_active=0; - -int nubus_request_irq(int slot, void (*handler)(int,void *,struct pt_regs *)) -{ - slot-=9; -/* printk("Nubus request irq for slot %d\n",slot);*/ - if(nubus_func_tab.vector[slot]==nubus_wtf) - return -EBUSY; - nubus_func_tab.vector[slot]=handler; - nubus_active|=1<<slot; -/* printk("program slot %d\n",slot);*/ -/* printk("via2=%p\n",via2);*/ -#if 0 - via_write(via2, vDirA, - via_read(via2, vDirA)|(1<<slot)); - via_write(via2, vBufA, 0); -#endif - if (!rbv) { - /* Make sure the bit is an input */ - via_write(via2, vDirA, - via_read(via2, vDirA)&~(1<<slot)); - } -/* printk("nubus irq on\n");*/ - return 0; -} - -int nubus_free_irq(int slot) -{ - slot-=9; - nubus_active&=~(1<<slot); - nubus_func_tab.vector[slot]=nubus_wtf; - if (rbv) { - via_write(via2, rBufA, 1<<slot); - } else { - via_write(via2, vDirA, - via_read(via2, vDirA)|(1<<slot)); - via_write(via2, vBufA, 1<<slot); - via_write(via2, vDirA, - via_read(via2, vDirA)&~(1<<slot)); - } - return 0; -} - -static void via_do_nubus(int slot, volatile void *via, struct pt_regs *regs) -{ - unsigned char map; - int i; - int ct=0; - -/* printk("nubus interrupt\n");*/ - - if (rbv) { - via_write(via2, rIFR, 0x82); /* lock the nubus interrupt */ - } else { - via_write(via2, vIFR, 0x82); /* lock the nubus interrupt */ - - while(1) - { - if(rbv) - map=~via_read(via2, rBufA); - else - map=~via_read(via2, vBufA); - if((map=(map&nubus_active))==0) - break; - if(ct++>2) - { - printk("nubus stuck events - %d/%d\n", map, nubus_active); - return; - } - for(i=0;i<7;i++) - { - if(map&(1<<i)) - { - (nubus_func_tab.vector[i])(i+9, via, regs); - } - } - if (rbv) - via_write(via2, rIFR, 0x02); /* clear it */ - else - via_write(via2, vIFR, 0x02); /* clear it */ - } - - /* And done */ -} -#endif - void nubus_init_via(void) { if (rbv) { - via_write(via2, rBufB, via_read(via2, rBufB)|0x02); - via_write(via2, rIER, 0x82); /* Interrupts on */ + if (oss==0) { + via_write(via2, rBufB, via_read(via2, rBufB)|0x02); + via_write(via2, rIER, 0x82); /* Interrupts on */ + } } else { /* Assert the nubus active */ via_write(via2, vDirB, via_read(via2, vDirB)|0x02); @@ -584,7 +312,13 @@ void nubus_init_via(void) /* via_write(via2, vDirA, 0xFF); */ via_write(via2, vIER, 0x82); /* Interrupts on */ } - printk("BTW boot via1 acr=%X datab=%X pcr=%X\n", - (int)via1_clock, (int)via1_datab, (int)via_read(via1, vPCR)); -} + printk("nubus_init_via: via1 acr=%X datab=%X pcr=%X\n", + (int)via_read(via1, vACR), (int)via_read(via1, vBufB), + (int)via_read(via1, vPCR)); + + if (rbv==0) + printk("nubus_init_via: via2 acr=%X datab=%X pcr=%X\n", + (int)via_read(via2, vACR), (int)via_read(via2, vBufB), + (int)via_read(via2, vPCR)); +} diff --git a/arch/m68k/mm/Makefile b/arch/m68k/mm/Makefile index 2ad15d861..54f0fae1a 100644 --- a/arch/m68k/mm/Makefile +++ b/arch/m68k/mm/Makefile @@ -8,6 +8,6 @@ # Note 2! The CFLAGS definition is now in the main makefile... O_TARGET := mm.o -O_OBJS := init.o fault.o memory.o kmap.o extable.o +O_OBJS := init.o fault.o memory.o kmap.o extable.o hwtest.o include $(TOPDIR)/Rules.make diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c index aecbe0a5d..62129782b 100644 --- a/arch/m68k/mm/fault.c +++ b/arch/m68k/mm/fault.c @@ -45,9 +45,12 @@ asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, #endif down(&mm->mmap_sem); + vma = find_vma(mm, address); if (!vma) - goto bad_area; + goto bad_area; + if (vma->vm_flags & VM_IO) + goto bad_area; if (vma->vm_start <= address) goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) @@ -84,7 +87,6 @@ good_area: goto bad_area; } handle_mm_fault(current, vma, address, write); - up(&mm->mmap_sem); /* There seems to be a missing invalidate somewhere in do_no_page. * Until I found it, this one cures the problem and makes @@ -92,6 +94,7 @@ good_area: */ if (CPU_IS_040_OR_060) flush_tlb_page(vma, address); + up(&mm->mmap_sem); return 0; /* diff --git a/arch/m68k/mm/hwtest.c b/arch/m68k/mm/hwtest.c new file mode 100644 index 000000000..60ad5e812 --- /dev/null +++ b/arch/m68k/mm/hwtest.c @@ -0,0 +1,81 @@ +/* Tests for presence or absence of hardware registers. + * This code was originally in atari/config.c, but I noticed + * that it was also in drivers/nubus/nubus.c and I wanted to + * use it in hp300/config.c, so it seemed sensible to pull it + * out into its own file. + * + * The test is for use when trying to read a hardware register + * that isn't present would cause a bus error. We set up a + * temporary handler so that this doesn't kill the kernel. + * + * There is a test-by-reading and a test-by-writing; I present + * them here complete with the comments from the original atari + * config.c... + * -- PMM <pmaydell@chiark.greenend.org.uk>, 05/1998 + */ + +/* This function tests for the presence of an address, specially a + * hardware register address. It is called very early in the kernel + * initialization process, when the VBR register isn't set up yet. On + * an Atari, it still points to address 0, which is unmapped. So a bus + * error would cause another bus error while fetching the exception + * vector, and the CPU would do nothing at all. So we needed to set up + * a temporary VBR and a vector table for the duration of the test. + */ + +int hwreg_present( volatile void *regp ) +{ + int ret = 0; + long save_sp, save_vbr; + long tmp_vectors[3]; + + __asm__ __volatile__ + ( "movec %/vbr,%2\n\t" + "movel #Lberr1,%4@(8)\n\t" + "movec %4,%/vbr\n\t" + "movel %/sp,%1\n\t" + "moveq #0,%0\n\t" + "tstb %3@\n\t" + "nop\n\t" + "moveq #1,%0\n" + "Lberr1:\n\t" + "movel %1,%/sp\n\t" + "movec %2,%/vbr" + : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr) + : "a" (regp), "a" (tmp_vectors) + ); + + return( ret ); +} + +/* Basically the same, but writes a value into a word register, protected + * by a bus error handler. Returns 1 if successful, 0 otherwise. + */ + +int hwreg_write( volatile void *regp, unsigned short val ) +{ + int ret; + long save_sp, save_vbr; + long tmp_vectors[3]; + + __asm__ __volatile__ + ( "movec %/vbr,%2\n\t" + "movel #Lberr2,%4@(8)\n\t" + "movec %4,%/vbr\n\t" + "movel %/sp,%1\n\t" + "moveq #0,%0\n\t" + "movew %5,%3@\n\t" + "nop \n\t" /* If this nop isn't present, 'ret' may already be + * loaded with 1 at the time the bus error + * happens! */ + "moveq #1,%0\n" + "Lberr2:\n\t" + "movel %1,%/sp\n\t" + "movec %2,%/vbr" + : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr) + : "a" (regp), "a" (tmp_vectors), "g" (val) + ); + + return( ret ); +} + diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c index 6dab5db9d..7ea05b3dd 100644 --- a/arch/m68k/mm/init.c +++ b/arch/m68k/mm/init.c @@ -31,6 +31,20 @@ extern void die_if_kernel(char *,struct pt_regs *,long); extern void init_kpointer_table(void); extern void show_net_buffers(void); +int do_check_pgt_cache(int low, int high) +{ + int freed = 0; + if(pgtable_cache_size > high) { + do { + if(pmd_quicklist) + freed += free_pmd_slow(get_pmd_fast()); + if(pte_quicklist) + free_pte_slow(get_pte_fast()), freed++; + } while(pgtable_cache_size > low); + } + return freed; +} + /* * BAD_PAGE is the page that is used for page faults when linux * is out-of-memory. Older versions of linux just did a @@ -76,7 +90,7 @@ void show_mem(void) total++; if (PageReserved(mem_map+i)) reserved++; - if (PageSwapCache(mem_map+i)) + else if (PageSwapCache(mem_map+i)) cached++; else if (!atomic_read(&mem_map[i].count)) free++; @@ -91,6 +105,7 @@ void show_mem(void) printk("%d pages nonshared\n",nonshared); printk("%d pages shared\n",shared); printk("%d pages swap cached\n",cached); + printk("%ld pages in page table cache\n",pgtable_cache_size); show_buffers(); #ifdef CONFIG_NET show_net_buffers(); @@ -231,7 +246,7 @@ map_chunk (unsigned long addr, unsigned long size, unsigned long *memavailp)) */ for (i = 0; i < 64; i++) { pte_val(ktablep[i]) = physaddr | _PAGE_PRESENT - | _PAGE_CACHE040 | _PAGE_GLOBAL040 + | m68k_supervisor_cachemode | _PAGE_GLOBAL040 | _PAGE_ACCESSED; physaddr += PAGE_SIZE; } diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c index e1bfa1540..be716a5b2 100644 --- a/arch/m68k/mm/kmap.c +++ b/arch/m68k/mm/kmap.c @@ -19,10 +19,6 @@ extern pte_t *kernel_page_table (unsigned long *memavailp); -/* Virtual address region for use by kernel_map() */ -#define KMAP_START 0xd0000000 -#define KMAP_END 0xf0000000 - /* Granularity of kernel_map() allocations */ #define KMAP_STEP (256*1024) diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c index 39a29b9b0..ad7c8141a 100644 --- a/arch/m68k/mm/memory.c +++ b/arch/m68k/mm/memory.c @@ -4,6 +4,7 @@ * Copyright (C) 1995 Hamish Macdonald */ +#include <linux/config.h> #include <linux/mm.h> #include <linux/kernel.h> #include <linux/string.h> @@ -16,38 +17,90 @@ #include <asm/pgtable.h> #include <asm/system.h> #include <asm/traps.h> +#ifdef CONFIG_AMIGA #include <asm/amigahw.h> +#endif -/* Strings for `extern inline' functions in <asm/pgtable.h>. If put - directly into these functions, they are output for every file that - includes pgtable.h */ +struct pgtable_cache_struct quicklists; -const char PgtabStr_bad_pmd[] = "Bad pmd in pte_alloc: %08lx\n"; -const char PgtabStr_bad_pgd[] = "Bad pgd in pmd_alloc: %08lx\n"; -const char PgtabStr_bad_pmdk[] = "Bad pmd in pte_alloc_kernel: %08lx\n"; -const char PgtabStr_bad_pgdk[] = "Bad pgd in pmd_alloc_kernel: %08lx\n"; +void __bad_pte(pmd_t *pmd) +{ + printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); + pmd_set(pmd, BAD_PAGETABLE); +} -static struct ptable_desc { - struct ptable_desc *prev; - struct ptable_desc *next; - unsigned long page; - unsigned char alloced; -} ptable_list = { &ptable_list, &ptable_list, 0, 0xff }; +void __bad_pmd(pgd_t *pgd) +{ + printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd)); + pgd_set(pgd, (pmd_t *)BAD_PAGETABLE); +} -#define PD_NONEFREE(dp) ((dp)->alloced == 0xff) -#define PD_ALLFREE(dp) ((dp)->alloced == 0) -#define PD_TABLEFREE(dp,i) (!((dp)->alloced & (1<<(i)))) -#define PD_MARKUSED(dp,i) ((dp)->alloced |= (1<<(i))) -#define PD_MARKFREE(dp,i) ((dp)->alloced &= ~(1<<(i))) +pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) +{ + pte_t *pte; + + pte = (pte_t *) __get_free_page(GFP_KERNEL); + if (pmd_none(*pmd)) { + if (pte) { + clear_page((unsigned long)pte); + flush_page_to_ram((unsigned long)pte); + flush_tlb_kernel_page((unsigned long)pte); + nocache_page((unsigned long)pte); + pmd_set(pmd, pte); + return pte + offset; + } + pmd_set(pmd, BAD_PAGETABLE); + return NULL; + } + free_page((unsigned long)pte); + if (pmd_bad(*pmd)) { + __bad_pte(pmd); + return NULL; + } + return (pte_t *) pmd_page(*pmd) + offset; +} + +pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset) +{ + pmd_t *pmd; + + pmd = get_pointer_table(); + if (pgd_none(*pgd)) { + if (pmd) { + pgd_set(pgd, pmd); + return pmd + offset; + } + pgd_set(pgd, (pmd_t *)BAD_PAGETABLE); + return NULL; + } + free_pointer_table(pmd); + if (pgd_bad(*pgd)) { + __bad_pmd(pgd); + return NULL; + } + return (pmd_t *) pgd_page(*pgd) + offset; +} + + +/* ++andreas: {get,free}_pointer_table rewritten to use unused fields from + struct page instead of separately kmalloced struct. Stolen from + arch/sparc/mm/srmmu.c ... */ + +typedef struct page ptable_desc; +static ptable_desc ptable_list = { &ptable_list, &ptable_list }; + +#define PD_MARKBITS(dp) (*(unsigned char *)&(dp)->offset) +#define PD_PAGE(dp) (PAGE_OFFSET + ((dp)->map_nr << PAGE_SHIFT)) +#define PAGE_PD(page) ((ptable_desc *)&mem_map[MAP_NR(page)]) #define PTABLE_SIZE (PTRS_PER_PMD * sizeof(pmd_t)) pmd_t *get_pointer_table (void) { - pmd_t *pmdp = NULL; - unsigned long flags; - struct ptable_desc *dp = ptable_list.next; - int i; + ptable_desc *dp = ptable_list.next; + unsigned char mask = PD_MARKBITS (dp); + unsigned char tmp; + unsigned int off; /* * For a pointer table for a user process address space, a @@ -55,102 +108,70 @@ pmd_t *get_pointer_table (void) * page can hold 8 pointer tables. The page is remapped in * virtual address space to be noncacheable. */ - if (PD_NONEFREE (dp)) { + if (mask == 0) { + unsigned long page; + ptable_desc *new; - if (!(dp = kmalloc (sizeof(struct ptable_desc),GFP_KERNEL))) { + if (!(page = get_free_page (GFP_KERNEL))) return 0; - } - if (!(dp->page = get_free_page (GFP_KERNEL))) { - kfree (dp); - return 0; - } + flush_tlb_kernel_page(page); + nocache_page (page); - flush_tlb_kernel_page((unsigned long) dp->page); - nocache_page (dp->page); - - dp->alloced = 0; - /* put at head of list */ - save_flags(flags); - cli(); - dp->next = ptable_list.next; - dp->prev = ptable_list.next->prev; - ptable_list.next->prev = dp; - ptable_list.next = dp; - restore_flags(flags); + new = PAGE_PD(page); + PD_MARKBITS(new) = 0xfe; + (new->prev = dp->prev)->next = new; + (new->next = dp)->prev = new; + return (pmd_t *)page; } - for (i = 0; i < 8; i++) - if (PD_TABLEFREE (dp, i)) { - PD_MARKUSED (dp, i); - pmdp = (pmd_t *)(dp->page + PTABLE_SIZE*i); - break; - } + for (tmp = 1, off = 0; (mask & tmp) == 0; tmp <<= 1, off += PTABLE_SIZE); + PD_MARKBITS(dp) = mask & ~tmp; + if (!PD_MARKBITS(dp)) { + ptable_desc *last, *next; - if (PD_NONEFREE (dp)) { /* move to end of list */ - save_flags(flags); - cli(); - dp->prev->next = dp->next; - dp->next->prev = dp->prev; - - dp->next = ptable_list.next->prev; - dp->prev = ptable_list.prev; - ptable_list.prev->next = dp; - ptable_list.prev = dp; - restore_flags(flags); - } - - memset (pmdp, 0, PTABLE_SIZE); + next = dp->next; + (next->prev = dp->prev)->next = next; - return pmdp; + last = ptable_list.prev; + (dp->next = last->next)->prev = dp; + (dp->prev = last)->next = dp; + } + return (pmd_t *) (PD_PAGE(dp) + off); } -void free_pointer_table (pmd_t *ptable) +int free_pointer_table (pmd_t *ptable) { - struct ptable_desc *dp; + ptable_desc *dp, *first; unsigned long page = (unsigned long)ptable & PAGE_MASK; - int index = ((unsigned long)ptable - page)/PTABLE_SIZE; - unsigned long flags; - - for (dp = ptable_list.next; dp->page && dp->page != page; dp = dp->next) - ; - - if (!dp->page) - panic ("unable to find desc for ptable %p on list!", ptable); + unsigned char mask = 1 << (((unsigned long)ptable - page)/PTABLE_SIZE); - if (PD_TABLEFREE (dp, index)) + dp = PAGE_PD(page); + if (PD_MARKBITS (dp) & mask) panic ("table already free!"); - PD_MARKFREE (dp, index); + PD_MARKBITS (dp) |= mask; - if (PD_ALLFREE (dp)) { + if (PD_MARKBITS(dp) == 0xff) { /* all tables in page are free, free page */ - save_flags(flags); - cli(); - dp->prev->next = dp->next; - dp->next->prev = dp->prev; - restore_flags(flags); - cache_page (dp->page); - free_page (dp->page); - kfree (dp); - return; - } else { + ptable_desc *next = dp->next; + (next->prev = dp->prev)->next = next; + cache_page (page); + free_page (page); + return 1; + } else if ((first = ptable_list.next) != dp) { /* - * move this descriptor the the front of the list, since + * move this descriptor to the front of the list, since * it has one or more free tables. */ - save_flags(flags); - cli(); - dp->prev->next = dp->next; - dp->next->prev = dp->prev; - - dp->next = ptable_list.next; - dp->prev = ptable_list.next->prev; - ptable_list.next->prev = dp; - ptable_list.next = dp; - restore_flags(flags); + ptable_desc *next = dp->next; + (next->prev = dp->prev)->next = next; + + (dp->prev = first->prev)->next = dp; + (dp->next = first)->prev = dp; } + return 0; } /* maximum pages used for kpointer tables */ @@ -451,12 +472,14 @@ unsigned long mm_ptov (unsigned long paddr) * */ +#ifdef CONFIG_AMIGA /* * if on an amiga and address is in first 16M, move it * to the ZTWO_VADDR range */ if (MACH_IS_AMIGA && paddr < 16*1024*1024) return ZTWO_VADDR(paddr); +#endif return paddr; } diff --git a/arch/m68k/mvme16x/16xints.c b/arch/m68k/mvme16x/16xints.c index c79ff17ad..fbb370a07 100644 --- a/arch/m68k/mvme16x/16xints.c +++ b/arch/m68k/mvme16x/16xints.c @@ -127,7 +127,7 @@ int mvme16x_get_irq_list (char *buf) static void mvme16x_defhand (int irq, void *dev_id, struct pt_regs *fp) { - panic ("Unknown interrupt 0x%02x", irq); + printk ("Unknown interrupt 0x%02x\n", irq); } diff --git a/arch/m68k/mvme16x/Makefile b/arch/m68k/mvme16x/Makefile index 97c670f3c..bb7485ab8 100644 --- a/arch/m68k/mvme16x/Makefile +++ b/arch/m68k/mvme16x/Makefile @@ -8,7 +8,7 @@ # Note 2! The CFLAGS definitions are now in the main makefile... O_TARGET := mvme16x.o -O_OBJS := config.o 16xints.o +O_OBJS := config.o 16xints.o rtc.o #OX_OBJS = ksyms.o include $(TOPDIR)/Rules.make diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c index 00e7db8d1..838c3bbac 100644 --- a/arch/m68k/mvme16x/config.c +++ b/arch/m68k/mvme16x/config.c @@ -34,26 +34,10 @@ #include <asm/machdep.h> #include <asm/mvme16xhw.h> -typedef struct { - unsigned char - ctrl, - bcd_sec, - bcd_min, - bcd_hr, - bcd_dow, - bcd_dom, - bcd_mth, - bcd_year; -} MK48T08; - -#define RTC_WRITE 0x80 -#define RTC_READ 0x40 -#define RTC_STOP 0x20 - int atari_SCC_reset_done = 1; /* So SCC doesn't get reset */ u_long atari_mch_cookie = 0; -MK48T08 * volatile rtc = (MK48T08 *)0xfffc1ff8; +static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE; extern void mvme16x_process_int (int level, struct pt_regs *regs); extern void mvme16x_init_IRQ (void); @@ -143,6 +127,11 @@ static int mvme16x_get_hardware_list(char *buffer) } +#define pcc2chip ((volatile u_char *)0xfff42000) +#define PccSCCMICR 0x1d +#define PccSCCTICR 0x1e +#define PccSCCRICR 0x1f + __initfunc(void config_mvme16x(void)) { p_bdid p = (p_bdid)mvme_bdid_ptr; @@ -197,7 +186,43 @@ __initfunc(void config_mvme16x(void)) rev & MVME16x_CONFIG_NO_ETHERNET ? "NOT " : ""); } else + { mvme16x_config = MVME16x_CONFIG_GOT_LP | MVME16x_CONFIG_GOT_CD2401; + + /* Dont allow any interrupts from the CD2401 until the interrupt */ + /* handlers are installed */ + + pcc2chip[PccSCCMICR] = 0x10; + pcc2chip[PccSCCTICR] = 0x10; + pcc2chip[PccSCCRICR] = 0x10; + } +} + +static void mvme16x_abort_int (int irq, void *dev_id, struct pt_regs *fp) +{ + p_bdid p = (p_bdid)mvme_bdid_ptr; + unsigned long *new = (unsigned long *)vectors; + unsigned long *old = (unsigned long *)0xffe00000; + volatile unsigned char uc, *ucp; + + if (p->brdno == 0x0162 || p->brdno == 0x172) + { + ucp = (volatile unsigned char *)0xfff42043; + uc = *ucp | 8; + *ucp = uc; + } + else + { + *(volatile unsigned long *)0xfff40074 = 0x40000000; + } + *(new+4) = *(old+4); /* Illegal instruction */ + *(new+9) = *(old+9); /* Trace */ + *(new+47) = *(old+47); /* Trap #15 */ + + if (p->brdno == 0x0162 || p->brdno == 0x172) + *(new+0x5e) = *(old+0x5e); /* ABORT switch */ + else + *(new+0x6e) = *(old+0x6e); /* ABORT switch */ } static void mvme16x_timer_int (int irq, void *dev_id, struct pt_regs *fp) @@ -208,15 +233,26 @@ static void mvme16x_timer_int (int irq, void *dev_id, struct pt_regs *fp) void mvme16x_sched_init (void (*timer_routine)(int, void *, struct pt_regs *)) { + p_bdid p = (p_bdid)mvme_bdid_ptr; + int irq; + tick_handler = timer_routine; /* Using PCCchip2 or MC2 chip tick timer 1 */ *(volatile unsigned long *)0xfff42008 = 0; *(volatile unsigned long *)0xfff42004 = 10000; /* 10ms */ *(volatile unsigned char *)0xfff42017 |= 3; *(volatile unsigned char *)0xfff4201b = 0x16; - if (request_irq(IRQ_MVME16x_TIMER, mvme16x_timer_int, 0, + if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, 0, "timer", mvme16x_timer_int)) panic ("Couldn't register timer int"); + + if (p->brdno == 0x0162 || p->brdno == 0x172) + irq = MVME162_IRQ_ABORT; + else + irq = MVME167_IRQ_ABORT; + if (request_irq(irq, mvme16x_abort_int, 0, + "abort", mvme16x_abort_int)) + panic ("Couldn't register abort int"); } @@ -254,76 +290,11 @@ int mvme16x_set_clock_mmss (unsigned long nowtime) return 0; } -/* - * console_map_init(), here to avoid having to modify drivers/block/genhd.c - */ - -void console_map_init(void) -{ -} - -/* - * fbmem_init(), here to avoid having to modify drivers/char/mem.c - */ - -void fbmem_init(void) -{ -} - -/* Avoid mods to drivers/char/tty_io.c */ - -unsigned long con_init(unsigned long kmem_start) -{ - return (kmem_start); -} - -/* Avoid mods to drivers/char/tty_io.c */ - -int vcs_init(void) -{ - return (0); -} - -/* Avoid mods to drivers/char/tty_io.c */ - -int kbd_init(void) -{ - return (0); -} - -/* Avoid mods to init/main.c */ - -void no_scroll(char *str, int *ints) -{ -} - -/* Avoid mods to kernel/panic.c */ - -void do_unblank_screen(void) -{ -} - int mvme16x_keyb_init (void) { return 0; } -void mvme16x_set_vectors (void) -{ - p_bdid p = (p_bdid)mvme_bdid_ptr; - unsigned long *new = (unsigned long *)vectors; - unsigned long *old = (unsigned long *)0xffe00000;; - - *(new+4) = *(old+4); /* Illegal instruction */ - *(new+9) = *(old+9); /* Trace */ - *(new+47) = *(old+47); /* Trap #15 */ - - if (p->brdno == 0x0162 || p->brdno == 0x172) - *(new+0x5e) = *(old+0x5e); /* ABORT switch */ - else - *(new+0x6e) = *(old+0x6e); /* ABORT switch */ -} - /*------------------- Serial console stuff ------------------------*/ extern void mvme167_serial_console_setup(int cflag); @@ -372,7 +343,7 @@ static void scc_delay (void) static void scc_write (char ch) { - volatile char *p = (volatile char *)SCC_A_ADDR; + volatile char *p = (volatile char *)MVME_SCC_A_ADDR; do { scc_delay(); diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c new file mode 100644 index 000000000..6b7c0c011 --- /dev/null +++ b/arch/m68k/mvme16x/rtc.c @@ -0,0 +1,166 @@ +/* + * Real Time Clock interface for Linux on the MVME16x + * + * Based on the PC driver by Paul Gortmaker. + */ + +#define RTC_VERSION "1.00" + +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/miscdevice.h> +#include <linux/malloc.h> +#include <linux/ioport.h> +#include <linux/fcntl.h> +#include <linux/init.h> +#include <linux/poll.h> +#include <linux/mc146818rtc.h> /* For struct rtc_time and ioctls, etc */ +#include <asm/mvme16xhw.h> + +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/system.h> +#include <asm/setup.h> + +/* + * We sponge a minor off of the misc major. No need slurping + * up another valuable major dev number for this. If you add + * an ioctl, make sure you don't conflict with SPARC's RTC + * ioctls. + */ + +#define BCD2BIN(val) (((val)&15) + ((val)>>4)*10) +#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10) + +static unsigned char days_in_mo[] = +{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +static char rtc_status = 0; + +static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + volatile MK48T08ptr_t rtc = (MK48T08ptr_t)MVME_RTC_BASE; + unsigned long flags; + struct rtc_time wtime; + + switch (cmd) { + case RTC_RD_TIME: /* Read the time/date from RTC */ + { + save_flags(flags); + cli(); + /* Ensure clock and real-time-mode-register are accessible */ + rtc->ctrl = RTC_READ; + wtime.tm_sec = BCD2BIN(rtc->bcd_sec); + wtime.tm_min = BCD2BIN(rtc->bcd_min); + wtime.tm_hour = BCD2BIN(rtc->bcd_hr); + wtime.tm_mday = BCD2BIN(rtc->bcd_dom); + wtime.tm_mon = BCD2BIN(rtc->bcd_mth)-1; + wtime.tm_year = BCD2BIN(rtc->bcd_year); + if (wtime.tm_year < 70) + wtime.tm_year += 100; + wtime.tm_wday = BCD2BIN(rtc->bcd_dow)-1; + rtc->ctrl = 0; + restore_flags(flags); + return copy_to_user((void *)arg, &wtime, sizeof wtime) ? + -EFAULT : 0; + } + case RTC_SET_TIME: /* Set the RTC */ + { + unsigned char leap_yr; + struct rtc_time rtc_tm; + + if (!suser()) + return -EACCES; + + if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, + sizeof(struct rtc_time))) + return -EFAULT; + + leap_yr = ((!(rtc_tm.tm_year % 4) && (rtc_tm.tm_year % 100)) || !(rtc_tm.tm_year % 400)); + + if ((rtc_tm.tm_mon > 12) || (rtc_tm.tm_mday == 0)) + return -EINVAL; + + if (rtc_tm.tm_mday > (days_in_mo[rtc_tm.tm_mon] + ((rtc_tm.tm_mon == 2) && leap_yr))) + return -EINVAL; + + if ((rtc_tm.tm_hour >= 24) || (rtc_tm.tm_min >= 60) || (rtc_tm.tm_sec >= 60)) + return -EINVAL; + + save_flags(flags); + cli(); + rtc->ctrl = RTC_WRITE; + + rtc->bcd_sec = BIN2BCD(rtc_tm.tm_sec); + rtc->bcd_min = BIN2BCD(rtc_tm.tm_min); + rtc->bcd_hr = BIN2BCD(rtc_tm.tm_hour); + rtc->bcd_dom = BIN2BCD(rtc_tm.tm_mday); + rtc->bcd_mth = BIN2BCD(rtc_tm.tm_mon + 1); + rtc->bcd_year = BIN2BCD(rtc_tm.tm_year%100); + if (rtc_tm.tm_wday >= 0) + rtc->bcd_dow = BIN2BCD(rtc_tm.tm_wday+1); + + rtc->ctrl = 0; + restore_flags(flags); + return 0; + } + default: + return -EINVAL; + } +} + +/* + * We enforce only one user at a time here with the open/close. + * Also clear the previous interrupt data on an open, and clean + * up things on a close. + */ + +static int rtc_open(struct inode *inode, struct file *file) +{ + if(rtc_status) + return -EBUSY; + + rtc_status = 1; + return 0; +} + +static int rtc_release(struct inode *inode, struct file *file) +{ + rtc_status = 0; + return 0; +} + +/* + * The various file operations we support. + */ + +static struct file_operations rtc_fops = { + NULL, + NULL, + NULL, /* No write */ + NULL, /* No readdir */ + NULL, + rtc_ioctl, + NULL, /* No mmap */ + rtc_open, + rtc_release +}; + +static struct miscdevice rtc_dev= +{ + RTC_MINOR, + "rtc", + &rtc_fops +}; + +__initfunc(int rtc_MK48T08_init(void)) +{ + if (!MACH_IS_MVME16x) + return -ENODEV; + + printk(KERN_INFO "MK48T08 Real Time Clock Driver v%s\n", RTC_VERSION); + misc_register(&rtc_dev); + return 0; +} + |