diff options
Diffstat (limited to 'arch/m68k/mac')
| -rw-r--r-- | arch/m68k/mac/Makefile | 4 | ||||
| -rw-r--r-- | arch/m68k/mac/baboon.c | 74 | ||||
| -rw-r--r-- | arch/m68k/mac/bootparse.c | 122 | ||||
| -rw-r--r-- | arch/m68k/mac/config.c | 576 | ||||
| -rw-r--r-- | arch/m68k/mac/debug.c | 388 | ||||
| -rw-r--r-- | arch/m68k/mac/iop.c | 108 | ||||
| -rw-r--r-- | arch/m68k/mac/macboing.c | 9 | ||||
| -rw-r--r-- | arch/m68k/mac/macints.c | 294 | ||||
| -rw-r--r-- | arch/m68k/mac/misc.c | 63 | ||||
| -rw-r--r-- | arch/m68k/mac/oss.c | 212 | ||||
| -rw-r--r-- | arch/m68k/mac/psc.c | 69 | ||||
| -rw-r--r-- | arch/m68k/mac/via.c | 364 |
12 files changed, 772 insertions, 1511 deletions
diff --git a/arch/m68k/mac/Makefile b/arch/m68k/mac/Makefile index 1d265ba365a..b8d4c835f9a 100644 --- a/arch/m68k/mac/Makefile +++ b/arch/m68k/mac/Makefile @@ -2,5 +2,5 @@ # Makefile for Linux arch/m68k/mac source directory # -obj-y := config.o bootparse.o macints.o iop.o via.o oss.o psc.o \ - baboon.o macboing.o debug.o misc.o +obj-y := config.o macints.o iop.o via.o oss.o psc.o \ + baboon.o macboing.o misc.o diff --git a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c index 673a1085984..3fe0e43d44f 100644 --- a/arch/m68k/mac/baboon.c +++ b/arch/m68k/mac/baboon.c @@ -8,24 +8,16 @@ #include <linux/types.h> #include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/ide.h> +#include <linux/irq.h> -#include <asm/traps.h> -#include <asm/bootinfo.h> #include <asm/macintosh.h> #include <asm/macints.h> #include <asm/mac_baboon.h> -/* #define DEBUG_BABOON */ /* #define DEBUG_IRQS */ int baboon_present; -volatile struct baboon *baboon; - -irqreturn_t baboon_irq(int, void *); +static volatile struct baboon *baboon; #if 0 extern int macide_ack_intr(struct ata_channel *); @@ -50,20 +42,10 @@ void __init baboon_init(void) } /* - * Register the Baboon interrupt dispatcher on nubus slot $C. - */ - -void __init baboon_register_interrupts(void) -{ - request_irq(IRQ_NUBUS_C, baboon_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST, - "baboon", (void *) baboon); -} - -/* * Baboon interrupt handler. This works a lot like a VIA. */ -irqreturn_t baboon_irq(int irq, void *dev_id) +static void baboon_irq(unsigned int irq, struct irq_desc *desc) { int irq_bit, irq_num; unsigned char events; @@ -74,15 +56,16 @@ irqreturn_t baboon_irq(int irq, void *dev_id) (uint) baboon->mb_status); #endif - if (!(events = baboon->mb_ifr & 0x07)) - return IRQ_NONE; + events = baboon->mb_ifr & 0x07; + if (!events) + return; irq_num = IRQ_BABOON_0; irq_bit = 1; do { if (events & irq_bit) { baboon->mb_ifr &= ~irq_bit; - m68k_handle_int(irq_num); + generic_handle_irq(irq_num); } irq_bit <<= 1; irq_num++; @@ -92,33 +75,40 @@ irqreturn_t baboon_irq(int irq, void *dev_id) /* for now we need to smash all interrupts */ baboon->mb_ifr &= ~events; #endif - return IRQ_HANDLED; } -void baboon_irq_enable(int irq) { -#ifdef DEBUG_IRQUSE - printk("baboon_irq_enable(%d)\n", irq); -#endif - /* FIXME: figure out how to mask and unmask baboon interrupt sources */ - enable_irq(IRQ_NUBUS_C); +/* + * Register the Baboon interrupt dispatcher on nubus slot $C. + */ + +void __init baboon_register_interrupts(void) +{ + irq_set_chained_handler(IRQ_NUBUS_C, baboon_irq); } -void baboon_irq_disable(int irq) { +/* + * The means for masking individual Baboon interrupts remains a mystery. + * However, since we only use the IDE IRQ, we can just enable/disable all + * Baboon interrupts. If/when we handle more than one Baboon IRQ, we must + * either figure out how to mask them individually or else implement the + * same workaround that's used for NuBus slots (see nubus_disabled and + * via_nubus_irq_shutdown). + */ + +void baboon_irq_enable(int irq) +{ #ifdef DEBUG_IRQUSE - printk("baboon_irq_disable(%d)\n", irq); + printk("baboon_irq_enable(%d)\n", irq); #endif - disable_irq(IRQ_NUBUS_C); -} - -void baboon_irq_clear(int irq) { - int irq_idx = IRQ_IDX(irq); - baboon->mb_ifr &= ~(1 << irq_idx); + mac_irq_enable(irq_get_irq_data(IRQ_NUBUS_C)); } -int baboon_irq_pending(int irq) +void baboon_irq_disable(int irq) { - int irq_idx = IRQ_IDX(irq); +#ifdef DEBUG_IRQUSE + printk("baboon_irq_disable(%d)\n", irq); +#endif - return baboon->mb_ifr & (1 << irq_idx); + mac_irq_disable(irq_get_irq_data(IRQ_NUBUS_C)); } diff --git a/arch/m68k/mac/bootparse.c b/arch/m68k/mac/bootparse.c deleted file mode 100644 index 36d22360982..00000000000 --- a/arch/m68k/mac/bootparse.c +++ /dev/null @@ -1,122 +0,0 @@ -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <asm/irq.h> -#include <asm/setup.h> -#include <asm/bootinfo.h> -#include <asm/macintosh.h> - -/* - * Booter vars - */ - -int boothowto; -int _boothowto; - -/* - * Called early to parse the environment (passed to us from the booter) - * into a bootinfo struct. Will die as soon as we have our own booter - */ - -#define atol(x) simple_strtoul(x,NULL,0) - -void parse_booter(char *env) -{ - char *name; - char *value; -#if 0 - while(0 && *env) -#else - while(*env) -#endif - { - name=env; - value=name; - while(*value!='='&&*value) - value++; - if(*value=='=') - *value++=0; - env=value; - while(*env) - env++; - env++; -#if 0 - if(strcmp(name,"VIDEO_ADDR")==0) - mac_mch.videoaddr=atol(value); - if(strcmp(name,"ROW_BYTES")==0) - mac_mch.videorow=atol(value); - if(strcmp(name,"SCREEN_DEPTH")==0) - mac_mch.videodepth=atol(value); - if(strcmp(name,"DIMENSIONS")==0) - mac_mch.dimensions=atol(value); -#endif - if(strcmp(name,"BOOTTIME")==0) - mac_bi_data.boottime=atol(value); - if(strcmp(name,"GMTBIAS")==0) - mac_bi_data.gmtbias=atol(value); - if(strcmp(name,"BOOTERVER")==0) - mac_bi_data.bootver=atol(value); - if(strcmp(name,"MACOS_VIDEO")==0) - mac_bi_data.videological=atol(value); - if(strcmp(name,"MACOS_SCC")==0) - mac_bi_data.sccbase=atol(value); - if(strcmp(name,"MACHINEID")==0) - mac_bi_data.id=atol(value); - if(strcmp(name,"MEMSIZE")==0) - mac_bi_data.memsize=atol(value); - if(strcmp(name,"SERIAL_MODEM_FLAGS")==0) - mac_bi_data.serialmf=atol(value); - if(strcmp(name,"SERIAL_MODEM_HSKICLK")==0) - mac_bi_data.serialhsk=atol(value); - if(strcmp(name,"SERIAL_MODEM_GPICLK")==0) - mac_bi_data.serialgpi=atol(value); - if(strcmp(name,"SERIAL_PRINT_FLAGS")==0) - mac_bi_data.printmf=atol(value); - if(strcmp(name,"SERIAL_PRINT_HSKICLK")==0) - mac_bi_data.printhsk=atol(value); - if(strcmp(name,"SERIAL_PRINT_GPICLK")==0) - mac_bi_data.printgpi=atol(value); - if(strcmp(name,"PROCESSOR")==0) - mac_bi_data.cpuid=atol(value); - if(strcmp(name,"ROMBASE")==0) - mac_bi_data.rombase=atol(value); - if(strcmp(name,"TIMEDBRA")==0) - mac_bi_data.timedbra=atol(value); - if(strcmp(name,"ADBDELAY")==0) - mac_bi_data.adbdelay=atol(value); - } -#if 0 /* XXX: TODO with m68k_mach_* */ - /* Fill in the base stuff */ - boot_info.machtype=MACH_MAC; - /* Read this from the macinfo we got ! */ -/* boot_info.cputype=CPU_68020|FPUB_68881;*/ -/* boot_info.memory[0].addr=0;*/ -/* boot_info.memory[0].size=((mac_bi_data.id>>7)&31)<<20;*/ - boot_info.num_memory=1; /* On a MacII */ - boot_info.ramdisk_size=0; /* For now */ - *boot_info.command_line=0; -#endif - } - - -void print_booter(char *env) -{ - char *name; - char *value; - while(*env) - { - name=env; - value=name; - while(*value!='='&&*value) - value++; - if(*value=='=') - *value++=0; - env=value; - while(*env) - env++; - env++; - printk("%s=%s\n", name,value); - } - } - - diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index 735a49b4b93..a471eab1a4d 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c @@ -22,12 +22,15 @@ /* keyb */ #include <linux/init.h> #include <linux/vt_kern.h> +#include <linux/platform_device.h> +#include <linux/adb.h> +#include <linux/cuda.h> -#define BOOTINFO_COMPAT_1_0 #include <asm/setup.h> #include <asm/bootinfo.h> +#include <asm/bootinfo-mac.h> +#include <asm/byteorder.h> -#include <asm/system.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/pgtable.h> @@ -44,30 +47,15 @@ #include <asm/mac_psc.h> /* Mac bootinfo struct */ - struct mac_booter_data mac_bi_data; -int mac_bisize = sizeof mac_bi_data; - -struct mac_hw_present mac_hw_present; -EXPORT_SYMBOL(mac_hw_present); - -/* New m68k bootinfo stuff and videobase */ - -extern int m68k_num_memory; -extern struct mem_info m68k_memory[NUM_MEMINFO]; - -extern struct mem_info m68k_ramdisk; - -void *mac_env; /* Loaded by the boot asm */ /* The phys. video addr. - might be bogus on some machines */ -unsigned long mac_orig_videoaddr; +static unsigned long mac_orig_videoaddr; /* Mac specific timer functions */ -extern unsigned long mac_gettimeoffset(void); +extern u32 mac_gettimeoffset(void); extern int mac_hwclk(int, struct rtc_time *); extern int mac_set_clock_mmss(unsigned long); -extern int show_mac_interrupts(struct seq_file *, void *); extern void iop_preinit(void); extern void iop_init(void); extern void via_init(void); @@ -79,9 +67,9 @@ extern void baboon_init(void); extern void mac_mksound(unsigned int, unsigned int); -extern void nubus_sweep_video(void); - static void mac_get_model(char *str); +static void mac_identify(void); +static void mac_report_hardware(void); static void __init mac_sched_init(irq_handler_t vector) { @@ -95,45 +83,46 @@ static void __init mac_sched_init(irq_handler_t vector) int __init mac_parse_bootinfo(const struct bi_record *record) { int unknown = 0; - const u_long *data = record->data; + const void *data = record->data; - switch (record->tag) { + switch (be16_to_cpu(record->tag)) { case BI_MAC_MODEL: - mac_bi_data.id = *data; + mac_bi_data.id = be32_to_cpup(data); break; case BI_MAC_VADDR: - mac_bi_data.videoaddr = *data; + mac_bi_data.videoaddr = be32_to_cpup(data); break; case BI_MAC_VDEPTH: - mac_bi_data.videodepth = *data; + mac_bi_data.videodepth = be32_to_cpup(data); break; case BI_MAC_VROW: - mac_bi_data.videorow = *data; + mac_bi_data.videorow = be32_to_cpup(data); break; case BI_MAC_VDIM: - mac_bi_data.dimensions = *data; + mac_bi_data.dimensions = be32_to_cpup(data); break; case BI_MAC_VLOGICAL: - mac_bi_data.videological = VIDEOMEMBASE + (*data & ~VIDEOMEMMASK); - mac_orig_videoaddr = *data; + mac_orig_videoaddr = be32_to_cpup(data); + mac_bi_data.videological = + VIDEOMEMBASE + (mac_orig_videoaddr & ~VIDEOMEMMASK); break; case BI_MAC_SCCBASE: - mac_bi_data.sccbase = *data; + mac_bi_data.sccbase = be32_to_cpup(data); break; case BI_MAC_BTIME: - mac_bi_data.boottime = *data; + mac_bi_data.boottime = be32_to_cpup(data); break; case BI_MAC_GMTBIAS: - mac_bi_data.gmtbias = *data; + mac_bi_data.gmtbias = be32_to_cpup(data); break; case BI_MAC_MEMSIZE: - mac_bi_data.memsize = *data; + mac_bi_data.memsize = be32_to_cpup(data); break; case BI_MAC_CPUID: - mac_bi_data.cpuid = *data; + mac_bi_data.cpuid = be32_to_cpup(data); break; case BI_MAC_ROMBASE: - mac_bi_data.rombase = *data; + mac_bi_data.rombase = be32_to_cpup(data); break; default: unknown = 1; @@ -160,16 +149,13 @@ static void mac_cache_card_flush(int writeback) void __init config_mac(void) { if (!MACH_IS_MAC) - printk(KERN_ERR "ERROR: no Mac, but config_mac() called!! \n"); + printk(KERN_ERR "ERROR: no Mac, but config_mac() called!!\n"); mach_sched_init = mac_sched_init; mach_init_IRQ = mac_init_IRQ; mach_get_model = mac_get_model; - mach_gettimeoffset = mac_gettimeoffset; -#warning move to adb/via init -#if 0 + arch_gettimeoffset = mac_gettimeoffset; mach_hwclk = mac_hwclk; -#endif mach_set_clock_mmss = mac_set_clock_mmss; mach_reset = mac_reset; mach_halt = mac_poweroff; @@ -178,12 +164,6 @@ void __init config_mac(void) #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE) mach_beep = mac_mksound; #endif -#ifdef CONFIG_HEARTBEAT -#if 0 - mach_heartbeat = mac_heartbeat; - mach_heartbeat_irq = IRQ_MAC_TIMER; -#endif -#endif /* * Determine hardware present @@ -201,27 +181,19 @@ void __init config_mac(void) if (macintosh_config->ident == MAC_MODEL_IICI || macintosh_config->ident == MAC_MODEL_IIFX) mach_l2_flush = mac_cache_card_flush; - - /* - * Check for machine specific fixups. - */ - -#ifdef OLD_NUBUS_CODE - nubus_sweep_video(); -#endif } /* - * Macintosh Table: hardcoded model configuration data. + * 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 :-) + * 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; @@ -229,7 +201,7 @@ EXPORT_SYMBOL(macintosh_config); static struct mac_model mac_data_table[] = { /* - * We'll pretend to be a Macintosh II, that's pretty safe. + * We'll pretend to be a Macintosh II, that's pretty safe. */ { @@ -239,12 +211,12 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_II, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_IWM, }, /* - * Original MacII hardware - * + * Original Mac II hardware */ { @@ -254,7 +226,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_II, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_IWM, }, { .ident = MAC_MODEL_IIX, .name = "IIx", @@ -262,7 +235,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_II, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_IICX, .name = "IIcx", @@ -270,7 +244,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_II, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_SE30, .name = "SE/30", @@ -278,13 +253,14 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_II, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, /* - * Weirdified MacII hardware - all subtly different. Gee thanks - * Apple. All these boxes seem to have VIA2 in a different place to - * the MacII (+1A000 rather than +4000) + * Weirdified Mac II hardware - all subtly different. Gee thanks + * Apple. All these boxes seem to have VIA2 in a different place to + * the Mac II (+1A000 rather than +4000) * CSA: see http://developer.apple.com/technotes/hw/hw_09.html */ @@ -292,103 +268,123 @@ static struct mac_model mac_data_table[] = { .ident = MAC_MODEL_IICI, .name = "IIci", .adb_type = MAC_ADB_II, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_IIFX, .name = "IIfx", .adb_type = MAC_ADB_IOP, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_IOP, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_IOP, }, { .ident = MAC_MODEL_IISI, .name = "IIsi", .adb_type = MAC_ADB_IISI, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_IIVI, .name = "IIvi", .adb_type = MAC_ADB_IISI, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_IIVX, .name = "IIvx", .adb_type = MAC_ADB_IISI, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, /* - * Classic models (guessing: similar to SE/30 ?? Nope, similar to LC ...) + * Classic models (guessing: similar to SE/30? Nope, similar to LC...) */ { .ident = MAC_MODEL_CLII, .name = "Classic II", .adb_type = MAC_ADB_IISI, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_CCL, .name = "Color Classic", .adb_type = MAC_ADB_CUDA, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS}, + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, + }, { + .ident = MAC_MODEL_CCLII, + .name = "Color Classic II", + .adb_type = MAC_ADB_CUDA, + .via_type = MAC_VIA_IICI, + .scsi_type = MAC_SCSI_OLD, + .scc_type = MAC_SCC_II, + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, + }, /* - * Some Mac LC machines. Basically the same as the IIci, ADB like IIsi + * Some Mac LC machines. Basically the same as the IIci, ADB like IIsi */ { .ident = MAC_MODEL_LC, .name = "LC", .adb_type = MAC_ADB_IISI, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_LCII, .name = "LC II", .adb_type = MAC_ADB_IISI, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_LCIII, .name = "LC III", .adb_type = MAC_ADB_IISI, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, /* - * Quadra. Video is at 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 using a NatSemi SONIC except the 660AV and 840AV which use an - * AMD 79C940 (MACE). - * The 700, 900 and 950 have some I/O chips in the wrong place to - * confuse us. The 840AV has a SCSI location of its own (same as - * the 660AV). + * Quadra. Video is at 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 using a NatSemi SONIC except + * the 660AV and 840AV which use an AMD 79C940 (MACE). + * The 700, 900 and 950 have some I/O chips in the wrong place to + * confuse us. The 840AV has a SCSI location of its own (same as + * the 660AV). */ { @@ -398,7 +394,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_Q605_ACC, .name = "Quadra 605", @@ -406,7 +403,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_Q610, .name = "Quadra 610", @@ -415,7 +413,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_Q630, .name = "Quadra 630", @@ -425,7 +424,8 @@ static struct mac_model mac_data_table[] = { .ide_type = MAC_IDE_QUADRA, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_Q650, .name = "Quadra 650", @@ -434,9 +434,10 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, - /* The Q700 does have a NS Sonic */ + /* The Q700 does have a NS Sonic */ { .ident = MAC_MODEL_Q700, .name = "Quadra 700", @@ -445,7 +446,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA2, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_Q800, .name = "Quadra 800", @@ -454,7 +456,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_Q840, .name = "Quadra 840AV", @@ -463,7 +466,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA3, .scc_type = MAC_SCC_PSC, .ether_type = MAC_ETHER_MACE, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_AV, }, { .ident = MAC_MODEL_Q900, .name = "Quadra 900", @@ -472,7 +476,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA2, .scc_type = MAC_SCC_IOP, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_IOP, }, { .ident = MAC_MODEL_Q950, .name = "Quadra 950", @@ -481,55 +486,61 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA2, .scc_type = MAC_SCC_IOP, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_IOP, }, /* - * Performa - more LC type machines + * Performa - more LC type machines */ { .ident = MAC_MODEL_P460, - .name = "Performa 460", + .name = "Performa 460", .adb_type = MAC_ADB_IISI, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_P475, - .name = "Performa 475", + .name = "Performa 475", .adb_type = MAC_ADB_CUDA, .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_P475F, - .name = "Performa 475", + .name = "Performa 475", .adb_type = MAC_ADB_CUDA, .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_P520, - .name = "Performa 520", + .name = "Performa 520", .adb_type = MAC_ADB_CUDA, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_P550, - .name = "Performa 550", + .name = "Performa 550", .adb_type = MAC_ADB_CUDA, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, - /* These have the comm slot, and therefore the possibility of SONIC ethernet */ + /* These have the comm slot, and therefore possibly SONIC ethernet */ { .ident = MAC_MODEL_P575, .name = "Performa 575", @@ -538,7 +549,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_II, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_P588, .name = "Performa 588", @@ -548,30 +560,33 @@ static struct mac_model mac_data_table[] = { .ide_type = MAC_IDE_QUADRA, .scc_type = MAC_SCC_II, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_TV, .name = "TV", .adb_type = MAC_ADB_CUDA, - .via_type = MAC_VIA_QUADRA, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_P600, .name = "Performa 600", .adb_type = MAC_ADB_IISI, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, /* - * Centris - just guessing again; maybe like Quadra + * Centris - just guessing again; maybe like Quadra. + * The C610 may or may not have SONIC. We probe to make sure. */ - /* The C610 may or may not have SONIC. We probe to make sure */ { .ident = MAC_MODEL_C610, .name = "Centris 610", @@ -580,7 +595,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_C650, .name = "Centris 650", @@ -589,7 +605,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_C660, .name = "Centris 660AV", @@ -598,7 +615,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA3, .scc_type = MAC_SCC_PSC, .ether_type = MAC_ETHER_MACE, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_AV, }, /* @@ -614,7 +632,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB145, .name = "PowerBook 145", @@ -622,16 +641,18 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB150, .name = "PowerBook 150", - .adb_type = MAC_ADB_PB1, - .via_type = MAC_VIA_IIci, + .adb_type = MAC_ADB_PB2, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .ide_type = MAC_IDE_PB, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB160, .name = "PowerBook 160", @@ -639,7 +660,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB165, .name = "PowerBook 165", @@ -647,7 +669,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB165C, .name = "PowerBook 165c", @@ -655,7 +678,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB170, .name = "PowerBook 170", @@ -663,7 +687,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB180, .name = "PowerBook 180", @@ -671,7 +696,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB180C, .name = "PowerBook 180c", @@ -679,7 +705,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB190, .name = "PowerBook 190", @@ -688,7 +715,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_OLD, .ide_type = MAC_IDE_BABOON, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB520, .name = "PowerBook 520", @@ -697,78 +725,108 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, /* * PowerBook Duos are pretty much like normal PowerBooks * All of these probably have onboard SONIC in the Dock which * means we'll have to probe for it eventually. - * - * Are these really MAC_VIA_IIci? The developer notes for the - * Duos show pretty much the same custom parts as in most of - * the other PowerBooks which would imply MAC_VIA_QUADRA. */ { .ident = MAC_MODEL_PB210, .name = "PowerBook Duo 210", .adb_type = MAC_ADB_PB2, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB230, .name = "PowerBook Duo 230", .adb_type = MAC_ADB_PB2, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB250, .name = "PowerBook Duo 250", .adb_type = MAC_ADB_PB2, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB270C, .name = "PowerBook Duo 270c", .adb_type = MAC_ADB_PB2, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB280, .name = "PowerBook Duo 280", .adb_type = MAC_ADB_PB2, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB280C, .name = "PowerBook Duo 280c", .adb_type = MAC_ADB_PB2, - .via_type = MAC_VIA_IIci, + .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, /* - * Other stuff ?? + * Other stuff? */ + { .ident = -1 } }; -void __init mac_identify(void) +static struct resource scc_a_rsrcs[] = { + { .flags = IORESOURCE_MEM }, + { .flags = IORESOURCE_IRQ }, +}; + +static struct resource scc_b_rsrcs[] = { + { .flags = IORESOURCE_MEM }, + { .flags = IORESOURCE_IRQ }, +}; + +struct platform_device scc_a_pdev = { + .name = "scc", + .id = 0, + .num_resources = ARRAY_SIZE(scc_a_rsrcs), + .resource = scc_a_rsrcs, +}; +EXPORT_SYMBOL(scc_a_pdev); + +struct platform_device scc_b_pdev = { + .name = "scc", + .id = 1, + .num_resources = ARRAY_SIZE(scc_b_rsrcs), + .resource = scc_b_rsrcs, +}; +EXPORT_SYMBOL(scc_b_pdev); + +static void __init mac_identify(void) { struct mac_model *m; @@ -778,7 +836,8 @@ void __init mac_identify(void) /* no bootinfo model id -> NetBSD booter was used! */ /* XXX FIXME: breaks for model > 31 */ model = (mac_bi_data.cpuid >> 2) & 63; - printk(KERN_WARNING "No bootinfo model ID, using cpuid instead (hey, use Penguin!)\n"); + printk(KERN_WARNING "No bootinfo model ID, using cpuid instead " + "(obsolete bootloader?)\n"); } macintosh_config = mac_data_table; @@ -789,63 +848,68 @@ void __init mac_identify(void) } } - /* We need to pre-init the IOPs, if any. Otherwise */ - /* the serial console won't work if the user had */ - /* the serial ports set to "Faster" mode in MacOS. */ + /* Set up serial port resources for the console initcall. */ + + scc_a_rsrcs[0].start = (resource_size_t) mac_bi_data.sccbase + 2; + scc_a_rsrcs[0].end = scc_a_rsrcs[0].start; + scc_b_rsrcs[0].start = (resource_size_t) mac_bi_data.sccbase; + scc_b_rsrcs[0].end = scc_b_rsrcs[0].start; + + switch (macintosh_config->scc_type) { + case MAC_SCC_PSC: + scc_a_rsrcs[1].start = scc_a_rsrcs[1].end = IRQ_MAC_SCC_A; + scc_b_rsrcs[1].start = scc_b_rsrcs[1].end = IRQ_MAC_SCC_B; + break; + default: + /* On non-PSC machines, the serial ports share an IRQ. */ + if (macintosh_config->ident == MAC_MODEL_IIFX) { + scc_a_rsrcs[1].start = scc_a_rsrcs[1].end = IRQ_MAC_SCC; + scc_b_rsrcs[1].start = scc_b_rsrcs[1].end = IRQ_MAC_SCC; + } else { + scc_a_rsrcs[1].start = scc_a_rsrcs[1].end = IRQ_AUTO_4; + scc_b_rsrcs[1].start = scc_b_rsrcs[1].end = IRQ_AUTO_4; + } + break; + } + /* + * We need to pre-init the IOPs, if any. Otherwise + * the serial console won't work if the user had + * the serial ports set to "Faster" mode in MacOS. + */ iop_preinit(); - printk(KERN_INFO "Detected Macintosh model: %d \n", model); + printk(KERN_INFO "Detected Macintosh model: %d\n", model); /* * Report booter data: */ printk(KERN_DEBUG " Penguin bootinfo data:\n"); - printk(KERN_DEBUG " Video: addr 0x%lx row 0x%lx depth %lx dimensions %ld x %ld\n", + printk(KERN_DEBUG " 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); - printk(KERN_DEBUG " Videological 0x%lx phys. 0x%lx, SCC at 0x%lx \n", + printk(KERN_DEBUG " Videological 0x%lx phys. 0x%lx, SCC at 0x%lx\n", mac_bi_data.videological, mac_orig_videoaddr, mac_bi_data.sccbase); - printk(KERN_DEBUG " Boottime: 0x%lx GMTBias: 0x%lx \n", + printk(KERN_DEBUG " Boottime: 0x%lx GMTBias: 0x%lx\n", mac_bi_data.boottime, mac_bi_data.gmtbias); - printk(KERN_DEBUG " Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n", + printk(KERN_DEBUG " 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 - - /* - * 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(KERN_WARNING "config.c: wtf: unknown scsi, using 53c80\n"); - MACHW_SET(MAC_SCSI_80); - break; - } iop_init(); via_init(); oss_init(); psc_init(); baboon_init(); + +#ifdef CONFIG_ADB_CUDA + find_via_cuda(); +#endif } -void __init mac_report_hardware(void) +static void __init mac_report_hardware(void) { printk(KERN_INFO "Apple Macintosh %s\n", macintosh_config->name); } @@ -855,3 +919,103 @@ static void mac_get_model(char *str) strcpy(str, "Macintosh "); strcat(str, macintosh_config->name); } + +static struct resource swim_rsrc = { .flags = IORESOURCE_MEM }; + +static struct platform_device swim_pdev = { + .name = "swim", + .id = -1, + .num_resources = 1, + .resource = &swim_rsrc, +}; + +static struct platform_device esp_0_pdev = { + .name = "mac_esp", + .id = 0, +}; + +static struct platform_device esp_1_pdev = { + .name = "mac_esp", + .id = 1, +}; + +static struct platform_device sonic_pdev = { + .name = "macsonic", + .id = -1, +}; + +static struct platform_device mace_pdev = { + .name = "macmace", + .id = -1, +}; + +int __init mac_platform_init(void) +{ + u8 *swim_base; + + if (!MACH_IS_MAC) + return -ENODEV; + + /* + * Serial devices + */ + + platform_device_register(&scc_a_pdev); + platform_device_register(&scc_b_pdev); + + /* + * Floppy device + */ + + switch (macintosh_config->floppy_type) { + case MAC_FLOPPY_SWIM_ADDR1: + swim_base = (u8 *)(VIA1_BASE + 0x1E000); + break; + case MAC_FLOPPY_SWIM_ADDR2: + swim_base = (u8 *)(VIA1_BASE + 0x16000); + break; + default: + swim_base = NULL; + break; + } + + if (swim_base) { + swim_rsrc.start = (resource_size_t) swim_base, + swim_rsrc.end = (resource_size_t) swim_base + 0x2000, + platform_device_register(&swim_pdev); + } + + /* + * SCSI device(s) + */ + + switch (macintosh_config->scsi_type) { + case MAC_SCSI_QUADRA: + case MAC_SCSI_QUADRA3: + platform_device_register(&esp_0_pdev); + break; + case MAC_SCSI_QUADRA2: + platform_device_register(&esp_0_pdev); + if ((macintosh_config->ident == MAC_MODEL_Q900) || + (macintosh_config->ident == MAC_MODEL_Q950)) + platform_device_register(&esp_1_pdev); + break; + } + + /* + * Ethernet device + */ + + switch (macintosh_config->ether_type) { + case MAC_ETHER_SONIC: + platform_device_register(&sonic_pdev); + break; + case MAC_ETHER_MACE: + platform_device_register(&mace_pdev); + break; + } + + return 0; +} + +arch_initcall(mac_platform_init); diff --git a/arch/m68k/mac/debug.c b/arch/m68k/mac/debug.c deleted file mode 100644 index e8a57138b4a..00000000000 --- a/arch/m68k/mac/debug.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - * linux/arch/m68k/mac/debug.c - * - * Shamelessly stolen (SCC code and general framework) from: - * - * linux/arch/m68k/atari/debug.c - * - * Atari debugging and serial console stuff - * - * Assembled of parts of former atari/config.c 97-12-18 by Roman Hodek - * - * 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/types.h> -#include <linux/sched.h> -#include <linux/tty.h> -#include <linux/console.h> -#include <linux/init.h> -#include <linux/delay.h> - -#define BOOTINFO_COMPAT_1_0 -#include <asm/setup.h> -#include <asm/bootinfo.h> -#include <asm/machw.h> -#include <asm/macints.h> - -extern unsigned long mac_videobase; -extern unsigned long mac_videodepth; -extern unsigned long mac_rowbytes; - -extern void mac_serial_print(const char *); - -#define DEBUG_HEADS -#undef 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 - * setup routines :-) it permits writing 'data' to the screen as bit patterns - * (good luck reading those). Helped to figure that the bootinfo contained - * garbage data on the amount and size of memory chunks ... - * - * The 'pos' argument now simply means 'linefeed after print' ... - */ - -#ifdef DEBUG_SCREEN -static int peng, line; -#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 + - (150+line*2) * mac_rowbytes + 80 * peng; - - pptr = pengoffset; - - for (i = 0; i < 8 * sizeof(short); i++) { /* # of bits */ - /* value mask for bit i, reverse order */ - *pptr++ = (num & (1 << (8*sizeof(short)-i-1)) ? 0xFF : 0x00); - } - - peng++; - - if (pos) { - 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+(150+line*2)*mac_rowbytes) - +80*peng; - - pptr = pengoffset; - - for (i = 0; i < 8 * sizeof(long); i++) { /* # of bits */ - *pptr++ = (addr & (1 << (8*sizeof(long)-i-1)) ? 0xFF : 0x00); - } - - peng++; - - if (pos) { - line++; - peng = 0; - } -#endif -} - -#ifdef DEBUG_SERIAL -/* - * TODO: serial debug code - */ - -struct mac_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 mac_SCC*)mac_bi_data.sccbase)) - -/* Flag that serial port is already initialized and used */ -int mac_SCC_init_done; -/* Can be set somewhere, if a SCC master reset has already be done and should - * not be repeated; used by kgdb */ -int mac_SCC_reset_done; - -static int scc_port = -1; - -static struct console mac_console_driver = { - .name = "debug", - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -/* - * Crude hack to get console output to the screen before the framebuffer - * is initialized (happens a lot later in 2.1!). - * We just use the console routines declared in head.S, this will interfere - * with regular framebuffer console output and should be used exclusively - * to debug kernel problems manifesting before framebuffer init (aka WSOD) - * - * To keep this hack from interfering with the regular console driver, either - * deregister this driver before/on framebuffer console init, or silence this - * function after the fbcon driver is running (will lose console messages!?). - * To debug real early bugs, need to write a 'mac_register_console_hack()' - * that is called from start_kernel() before setup_arch() and just registers - * this driver if Mac. - */ - -void mac_debug_console_write(struct console *co, const char *str, - unsigned int count) -{ - mac_serial_print(str); -} - - - -/* Mac: loops_per_jiffy min. 19000 ^= .5 us; MFPDELAY was 0.6 us*/ - -#define uSEC 1 - -static inline void mac_sccb_out(char c) -{ - int i; - - do { - for (i = uSEC; i > 0; --i) - barrier(); - } while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */ - for (i = uSEC; i > 0; --i) - barrier(); - scc.cha_b_data = c; -} - -static inline void mac_scca_out(char c) -{ - int i; - - do { - for (i = uSEC; i > 0; --i) - barrier(); - } while (!(scc.cha_a_ctrl & 0x04)); /* wait for tx buf empty */ - for (i = uSEC; 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_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++); - } -} - - -/* 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 SCCB_WRITE(reg,val) \ - do { \ - int i; \ - scc.cha_b_ctrl = (reg); \ - for (i = uSEC; i > 0; --i) \ - barrier(); \ - scc.cha_b_ctrl = (val); \ - for (i = uSEC; i > 0; --i) \ - barrier(); \ - } while(0) - -#define SCCA_WRITE(reg,val) \ - do { \ - int i; \ - scc.cha_a_ctrl = (reg); \ - for (i = uSEC; i > 0; --i) \ - barrier(); \ - scc.cha_a_ctrl = (val); \ - for (i = uSEC; i > 0; --i) \ - barrier(); \ - } while(0) - -/* loops_per_jiffy isn't initialized yet, so we can't use udelay(). This does a - * delay of ~ 60us. */ -/* Mac: loops_per_jiffy min. 19000 ^= .5 us; MFPDELAY was 0.6 us*/ -#define LONG_DELAY() \ - do { \ - int i; \ - for (i = 60*uSEC; i > 0; --i) \ - barrier(); \ - } while(0) - -#ifndef CONFIG_SERIAL_CONSOLE -static void __init mac_init_scc_port(int cflag, int port) -#else -void mac_init_scc_port(int cflag, int port) -#endif -{ - extern int mac_SCC_reset_done; - - /* - * baud rates: 1200, 1800, 2400, 4800, 9600, 19.2k, 38.4k, 57.6k, 115.2k - */ - - static int clksrc_table[9] = - /* reg 11: 0x50 = BRG, 0x00 = RTxC, 0x28 = TRxC */ - { 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 }; - static int clkmode_table[9] = - /* reg 4: 0x40 = x16, 0x80 = x32, 0xc0 = x64 */ - { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0, 0x80 }; - static int div_table[9] = - /* reg12 (BRG low) */ - { 94, 62, 46, 22, 10, 4, 1, 0, 0 }; - - int baud = cflag & CBAUD; - int clksrc, clkmode, div, reg3, reg5; - - if (cflag & CBAUDEX) - baud += B38400; - if (baud < B1200 || baud > B38400+2) - baud = B9600; /* use default 9600bps for non-implemented rates */ - baud -= B1200; /* tables starts at 1200bps */ - - clksrc = clksrc_table[baud]; - clkmode = clkmode_table[baud]; - div = div_table[baud]; - - reg3 = (((cflag & CSIZE) == CS8) ? 0xc0 : 0x40); - reg5 = (((cflag & CSIZE) == CS8) ? 0x60 : 0x20) | 0x82 /* assert DTR/RTS */; - - if (port == 1) { - (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, 1); - SCCB_WRITE(3, reg3 | 1); - SCCB_WRITE(5, reg5 | 8); - } else if (port == 0) { - (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, 1); - SCCA_WRITE(3, reg3 | 1); - SCCA_WRITE(5, reg5 | 8); - } - - mac_SCC_reset_done = 1; - mac_SCC_init_done = 1; -} -#endif /* DEBUG_SERIAL */ - -void mac_init_scca_port(int cflag) -{ - mac_init_scc_port(cflag, 0); -} - -void mac_init_sccb_port(int cflag) -{ - mac_init_scc_port(cflag, 1); -} - -static int __init mac_debug_setup(char *arg) -{ - if (!MACH_IS_MAC) - return 0; - -#ifdef DEBUG_SERIAL - if (!strcmp(arg, "ser") || !strcmp(arg, "ser1")) { - /* Mac modem port */ - mac_init_scc_port(B9600|CS8, 0); - mac_console_driver.write = mac_scca_console_write; - scc_port = 0; - } else if (!strcmp(arg, "ser2")) { - /* Mac printer port */ - mac_init_scc_port(B9600|CS8, 1); - mac_console_driver.write = mac_sccb_console_write; - scc_port = 1; - } -#endif -#ifdef DEBUG_HEADS - if (!strcmp(arg, "scn") || !strcmp(arg, "con")) { - /* display, using head.S console routines */ - mac_console_driver.write = mac_debug_console_write; - } -#endif - if (mac_console_driver.write) - register_console(&mac_console_driver); - return 0; -} - -early_param("debug", mac_debug_setup); diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c index 5b2799eb96a..4d2adfb32a2 100644 --- a/arch/m68k/mac/iop.c +++ b/arch/m68k/mac/iop.c @@ -109,24 +109,17 @@ #include <linux/mm.h> #include <linux/delay.h> #include <linux/init.h> -#include <linux/proc_fs.h> #include <linux/interrupt.h> -#include <asm/bootinfo.h> #include <asm/macintosh.h> #include <asm/macints.h> #include <asm/mac_iop.h> -#include <asm/mac_oss.h> /*#define DEBUG_IOP*/ -/* Set to non-zero if the IOPs are present. Set by iop_init() */ +/* Non-zero if the IOPs are present */ -int iop_scc_present,iop_ism_present; - -#ifdef CONFIG_PROC_FS -static int iop_get_proc_info(char *, char **, off_t, int); -#endif /* CONFIG_PROC_FS */ +int iop_scc_present, iop_ism_present; /* structure for tracking channel listeners */ @@ -154,8 +147,6 @@ static struct listener iop_listeners[NUM_IOPS][NUM_IOP_CHAN]; irqreturn_t iop_ism_irq(int, void *); -extern void oss_irq_enable(int); - /* * Private access functions */ @@ -299,12 +290,6 @@ void __init iop_init(void) iop_listeners[IOP_NUM_ISM][i].devname = NULL; iop_listeners[IOP_NUM_ISM][i].handler = NULL; } - -#if 0 /* Crashing in 2.4 now, not yet sure why. --jmt */ -#ifdef CONFIG_PROC_FS - create_proc_info_entry("mac_iop", 0, &proc_root, iop_get_proc_info); -#endif -#endif } /* @@ -315,15 +300,14 @@ void __init iop_init(void) void __init iop_register_interrupts(void) { if (iop_ism_present) { - if (oss_present) { - request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq, - IRQ_FLG_LOCK, "ISM IOP", - (void *) IOP_NUM_ISM); - oss_irq_enable(IRQ_MAC_ADB); + if (macintosh_config->ident == MAC_MODEL_IIFX) { + if (request_irq(IRQ_MAC_ADB, iop_ism_irq, 0, + "ISM IOP", (void *)IOP_NUM_ISM)) + pr_err("Couldn't register ISM IOP interrupt\n"); } else { - request_irq(IRQ_VIA2_0, iop_ism_irq, - IRQ_FLG_LOCK|IRQ_FLG_FAST, "ISM IOP", - (void *) IOP_NUM_ISM); + if (request_irq(IRQ_VIA2_0, iop_ism_irq, 0, "ISM IOP", + (void *)IOP_NUM_ISM)) + pr_err("Couldn't register ISM IOP interrupt\n"); } if (!iop_alive(iop_base[IOP_NUM_ISM])) { printk("IOP: oh my god, they killed the ISM IOP!\n"); @@ -637,77 +621,3 @@ irqreturn_t iop_ism_irq(int irq, void *dev_id) } return IRQ_HANDLED; } - -#ifdef CONFIG_PROC_FS - -char *iop_chan_state(int state) -{ - switch(state) { - case IOP_MSG_IDLE : return "idle "; - case IOP_MSG_NEW : return "new "; - case IOP_MSG_RCVD : return "received "; - case IOP_MSG_COMPLETE : return "completed "; - default : return "unknown "; - } -} - -int iop_dump_one_iop(char *buf, int iop_num, char *iop_name) -{ - int i,len = 0; - volatile struct mac_iop *iop = iop_base[iop_num]; - - len += sprintf(buf+len, "%s IOP channel states:\n\n", iop_name); - len += sprintf(buf+len, "## send_state recv_state device\n"); - len += sprintf(buf+len, "------------------------------------------------\n"); - for (i = 0 ; i < NUM_IOP_CHAN ; i++) { - len += sprintf(buf+len, "%2d %10s %10s %s\n", i, - iop_chan_state(iop_readb(iop, IOP_ADDR_SEND_STATE+i)), - iop_chan_state(iop_readb(iop, IOP_ADDR_RECV_STATE+i)), - iop_listeners[iop_num][i].handler? - iop_listeners[iop_num][i].devname : ""); - - } - len += sprintf(buf+len, "\n"); - return len; -} - -static int iop_get_proc_info(char *buf, char **start, off_t pos, int count) -{ - int len, cnt; - - cnt = 0; - len = sprintf(buf, "IOPs detected:\n\n"); - - if (iop_scc_present) { - len += sprintf(buf+len, "SCC IOP (%p): status %02X\n", - iop_base[IOP_NUM_SCC], - (uint) iop_base[IOP_NUM_SCC]->status_ctrl); - } - if (iop_ism_present) { - len += sprintf(buf+len, "ISM IOP (%p): status %02X\n\n", - iop_base[IOP_NUM_ISM], - (uint) iop_base[IOP_NUM_ISM]->status_ctrl); - } - - if (iop_scc_present) { - len += iop_dump_one_iop(buf+len, IOP_NUM_SCC, "SCC"); - - } - - if (iop_ism_present) { - len += iop_dump_one_iop(buf+len, IOP_NUM_ISM, "ISM"); - - } - - if (len >= pos) { - if (!*start) { - *start = buf + pos; - cnt = len - pos; - } else { - cnt += len; - } - } - return (count > cnt) ? cnt : count; -} - -#endif /* CONFIG_PROC_FS */ diff --git a/arch/m68k/mac/macboing.c b/arch/m68k/mac/macboing.c index 8f0640847ad..ffaa1f6439a 100644 --- a/arch/m68k/mac/macboing.c +++ b/arch/m68k/mac/macboing.c @@ -114,7 +114,8 @@ static void mac_init_asc( void ) * 16-bit I/O functionality. The PowerBook 500 series computers * support 16-bit stereo output, but only mono input." * - * http://til.info.apple.com/techinfo.nsf/artnum/n16405 + * Technical Information Library (TIL) article number 16405. + * http://support.apple.com/kb/TA32601 * * --David Kilzer */ @@ -162,7 +163,7 @@ static void mac_init_asc( void ) void mac_mksound( unsigned int freq, unsigned int length ) { __u32 cfreq = ( freq << 5 ) / 468; - __u32 flags; + unsigned long flags; int i; if ( mac_special_bell == NULL ) @@ -224,7 +225,7 @@ static void mac_nosound( unsigned long ignored ) */ static void mac_quadra_start_bell( unsigned int freq, unsigned int length, unsigned int volume ) { - __u32 flags; + unsigned long flags; /* if the bell is already ringing, ring longer */ if ( mac_bell_duration > 0 ) @@ -271,7 +272,7 @@ static void mac_quadra_start_bell( unsigned int freq, unsigned int length, unsig static void mac_quadra_ring_bell( unsigned long ignored ) { int i, count = mac_asc_samplespersec / HZ; - __u32 flags; + unsigned long flags; /* * we neither want a sound buffer overflow nor underflow, so we need to match diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c index ecddac4a02b..5c1a6b2ff0a 100644 --- a/arch/m68k/mac/macints.c +++ b/arch/m68k/mac/macints.c @@ -26,17 +26,11 @@ * - slot 6: timer 1 (not on IIci) * - slot 7: status of IRQ; signals 'any enabled int.' * - * 2 - OSS (IIfx only?) - * - slot 0: SCSI interrupt - * - slot 1: Sound interrupt - * * Levels 3-6 vary by machine type. For VIA or RBV Macintoshes: * * 3 - unused (?) * - * 4 - SCC (slot number determined by reading RR3 on the SSC itself) - * - slot 1: SCC channel A - * - slot 2: SCC channel B + * 4 - SCC * * 5 - unused (?) * [serial errors or special conditions seem to raise level 6 @@ -44,23 +38,30 @@ * * 6 - off switch (?) * - * For OSS Macintoshes (IIfx only at this point): + * Machines with Quadra-like VIA hardware, except PSC and PMU machines, support + * an alternate interrupt mapping, as used by A/UX. It spreads ethernet and + * sound out to their own autovector IRQs and gives VIA1 a higher priority: * - * 3 - Nubus interrupt - * - slot 0: Slot $9 - * - slot 1: Slot $A - * - slot 2: Slot $B - * - slot 3: Slot $C - * - slot 4: Slot $D - * - slot 5: Slot $E + * 1 - unused (?) * - * 4 - SCC IOP - * - slot 1: SCC channel A - * - slot 2: SCC channel B + * 3 - on-board SONIC + * + * 5 - Apple Sound Chip (ASC) + * + * 6 - VIA1 * - * 5 - ISM IOP (ADB?) + * For OSS Macintoshes (IIfx only), we apply an interrupt mapping similar to + * the Quadra (A/UX) mapping: * - * 6 - unused + * 1 - ISM IOP (ADB) + * + * 2 - SCSI + * + * 3 - NuBus + * + * 4 - SCC IOP + * + * 6 - VIA1 * * For PSC Macintoshes (660AV, 840AV): * @@ -104,108 +105,28 @@ * case. They're hidden behind the Nubus slot $C interrupt thus adding a * third layer of indirection. Why oh why did the Apple engineers do that? * - * - We support "fast" and "slow" handlers, just like the Amiga port. The - * fast handlers are called first and with all interrupts disabled. They - * are expected to execute quickly (hence the name). The slow handlers are - * called last with interrupts enabled and the interrupt level restored. - * They must therefore be reentrant. - * - * TODO: - * */ -#include <linux/module.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/interrupt.h> +#include <linux/irq.h> #include <linux/delay.h> -#include <linux/seq_file.h> -#include <asm/system.h> #include <asm/irq.h> -#include <asm/traps.h> -#include <asm/bootinfo.h> -#include <asm/machw.h> #include <asm/macintosh.h> +#include <asm/macints.h> #include <asm/mac_via.h> #include <asm/mac_psc.h> +#include <asm/mac_oss.h> +#include <asm/mac_iop.h> +#include <asm/mac_baboon.h> #include <asm/hwtest.h> -#include <asm/errno.h> -#include <asm/macints.h> #include <asm/irq_regs.h> -#define DEBUG_SPURIOUS #define SHUTUP_SONIC -/* SCC interrupt mask */ - -static int scc_mask; - -/* - * VIA/RBV hooks - */ - -extern void via_init(void); -extern void via_register_interrupts(void); -extern void via_irq_enable(int); -extern void via_irq_disable(int); -extern void via_irq_clear(int); -extern int via_irq_pending(int); - -/* - * OSS hooks - */ - -extern int oss_present; - -extern void oss_init(void); -extern void oss_register_interrupts(void); -extern void oss_irq_enable(int); -extern void oss_irq_disable(int); -extern void oss_irq_clear(int); -extern int oss_irq_pending(int); - -/* - * PSC hooks - */ - -extern int psc_present; - -extern void psc_init(void); -extern void psc_register_interrupts(void); -extern void psc_irq_enable(int); -extern void psc_irq_disable(int); -extern void psc_irq_clear(int); -extern int psc_irq_pending(int); - -/* - * IOP hooks - */ - -extern void iop_register_interrupts(void); - -/* - * Baboon hooks - */ - -extern int baboon_present; - -extern void baboon_init(void); -extern void baboon_register_interrupts(void); -extern void baboon_irq_enable(int); -extern void baboon_irq_disable(int); -extern void baboon_irq_clear(int); -extern int baboon_irq_pending(int); - -/* - * SCC interrupt routines - */ - -static void scc_irq_enable(unsigned int); -static void scc_irq_disable(unsigned int); - /* * console_loglevel determines NMI handler function */ @@ -215,14 +136,15 @@ irqreturn_t mac_debug_handler(int, void *); /* #define DEBUG_MACINTS */ -static void mac_enable_irq(unsigned int irq); -static void mac_disable_irq(unsigned int irq); +static unsigned int mac_irq_startup(struct irq_data *); +static void mac_irq_shutdown(struct irq_data *); -static struct irq_controller mac_irq_controller = { +static struct irq_chip mac_irq_chip = { .name = "mac", - .lock = __SPIN_LOCK_UNLOCKED(mac_irq_controller.lock), - .enable = mac_enable_irq, - .disable = mac_disable_irq, + .irq_enable = mac_irq_enable, + .irq_disable = mac_irq_disable, + .irq_startup = mac_irq_startup, + .irq_shutdown = mac_irq_shutdown, }; void __init mac_init_IRQ(void) @@ -230,9 +152,7 @@ void __init mac_init_IRQ(void) #ifdef DEBUG_MACINTS printk("mac_init_IRQ(): Setting things up...\n"); #endif - scc_mask = 0; - - m68k_setup_irq_controller(&mac_irq_controller, IRQ_USER, + m68k_setup_irq_controller(&mac_irq_chip, handle_simple_irq, IRQ_USER, NUM_MAC_SOURCES - IRQ_USER); /* Make sure the SONIC interrupt is cleared or things get ugly */ #ifdef SHUTUP_SONIC @@ -259,30 +179,28 @@ void __init mac_init_IRQ(void) if (baboon_present) baboon_register_interrupts(); iop_register_interrupts(); - request_irq(IRQ_AUTO_7, mac_nmi_handler, 0, "NMI", - mac_nmi_handler); + if (request_irq(IRQ_AUTO_7, mac_nmi_handler, 0, "NMI", + mac_nmi_handler)) + pr_err("Couldn't register NMI\n"); #ifdef DEBUG_MACINTS printk("mac_init_IRQ(): Done!\n"); #endif } /* - * mac_enable_irq - enable an interrupt source - * mac_disable_irq - disable an interrupt source - * mac_clear_irq - clears a pending interrupt - * mac_pending_irq - Returns the pending status of an IRQ (nonzero = pending) + * mac_irq_enable - enable an interrupt source + * mac_irq_disable - disable an interrupt source * * These routines are just dispatchers to the VIA/OSS/PSC routines. */ -static void mac_enable_irq(unsigned int irq) +void mac_irq_enable(struct irq_data *data) { + int irq = data->irq; int irq_src = IRQ_SRC(irq); switch(irq_src) { case 1: - via_irq_enable(irq); - break; case 2: case 7: if (oss_present) @@ -298,8 +216,6 @@ static void mac_enable_irq(unsigned int irq) psc_irq_enable(irq); else if (oss_present) oss_irq_enable(irq); - else if (irq_src == 4) - scc_irq_enable(irq); break; case 8: if (baboon_present) @@ -308,14 +224,13 @@ static void mac_enable_irq(unsigned int irq) } } -static void mac_disable_irq(unsigned int irq) +void mac_irq_disable(struct irq_data *data) { + int irq = data->irq; int irq_src = IRQ_SRC(irq); switch(irq_src) { case 1: - via_irq_disable(irq); - break; case 2: case 7: if (oss_present) @@ -331,8 +246,6 @@ static void mac_disable_irq(unsigned int irq) psc_irq_disable(irq); else if (oss_present) oss_irq_disable(irq); - else if (irq_src == 4) - scc_irq_disable(irq); break; case 8: if (baboon_present) @@ -341,58 +254,27 @@ static void mac_disable_irq(unsigned int irq) } } -void mac_clear_irq(unsigned int irq) +static unsigned int mac_irq_startup(struct irq_data *data) { - switch(IRQ_SRC(irq)) { - case 1: - via_irq_clear(irq); - break; - case 2: - case 7: - if (oss_present) - oss_irq_clear(irq); - else - via_irq_clear(irq); - break; - case 3: - case 4: - case 5: - case 6: - if (psc_present) - psc_irq_clear(irq); - else if (oss_present) - oss_irq_clear(irq); - break; - case 8: - if (baboon_present) - baboon_irq_clear(irq); - break; - } + int irq = data->irq; + + if (IRQ_SRC(irq) == 7 && !oss_present) + via_nubus_irq_startup(irq); + else + mac_irq_enable(data); + + return 0; } -int mac_irq_pending(unsigned int irq) +static void mac_irq_shutdown(struct irq_data *data) { - switch(IRQ_SRC(irq)) { - case 1: - return via_irq_pending(irq); - case 2: - case 7: - if (oss_present) - return oss_irq_pending(irq); - else - return via_irq_pending(irq); - case 3: - case 4: - case 5: - case 6: - if (psc_present) - return psc_irq_pending(irq); - else if (oss_present) - return oss_irq_pending(irq); - } - return 0; + int irq = data->irq; + + if (IRQ_SRC(irq) == 7 && !oss_present) + via_nubus_irq_shutdown(irq); + else + mac_irq_disable(data); } -EXPORT_SYMBOL(mac_irq_pending); static int num_debug[8]; @@ -456,59 +338,3 @@ irqreturn_t mac_nmi_handler(int irq, void *dev_id) in_nmi--; return IRQ_HANDLED; } - -/* - * Simple routines for masking and unmasking - * SCC interrupts in cases where this can't be - * done in hardware (only the PSC can do that.) - */ - -static void scc_irq_enable(unsigned int irq) -{ - int irq_idx = IRQ_IDX(irq); - - scc_mask |= (1 << irq_idx); -} - -static void scc_irq_disable(unsigned int irq) -{ - int irq_idx = IRQ_IDX(irq); - - scc_mask &= ~(1 << irq_idx); -} - -/* - * SCC master interrupt handler. We have to do a bit of magic here - * to figure out what channel gave us the interrupt; putting this - * here is cleaner than hacking it into drivers/char/macserial.c. - */ - -void mac_scc_dispatch(int irq, void *dev_id) -{ - volatile unsigned char *scc = (unsigned char *) mac_bi_data.sccbase + 2; - unsigned char reg; - unsigned long flags; - - /* Read RR3 from the chip. Always do this on channel A */ - /* This must be an atomic operation so disable irqs. */ - - local_irq_save(flags); - *scc = 3; - reg = *scc; - local_irq_restore(flags); - - /* Now dispatch. Bits 0-2 are for channel B and */ - /* bits 3-5 are for channel A. We can safely */ - /* ignore the remaining bits here. */ - /* */ - /* Note that we're ignoring scc_mask for now. */ - /* If we actually mask the ints then we tend to */ - /* get hammered by very persistent SCC irqs, */ - /* and since they're autovector interrupts they */ - /* pretty much kill the system. */ - - if (reg & 0x38) - m68k_handle_int(IRQ_SCCA); - if (reg & 0x07) - m68k_handle_int(IRQ_SCCB); -} diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c index 56d1f5676ad..707b61aea20 100644 --- a/arch/m68k/mac/misc.c +++ b/arch/m68k/mac/misc.c @@ -8,7 +8,6 @@ #include <linux/kernel.h> #include <linux/delay.h> #include <linux/sched.h> -#include <linux/slab.h> #include <linux/time.h> #include <linux/rtc.h> #include <linux/mm.h> @@ -20,22 +19,18 @@ #include <asm/uaccess.h> #include <asm/io.h> #include <asm/rtc.h> -#include <asm/system.h> #include <asm/segment.h> #include <asm/setup.h> #include <asm/macintosh.h> #include <asm/mac_via.h> #include <asm/mac_oss.h> -#define BOOTINFO_COMPAT_1_0 -#include <asm/bootinfo.h> #include <asm/machdep.h> /* Offset between Unix time (1970-based) and Mac time (1904-based) */ #define RTC_OFFSET 2082844800 -extern struct mac_booter_data mac_bi_data; static void (*rom_reset)(void); #ifdef CONFIG_ADB_CUDA @@ -104,8 +99,8 @@ static long pmu_read_time(void) while (!req.complete) pmu_poll(); - time = (req.reply[0] << 24) | (req.reply[1] << 16) - | (req.reply[2] << 8) | req.reply[3]; + time = (req.reply[1] << 24) | (req.reply[2] << 16) + | (req.reply[3] << 8) | req.reply[4]; return time - RTC_OFFSET; } @@ -148,7 +143,7 @@ static void pmu_write_pram(int offset, __u8 data) #define pmu_write_pram NULL #endif -#ifdef CONFIG_ADB_MACIISI +#if 0 /* def CONFIG_ADB_MACIISI */ extern int maciisi_request(struct adb_request *req, void (*done)(struct adb_request *), int nbytes, ...); @@ -306,35 +301,41 @@ static void via_write_pram(int offset, __u8 data) static long via_read_time(void) { union { - __u8 cdata[4]; - long idata; + __u8 cdata[4]; + long idata; } result, last_result; - int ct; + int count = 1; + + via_pram_command(0x81, &last_result.cdata[3]); + via_pram_command(0x85, &last_result.cdata[2]); + via_pram_command(0x89, &last_result.cdata[1]); + via_pram_command(0x8D, &last_result.cdata[0]); /* * The NetBSD guys say to loop until you get the same reading * twice in a row. */ - ct = 0; - do { - if (++ct > 10) { - printk("via_read_time: couldn't get valid time, " - "last read = 0x%08lx and 0x%08lx\n", - last_result.idata, result.idata); - break; - } - - last_result.idata = result.idata; - result.idata = 0; - + while (1) { via_pram_command(0x81, &result.cdata[3]); via_pram_command(0x85, &result.cdata[2]); via_pram_command(0x89, &result.cdata[1]); via_pram_command(0x8D, &result.cdata[0]); - } while (result.idata != last_result.idata); - return result.idata - RTC_OFFSET; + if (result.idata == last_result.idata) + return result.idata - RTC_OFFSET; + + if (++count > 10) + break; + + last_result.idata = result.idata; + } + + pr_err("via_read_time: failed to read a stable value; " + "got 0x%08lx then 0x%08lx\n", + last_result.idata, result.idata); + + return 0; } /* @@ -717,13 +718,18 @@ int mac_hwclk(int op, struct rtc_time *t) unmktime(now, 0, &t->tm_year, &t->tm_mon, &t->tm_mday, &t->tm_hour, &t->tm_min, &t->tm_sec); +#if 0 printk("mac_hwclk: read %04d-%02d-%-2d %02d:%02d:%02d\n", - t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); + t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); +#endif } else { /* write */ +#if 0 printk("mac_hwclk: tried to write %04d-%02d-%-2d %02d:%02d:%02d\n", - t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); + t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); +#endif -#if 0 /* it trashes my rtc */ now = mktime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); @@ -742,7 +748,6 @@ int mac_hwclk(int op, struct rtc_time *t) case MAC_ADB_IISI: maciisi_write_time(now); } -#endif } return 0; } diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c index 50603d3dce8..54037125ebf 100644 --- a/arch/m68k/mac/oss.c +++ b/arch/m68k/mac/oss.c @@ -1,5 +1,5 @@ /* - * OSS handling + * Operating System Services (OSS) chip handling * Written by Joshua M. Thompson (funaho@jurai.org) * * @@ -19,9 +19,8 @@ #include <linux/mm.h> #include <linux/delay.h> #include <linux/init.h> +#include <linux/irq.h> -#include <asm/bootinfo.h> -#include <asm/machw.h> #include <asm/macintosh.h> #include <asm/macints.h> #include <asm/mac_via.h> @@ -30,12 +29,6 @@ int oss_present; volatile struct mac_oss *oss; -irqreturn_t oss_irq(int, void *); -irqreturn_t oss_nubus_irq(int, void *); - -extern irqreturn_t via1_irq(int, void *); -extern irqreturn_t mac_scc_dispatch(int, void *); - /* * Initialize the OSS * @@ -55,28 +48,8 @@ void __init oss_init(void) /* do this by setting the source's interrupt level to zero. */ for (i = 0; i <= OSS_NUM_SOURCES; i++) { - oss->irq_level[i] = OSS_IRQLEV_DISABLED; + oss->irq_level[i] = 0; } - /* If we disable VIA1 here, we never really handle it... */ - oss->irq_level[OSS_VIA1] = OSS_IRQLEV_VIA1; -} - -/* - * Register the OSS and NuBus interrupt dispatchers. - */ - -void __init oss_register_interrupts(void) -{ - request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK, - "scsi", (void *) oss); - request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK, - "scc", mac_scc_dispatch); - request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK, - "nubus", (void *) oss); - request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK, - "sound", (void *) oss); - request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK, - "via1", (void *) via1); } /* @@ -88,36 +61,35 @@ void __init oss_nubus_init(void) } /* - * Handle miscellaneous OSS interrupts. Right now that's just sound - * and SCSI; everything else is routed to its own autovector IRQ. + * Handle miscellaneous OSS interrupts. */ -irqreturn_t oss_irq(int irq, void *dev_id) +static void oss_irq(unsigned int irq, struct irq_desc *desc) { - int events; - - events = oss->irq_pending & (OSS_IP_SOUND|OSS_IP_SCSI); - if (!events) - return IRQ_NONE; + int events = oss->irq_pending & + (OSS_IP_IOPSCC | OSS_IP_SCSI | OSS_IP_IOPISM); #ifdef DEBUG_IRQS if ((console_loglevel == 10) && !(events & OSS_IP_SCSI)) { - printk("oss_irq: irq %d events = 0x%04X\n", irq, + printk("oss_irq: irq %u events = 0x%04X\n", irq, (int) oss->irq_pending); } #endif - /* FIXME: how do you clear a pending IRQ? */ - if (events & OSS_IP_SOUND) { - oss->irq_pending &= ~OSS_IP_SOUND; - /* FIXME: call sound handler */ - } else if (events & OSS_IP_SCSI) { + if (events & OSS_IP_IOPSCC) { + oss->irq_pending &= ~OSS_IP_IOPSCC; + generic_handle_irq(IRQ_MAC_SCC); + } + + if (events & OSS_IP_SCSI) { oss->irq_pending &= ~OSS_IP_SCSI; - m68k_handle_int(IRQ_MAC_SCSI); - } else { - /* FIXME: error check here? */ + generic_handle_irq(IRQ_MAC_SCSI); + } + + if (events & OSS_IP_IOPISM) { + oss->irq_pending &= ~OSS_IP_IOPISM; + generic_handle_irq(IRQ_MAC_ADB); } - return IRQ_HANDLED; } /* @@ -126,13 +98,13 @@ irqreturn_t oss_irq(int irq, void *dev_id) * Unlike the VIA/RBV this is on its own autovector interrupt level. */ -irqreturn_t oss_nubus_irq(int irq, void *dev_id) +static void oss_nubus_irq(unsigned int irq, struct irq_desc *desc) { int events, irq_bit, i; events = oss->irq_pending & OSS_IP_NUBUS; if (!events) - return IRQ_NONE; + return; #ifdef DEBUG_NUBUS_INT if (console_loglevel > 7) { @@ -148,10 +120,36 @@ irqreturn_t oss_nubus_irq(int irq, void *dev_id) irq_bit >>= 1; if (events & irq_bit) { oss->irq_pending &= ~irq_bit; - m68k_handle_int(NUBUS_SOURCE_BASE + i); + generic_handle_irq(NUBUS_SOURCE_BASE + i); } } while(events & (irq_bit - 1)); - return IRQ_HANDLED; +} + +/* + * Register the OSS and NuBus interrupt dispatchers. + * + * This IRQ mapping is laid out with two things in mind: first, we try to keep + * things on their own levels to avoid having to do double-dispatches. Second, + * the levels match as closely as possible the alternate IRQ mapping mode (aka + * "A/UX mode") available on some VIA machines. + */ + +#define OSS_IRQLEV_IOPISM IRQ_AUTO_1 +#define OSS_IRQLEV_SCSI IRQ_AUTO_2 +#define OSS_IRQLEV_NUBUS IRQ_AUTO_3 +#define OSS_IRQLEV_IOPSCC IRQ_AUTO_4 +#define OSS_IRQLEV_VIA1 IRQ_AUTO_6 + +void __init oss_register_interrupts(void) +{ + irq_set_chained_handler(OSS_IRQLEV_IOPISM, oss_irq); + irq_set_chained_handler(OSS_IRQLEV_SCSI, oss_irq); + irq_set_chained_handler(OSS_IRQLEV_NUBUS, oss_nubus_irq); + irq_set_chained_handler(OSS_IRQLEV_IOPSCC, oss_irq); + irq_set_chained_handler(OSS_IRQLEV_VIA1, via1_irq); + + /* OSS_VIA1 gets enabled here because it has no machspec interrupt. */ + oss->irq_level[OSS_VIA1] = IRQ_AUTO_6; } /* @@ -168,17 +166,15 @@ void oss_irq_enable(int irq) { printk("oss_irq_enable(%d)\n", irq); #endif switch(irq) { - case IRQ_SCC: - case IRQ_SCCA: - case IRQ_SCCB: + case IRQ_MAC_SCC: oss->irq_level[OSS_IOPSCC] = OSS_IRQLEV_IOPSCC; - break; + return; case IRQ_MAC_ADB: oss->irq_level[OSS_IOPISM] = OSS_IRQLEV_IOPISM; - break; + return; case IRQ_MAC_SCSI: oss->irq_level[OSS_SCSI] = OSS_IRQLEV_SCSI; - break; + return; case IRQ_NUBUS_9: case IRQ_NUBUS_A: case IRQ_NUBUS_B: @@ -187,13 +183,11 @@ void oss_irq_enable(int irq) { case IRQ_NUBUS_E: irq -= NUBUS_SOURCE_BASE; oss->irq_level[irq] = OSS_IRQLEV_NUBUS; - break; -#ifdef DEBUG_IRQUSE - default: - printk("%s unknown irq %d\n",__FUNCTION__, irq); - break; -#endif + return; } + + if (IRQ_SRC(irq) == 1) + via_irq_enable(irq); } /* @@ -208,55 +202,15 @@ void oss_irq_disable(int irq) { printk("oss_irq_disable(%d)\n", irq); #endif switch(irq) { - case IRQ_SCC: - case IRQ_SCCA: - case IRQ_SCCB: - oss->irq_level[OSS_IOPSCC] = OSS_IRQLEV_DISABLED; - break; - case IRQ_MAC_ADB: - oss->irq_level[OSS_IOPISM] = OSS_IRQLEV_DISABLED; - break; - case IRQ_MAC_SCSI: - oss->irq_level[OSS_SCSI] = OSS_IRQLEV_DISABLED; - break; - case IRQ_NUBUS_9: - case IRQ_NUBUS_A: - case IRQ_NUBUS_B: - case IRQ_NUBUS_C: - case IRQ_NUBUS_D: - case IRQ_NUBUS_E: - irq -= NUBUS_SOURCE_BASE; - oss->irq_level[irq] = OSS_IRQLEV_DISABLED; - break; -#ifdef DEBUG_IRQUSE - default: - printk("%s unknown irq %d\n", __FUNCTION__, irq); - break; -#endif - } -} - -/* - * Clear an OSS interrupt - * - * Not sure if this works or not but it's the only method I could - * think of based on the contents of the mac_oss structure. - */ - -void oss_irq_clear(int irq) { - /* FIXME: how to do this on OSS? */ - switch(irq) { - case IRQ_SCC: - case IRQ_SCCA: - case IRQ_SCCB: - oss->irq_pending &= ~OSS_IP_IOPSCC; - break; + case IRQ_MAC_SCC: + oss->irq_level[OSS_IOPSCC] = 0; + return; case IRQ_MAC_ADB: - oss->irq_pending &= ~OSS_IP_IOPISM; - break; + oss->irq_level[OSS_IOPISM] = 0; + return; case IRQ_MAC_SCSI: - oss->irq_pending &= ~OSS_IP_SCSI; - break; + oss->irq_level[OSS_SCSI] = 0; + return; case IRQ_NUBUS_9: case IRQ_NUBUS_A: case IRQ_NUBUS_B: @@ -264,38 +218,10 @@ void oss_irq_clear(int irq) { case IRQ_NUBUS_D: case IRQ_NUBUS_E: irq -= NUBUS_SOURCE_BASE; - oss->irq_pending &= ~(1 << irq); - break; + oss->irq_level[irq] = 0; + return; } -} - -/* - * Check to see if a specific OSS interrupt is pending - */ -int oss_irq_pending(int irq) -{ - switch(irq) { - case IRQ_SCC: - case IRQ_SCCA: - case IRQ_SCCB: - return oss->irq_pending & OSS_IP_IOPSCC; - break; - case IRQ_MAC_ADB: - return oss->irq_pending & OSS_IP_IOPISM; - break; - case IRQ_MAC_SCSI: - return oss->irq_pending & OSS_IP_SCSI; - break; - case IRQ_NUBUS_9: - case IRQ_NUBUS_A: - case IRQ_NUBUS_B: - case IRQ_NUBUS_C: - case IRQ_NUBUS_D: - case IRQ_NUBUS_E: - irq -= NUBUS_SOURCE_BASE; - return oss->irq_pending & (1 << irq); - break; - } - return 0; + if (IRQ_SRC(irq) == 1) + via_irq_disable(irq); } diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c index d66f723b17c..835fa04511c 100644 --- a/arch/m68k/mac/psc.c +++ b/arch/m68k/mac/psc.c @@ -18,9 +18,9 @@ #include <linux/mm.h> #include <linux/delay.h> #include <linux/init.h> +#include <linux/irq.h> #include <asm/traps.h> -#include <asm/bootinfo.h> #include <asm/macintosh.h> #include <asm/macints.h> #include <asm/mac_psc.h> @@ -30,13 +30,11 @@ int psc_present; volatile __u8 *psc; -irqreturn_t psc_irq(int, void *); - /* * Debugging dump, used in various places to see what's going on. */ -void psc_debug_dump(void) +static void psc_debug_dump(void) { int i; @@ -55,7 +53,7 @@ void psc_debug_dump(void) * expanded to cover what I think are the other 7 channels. */ -void psc_dma_die_die_die(void) +static __init void psc_dma_die_die_die(void) { int i; @@ -88,7 +86,7 @@ void __init psc_init(void) /* * The PSC is always at the same spot, but using psc - * keeps things consisant with the psc_xxxx functions. + * keeps things consistent with the psc_xxxx functions. */ psc = (void *) PSC_BASE; @@ -112,48 +110,52 @@ void __init psc_init(void) } /* - * Register the PSC interrupt dispatchers for autovector interrupts 3-6. - */ - -void __init psc_register_interrupts(void) -{ - request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30); - request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40); - request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50); - request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60); -} - -/* * PSC interrupt handler. It's a lot like the VIA interrupt handler. */ -irqreturn_t psc_irq(int irq, void *dev_id) +static void psc_irq(unsigned int irq, struct irq_desc *desc) { - int pIFR = pIFRbase + ((int) dev_id); - int pIER = pIERbase + ((int) dev_id); + unsigned int offset = (unsigned int)irq_desc_get_handler_data(desc); + int pIFR = pIFRbase + offset; + int pIER = pIERbase + offset; int irq_num; unsigned char irq_bit, events; #ifdef DEBUG_IRQS - printk("psc_irq: irq %d pIFR = 0x%02X pIER = 0x%02X\n", + printk("psc_irq: irq %u pIFR = 0x%02X pIER = 0x%02X\n", irq, (int) psc_read_byte(pIFR), (int) psc_read_byte(pIER)); #endif events = psc_read_byte(pIFR) & psc_read_byte(pIER) & 0xF; if (!events) - return IRQ_NONE; + return; irq_num = irq << 3; irq_bit = 1; do { if (events & irq_bit) { psc_write_byte(pIFR, irq_bit); - m68k_handle_int(irq_num); + generic_handle_irq(irq_num); } irq_num++; irq_bit <<= 1; } while (events >= irq_bit); - return IRQ_HANDLED; +} + +/* + * Register the PSC interrupt dispatchers for autovector interrupts 3-6. + */ + +void __init psc_register_interrupts(void) +{ + irq_set_chained_handler(IRQ_AUTO_3, psc_irq); + irq_set_handler_data(IRQ_AUTO_3, (void *)0x30); + irq_set_chained_handler(IRQ_AUTO_4, psc_irq); + irq_set_handler_data(IRQ_AUTO_4, (void *)0x40); + irq_set_chained_handler(IRQ_AUTO_5, psc_irq); + irq_set_handler_data(IRQ_AUTO_5, (void *)0x50); + irq_set_chained_handler(IRQ_AUTO_6, psc_irq); + irq_set_handler_data(IRQ_AUTO_6, (void *)0x60); } void psc_irq_enable(int irq) { @@ -177,20 +179,3 @@ void psc_irq_disable(int irq) { #endif psc_write_byte(pIER, 1 << irq_idx); } - -void psc_irq_clear(int irq) { - int irq_src = IRQ_SRC(irq); - int irq_idx = IRQ_IDX(irq); - int pIFR = pIERbase + (irq_src << 4); - - psc_write_byte(pIFR, 1 << irq_idx); -} - -int psc_irq_pending(int irq) -{ - int irq_src = IRQ_SRC(irq); - int irq_idx = IRQ_IDX(irq); - int pIFR = pIERbase + (irq_src << 4); - - return psc_read_byte(pIFR) & (1 << irq_idx); -} diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c index fa485df4160..e198dec868e 100644 --- a/arch/m68k/mac/via.c +++ b/arch/m68k/mac/via.c @@ -27,25 +27,20 @@ #include <linux/mm.h> #include <linux/delay.h> #include <linux/init.h> -#include <linux/ide.h> #include <linux/module.h> +#include <linux/irq.h> -#include <asm/bootinfo.h> #include <asm/macintosh.h> #include <asm/macints.h> -#include <asm/machw.h> #include <asm/mac_via.h> #include <asm/mac_psc.h> +#include <asm/mac_oss.h> volatile __u8 *via1, *via2; -#if 0 -/* See note in mac_via.h about how this is possibly not useful */ -volatile long *via_memory_bogon=(long *)&via_memory_bogon; -#endif int rbv_present; int via_alt_mapping; EXPORT_SYMBOL(via_alt_mapping); -__u8 rbv_clear; +static __u8 rbv_clear; /* * Globals for accessing the VIA chip registers without having to @@ -67,30 +62,50 @@ static int gIER,gIFR,gBufA,gBufB; #define MAC_CLOCK_LOW (MAC_CLOCK_TICK&0xFF) #define MAC_CLOCK_HIGH (MAC_CLOCK_TICK>>8) -/* To disable a NuBus slot on Quadras we make the slot IRQ lines outputs, set - * high. On RBV we just use the slot interrupt enable register. On Macs with - * genuine VIA chips we must use nubus_disabled to keep track of disabled slot - * interrupts. When any slot IRQ is disabled we mask the (edge triggered) CA1 - * or "SLOTS" interrupt. When no slot is disabled, we unmask the CA1 interrupt. - * So, on genuine VIAs, having more than one NuBus IRQ can mean trouble, - * because closing one of those drivers can mask all of the NuBus interrupts. - * Also, since we can't mask the unregistered slot IRQs on genuine VIAs, it's - * possible to get interrupts from cards that MacOS or the ROM has configured - * but we have not. FWIW, "Designing Cards and Drivers for Macintosh II and - * Macintosh SE", page 9-8, says, a slot IRQ with no driver would crash MacOS. + +/* + * On Macs with a genuine VIA chip there is no way to mask an individual slot + * interrupt. This limitation also seems to apply to VIA clone logic cores in + * Quadra-like ASICs. (RBV and OSS machines don't have this limitation.) + * + * We used to fake it by configuring the relevent VIA pin as an output + * (to mask the interrupt) or input (to unmask). That scheme did not work on + * (at least) the Quadra 700. A NuBus card's /NMRQ signal is an open-collector + * circuit (see Designing Cards and Drivers for Macintosh II and Macintosh SE, + * p. 10-11 etc) but VIA outputs are not (see datasheet). + * + * Driving these outputs high must cause the VIA to source current and the + * card to sink current when it asserts /NMRQ. Current will flow but the pin + * voltage is uncertain and so the /NMRQ condition may still cause a transition + * at the VIA2 CA1 input (which explains the lost interrupts). A side effect + * is that a disabled slot IRQ can never be tested as pending or not. + * + * Driving these outputs low doesn't work either. All the slot /NMRQ lines are + * (active low) OR'd together to generate the CA1 (aka "SLOTS") interrupt (see + * The Guide To Macintosh Family Hardware, 2nd edition p. 167). If we drive a + * disabled /NMRQ line low, the falling edge immediately triggers a CA1 + * interrupt and all slot interrupts after that will generate no transition + * and therefore no interrupt, even after being re-enabled. + * + * So we make the VIA port A I/O lines inputs and use nubus_disabled to keep + * track of their states. When any slot IRQ becomes disabled we mask the CA1 + * umbrella interrupt. Only when all slot IRQs become enabled do we unmask + * the CA1 interrupt. It must remain enabled even when cards have no interrupt + * handler registered. Drivers must therefore disable a slot interrupt at the + * device before they call free_irq (like shared and autovector interrupts). + * + * There is also a related problem when MacOS is used to boot Linux. A network + * card brought up by a MacOS driver may raise an interrupt while Linux boots. + * This can be fatal since it can't be handled until the right driver loads + * (if such a driver exists at all). Apparently related to this hardware + * limitation, "Designing Cards and Drivers", p. 9-8, says that a slot + * interrupt with no driver would crash MacOS (the book was written before + * the appearance of Macs with RBV or OSS). */ + static u8 nubus_disabled; void via_debug_dump(void); -irqreturn_t via1_irq(int, void *); -irqreturn_t via2_irq(int, void *); -irqreturn_t via_nubus_irq(int, void *); -void via_irq_enable(int irq); -void via_irq_disable(int irq); -void via_irq_clear(int irq); - -extern irqreturn_t mac_scc_dispatch(int, void *); -extern int oss_present; /* * Initialize the VIAs @@ -110,7 +125,7 @@ void __init via_init(void) /* IIci, IIsi, IIvx, IIvi (P6xx), LC series */ - case MAC_VIA_IIci: + case MAC_VIA_IICI: via1 = (void *) VIA1_BASE; if (macintosh_config->ident == MAC_MODEL_IIFX) { via2 = NULL; @@ -181,7 +196,7 @@ void __init via_init(void) via1[vT1CH] = 0; via1[vT2CL] = 0; via1[vT2CH] = 0; - via1[vACR] &= 0x3F; + via1[vACR] &= ~0xC0; /* setup T1 timer with no PB7 output */ via1[vACR] &= ~0x03; /* disable port A & B latches */ /* @@ -204,40 +219,20 @@ void __init via_init(void) /* Everything below this point is VIA2/RBV only... */ - if (oss_present) return; - -#if 1 - /* Some machines support an alternate IRQ mapping that spreads */ - /* Ethernet and Sound out to their own autolevel IRQs and moves */ - /* VIA1 to level 6. A/UX uses this mapping and we do too. Note */ - /* that the IIfx emulates this alternate mapping using the OSS. */ - - switch(macintosh_config->ident) { - case MAC_MODEL_P475: - case MAC_MODEL_P475F: - case MAC_MODEL_P575: - case MAC_MODEL_Q605: - case MAC_MODEL_Q605_ACC: - case MAC_MODEL_C610: - case MAC_MODEL_Q610: - case MAC_MODEL_Q630: - case MAC_MODEL_C650: - case MAC_MODEL_Q650: - case MAC_MODEL_Q700: - case MAC_MODEL_Q800: - case MAC_MODEL_Q900: - case MAC_MODEL_Q950: - via_alt_mapping = 1; - via1[vDirB] |= 0x40; - via1[vBufB] &= ~0x40; - break; - default: - via_alt_mapping = 0; - break; + if (oss_present) + return; + + if ((macintosh_config->via_type == MAC_VIA_QUADRA) && + (macintosh_config->adb_type != MAC_ADB_PB1) && + (macintosh_config->adb_type != MAC_ADB_PB2) && + (macintosh_config->ident != MAC_MODEL_C660) && + (macintosh_config->ident != MAC_MODEL_Q840)) { + via_alt_mapping = 1; + via1[vDirB] |= 0x40; + via1[vBufB] &= ~0x40; + } else { + via_alt_mapping = 0; } -#else - via_alt_mapping = 0; -#endif /* * Now initialize VIA2. For RBV we just kill all interrupts; @@ -253,23 +248,32 @@ void __init via_init(void) via2[vT1CH] = 0; via2[vT2CL] = 0; via2[vT2CH] = 0; - via2[vACR] &= 0x3F; + via2[vACR] &= ~0xC0; /* setup T1 timer with no PB7 output */ via2[vACR] &= ~0x03; /* disable port A & B latches */ } + /* Everything below this point is VIA2 only... */ + + if (rbv_present) + return; + /* - * Set vPCR for SCSI interrupts (but not on RBV) + * Set vPCR for control line interrupts. + * + * CA1 (SLOTS IRQ), CB1 (ASC IRQ): negative edge trigger. + * + * Macs with ESP SCSI have a negative edge triggered SCSI interrupt. + * Testing reveals that PowerBooks do too. However, the SE/30 + * schematic diagram shows an active high NCR5380 IRQ line. */ - if (!rbv_present) { - if (macintosh_config->scsi_type == MAC_SCSI_OLD) { - /* CB2 (IRQ) indep. input, positive edge */ - /* CA2 (DRQ) indep. input, positive edge */ - via2[vPCR] = 0x66; - } else { - /* CB2 (IRQ) indep. input, negative edge */ - /* CA2 (DRQ) indep. input, negative edge */ - via2[vPCR] = 0x22; - } + + pr_debug("VIA2 vPCR is 0x%02X\n", via2[vPCR]); + if (macintosh_config->via_type == MAC_VIA_II) { + /* CA2 (SCSI DRQ), CB2 (SCSI IRQ): indep. input, pos. edge */ + via2[vPCR] = 0x66; + } else { + /* CA2 (SCSI DRQ), CB2 (SCSI IRQ): indep. input, neg. edge */ + via2[vPCR] = 0x22; } } @@ -285,35 +289,8 @@ void __init via_init_clock(irq_handler_t func) via1[vT1CL] = MAC_CLOCK_LOW; via1[vT1CH] = MAC_CLOCK_HIGH; - request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func); -} - -/* - * Register the interrupt dispatchers for VIA or RBV machines only. - */ - -void __init via_register_interrupts(void) -{ - if (via_alt_mapping) { - request_irq(IRQ_AUTO_1, via1_irq, - IRQ_FLG_LOCK|IRQ_FLG_FAST, "software", - (void *) via1); - request_irq(IRQ_AUTO_6, via1_irq, - IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1", - (void *) via1); - } else { - request_irq(IRQ_AUTO_1, via1_irq, - IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1", - (void *) via1); - } - request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST, - "via2", (void *) via2); - if (!psc_present) { - request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK, - "scc", mac_scc_dispatch); - } - request_irq(IRQ_MAC_NUBUS, via_nubus_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST, - "nubus", (void *) via2); + if (request_irq(IRQ_MAC_TIMER_1, func, 0, "timer", func)) + pr_err("Couldn't register %s interrupt\n", "timer"); } /* @@ -349,7 +326,7 @@ void via_debug_dump(void) * TBI: get time offset between scheduling timer ticks */ -unsigned long mac_gettimeoffset (void) +u32 mac_gettimeoffset(void) { unsigned long ticks, offset = 0; @@ -363,7 +340,7 @@ unsigned long mac_gettimeoffset (void) ticks = MAC_CLOCK_TICK - ticks; ticks = ticks * 10000L / MAC_CLOCK_TICK; - return ticks + offset; + return (ticks + offset) * 1000; } /* @@ -411,34 +388,55 @@ void __init via_nubus_init(void) via2[gBufB] |= 0x02; } - /* Disable all the slot interrupts (where possible). */ + /* + * Disable the slot interrupts. On some hardware that's not possible. + * On some hardware it's unclear what all of these I/O lines do. + */ switch (macintosh_config->via_type) { case MAC_VIA_II: - /* Just make the port A lines inputs. */ - switch(macintosh_config->ident) { - case MAC_MODEL_II: - case MAC_MODEL_IIX: - case MAC_MODEL_IICX: - case MAC_MODEL_SE30: - /* The top two bits are RAM size outputs. */ - via2[vDirA] &= 0xC0; - break; - default: - via2[vDirA] &= 0x80; - } + case MAC_VIA_QUADRA: + pr_debug("VIA2 vDirA is 0x%02X\n", via2[vDirA]); break; - case MAC_VIA_IIci: + case MAC_VIA_IICI: /* RBV. Disable all the slot interrupts. SIER works like IER. */ via2[rSIER] = 0x7F; break; + } +} + +void via_nubus_irq_startup(int irq) +{ + int irq_idx = IRQ_IDX(irq); + + switch (macintosh_config->via_type) { + case MAC_VIA_II: case MAC_VIA_QUADRA: - /* Disable the inactive slot interrupts by making those lines outputs. */ - if ((macintosh_config->adb_type != MAC_ADB_PB1) && - (macintosh_config->adb_type != MAC_ADB_PB2)) { - via2[vBufA] |= 0x7F; - via2[vDirA] |= 0x7F; + /* Make the port A line an input. Probably redundant. */ + if (macintosh_config->via_type == MAC_VIA_II) { + /* The top two bits are RAM size outputs. */ + via2[vDirA] &= 0xC0 | ~(1 << irq_idx); + } else { + /* Allow NuBus slots 9 through F. */ + via2[vDirA] &= 0x80 | ~(1 << irq_idx); } + /* fall through */ + case MAC_VIA_IICI: + via_irq_enable(irq); + break; + } +} + +void via_nubus_irq_shutdown(int irq) +{ + switch (macintosh_config->via_type) { + case MAC_VIA_II: + case MAC_VIA_QUADRA: + /* Ensure that the umbrella CA1 interrupt remains enabled. */ + via_irq_enable(irq); + break; + case MAC_VIA_IICI: + via_irq_disable(irq); break; } } @@ -448,63 +446,46 @@ void __init via_nubus_init(void) * via6522.c :-), disable/pending masks added. */ -irqreturn_t via1_irq(int irq, void *dev_id) +void via1_irq(unsigned int irq, struct irq_desc *desc) { int irq_num; unsigned char irq_bit, events; events = via1[vIFR] & via1[vIER] & 0x7F; if (!events) - return IRQ_NONE; + return; irq_num = VIA1_SOURCE_BASE; irq_bit = 1; do { if (events & irq_bit) { via1[vIFR] = irq_bit; - m68k_handle_int(irq_num); + generic_handle_irq(irq_num); } ++irq_num; irq_bit <<= 1; } while (events >= irq_bit); - -#if 0 /* freakin' pmu is doing weird stuff */ - if (!oss_present) { - /* This (still) seems to be necessary to get IDE - working. However, if you enable VBL interrupts, - you're screwed... */ - /* FIXME: should we check the SLOTIRQ bit before - pulling this stunt? */ - /* No, it won't be set. that's why we're doing this. */ - via_irq_disable(IRQ_MAC_NUBUS); - via_irq_clear(IRQ_MAC_NUBUS); - m68k_handle_int(IRQ_MAC_NUBUS); - via_irq_enable(IRQ_MAC_NUBUS); - } -#endif - return IRQ_HANDLED; } -irqreturn_t via2_irq(int irq, void *dev_id) +static void via2_irq(unsigned int irq, struct irq_desc *desc) { int irq_num; unsigned char irq_bit, events; events = via2[gIFR] & via2[gIER] & 0x7F; if (!events) - return IRQ_NONE; + return; irq_num = VIA2_SOURCE_BASE; irq_bit = 1; do { if (events & irq_bit) { via2[gIFR] = irq_bit | rbv_clear; - m68k_handle_int(irq_num); + generic_handle_irq(irq_num); } ++irq_num; irq_bit <<= 1; } while (events >= irq_bit); - return IRQ_HANDLED; } /* @@ -512,7 +493,7 @@ irqreturn_t via2_irq(int irq, void *dev_id) * VIA2 dispatcher as a fast interrupt handler. */ -irqreturn_t via_nubus_irq(int irq, void *dev_id) +void via_nubus_irq(unsigned int irq, struct irq_desc *desc) { int slot_irq; unsigned char slot_bit, events; @@ -523,7 +504,7 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id) else events &= ~via2[vDirA]; if (!events) - return IRQ_NONE; + return; do { slot_irq = IRQ_NUBUS_F; @@ -531,7 +512,7 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id) do { if (events & slot_bit) { events &= ~slot_bit; - m68k_handle_int(slot_irq); + generic_handle_irq(slot_irq); } --slot_irq; slot_bit >>= 1; @@ -545,7 +526,24 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id) else events &= ~via2[vDirA]; } while (events); - return IRQ_HANDLED; +} + +/* + * Register the interrupt dispatchers for VIA or RBV machines only. + */ + +void __init via_register_interrupts(void) +{ + if (via_alt_mapping) { + /* software interrupt */ + irq_set_chained_handler(IRQ_AUTO_1, via1_irq); + /* via1 interrupt */ + irq_set_chained_handler(IRQ_AUTO_6, via1_irq); + } else { + irq_set_chained_handler(IRQ_AUTO_1, via1_irq); + } + irq_set_chained_handler(IRQ_AUTO_2, via2_irq); + irq_set_chained_handler(IRQ_MAC_NUBUS, via_nubus_irq); } void via_irq_enable(int irq) { @@ -564,25 +562,18 @@ void via_irq_enable(int irq) { } else if (irq_src == 7) { switch (macintosh_config->via_type) { case MAC_VIA_II: + case MAC_VIA_QUADRA: nubus_disabled &= ~(1 << irq_idx); /* Enable the CA1 interrupt when no slot is disabled. */ if (!nubus_disabled) via2[gIER] = IER_SET_BIT(1); break; - case MAC_VIA_IIci: + case MAC_VIA_IICI: /* On RBV, enable the slot interrupt. * SIER works like IER. */ via2[rSIER] = IER_SET_BIT(irq_idx); break; - case MAC_VIA_QUADRA: - /* Make the port A line an input to enable the slot irq. - * But not on PowerBooks, that's ADB. - */ - if ((macintosh_config->adb_type != MAC_ADB_PB1) && - (macintosh_config->adb_type != MAC_ADB_PB2)) - via2[vDirA] &= ~(1 << irq_idx); - break; } } } @@ -602,56 +593,29 @@ void via_irq_disable(int irq) { } else if (irq_src == 7) { switch (macintosh_config->via_type) { case MAC_VIA_II: + case MAC_VIA_QUADRA: nubus_disabled |= 1 << irq_idx; if (nubus_disabled) via2[gIER] = IER_CLR_BIT(1); break; - case MAC_VIA_IIci: + case MAC_VIA_IICI: via2[rSIER] = IER_CLR_BIT(irq_idx); break; - case MAC_VIA_QUADRA: - if ((macintosh_config->adb_type != MAC_ADB_PB1) && - (macintosh_config->adb_type != MAC_ADB_PB2)) - via2[vDirA] |= 1 << irq_idx; - break; } } } -void via_irq_clear(int irq) { - int irq_src = IRQ_SRC(irq); - int irq_idx = IRQ_IDX(irq); - int irq_bit = 1 << irq_idx; - - if (irq_src == 1) { - via1[vIFR] = irq_bit; - } else if (irq_src == 2) { - via2[gIFR] = irq_bit | rbv_clear; - } else if (irq_src == 7) { - /* FIXME: There is no way to clear an individual nubus slot - * IRQ flag, other than getting the device to do it. - */ - } +void via1_set_head(int head) +{ + if (head == 0) + via1[vBufA] &= ~VIA1A_vHeadSel; + else + via1[vBufA] |= VIA1A_vHeadSel; } +EXPORT_SYMBOL(via1_set_head); -/* - * Returns nonzero if an interrupt is pending on the given - * VIA/IRQ combination. - */ - -int via_irq_pending(int irq) +int via2_scsi_drq_pending(void) { - int irq_src = IRQ_SRC(irq); - int irq_idx = IRQ_IDX(irq); - int irq_bit = 1 << irq_idx; - - if (irq_src == 1) { - return via1[vIFR] & irq_bit; - } else if (irq_src == 2) { - return via2[gIFR] & irq_bit; - } else if (irq_src == 7) { - /* Always 0 for MAC_VIA_QUADRA if the slot irq is disabled. */ - return ~via2[gBufA] & irq_bit; - } - return 0; + return via2[gIFR] & (1 << IRQ_IDX(IRQ_MAC_SCSIDRQ)); } +EXPORT_SYMBOL(via2_scsi_drq_pending); |
