diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-08-25 09:12:35 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-08-25 09:12:35 +0000 |
commit | c7fc24dc4420057f103afe8fc64524ebc25c5d37 (patch) | |
tree | 3682407a599b8f9f03fc096298134cafba1c9b2f /arch/m68k/mac | |
parent | 1d793fade8b063fde3cf275bf1a5c2d381292cd9 (diff) |
o Merge with Linux 2.1.116.
o New Newport console code.
o New G364 console code.
Diffstat (limited to 'arch/m68k/mac')
-rw-r--r-- | arch/m68k/mac/Makefile | 3 | ||||
-rw-r--r-- | arch/m68k/mac/adb-bus.c | 831 | ||||
-rw-r--r-- | arch/m68k/mac/config.c | 308 | ||||
-rw-r--r-- | arch/m68k/mac/debug.c | 234 | ||||
-rw-r--r-- | arch/m68k/mac/mac_ksyms.c (renamed from arch/m68k/mac/ksyms.c) | 0 | ||||
-rw-r--r-- | arch/m68k/mac/macints.c | 777 | ||||
-rw-r--r-- | arch/m68k/mac/mackeyb.c | 64 | ||||
-rw-r--r-- | arch/m68k/mac/psc.h | 18 | ||||
-rw-r--r-- | arch/m68k/mac/via6522.c | 442 |
9 files changed, 1900 insertions, 777 deletions
diff --git a/arch/m68k/mac/Makefile b/arch/m68k/mac/Makefile index 458a01f44..cfd63295a 100644 --- a/arch/m68k/mac/Makefile +++ b/arch/m68k/mac/Makefile @@ -10,7 +10,8 @@ EXTRA_CFLAGS := -Wa,-m68020 O_TARGET := mac.o -O_OBJS := config.o ksyms.o bootparse.o macints.o via6522.o \ +O_OBJS := config.o bootparse.o macints.o via6522.o \ mackeyb.o adb-bus.o macboing.o debug.o +OX_OBJS := mac_ksyms.o include $(TOPDIR)/Rules.make diff --git a/arch/m68k/mac/adb-bus.c b/arch/m68k/mac/adb-bus.c index ddd5176c4..0f41bc6aa 100644 --- a/arch/m68k/mac/adb-bus.c +++ b/arch/m68k/mac/adb-bus.c @@ -6,9 +6,11 @@ * Copyright (C) 1996 Paul Mackerras. * * MSch (9/97) Partial rewrite of interrupt handler to MacII style - * ADB handshake, based on: - * - Guide to Mac Hardware - * - Guido Koerber's session with a logic analyzer + * ADB handshake, based on: + * - Guide to Mac Hardware + * - Guido Koerber's session with a logic analyzer + * + * MSch (1/98) Integrated start of IIsi driver by Robert Thompson */ #include <stdarg.h> @@ -63,6 +65,9 @@ #define SR_DATA 0x08 /* Shift register data */ #define SR_CLOCK 0x10 /* Shift register clock */ +/* JRT */ +#define ADB_DELAY 150 + static struct adb_handler { void (*handler)(unsigned char *, int, struct pt_regs *); } adb_handler[16]; @@ -88,6 +93,9 @@ static int prefix_len; static int status = ST_IDLE|TREQ; static int last_status; + +static int driver_running = 0; + /*static int adb_delay;*/ int in_keybinit = 1; @@ -98,12 +106,19 @@ extern void adb_clock_interrupt(int irq, void *arg, struct pt_regs *regs); extern void adb_data_interrupt(int irq, void *arg, struct pt_regs *regs); static void adb_input(unsigned char *buf, int nb, struct pt_regs *regs); +static void adb_hw_setup_IIsi(void); +static void adb_hw_setup_cuda(void); + /* - * Misc. defines for testing + * debug level 10 required for ADB logging (should be && debug_adb, ideally) */ extern int console_loglevel; +/* + * Misc. defines for testing - should go to header :-( + */ + #define ADBDEBUG_STATUS (1) #define ADBDEBUG_STATE (2) #define ADBDEBUG_READ (4) @@ -118,11 +133,13 @@ extern int console_loglevel; #define ADBDEBUG_INPUT (2048) #define ADBDEBUG_DEVICE (4096) +#define ADBDEBUG_IISI (8192) + -#define DEBUG_ADB +/*#define DEBUG_ADB*/ #ifdef DEBUG_ADB -#define ADBDEBUG (ADBDEBUG_READ | ADBDEBUG_START | ADBDEBUG_WRITE | ADBDEBUG_SRQ | ADBDEBUG_REQUEST) +#define ADBDEBUG (ADBDEBUG_INPUT | ADBDEBUG_READ | ADBDEBUG_START | ADBDEBUG_WRITE | ADBDEBUG_SRQ | ADBDEBUG_REQUEST) #else #define ADBDEBUG (0) #endif @@ -132,7 +149,7 @@ extern int console_loglevel; void adb_bus_init(void) { unsigned long flags; - unsigned char c; + unsigned char c, i; save_flags(flags); cli(); @@ -174,31 +191,7 @@ void adb_bus_init(void) via_write(via1, vIER, IER_SET|SR_INT); /* This clears the interrupt bit */ via_write(via1, vIFR, SR_INT); -#if 0 - ct=1000; - while( ct-- && (via_read(via1, vBufB)&TREQ)) - udelay(1000); - if(ct<0) - printk("No sync occured\n"); - ct=1000; - while( ct-- && !(via_read(via1, vIFR)&SR_INT)) - udelay(1000); - if(ct<0) - printk("No sync 2 occured\n"); - via_read(via1, vSR); - via_write(via1, vBufB, via_read(via1, vBufB)|TACK); - while( ct-- && !(via_read(via1, vBufB)&TREQ)) - udelay(1000); - if(ct<0) - printk("No sync 3 occured\n"); - ct=1000; - while( ct-- && !(via_read(via1, vIFR)&SR_INT)) - udelay(1000); - if(ct<0) - printk("No sync 4 occured\n"); - via_read(via1, vSR); - via_write(via1, vBufB, via_read(via1, vBufB)|TIP); -#endif + /* * Ok we probably ;) have a ready to use adb bus. Its also * hopefully idle (Im assuming the mac didnt leave a half @@ -214,20 +207,58 @@ void adb_bus_init(void) */ case MAC_ADB_CUDA: printk("adb: CUDA interface.\n"); -#ifdef TRY_CUDA +#if 0 /* don't know what to set up here ... */ adb_state = idle; /* Set the lines up. We want TREQ as input TACK|TIP as output */ via_write(via1, vDirB, ((via_read(via1,vDirB)|TACK|TIP)&~TREQ)); +#endif + adb_hw_setup_cuda(); + adb_state = idle; request_irq(IRQ_MAC_ADB, adb_cuda_interrupt, IRQ_FLG_LOCK, "adb CUDA interrupt", adb_cuda_interrupt); break; -#else - goto nosupp; -#endif case MAC_ADB_IISI: printk("adb: Using IIsi hardware.\n"); - goto nosupp; + printk("\tDEBUG_JRT\n"); + /* Set the lines up. We want TREQ as input TACK|TIP as output */ + via_write(via1, vDirB, ((via_read(via1,vDirB)|TACK|TIP)&~TREQ)); + + /* + * MSch: I'm pretty sure the setup is mildly wrong + * for the IIsi. + */ + /* Initial state: idle (clear state bits) */ + via_write(via1, vBufB, (via_read(via1, vBufB) & ~(TIP|TACK)) ); + last_status = (via_read(via1, vBufB)&~ST_MASK); + /* Shift register on input */ + c=via_read(via1, vACR); + c&=~SR_CTRL; /* Clear shift register bits */ + c|=SR_EXT; /* Shift on external clock; out or in? */ + via_write(via1, vACR, c); + /* Wipe any pending data and int */ + via_read(via1, vSR); + + /* This is interrupts on enable SR for keyboard */ + via_write(via1, vIER, IER_SET|SR_INT); + /* This clears the interrupt bit */ + via_write(via1, vIFR, SR_INT); + + /* get those pesky clock ticks we missed while booting */ + for ( i = 0; i < 30; i++) { + udelay(ADB_DELAY); + adb_hw_setup_IIsi(); + udelay(ADB_DELAY); + if (via_read(via1, vBufB) & TREQ) + break; + } + /* + * Ok we probably ;) have a ready to use adb bus. Its also + */ + request_irq(IRQ_MAC_ADB, adb_cuda_interrupt, IRQ_FLG_LOCK, + "adb interrupt", adb_cuda_interrupt); + adb_state = idle; + break; default: printk("adb: Unknown hardware interface.\n"); nosupp: @@ -255,6 +286,171 @@ void adb_bus_init(void) restore_flags(flags); } +void adb_hw_setup_cuda(void) +{ + int x; + unsigned long flags; + + printk("CUDA: HW Setup:"); + + save_flags(flags); + cli(); + + if (console_loglevel == 10) + printk(" 1,"); + + /* Set the direction of the cuda signals, TIP+TACK are output TREQ is an input */ + via_write( via1, vDirB, via_read( via1, vDirB ) | TIP | TACK ); + via_write( via1, vDirB, via_read( via1, vDirB ) & ~TREQ ); + + if (console_loglevel == 10) + printk("2,"); + + /* Set the clock control. Set to shift data in by external clock CB1 */ + via_write( via1, vACR, ( via_read(via1, vACR ) | SR_EXT ) & ~SR_OUT ); + + if (console_loglevel == 10) + printk("3,"); + + /* Clear any possible Cuda interrupt */ + x = via_read( via1, vSR ); + + if (console_loglevel == 10) + printk("4,"); + + /* Terminate transaction and set idle state */ + via_write( via1, vBufB, via_read( via1, vBufB ) | TIP | TACK ); + + if (console_loglevel == 10) + printk("5,"); + + /* Delay 4 mS for ADB reset to complete */ + udelay(4000); + + if (console_loglevel == 10) + printk("6,"); + + /* Clear pending interrupts... */ + x = via_read( via1, vSR ); + + if (console_loglevel == 10) + printk("7,"); + /* Issue a sync transaction, TACK asserted while TIP negated */ + via_write( via1, vBufB, via_read( via1, vBufB ) & ~TACK ); + + if (console_loglevel == 10) + printk("8,"); + + /* Wait for the sync acknowledgement, Cuda to assert TREQ */ + while( ( via_read( via1, vBufB ) & TREQ ) != 0 ) + barrier(); + + if (console_loglevel == 10) + printk("9,"); + + /* Wait for the sync acknowledment interrupt */ + while( ( via_read( via1, vIFR ) & SR_INT ) == 0 ) + barrier(); + + if (console_loglevel == 10) + printk("10,"); + + /* Clear pending interrupts... */ + x = via_read( via1, vSR ); + + if (console_loglevel == 10) + printk("11,"); + + /* Terminate the sync cycle by negating TACK */ + via_write( via1, vBufB, via_read( via1, vBufB ) | TACK ); + + if (console_loglevel == 10) + printk("12,"); + + /* Wait for the sync termination acknowledgement, Cuda to negate TREQ */ + while( ( via_read( via1, vBufB ) & TREQ ) == 0 ) + barrier(); + + if (console_loglevel == 10) + printk("13,"); + + /* Wait for the sync termination acknowledment interrupt */ + while( ( via_read( via1, vIFR ) & SR_INT ) == 0 ) + barrier(); + + if (console_loglevel == 10) + printk("14,"); + + /* Terminate transaction and set idle state, TIP+TACK negate */ + via_write( via1, vBufB, via_read( via1, vBufB ) | TIP ); + + if (console_loglevel == 10) + printk("15 !"); + + /* Clear pending interrupts... */ + x = via_read( via1, vSR ); + + restore_flags(flags); + + printk("\nCUDA: HW Setup done!\n"); +} + +void adb_hw_setup_IIsi(void) +{ + int dummy; + long poll_timeout; + + printk("adb_IIsi: cleanup!\n"); + + /* ??? */ + udelay(ADB_DELAY); + + /* disable SR int. */ + via_write(via1, vIER, IER_CLR|SR_INT); + /* set SR to shift in */ + via_write(via1, vACR, via_read(via1, vACR ) & ~SR_OUT); + + /* this is required, especially on faster machines */ + udelay(ADB_DELAY); + + if (!(via_read(via1, vBufB) & TREQ)) { /* IRQ on */ + /* start frame */ + via_write(via1, vBufB,via_read(via1,vBufB) | TIP); + + while (1) { + /* poll for ADB interrupt and watch for timeout */ + /* if time out, keep going in hopes of not hanging the + * ADB chip - I think */ + poll_timeout = ADB_DELAY * 5; + while ( !(via_read(via1, vIFR) & SR_INT) + && (poll_timeout-- > 0) ) + dummy = via_read(via1, vBufB); + + dummy = via_read(via1, vSR); /* reset interrupt flag */ + + /* perhaps put in a check here that ignores all data + * after the first ADB_MAX_MSG_LENGTH bytes ??? */ + + /* end of frame reached ?? */ + if (via_read(via1, vBufB) & TREQ) + break; + + /* set ACK */ + via_write(via1,vBufB,via_read(via1, vBufB) | TACK); + /* delay */ + udelay(ADB_DELAY); + /* clear ACK */ + via_write(via1,vBufB,via_read(via1, vBufB) & ~TACK); + } + /* end frame */ + via_write(via1, vBufB,via_read(via1,vBufB) & ~TIP); + /* probably don't need to delay this long */ + udelay(ADB_DELAY); + } + /* re-enable SR int. */ + via_write(via1, vIER, IER_SET|SR_INT); +} + #define WAIT_FOR(cond, what) \ do { \ for (x = 1000; !(cond); --x) { \ @@ -288,7 +484,7 @@ int adb_request(struct adb_request *req, void (*done)(struct adb_request *), /* * skip first byte if not CUDA */ - if (macintosh_config->adb_type != MAC_ADB_CUDA) { + if (macintosh_config->adb_type == MAC_ADB_II) { start = va_arg(list, int); nbytes--; } @@ -390,8 +586,12 @@ void adb_queue_poll(void) printk("adb: Polling %d\n",pod); #endif - /* XXX: that's a TALK, register 0, MacII version */ - adb_build_request(&r,NULL, 1, (pod<<4|0xC)); + if (macintosh_config->adb_type == MAC_ADB_II) + /* XXX: that's a TALK, register 0, MacII version */ + adb_build_request(&r,NULL, 1, (pod<<4|0xC)); + else + /* CUDA etc. version */ + adb_build_request(&r,NULL, 2, 0, (pod<<4|0xC)); r.reply_expected=0; r.done=NULL; @@ -545,7 +745,7 @@ static void adb_start(void) * IRQ signaled ?? (means ADB controller wants to send, or might * be end of packet if we were reading) */ - if ((via_read(via1, vBufB)& TREQ) == 0) + if ((via_read(via1, vBufB) & TREQ) == 0) { switch(macintosh_config->adb_type) { @@ -560,7 +760,12 @@ static void adb_start(void) /* printk("device busy - fail\n"); */ restore_flags(flags); /* a byte is coming in from the CUDA */ - return; + return; + case MAC_ADB_IISI: + printk("adb_start: device busy - fail\n"); + retry_req = req; + restore_flags(flags); + return; case MAC_ADB_II: /* * if the interrupt handler set the need_poll @@ -635,6 +840,19 @@ static void adb_start(void) via_write(via1, vSR, req->data[0]); via_write(via1, vBufB, via_read(via1, vBufB)&~TIP); break; + case MAC_ADB_IISI: + /* store command byte (first byte is 'type' byte) */ + command_byte = req->data[1]; + /* set ADB state to 'active' */ + via_write(via1, vBufB, via_read(via1, vBufB) | TIP); + /* switch ACK off (in case it was left on) */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* set the shift register to shift out and send a byte */ + via_write(via1, vACR, via_read(via1, vACR) | SR_OUT); + via_write(via1, vSR, req->data[0]); + /* signal 'byte ready' */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + break; case MAC_ADB_II: /* store command byte */ command_byte = req->data[0]; @@ -653,14 +871,14 @@ static void adb_start(void) #endif break; } + adb_state = sent_first_byte; + data_index = 1; #if (ADBDEBUG & ADBDEBUG_START) if (console_loglevel == 10) printk("sent first byte of %d: %x, (%x %x) ... ", req->nbytes, req->data[0], adb_state, (via_read(via1, vBufB) & (ST_MASK|TREQ)) ); #endif - adb_state = sent_first_byte; - data_index = 1; restore_flags(flags); } @@ -748,16 +966,34 @@ void adb_data_interrupt(int irq, void *arg, struct pt_regs *regs) * and retransmit (Talk to the last active device). Cleanup of code and * testing of the CUDA functionality is required, though. * Note2: As of 13/12/97, CUDA support is definitely broken ... + * Note3: As of 21/12/97, CUDA works on a P475. What was broken? The assumption + * that Q700 and Q800 use CUDA :-( + * + * 27/01/98: IIsi driver implemented (thanks to Robert Thompson for the + * initial bits). See adb_cuda_interrupts ... + * * Next TODO: implementation of IIsi ADB protocol (maybe the USE_ORIG * conditionals can be a start?) */ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) { int x, adbdir; + unsigned long flags; struct adb_request *req; last_status = status; + /* prevent races due to SCSI enabling ints */ + save_flags(flags); + cli(); + + if (driver_running) { + restore_flags(flags); + return; + } + + driver_running = 1; + #ifdef USE_ORIG status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT); #else @@ -774,7 +1010,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) adb_state, status, last_status, adbdir); #endif - switch (adb_state) { case idle: @@ -786,6 +1021,26 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) x = via_read(via1, vSR); via_write(via1, vBufB, via_read(via1,vBufB)&~TIP); } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + udelay(150); + /* set SR to IN (??? no byte received else) */ + via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT); + /* signal start of frame */ + via_write(via1, vBufB, via_read(via1, vBufB) | TIP); + /* read first byte */ + x = via_read(via1, vSR); + first_byte = x; +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_macIIsi : receiving unsol. packet: %x (%x %x) ", + x, adb_state, status); +#endif + /* ACK adb chip */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + udelay(150); + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + } else if(macintosh_config->adb_type==MAC_ADB_II) { #if (ADBDEBUG & ADBDEBUG_STATUS) @@ -801,12 +1056,8 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) printk("adb_macII: receiving unsol. packet: %x (%x %x) ", x, adb_state, status); #endif -#ifdef USE_ORIG - via_write(via1, vBufB, via_read(via1, vBufB)&~(TIP|TACK)); -#else /* set ADB state = even for first data byte */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN); -#endif } adb_state = reading; reply_ptr = cuda_rbuf; @@ -831,7 +1082,34 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) x = via_read(via1, vSR); via_write(via1,vBufB, via_read(via1, vBufB)&~TIP); - } else if(macintosh_config->adb_type==MAC_ADB_II) { + } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + /* set SR to IN */ + via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT); + /* signal start of frame */ + via_write(via1, vBufB, via_read(via1, vBufB) | TIP); + /* read first byte */ + x = via_read(via1, vSR); + first_byte = x; +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_macIIsi: reading reply: %x (%x %x) ", + x, adb_state, status); +#endif +#if 0 + if( via_read(via1,vBufB) & TREQ) + ending = 1; + else + ending = 0; +#endif + /* ACK adb chip */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + udelay(150); + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + } + else if(macintosh_config->adb_type==MAC_ADB_II) + { /* handshake etc. for II ?? */ x = via_read(via1, vSR); first_byte = x; @@ -840,12 +1118,8 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) printk("adb_macII: reading reply: %x (%x %x) ", x, adb_state, status); #endif -#ifdef USE_ORIG - via_write(via1, vBufB, via_read(via1, vBufB)&~(TIP|TACK)); -#else /* set ADB state = even for first data byte */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN); -#endif } adb_state = reading; reply_ptr = current_req->reply; @@ -862,6 +1136,11 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) break; case sent_first_byte: +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk(" sending: %x (%x %x) ", + current_req->data[1], adb_state, status); +#endif if(macintosh_config->adb_type==MAC_ADB_CUDA) { if (status == TREQ + TIP + SR_OUT) @@ -886,14 +1165,45 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) adb_state = sending; } } - else if(macintosh_config->adb_type==MAC_ADB_II) + else if(macintosh_config->adb_type==MAC_ADB_IISI) { - /* how to detect a collision here ?? */ + /* switch ACK off */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + if ( !(via_read(via1, vBufB) & TREQ) ) + { + /* collision */ #if (ADBDEBUG & ADBDEBUG_WRITE) - if (console_loglevel == 10) - printk(" sending: %x (%x %x) ", - current_req->data[1], adb_state, status); + if (console_loglevel == 10) + printk("adb_macIIsi: send collison, aborting!\n"); +#endif + /* set shift in */ + via_write(via1, vACR, + via_read(via1, vACR)&~SR_OUT); + /* clear SR int. */ + x = via_read(via1, vSR); + /* set ADB state to 'idle' */ + via_write(via1, vBufB, + via_read(via1,vBufB) & ~(TIP|TACK)); + adb_state = idle; + } + else + { + /* delay */ + udelay(ADB_DELAY); + /* set the shift register to shift out and send a byte */ +#if 0 + via_write(via1, vACR, via_read(via1, vACR) | SR_OUT); #endif + via_write(via1, vSR, current_req->data[1]); + /* signal 'byte ready' */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + data_index=2; + adb_state = sending; + } + } + else if(macintosh_config->adb_type==MAC_ADB_II) + { + /* how to detect a collision here ?? */ /* maybe we're already done (Talk, or Poll)? */ if (data_index >= current_req->nbytes) { @@ -934,14 +1244,9 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) via_write(via1, vACR, via_read(via1, vACR) & ~SR_OUT); x=via_read(via1, vSR); -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)|TACK|TIP); -#else /* set ADB state idle - might get SRQ */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE); -#endif break; } #if (ADBDEBUG & ADBDEBUG_STATUS) @@ -951,14 +1256,9 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) #endif /* SR already set to shift out; send byte */ via_write(via1, vSR, current_req->data[1]); -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)^TACK); -#else /* set state to ST_EVEN (first byte was: ST_CMD) */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN); -#endif data_index=2; adb_state = sending; } @@ -968,6 +1268,11 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) req = current_req; if (data_index >= req->nbytes) { +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk(" -> end (%d of %d) (%x %x)!\n", + data_index-1, req->nbytes, adb_state, status); +#endif /* end of packet */ if(macintosh_config->adb_type==MAC_ADB_CUDA) { @@ -977,29 +1282,34 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) via_write(via1, vBufB, via_read(via1,vBufB)|TACK|TIP); } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + /* XXX maybe clear ACK here ??? */ + /* switch ACK off */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* delay */ + udelay(ADB_DELAY); + /* set the shift register to shift in */ + via_write(via1, vACR, via_read(via1, vACR)|SR_OUT); + /* clear SR int. */ + x = via_read(via1, vSR); + /* set ADB state 'idle' (end of frame) */ + via_write(via1, vBufB, + via_read(via1,vBufB) & ~(TACK|TIP)); + } else if(macintosh_config->adb_type==MAC_ADB_II) { /* * XXX Not sure: maybe only switch to * input mode on Talk ?? */ -#if (ADBDEBUG & ADBDEBUG_WRITE) - if (console_loglevel == 10) - printk(" -> end (%d of %d) (%x %x)!\n", - data_index-1, req->nbytes, adb_state, status); -#endif /* set to shift in */ via_write(via1, vACR, via_read(via1, vACR) & ~SR_OUT); x=via_read(via1, vSR); -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)|TACK|TIP); -#else /* set ADB state idle - might get SRQ */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE); -#endif } req->sent = 1; if (req->reply_expected) @@ -1008,7 +1318,12 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) * maybe fake a reply here on Listen ?? * Otherwise, a Listen hangs on success */ - if ( ((req->data[0]&0xc) == 0xc) ) + if ( macintosh_config->adb_type==MAC_ADB_II + && ((req->data[0]&0xc) == 0xc) ) + adb_state = awaiting_reply; + else if ( macintosh_config->adb_type != MAC_ADB_II + && ( req->data[0] == 0x0) + && ((req->data[1]&0xc) == 0xc) ) adb_state = awaiting_reply; else { /* @@ -1063,34 +1378,46 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) } else { +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk(" %x (%x %x) ", + req->data[data_index], adb_state, status); +#endif if(macintosh_config->adb_type==MAC_ADB_CUDA) { via_write(via1, vSR, req->data[data_index++]); via_write(via1, vBufB, via_read(via1, vBufB)^TACK); } - else if(macintosh_config->adb_type==MAC_ADB_II) + else if(macintosh_config->adb_type==MAC_ADB_IISI) { -#if (ADBDEBUG & ADBDEBUG_WRITE) - if (console_loglevel == 10) - printk(" %x (%x %x) ", - req->data[data_index], adb_state, status); + /* switch ACK off */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* delay */ + udelay(ADB_DELAY); + /* XXX: need to check for collision?? */ + /* set the shift register to shift out and send a byte */ +#if 0 + via_write(via1, vACR, via_read(via1, vACR)|SR_OUT); #endif via_write(via1, vSR, req->data[data_index++]); -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)^TACK); -#else + /* signal 'byte ready' */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + } + else if(macintosh_config->adb_type==MAC_ADB_II) + { + via_write(via1, vSR, req->data[data_index++]); /* invert state bits, toggle ODD/EVEN */ x = via_read(via1, vBufB); via_write(via1, vBufB, (x&~ST_MASK)|~(x&ST_MASK)); -#endif } } break; case reading: + + /* timeout / SRQ handling for II hw */ #ifdef POLL_ON_TIMEOUT if((reply_len-prefix_len)==3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0) #else @@ -1128,16 +1455,12 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) x, adb_state, status); #endif -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)|TACK|TIP); -#else #if 0 /* XXX leave status unchanged!! - need to check this again! */ + /* XXX Only touch status on II !!! */ /* set ADB state to idle (required by adb_start()) */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE); #endif -#endif /* * What if the timeout happens on reading a @@ -1206,6 +1529,7 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) */ break; } + /* end timeout / SRQ handling for II hw. */ if((reply_len-prefix_len)>3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0) { /* SRQ tacked on data packet */ @@ -1241,7 +1565,7 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) reply_len++; } /* The usual handshake ... */ - if(macintosh_config->adb_type==MAC_ADB_CUDA) + if (macintosh_config->adb_type==MAC_ADB_CUDA) { if (status == TIP) { @@ -1259,7 +1583,27 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) via_read(via1, vBufB)^TACK); } } - if(macintosh_config->adb_type==MAC_ADB_II) + else if (macintosh_config->adb_type==MAC_ADB_IISI) + { + /* ACK adb chip (maybe check for end first?) */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + udelay(150); + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* end of frame?? */ + if (status & TREQ) + { +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_IIsi: end of frame!\n"); +#endif + /* that's all folks */ + via_write(via1, vBufB, + via_read(via1, vBufB) & ~(TACK|TIP)); + adb_state = read_done; + /* maybe process read_done here?? Handshake anyway?? */ + } + } + else if (macintosh_config->adb_type==MAC_ADB_II) { /* * NetBSD hints that the next to last byte @@ -1277,10 +1621,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) if (console_loglevel == 10) printk(" -> read done!\n"); #endif -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)|TACK|TIP); -#else #if 0 /* XXX: we take one more byte (why?), so handshake! */ /* set ADB state to idle */ via_write(via1, vBufB, @@ -1291,7 +1631,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) via_write(via1, vBufB, (x&~ST_MASK)|~(x&ST_MASK)); #endif -#endif /* adjust packet length */ reply_len--; reply_ptr--; @@ -1303,10 +1642,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) if(status!=TIP+TREQ) printk("macII_adb: state=reading status=%x\n", status); #endif -#ifdef USE_ORIG - via_write(via1, vBufB, - via_read(via1, vBufB)^TACK); -#else /* not caught: ST_CMD */ /* required for re-entry 'reading'! */ if ((status&ST_MASK) == ST_IDLE) { @@ -1319,7 +1654,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) via_write(via1, vBufB, (x&~ST_MASK)|~(x&ST_MASK)); } -#endif } } break; @@ -1352,7 +1686,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) last_reply = command_byte; last_active = (command_byte&0xf0)>>4; - /* * Assert status = ST_IDLE ?? */ @@ -1374,15 +1707,6 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) break; } -#ifdef USE_ORIG - /* - * This will fail - TREQ is active low -> 0 is IRQ !! - */ - if (status == TREQ) - { - via_write(via1, vBufB, - via_read(via1, vBufB)|~TIP); -#else /* * /IRQ seen, so the ADB controller has data for us */ @@ -1391,7 +1715,7 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) /* set ADB state to idle */ via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE); -#endif + adb_state = reading; reply_ptr = cuda_rbuf; reply_len = 0; @@ -1422,35 +1746,81 @@ void adb_interrupt(int irq, void *arg, struct pt_regs *regs) printk("adb_interrupt: unknown adb_state %d?\n", adb_state); #endif } + /* reset mutex and interrupts */ + driver_running = 0; + restore_flags(flags); } /* * Restart of CUDA support: please modify this interrupt handler while * working at the Quadra etc. ADB driver. We can try to merge them later, or * remove the CUDA stuff from the MacII handler + * + * MSch 27/01/98: Implemented IIsi driver based on initial code by Robert + * Thompson and hints from the NetBSD driver. CUDA and IIsi seem more closely + * related than to the MacII code, so merging all three might be a bad + * idea. */ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) { int x, status; struct adb_request *req; + unsigned long flags; + + save_flags(flags); + cli(); - status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT); + if(macintosh_config->adb_type==MAC_ADB_CUDA) + status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT); + else + status = via_read(via1, vBufB) & (TIP|TREQ); + +#if (ADBDEBUG & ADBDEBUG_INT) if (console_loglevel == 10) printk("adb_interrupt: state=%d status=%x\n", adb_state, status); +#endif switch (adb_state) { case idle: + first_byte = 0; if(macintosh_config->adb_type==MAC_ADB_CUDA) { +#if (ADBDEBUG & ADBDEBUG_STATUS) /* CUDA has sent us the first byte of data - unsolicited */ if (status != TREQ) printk("cuda: state=idle, status=%x want=%x\n", status, TREQ); +#endif x = via_read(via1, vSR); +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_cuda: receiving unsol. packet: %x (%x %x) ", + x, adb_state, status); +#endif via_write(via1, vBufB, via_read(via1,vBufB)&~TIP); } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + udelay(150); + /* set SR to IN */ + via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT); + /* signal start of frame */ + via_write(via1, vBufB, via_read(via1, vBufB) | TIP); + /* read first byte */ + x = via_read(via1, vSR); + first_byte = x; +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_IIsi : receiving unsol. packet: %x (%x %x) ", + x, adb_state, status); +#endif + /* ACK adb chip */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + udelay(150); + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + } else if(macintosh_config->adb_type==MAC_ADB_II) { if (status != TREQ) @@ -1469,13 +1839,46 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) if(macintosh_config->adb_type==MAC_ADB_CUDA) { /* CUDA has sent us the first byte of data of a reply */ +#if (ADBDEBUG & ADBDEBUG_STATUS) if (status != TREQ) printk("cuda: state=awaiting_reply, status=%x want=%x\n", status, TREQ); +#endif x = via_read(via1, vSR); +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_cuda: reading reply: %x (%x %x) ", + x, adb_state, status); +#endif via_write(via1,vBufB, via_read(via1, vBufB)&~TIP); } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + /* udelay(150);*/ + /* set SR to IN */ + via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT); + /* signal start of frame */ + via_write(via1, vBufB, via_read(via1, vBufB) | TIP); + /* read first byte */ + x = via_read(via1, vSR); + first_byte = x; +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_IIsi: reading reply: %x (%x %x) ", + x, adb_state, status); +#endif +#if 0 + if( via_read(via1,vBufB) & TREQ) + ending = 1; + else + ending = 0; +#endif + /* ACK adb chip */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + udelay(150); + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + } adb_state = reading; reply_ptr = current_req->reply; reading_reply = 1; @@ -1485,11 +1888,16 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) case sent_first_byte: if(macintosh_config->adb_type==MAC_ADB_CUDA) { +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk(" sending: %x (%x %x) ", + current_req->data[1], adb_state, status); +#endif if (status == TREQ + TIP + SR_OUT) { /* collision */ if (console_loglevel == 10) - printk("cuda: send collision!\n"); + printk("adb_cuda: send collision!\n"); via_write(via1, vACR, via_read(via1, vACR)&~SR_OUT); x = via_read(via1, vSR); @@ -1500,9 +1908,11 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) else { /* assert status == TIP + SR_OUT */ +#if (ADBDEBUG & ADBDEBUG_STATUS) if (status != TIP + SR_OUT) - printk("cuda: state=sent_first_byte status=%x want=%x\n", + printk("adb_cuda: state=sent_first_byte status=%x want=%x\n", status, TIP + SR_OUT); +#endif via_write(via1,vSR,current_req->data[1]); via_write(via1, vBufB, via_read(via1, vBufB)^TACK); @@ -1510,6 +1920,42 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) adb_state = sending; } } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + /* switch ACK off */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + if ( !(via_read(via1, vBufB) & TREQ) ) + { + /* collision */ +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk("adb_macIIsi: send collison, aborting!\n"); +#endif + /* set shift in */ + via_write(via1, vACR, + via_read(via1, vACR)&~SR_OUT); + /* clear SR int. */ + x = via_read(via1, vSR); + /* set ADB state to 'idle' */ + via_write(via1, vBufB, + via_read(via1,vBufB) & ~(TIP|TACK)); + adb_state = idle; + } + else + { + /* delay */ + udelay(ADB_DELAY); + /* set the shift register to shift out and send a byte */ +#if 0 + via_write(via1, vACR, via_read(via1, vACR) | SR_OUT); +#endif + via_write(via1, vSR, current_req->data[1]); + /* signal 'byte ready' */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + data_index=2; + adb_state = sending; + } + } else if(macintosh_config->adb_type==MAC_ADB_II) { if(status!=TIP+SR_OUT) @@ -1527,6 +1973,11 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) req = current_req; if (data_index >= req->nbytes) { +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk(" -> end (%d of %d) (%x %x)!\n", + data_index-1, req->nbytes, adb_state, status); +#endif if(macintosh_config->adb_type==MAC_ADB_CUDA) { via_write(via1, vACR, @@ -1535,6 +1986,21 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) via_write(via1, vBufB, via_read(via1,vBufB)|TACK|TIP); } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + /* XXX maybe clear ACK here ??? */ + /* switch ACK off */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* delay */ + udelay(ADB_DELAY); + /* set the shift register to shift in */ + via_write(via1, vACR, via_read(via1, vACR)|SR_OUT); + /* clear SR int. */ + x = via_read(via1, vSR); + /* set ADB state 'idle' (end of frame) */ + via_write(via1, vBufB, + via_read(via1,vBufB) & ~(TACK|TIP)); + } else if(macintosh_config->adb_type==MAC_ADB_II) { via_write(via1, vACR, @@ -1546,7 +2012,40 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) req->sent = 1; if (req->reply_expected) { - adb_state = awaiting_reply; + /* + * maybe fake a reply here on Listen ?? + * Otherwise, a Listen hangs on success + * CUDA+IIsi: only ADB Talk considered + * RTC/PRAM read (0x1 0x3) to follow. + */ + if ( (req->data[0] == 0x0) && ((req->data[1]&0xc) == 0xc) ) + adb_state = awaiting_reply; + else { + /* + * Reply expected, but none + * possible -> fake reply. + */ +#if (ADBDEBUG & ADBDEBUG_PROT) + printk("ADB: reply expected on Listen, faking reply\n"); +#endif + /* make it look weird */ + /* XXX: return reply_len -1? */ + /* XXX: fake ADB header? */ + req->reply[0] = req->reply[1] = req->reply[2] = 0xFF; + req->reply_len = 3; + req->got_reply = 1; + current_req = req->next; + if (req->done) + (*req->done)(req); + /* + * ready with this one, run + * next command ! + */ + /* set state to idle !! */ + adb_state = idle; + if (current_req || retry_req) + adb_start(); + } } else { @@ -1560,12 +2059,32 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) } else { +#if (ADBDEBUG & ADBDEBUG_WRITE) + if (console_loglevel == 10) + printk(" %x (%x %x) ", + req->data[data_index], adb_state, status); +#endif if(macintosh_config->adb_type==MAC_ADB_CUDA) { via_write(via1, vSR, req->data[data_index++]); via_write(via1, vBufB, via_read(via1, vBufB)^TACK); } + else if(macintosh_config->adb_type==MAC_ADB_IISI) + { + /* switch ACK off */ + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* delay */ + udelay(ADB_DELAY); + /* XXX: need to check for collision?? */ + /* set the shift register to shift out and send a byte */ +#if 0 + via_write(via1, vACR, via_read(via1, vACR)|SR_OUT); +#endif + via_write(via1, vSR, req->data[data_index++]); + /* signal 'byte ready' */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + } else if(macintosh_config->adb_type==MAC_ADB_II) { via_write(via1, vSR, req->data[data_index++]); @@ -1579,14 +2098,17 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) if(reply_len==3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0) { /* Terminate the SRQ packet */ - printk("CUDA: Got an SRQ\n"); +#if (ADBDEBUG & ADBDEBUG_SRQ) + if (console_loglevel == 10) + printk("adb: Got an SRQ\n"); +#endif adb_state = idle; adb_queue_poll(); break; } /* Sanity check - botched in orig. code! */ if(reply_len>15) { - printk("CUDA: reply buffer overrun!\n"); + printk("adb_cuda: reply buffer overrun!\n"); /* wrap buffer */ reply_len=0; if (reading_reply) @@ -1595,9 +2117,11 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) reply_ptr = cuda_rbuf; } *reply_ptr = via_read(via1, vSR); +#if (ADBDEBUG & ADBDEBUG_READ) if (console_loglevel == 10) - printk(" %p-> %x (%x %x) ", - reply_ptr, *reply_ptr, adb_state, status); + printk(" %x (%x %x) ", + *reply_ptr, adb_state, status); +#endif reply_ptr++; reply_len++; if(macintosh_config->adb_type==MAC_ADB_CUDA) @@ -1612,13 +2136,36 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) else { /* assert status == TIP | TREQ */ +#if (ADBDEBUG & ADBDEBUG_STATUS) if (status != TIP + TREQ) printk("cuda: state=reading status=%x want=%x\n", status, TIP + TREQ); +#endif via_write(via1, vBufB, via_read(via1, vBufB)^TACK); } } + else if (macintosh_config->adb_type==MAC_ADB_IISI) + { + /* ACK adb chip (maybe check for end first?) */ + via_write(via1, vBufB, via_read(via1, vBufB) | TACK); + udelay(150); + via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK); + /* end of frame?? */ + if (status & TREQ) + { +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb_IIsi: end of frame!\n"); +#endif + /* that's all folks */ + via_write(via1, vBufB, + via_read(via1, vBufB) & ~(TACK|TIP)); + adb_state = read_done; + /* XXX maybe process read_done here?? + Handshake anyway?? */ + } + } if(macintosh_config->adb_type==MAC_ADB_II) { if( status == TIP) @@ -1629,16 +2176,26 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) } else { +#if (ADBDEBUG & ADBDEBUG_STATUS) if(status!=TIP+TREQ) printk("macII_adb: state=reading status=%x\n", status); +#endif via_write(via1, vBufB, via_read(via1, vBufB)^TACK); } } - break; + /* fall through for IIsi on end of frame */ + if (macintosh_config->adb_type != MAC_ADB_IISI + || adb_state != read_done) + break; case read_done: x = via_read(via1, vSR); +#if (ADBDEBUG & ADBDEBUG_READ) + if (console_loglevel == 10) + printk("adb: read done: %x (%x %x)!\n", + x, adb_state, status); +#endif if (reading_reply) { req = current_req; @@ -1653,10 +2210,21 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) adb_input(cuda_rbuf, reply_ptr - cuda_rbuf, regs); } - if (status == TREQ) + if (macintosh_config->adb_type==MAC_ADB_CUDA + && status & TREQ) + { + via_write(via1, vBufB, + via_read(via1, vBufB)&~TIP); + adb_state = reading; + reply_ptr = cuda_rbuf; + reading_reply = 0; + } + else if (macintosh_config->adb_type==MAC_ADB_IISI + && !(status & TREQ)) { + udelay(150); via_write(via1, vBufB, - via_read(via1, vBufB)|~TIP); + via_read(via1, vBufB) | TIP); adb_state = reading; reply_ptr = cuda_rbuf; reading_reply = 0; @@ -1669,8 +2237,11 @@ void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs) break; default: - printk("adb_interrupt: unknown adb_state %d?\n", adb_state); + printk("adb_cuda_interrupt: unknown adb_state %d?\n", adb_state); } + + restore_flags(flags); + } /* diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index d711dd7b3..fe77ded05 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c @@ -35,20 +35,16 @@ #include <asm/macintosh.h> #include <asm/macints.h> +#include <asm/machw.h> #include "via6522.h" -/* old bootinfo stuff */ +/* Mac bootinfo struct */ struct mac_booter_data mac_bi_data = {0,}; int mac_bisize = sizeof mac_bi_data; -struct compat_bootinfo compat_boot_info ={0,}; -int compat_bisize = sizeof compat_boot_info; - -int compat_bi = 0; - -/* New bootinfo stuff */ +/* New m68k bootinfo stuff and videobase */ extern int m68k_num_memory; extern struct mem_info m68k_memory[NUM_MEMINFO]; @@ -59,42 +55,67 @@ extern char m68k_command_line[CL_SIZE]; void *mac_env; /* Loaded by the boot asm */ +/* The logical video addr. determined by head.S - testing */ +extern unsigned long mac_videobase; + +/* The phys. video addr. - might be bogus on some machines */ +unsigned long mac_orig_videoaddr; + +/* Mac specific keyboard functions */ extern int mac_keyb_init(void); extern int mac_kbdrate(struct kbd_repeat *k); extern void mac_kbd_leds(unsigned int leds); +extern void mac_kbd_reset_setup(char*, int); + +/* Mac specific irq functions */ +extern void mac_init_IRQ (void); +extern void (*mac_handlers[]) (int, void *, struct pt_regs *); +extern int mac_request_irq (unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long flags, const char *devname, + void *dev_id); +extern void mac_free_irq (unsigned int irq, void *dev_id); +extern void mac_enable_irq (unsigned int); +extern void mac_disable_irq (unsigned int); +static void mac_get_model(char *model); +/*static int mac_get_hardware_list(char *buffer);*/ +extern int mac_get_irq_list (char *); + +/* Mac specific timer functions */ +extern unsigned long mac_gettimeoffset (void); +extern void mac_gettod (int *, int *, int *, int *, int *, int *); +extern int mac_hwclk (int, struct hwclk_time *); +extern int mac_set_clock_mmss (unsigned long); +extern void via_init_clock(void (*func)(int, void *, struct pt_regs *)); extern void (*kd_mksound)(unsigned int, unsigned int); extern void mac_mksound(unsigned int, unsigned int); extern int mac_floppy_init(void); extern void mac_floppy_setup(char *,int *); -extern void mac_gettod (int *, int *, int *, int *, int *, int *); - extern void nubus_sweep_video(void); -extern void via_init_clock(void (*func)(int, void *, struct pt_regs *)); -extern void mac_debugging_long(int, long); /* Mac specific debug functions (in debug.c) */ extern void mac_debug_init(void); +extern void mac_debugging_long(int, long); #ifdef CONFIG_MAGIC_SYSRQ + +/* XXX FIXME: Atari scancodes still */ static char mac_sysrq_xlate[128] = - "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ - "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ - "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ - "bnm,./\000\000\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ + "bnm,./\000\000\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ "\206\207\210\211\212\000\000\000\000\000-\000\000\000+\000"/* 0x40 - 0x4f */ "\000\000\000\177\000\000\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ - "\000\000\000()/*789456123" /* 0x60 - 0x6f */ + "\000\000\000()/*789456123" /* 0x60 - 0x6f */ "0.\r\000\000\000\000\000\000\000\000\000\000\000\000\000"; /* 0x70 - 0x7f */ #endif extern void (*kd_mksound)(unsigned int, unsigned int); -void mac_get_model(char *str) -{ - strcpy(str,"Macintosh"); -} +static void mac_get_model(char *str); void mac_bang(int irq, void *vector, struct pt_regs *p) { @@ -107,27 +128,22 @@ void mac_sched_init(void (*vector)(int, void *, struct pt_regs *)) via_init_clock(vector); } -unsigned long mac_gettimeoffset (void) -{ - return 0L; -} - extern int console_loglevel; +/* + * This function translates the boot timeval into a proper date, to initialize + * the system time. + */ + void mac_gettod (int *yearp, int *monp, int *dayp, int *hourp, int *minp, int *secp) { unsigned long time; int leap, oldleap, isleap; - int mon_days[14] = { -1, 31, 27, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, -1 }; + int mon_days[14] = { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, -1 }; time = mac_bi_data.boottime - 60*mac_bi_data.gmtbias; /* seconds */ -#if 0 - printk("mac_gettod: boottime 0x%lx gmtbias %ld \n", - mac_bi_data.boottime, mac_bi_data.gmtbias); -#endif - *minp = time / 60; *secp = time - (*minp * 60); time = *minp; /* minutes now */ @@ -143,7 +159,7 @@ void mac_gettod (int *yearp, int *monp, int *dayp, /* for leap day calculation */ *yearp = (time / 365) + 1970; /* approx. year */ - /* leap year calculation - there's an easier way, I bet */ + /* leap year calculation - there's an easier way, I bet. And it's broken :-( */ /* calculate leap days up to previous year */ oldleap = (*yearp-1)/4 - (*yearp-1)/100 + (*yearp-1)/400; /* calculate leap days incl. this year */ @@ -161,7 +177,7 @@ void mac_gettod (int *yearp, int *monp, int *dayp, time = *dayp; if (isleap) /* add leap day ?? */ - mon_days[2] = 28; + mon_days[2] += 1; /* count the months */ for (*monp = 1; time > mon_days[*monp]; (*monp)++) @@ -169,15 +185,29 @@ void mac_gettod (int *yearp, int *monp, int *dayp, *dayp = time; -#if 1 - printk("mac_gettod: %d-%d-%d %d:%d.%d GMT (GMT offset %d)\n", - *yearp, *monp, *dayp, *hourp, *minp, *secp, - (signed long) mac_bi_data.gmtbias); -#endif - return; } +/* + * TBI: read and write hwclock + */ + +int mac_hwclk( int op, struct hwclk_time *t ) +{ + return 0; +} + +/* + * TBI: set minutes/seconds in hwclock + */ + +int mac_set_clock_mmss (unsigned long nowtime) +{ + short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60; + + return 0; +} + void mac_waitbut (void) { ; @@ -187,11 +217,6 @@ extern struct consw fb_con; extern struct fb_info *mac_fb_init(long *); extern void mac_video_setup(char *, int *); -void mac_debug_init (void) -{ - ; -} - void (*mac_handlers[8])(int, void *, struct pt_regs *)= { mac_default_handler, @@ -213,15 +238,14 @@ __initfunc(int mac_parse_bootinfo(const struct bi_record *record)) int unknown = 0; const u_long *data = record->data; - if (compat_bi) - return(unknown); - switch (record->tag) { case BI_MAC_MODEL: mac_bi_data.id = *data; break; case BI_MAC_VADDR: - mac_bi_data.videoaddr = *data; + /* save booter supplied videobase; use the one mapped in head.S! */ + mac_orig_videoaddr = *data; + mac_bi_data.videoaddr = mac_videobase; break; case BI_MAC_VDEPTH: mac_bi_data.videodepth = *data; @@ -256,39 +280,6 @@ __initfunc(int mac_parse_bootinfo(const struct bi_record *record)) return(unknown); } -__initfunc(void mac_copy_compat(void)) -{ - int i; - - compat_bi = 1; - - for (i=0; i<compat_boot_info.num_memory; i++) { - m68k_memory[m68k_num_memory].addr = compat_boot_info.memory[i].addr; - m68k_memory[m68k_num_memory].size = compat_boot_info.memory[i].size; - m68k_num_memory++; - } - - m68k_ramdisk.addr = compat_boot_info.ramdisk_addr; - m68k_ramdisk.size = compat_boot_info.ramdisk_size; - - strncpy(m68k_command_line, (const char *)compat_boot_info.command_line, - CL_SIZE); - m68k_command_line[CL_SIZE-1] = '\0'; - - mac_bi_data.id = compat_boot_info.bi_mac.id; - mac_bi_data.videoaddr = compat_boot_info.bi_mac.videoaddr; - mac_bi_data.videodepth = compat_boot_info.bi_mac.videodepth; - mac_bi_data.videorow = compat_boot_info.bi_mac.videorow; - mac_bi_data.dimensions = compat_boot_info.bi_mac.dimensions; - mac_bi_data.videological = compat_boot_info.bi_mac.videological; - mac_bi_data.sccbase = compat_boot_info.bi_mac.sccbase; - mac_bi_data.boottime = compat_boot_info.bi_mac.boottime; - mac_bi_data.gmtbias = compat_boot_info.bi_mac.gmtbias; - mac_bi_data.memsize = compat_boot_info.bi_mac.memsize; - mac_bi_data.cpuid = compat_boot_info.bi_mac.cpuid; - -} - __initfunc(void config_mac(void)) { @@ -296,14 +287,13 @@ __initfunc(void config_mac(void)) printk("ERROR: no Mac, but config_mac() called!! \n"); } - mac_debugging_penguin(5); - mac_debug_init(); mach_sched_init = mac_sched_init; mach_keyb_init = mac_keyb_init; mach_kbdrate = mac_kbdrate; mach_kbd_leds = mac_kbd_leds; + kbd_reset_setup = mac_kbd_reset_setup; mach_init_IRQ = mac_init_IRQ; mach_request_irq = mac_request_irq; mach_free_irq = mac_free_irq; @@ -316,15 +306,13 @@ __initfunc(void config_mac(void)) mach_get_irq_list = mac_get_irq_list; mach_gettimeoffset = mac_gettimeoffset; mach_gettod = mac_gettod; + mach_hwclk = mac_hwclk; + mach_set_clock_mmss = mac_set_clock_mmss; #if 0 mach_mksound = mac_mksound; #endif mach_reset = mac_reset; -#ifdef CONFIG_BLK_DEV_FD - mach_floppy_init = mac_floppy_init; - mach_floppy_setup = mac_floppy_setup; -#endif - conswitchp = &fb_con; + conswitchp = &dummy_con; mach_max_dma_address = 0xffffffff; #if 0 mach_debug_init = mac_debug_init; @@ -361,11 +349,20 @@ __initfunc(void config_mac(void)) */ nubus_sweep_video(); + } /* - * Macintosh Table + * Macintosh Table: hardcoded model configuration data. + * + * Much of this was defined by Alan, based on who knows what docs. + * I've added a lot more, and some of that was pure guesswork based + * on hardware pages present on the Mac web site. Possibly wildly + * inaccurate, so look here if a new Mac model won't run. Example: if + * a Mac crashes immediately after the VIA1 registers have been dumped + * to the screen, it probably died attempting to read DirB on a RBV. + * Meaning it should have MAC_VIA_IIci here :-) */ struct mac_model *macintosh_config; @@ -389,10 +386,11 @@ static struct mac_model mac_data_table[]= * * The IIfx apparently has different ADB hardware, and stuff * so zany nobody knows how to drive it. + * Even so, with Marten's help we'll try to deal with it :-) */ { MAC_MODEL_IICI, "IIci", MAC_ADB_II, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_IIFX, "IIfx", MAC_ADB_NONE, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_IIFX, "IIfx", MAC_ADB_II, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_IISI, "IIsi", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_IIVI, "IIvi", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_IIVX, "IIvx", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, @@ -405,9 +403,10 @@ static struct mac_model mac_data_table[]= { MAC_MODEL_CCL, "Color Classic", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, /* - * Some Mac LC machines. Basically the same as the IIci + * Some Mac LC machines. Basically the same as the IIci, ADB like IIsi */ + { MAC_MODEL_LC, "LC", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_LCII, "LC II", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_LCIII,"LC III", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, @@ -416,75 +415,74 @@ static struct mac_model mac_data_table[]= * 0xF9000000, via is like a MacII. We label it differently as some of the * stuff connected to VIA2 seems different. Better SCSI chip and ???? onboard ethernet * in all cases using a NatSemi SONIC. The 700, 900 and 950 have some I/O chips in the wrong - * place to confuse us. The 840 seems to have a scsi location of its own + * place to confuse us. The 840AV seems to have a scsi location of its own */ - { MAC_MODEL_Q605, "Quadra 605", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, - { MAC_MODEL_Q610, "Quadra 610", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, - { MAC_MODEL_Q630, "Quadra 630", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, - { MAC_MODEL_Q650, "Quadra 650", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q605, "Quadra 605", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q610, "Quadra 610", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q630, "Quadra 630", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_QUADRA, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q650, "Quadra 650", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, /* The Q700 does have a NS Sonic */ -#if 0 - { MAC_MODEL_Q700, "Quadra 700", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS}, - { MAC_MODEL_Q800, "Quadra 800", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, -#else - { MAC_MODEL_Q700, "Quadra 700", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS}, - { MAC_MODEL_Q800, "Quadra 800", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, -#endif - /* Does the 840 have ethernet ??? documents seem to indicate its not quite a + { MAC_MODEL_Q700, "Quadra 700", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q800, "Quadra 800", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, + /* Does the 840AV have ethernet ??? documents seem to indicate its not quite a Quadra in this respect ? */ - { MAC_MODEL_Q840, "Quadra 840", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_Q900, "Quadra 900", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS}, - { MAC_MODEL_Q950, "Quadra 950", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q840, "Quadra 840AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + /* These might have IOP problems */ + { MAC_MODEL_Q900, "Quadra 900", MAC_ADB_IISI, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_IOP, MAC_ETHER_SONIC, MAC_NUBUS}, + { MAC_MODEL_Q950, "Quadra 950", MAC_ADB_IISI, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_IOP, MAC_ETHER_SONIC, MAC_NUBUS}, /* * Performa - more LC type machines */ - { MAC_MODEL_P460, "Performa 460", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_P475, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_P520, "Performa 520", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_P550, "Performa 550", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_P575, "Performa 575", MAC_ADB_CUDA, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_TV, "TV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P460, "Performa 460", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P475, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P475F, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P520, "Performa 520", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P550, "Performa 550", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P575, "Performa 575", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P588, "Performa 588", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_TV, "TV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P600, "Performa 600", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, #if 0 /* other sources seem to suggest the P630/Q630/LC630 is more like LCIII */ - { MAC_MODEL_P630, "Performa 630", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_P630, "Performa 630", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, #endif /* * Centris - just guessing again; maybe like Quadra */ - { MAC_MODEL_C610, "Centris 610", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_C650, "Centris 650", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_C660, "Centris 660AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_C610, "Centris 610", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_C650, "Centris 650", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_C660, "Centris 660AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, /* * Power books - seem similar to early Quadras ? (most have 030 though) */ - { MAC_MODEL_PB140, "PowerBook 140", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB145, "PowerBook 145", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB140, "PowerBook 140", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB145, "PowerBook 145", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, /* The PB150 has IDE, and IIci style VIA */ - { MAC_MODEL_PB150, "PowerBook 150", MAC_ADB_CUDA, MAC_VIA_IIci, MAC_SCSI_QUADRA, MAC_IDE_PB, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB160, "PowerBook 160", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB165, "PowerBook 165", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB165C, "PowerBook 165c", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB170, "PowerBook 170", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB180, "PowerBook 180", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB180C, "PowerBook 180c", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB190, "PowerBook 190cs", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB520, "PowerBook 520", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB150, "PowerBook 150", MAC_ADB_PB1, MAC_VIA_IIci, MAC_SCSI_QUADRA, MAC_IDE_PB, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB160, "PowerBook 160", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB165, "PowerBook 165", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB165C, "PowerBook 165c", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB170, "PowerBook 170", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB180, "PowerBook 180", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB180C, "PowerBook 180c", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB190, "PowerBook 190cs", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_PB, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB520, "PowerBook 520", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, /* * Power book Duos - similar to Power books, I hope */ - { MAC_MODEL_PB210, "PowerBook Duo 210", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB230, "PowerBook Duo 230", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB250, "PowerBook Duo 250", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB270C, "PowerBook Duo 270c", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB280, "PowerBook Duo 280", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_PB280C, "PowerBook Duo 280c", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB210, "PowerBook Duo 210", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB230, "PowerBook Duo 230", MAC_ADB_PB2, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB250, "PowerBook Duo 250", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB270C, "PowerBook Duo 270c", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB280, "PowerBook Duo 280", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_PB280C, "PowerBook Duo 280c", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, /* * Other stuff ?? @@ -517,8 +515,6 @@ void mac_identify(void) { printk("\nUnknown macintosh model %d, probably unsupported.\n", model); - mac_debugging_long(1, (long) 0x55555555); - mac_debugging_long(1, (long) model); model = MAC_MODEL_Q800; printk("Defaulting to: Quadra800, model id %d\n", model); printk("Please report this case to linux-mac68k@wave.lm.com\n"); @@ -536,19 +532,22 @@ void mac_identify(void) /* * Report booter data: */ - printk (" Penguin (bootinfo version %d) data:\n", 2-compat_bi); - printk (" Video: addr 0x%lx row 0x%lx depth %lx dimensions %d x %d\n", + printk (" Penguin bootinfo data:\n"); + printk (" Video: addr 0x%lx row 0x%lx depth %lx dimensions %ld x %ld\n", mac_bi_data.videoaddr, mac_bi_data.videorow, - mac_bi_data.videodepth, mac_bi_data.dimensions & 0xFFFF, - mac_bi_data.dimensions >> 16); + mac_bi_data.videodepth, (int) (mac_bi_data.dimensions & 0xFFFF), + (int) (mac_bi_data.dimensions >> 16)); + printk (" Videological 0x%lx phys. 0x%lx, SCC at 0x%lx \n", + mac_bi_data.videological, mac_orig_videoaddr, + mac_bi_data.sccbase); printk (" Boottime: 0x%lx GMTBias: 0x%lx \n", mac_bi_data.boottime, mac_bi_data.gmtbias); - printk (" Videological 0x%lx, SCC at 0x%lx \n", - mac_bi_data.videological, mac_bi_data.sccbase); printk (" Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n", mac_bi_data.id, mac_bi_data.cpuid, mac_bi_data.memsize); +#if 0 printk ("Ramdisk: addr 0x%lx size 0x%lx\n", m68k_ramdisk.addr, m68k_ramdisk.size); +#endif /* * Save the pointer @@ -559,6 +558,25 @@ void mac_identify(void) /* * TODO: set the various fields in macintosh_config->hw_present here! */ + switch (macintosh_config->scsi_type) { + case MAC_SCSI_OLD: + MACHW_SET(MAC_SCSI_80); + break; + case MAC_SCSI_QUADRA: + case MAC_SCSI_QUADRA2: + case MAC_SCSI_QUADRA3: + MACHW_SET(MAC_SCSI_96); + if ((macintosh_config->ident == MAC_MODEL_Q900) || + (macintosh_config->ident == MAC_MODEL_Q950)) + MACHW_SET(MAC_SCSI_96_2); + break; + default: + printk("config.c: wtf: unknown scsi, using 53c80\n"); + MACHW_SET(MAC_SCSI_80); + break; + + } + } @@ -567,6 +585,12 @@ void mac_report_hardware(void) printk("Apple Macintosh %s\n", macintosh_config->name); } +static void mac_get_model(char *str) +{ + strcpy(str,"Macintosh "); + strcat(str, macintosh_config->name); +} + /* * Local variables: * c-indent-level: 4 diff --git a/arch/m68k/mac/debug.c b/arch/m68k/mac/debug.c index cc6f491fb..6fc3ac52d 100644 --- a/arch/m68k/mac/debug.c +++ b/arch/m68k/mac/debug.c @@ -16,6 +16,7 @@ #include <linux/config.h> #include <linux/types.h> +#include <linux/sched.h> #include <linux/tty.h> #include <linux/console.h> #include <linux/init.h> @@ -35,6 +36,9 @@ extern unsigned long mac_videobase; extern unsigned long mac_videodepth; extern unsigned long mac_rowbytes; +#define DEBUG_SCREEN +#define DEBUG_SERIAL + /* * These two auxiliary debug functions should go away ASAP. Only usage: * before the console output is up (after head.S come some other crucial @@ -45,21 +49,30 @@ extern unsigned long mac_rowbytes; * The 'pos' argument now simply means 'linefeed after print' ... */ +#ifdef DEBUG_SCREEN static int peng=0, line=0; +#endif void mac_debugging_short(int pos, short num) { +#ifdef DEBUG_SCREEN unsigned char *pengoffset; unsigned char *pptr; int i; +#endif + +#ifdef DEBUG_SERIAL + printk("debug: %d !\n", num); +#endif +#ifdef DEBUG_SCREEN if (!MACH_IS_MAC) { /* printk("debug: %d !\n", num); */ return; } /* calculate current offset */ - pengoffset=(unsigned char *)(mac_videobase+(20+line*2)*mac_rowbytes) + pengoffset=(unsigned char *)(mac_videobase+(150+line*2)*mac_rowbytes) +80*peng; pptr=pengoffset; @@ -76,20 +89,28 @@ void mac_debugging_short(int pos, short num) line++; peng = 0; } +#endif } void mac_debugging_long(int pos, long addr) { +#ifdef DEBUG_SCREEN unsigned char *pengoffset; unsigned char *pptr; int i; +#endif +#ifdef DEBUG_SERIAL + printk("debug: #%ld !\n", addr); +#endif + +#ifdef DEBUG_SCREEN if (!MACH_IS_MAC) { /* printk("debug: #%ld !\n", addr); */ return; } - pengoffset=(unsigned char *)(mac_videobase+(20+line*2)*mac_rowbytes) + pengoffset=(unsigned char *)(mac_videobase+(150+line*2)*mac_rowbytes) +80*peng; pptr=pengoffset; @@ -105,6 +126,7 @@ void mac_debugging_long(int pos, long addr) line++; peng = 0; } +#endif } /* @@ -114,24 +136,33 @@ char that_penguin[]={ #include "that_penguin.h" }; +#ifdef DEBUG_SCREEN /* * B/W version of penguin, unfinished - any takers?? */ static char bw_penguin[]={ #include "bw_penguin.h" }; +#endif void mac_debugging_penguin(int peng) { +#ifdef DEBUG_SCREEN unsigned char *pengoffset; unsigned char *pptr; unsigned char *bwpdptr=bw_penguin; int i; +#endif +#ifdef DEBUG_SERIAL + printk("Penguin: #%d !\n", peng); +#endif + +#ifdef DEBUG_SCREEN if (!MACH_IS_MAC) return; - if (compat_boot_info.bi_mac.videodepth ==1) + if (mac_videodepth ==1) pengoffset=(unsigned char *)(mac_videobase+80*mac_rowbytes) +5*peng; else @@ -146,15 +177,19 @@ void mac_debugging_penguin(int peng) bwpdptr+=4; pptr+=mac_rowbytes; } +#endif } +#ifdef DEBUG_SCREEN /* * B/W version of flaming Mac, unfinished (see above). */ static char bw_kaboom_map[]={ #include "bw_mac.h" }; +#endif +#ifdef DEBUG_SCREEN static void mac_boom_boom(void) { static unsigned char *boomoffset=NULL; @@ -162,14 +197,21 @@ static void mac_boom_boom(void) unsigned char *bwpdptr=bw_kaboom_map; int i; +#ifdef DEBUG_SERIAL + printk("BOOM !\n"); +#endif + + if (!MACH_IS_MAC) + return; + if(!boomoffset) - if (compat_boot_info.bi_mac.videodepth == 1) { + if (mac_videodepth == 1) { boomoffset=(unsigned char *)(mac_videobase+160*mac_rowbytes); } else { boomoffset=(unsigned char *)(mac_videobase+256*mac_rowbytes); } else - if (compat_boot_info.bi_mac.videodepth == 1) + if (mac_videodepth == 1) boomoffset+=5; else boomoffset+=32; @@ -183,25 +225,43 @@ static void mac_boom_boom(void) pptr+=mac_rowbytes; } } +#endif void mac_boom(int booms) { +#ifdef DEBUG_SCREEN int i; +#endif if (!MACH_IS_MAC) return; +#ifdef DEBUG_SCREEN for(i=0;i<booms;i++) mac_boom_boom(); while(1); +#endif } -#if 0 +#ifdef DEBUG_SERIAL /* * TODO: serial debug code */ +#define SCC_BAS (0x50F04000) +struct SCC + { + u_char cha_b_ctrl; + u_char char_dummy1; + u_char cha_a_ctrl; + u_char char_dummy2; + u_char cha_b_data; + u_char char_dummy3; + u_char cha_a_data; + }; +# define scc ((*(volatile struct SCC*)SCC_BAS)) + /* Flag that serial port is already initialized and used */ int mac_SCC_init_done = 0; /* Can be set somewhere, if a SCC master reset has already be done and should @@ -224,54 +284,113 @@ static struct console mac_console_driver = { static int scc_port; -static inline void mac_scc_out (char c) +/* Mac: loops_per_sec min. 1900000 ^= .5 us; MFPDELAY was 0.6 us*/ + +#define US 1 + +static inline void mac_sccb_out (char c) { + int i; do { - MFPDELAY(); + for( i = US; i > 0; --i ) + barrier(); } while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */ - MFPDELAY(); + for( i = US; i > 0; --i ) + barrier(); scc.cha_b_data = c; } -void mac_scc_console_write (struct console *co, const char *str, +static inline void mac_scca_out (char c) +{ + int i; + do { + for( i = US; i > 0; --i ) + barrier(); + } while (!(scc.cha_a_ctrl & 0x04)); /* wait for tx buf empty */ + for( i = US; i > 0; --i ) + barrier(); + scc.cha_a_data = c; +} + +void mac_sccb_console_write (struct console *co, const char *str, unsigned int count) { while (count--) { if (*str == '\n') - mac_scc_out( '\r' ); - mac_scc_out( *str++ ); + mac_sccb_out( '\r' ); + mac_sccb_out( *str++ ); + } +} + +void mac_scca_console_write (struct console *co, const char *str, + unsigned int count) +{ + while (count--) { + if (*str == '\n') + mac_scca_out( '\r' ); + mac_scca_out( *str++ ); } } #ifdef CONFIG_SERIAL_CONSOLE -int mac_scc_console_wait_key(struct console *co) +int mac_sccb_console_wait_key(struct console *co) { + int i; do { - MFPDELAY(); + for( i = US; i > 0; --i ) + barrier(); } while( !(scc.cha_b_ctrl & 0x01) ); /* wait for rx buf filled */ - MFPDELAY(); + for( i = US; i > 0; --i ) + barrier(); return( scc.cha_b_data ); } + +int mac_scca_console_wait_key(struct console *co) +{ + int i; + do { + for( i = US; i > 0; --i ) + barrier(); + } while( !(scc.cha_a_ctrl & 0x01) ); /* wait for rx buf filled */ + for( i = US; i > 0; --i ) + barrier(); + return( scc.cha_a_data ); +} #endif /* The following two functions do a quick'n'dirty initialization of the MFP or * SCC serial ports. They're used by the debugging interface, kgdb, and the * serial console code. */ -#define SCC_WRITE(reg,val) \ +#define SCCB_WRITE(reg,val) \ do { \ + int i; \ scc.cha_b_ctrl = (reg); \ - MFPDELAY(); \ + for( i = US; i > 0; --i ) \ + barrier(); \ scc.cha_b_ctrl = (val); \ - MFPDELAY(); \ + for( i = US; i > 0; --i ) \ + barrier(); \ + } while(0) + +#define SCCA_WRITE(reg,val) \ + do { \ + int i; \ + scc.cha_a_ctrl = (reg); \ + for( i = US; i > 0; --i ) \ + barrier(); \ + scc.cha_a_ctrl = (val); \ + for( i = US; i > 0; --i ) \ + barrier(); \ } while(0) /* loops_per_sec isn't initialized yet, so we can't use udelay(). This does a * delay of ~ 60us. */ +/* Mac: loops_per_sec min. 1900000 ^= .5 us; MFPDELAY was 0.6 us*/ #define LONG_DELAY() \ do { \ int i; \ - for( i = 100; i > 0; --i ) \ - MFPDELAY(); \ + for( i = 60*US; i > 0; --i ) \ + barrier(); \ } while(0) #ifndef CONFIG_SERIAL_CONSOLE @@ -309,30 +428,56 @@ void mac_init_scc_port( int cflag, int port ) reg3 = (cflag & CSIZE) == CS8 ? 0xc0 : 0x40; reg5 = (cflag & CSIZE) == CS8 ? 0x60 : 0x20 | 0x82 /* assert DTR/RTS */; - - (void)scc.cha_b_ctrl; /* reset reg pointer */ - SCC_WRITE( 9, 0xc0 ); /* reset */ - LONG_DELAY(); /* extra delay after WR9 access */ - SCC_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 | - 0x04 /* 1 stopbit */ | - clkmode ); - SCC_WRITE( 3, reg3 ); - SCC_WRITE( 5, reg5 ); - SCC_WRITE( 9, 0 ); /* no interrupts */ - LONG_DELAY(); /* extra delay after WR9 access */ - SCC_WRITE( 10, 0 ); /* NRZ mode */ - SCC_WRITE( 11, clksrc ); /* main clock source */ - SCC_WRITE( 12, div ); /* BRG value */ - SCC_WRITE( 13, 0 ); /* BRG high byte */ - SCC_WRITE( 14, brgsrc_table[baud] ); - SCC_WRITE( 14, brgsrc_table[baud] | (div ? 1 : 0) ); - SCC_WRITE( 3, reg3 | 1 ); - SCC_WRITE( 5, reg5 | 8 ); - + +#if 0 + if (port) { +#endif + (void)scc.cha_b_ctrl; /* reset reg pointer */ + SCCB_WRITE( 9, 0xc0 ); /* reset */ + LONG_DELAY(); /* extra delay after WR9 access */ + SCCB_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 | + 0x04 /* 1 stopbit */ | + clkmode ); + SCCB_WRITE( 3, reg3 ); + SCCB_WRITE( 5, reg5 ); + SCCB_WRITE( 9, 0 ); /* no interrupts */ + LONG_DELAY(); /* extra delay after WR9 access */ + SCCB_WRITE( 10, 0 ); /* NRZ mode */ + SCCB_WRITE( 11, clksrc ); /* main clock source */ + SCCB_WRITE( 12, div ); /* BRG value */ + SCCB_WRITE( 13, 0 ); /* BRG high byte */ + SCCB_WRITE( 14, brgsrc_table[baud] ); + SCCB_WRITE( 14, brgsrc_table[baud] | (div ? 1 : 0) ); + SCCB_WRITE( 3, reg3 | 1 ); + SCCB_WRITE( 5, reg5 | 8 ); +#if 0 + } else { +#endif + (void)scc.cha_a_ctrl; /* reset reg pointer */ + SCCA_WRITE( 9, 0xc0 ); /* reset */ + LONG_DELAY(); /* extra delay after WR9 access */ + SCCA_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 | + 0x04 /* 1 stopbit */ | + clkmode ); + SCCA_WRITE( 3, reg3 ); + SCCA_WRITE( 5, reg5 ); + SCCA_WRITE( 9, 0 ); /* no interrupts */ + LONG_DELAY(); /* extra delay after WR9 access */ + SCCA_WRITE( 10, 0 ); /* NRZ mode */ + SCCA_WRITE( 11, clksrc ); /* main clock source */ + SCCA_WRITE( 12, div ); /* BRG value */ + SCCA_WRITE( 13, 0 ); /* BRG high byte */ + SCCA_WRITE( 14, brgsrc_table[baud] ); + SCCA_WRITE( 14, brgsrc_table[baud] | (div ? 1 : 0) ); + SCCA_WRITE( 3, reg3 | 1 ); + SCCA_WRITE( 5, reg5 | 8 ); +#if 0 + } +#endif mac_SCC_reset_done = 1; mac_SCC_init_done = 1; } - +#endif /* DEBUG_SERIAL */ __initfunc(void mac_debug_init(void)) { @@ -340,23 +485,24 @@ __initfunc(void mac_debug_init(void)) /* the m68k_debug_device is used by the GDB stub, do nothing here */ return; #endif +#ifdef DEBUG_SERIAL if (!strcmp( m68k_debug_device, "ser" )) { strcpy( m68k_debug_device, "ser1" ); } if (!strcmp( m68k_debug_device, "ser1" )) { /* ST-MFP Modem1 serial port */ mac_init_scc_port( B9600|CS8, 0 ); - mac_console_driver.write = mac_scc_console_write; + mac_console_driver.write = mac_scca_console_write; } else if (!strcmp( m68k_debug_device, "ser2" )) { /* SCC Modem2 serial port */ mac_init_scc_port( B9600|CS8, 1 ); - mac_console_driver.write = mac_scc_console_write; + mac_console_driver.write = mac_sccb_console_write; } if (mac_console_driver.write) register_console(&mac_console_driver); -} #endif +} /* * Local variables: diff --git a/arch/m68k/mac/ksyms.c b/arch/m68k/mac/mac_ksyms.c index 05373b04e..05373b04e 100644 --- a/arch/m68k/mac/ksyms.c +++ b/arch/m68k/mac/mac_ksyms.c diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c index b9c3331e9..d2ea26e05 100644 --- a/arch/m68k/mac/macints.c +++ b/arch/m68k/mac/macints.c @@ -28,6 +28,12 @@ * * 7 - Debug output * + * AV Macs only, handled by PSC: + * + * 3 - MACE ethernet IRQ (DMA complete on level 4) + * + * 5 - DSP ?? + * * Using the autovector irq numbers for Linux/m68k hardware interrupts without * the IRQ_MACHSPEC bit set would interfere with the general m68k interrupt * handling in kernel versions 2.0.x, so the following strategy is used: @@ -57,13 +63,19 @@ * should be sufficient to use the same numbers (everything > 7 is assumed * to be machspec, according to Jes!). * + * TODO: + * - integrate Nubus interrupts in request/free_irq + * + * - */ +#include <linux/config.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/kernel_stat.h> #include <linux/interrupt.h> /* for intr_count */ +#include <linux/delay.h> #include <asm/system.h> #include <asm/irq.h> @@ -98,7 +110,10 @@ struct irqflags { static struct irqhandler via1_handler[8]; static struct irqhandler via2_handler[8]; static struct irqhandler rbv_handler[8]; +static struct irqhandler psc3_handler[8]; static struct irqhandler scc_handler[8]; +static struct irqhandler psc5_handler[8]; +static struct irqhandler psc6_handler[8]; static struct irqhandler nubus_handler[8]; static struct irqhandler *handler_table[8]; @@ -111,7 +126,10 @@ static struct irqhandler *handler_table[8]; static struct irqparam via1_param[8]; static struct irqparam via2_param[8]; static struct irqparam rbv_param[8]; +static struct irqparam psc3_param[8]; static struct irqparam scc_param[8]; +static struct irqparam psc5_param[8]; +static struct irqparam psc6_param[8]; static struct irqparam nubus_param[8]; static struct irqparam *param_table[8]; @@ -125,27 +143,57 @@ static struct irqflags irq_flags[8]; /* * This array holds the pointers to the various VIA or other interrupt - * controllers + * controllers, indexed by interrupt level */ static volatile unsigned char *via_table[8]; -#ifdef VIABASE_WEIRDNESS /* - * VIA2 / RBV default base address + * Arrays with irq statistics */ +static unsigned long via1_irqs[8]; +static unsigned long via2_irqs[8]; +static unsigned long rbv_irqs[8]; +static unsigned long psc3_irqs[8]; +static unsigned long scc_irqs[8]; +static unsigned long psc5_irqs[8]; +static unsigned long psc6_irqs[8]; +static unsigned long nubus_irqs[8]; -volatile unsigned char *via2_regp = ((volatile unsigned char *)VIA2_BAS); -volatile unsigned char *rbv_regp = ((volatile unsigned char *)VIA2_BAS_IIci); -#endif +static unsigned long *mac_irqs[8]; + +/* + * VIA2 / RBV register base pointers + */ + +volatile unsigned char *via2_regp=(volatile unsigned char *)VIA2_BAS; +volatile unsigned char *rbv_regp=(volatile unsigned char *)VIA2_BAS_IIci; +volatile unsigned char *oss_regp=(volatile unsigned char *)OSS_BAS; +volatile unsigned char *psc_regp=(volatile unsigned char *)PSC_BAS; /* * Flags to control via2 / rbv behaviour */ static int via2_is_rbv = 0; +static int via2_is_oss = 0; static int rbv_clear = 0; +/* fake VIA2 to OSS bit mapping */ +static int oss_map[8] = {2, 7, 0, 1, 3, 4, 5}; + +void oss_irq(int irq, void *dev_id, struct pt_regs *regs); +static void oss_do_nubus(int irq, void *dev_id, struct pt_regs *regs); + +/* PSC ints */ +void psc_irq(int irq, void *dev_id, struct pt_regs *regs); + +/* + * PSC hooks + */ + +extern void psc_init(void); + /* * console_loglevel determines NMI handler function */ @@ -174,11 +222,13 @@ void mac_init_IRQ(void) { int i; - mac_debugging_penguin(6); - #ifdef DEBUG_MACINTS printk("Mac interrupt stuff initializing ...\n"); #endif + + via2_regp = (unsigned char *)VIA2_BAS; + rbv_regp = (unsigned char *)VIA2_BAS_IIci; + /* initialize the hardwired (primary, autovector) IRQs */ /* level 1 IRQ: VIA1, always present */ @@ -186,17 +236,33 @@ void mac_init_IRQ(void) /* via2 or rbv?? */ if (macintosh_config->via_type == MAC_VIA_IIci) { - /* VIA2 is part of the RBV: different base, other offsets */ - via2_is_rbv = 1; - /* LC III weirdness: IFR seems to behave like VIA2 */ - /* FIXME: maybe also for LC II ?? */ - if (macintosh_config->ident == MAC_MODEL_LCIII) { - rbv_clear = 0x0; + /* + * A word of caution: the definitions here only affect interrupt + * handling, see via6522.c for yet another file to change + * base addresses and RBV flags + */ + + /* yes, this is messy - the IIfx deserves a class of his own */ + if (macintosh_config->ident == MAC_MODEL_IIFX) { + /* no real VIA2, the OSS seems _very_different */ + via2_is_oss = 1; + /* IIfx has OSS, at a different base address than RBV */ + rbv_regp = (unsigned char *) OSS_BAS; + sys_request_irq(2, oss_irq, IRQ_FLG_LOCK, "oss", oss_irq); } else { - rbv_clear = 0x80; + /* VIA2 is part of the RBV: different base, other offsets */ + via2_is_rbv = 1; + + /* LC III weirdness: IFR seems to behave like VIA2 */ + /* FIXME: maybe also for LC II ?? */ + if (macintosh_config->ident == MAC_MODEL_LCIII) { + rbv_clear = 0x0; + } else { + rbv_clear = 0x80; + } + /* level 2 IRQ: RBV/OSS; we only care about RBV for now */ + sys_request_irq(2, rbv_irq, IRQ_FLG_LOCK, "rbv", rbv_irq); } - /* level 2 IRQ: RBV/OSS; we only care about RBV for now */ - sys_request_irq(2, rbv_irq, IRQ_FLG_LOCK, "rbv", rbv_irq); } else /* level 2 IRQ: VIA2 */ sys_request_irq(2, via2_irq, IRQ_FLG_LOCK, "via2", via2_irq); @@ -207,7 +273,7 @@ void mac_init_IRQ(void) * Currently, one interrupt per channel is used, solely * to pass the correct async_info as parameter! */ -#if 0 /* doesn't seem to work yet */ +#if 0 /* want to install debug/SCC shutup routine until SCC init */ sys_request_irq(4, mac_SCC_handler, IRQ_FLG_STD, "INT4", mac_SCC_handler); #else sys_request_irq(4, mac_debug_handler, IRQ_FLG_STD, "INT4", mac_debug_handler); @@ -255,26 +321,65 @@ void mac_init_IRQ(void) via_table[0] = via1_regp; handler_table[0] = &via1_handler[0]; param_table[0] = &via1_param[0]; + mac_irqs[0] = &via1_irqs[0]; - if (via2_is_rbv) { + if (via2_is_rbv || via2_is_oss) { via_table[1] = rbv_regp; handler_table[1] = &rbv_handler[0]; param_table[1] = &rbv_param[0]; + mac_irqs[1] = &rbv_irqs[0]; } else { via_table[1] = via2_regp; handler_table[1] = &via2_handler[0]; param_table[1] = &via2_param[0]; + mac_irqs[1] = &via2_irqs[0]; } via_table[2] = NULL; via_table[3] = NULL; handler_table[2] = &rbv_handler[0]; - handler_table[3] = &nubus_handler[0]; + handler_table[3] = &scc_handler[0]; + handler_table[4] = NULL; + handler_table[5] = NULL; + handler_table[6] = NULL; + handler_table[7] = &nubus_handler[0]; param_table[2] = &rbv_param[0]; - param_table[3] = &nubus_param[0]; + param_table[3] = &scc_param[0]; + param_table[7] = &nubus_param[0]; + + mac_irqs[2] = &rbv_irqs[0]; + mac_irqs[3] = &scc_irqs[0]; + mac_irqs[7] = &nubus_irqs[0]; + + /* + * AV Macs: shutup the PSC ints + */ + if (macintosh_config->ident == MAC_MODEL_C660 + || macintosh_config->ident == MAC_MODEL_Q840) { + psc_init(); + + handler_table[2] = &psc3_handler[0]; + /* handler_table[3] = &psc4_handler[0]; */ + handler_table[4] = &psc5_handler[0]; + handler_table[5] = &psc6_handler[0]; + + param_table[2] = &psc3_param[0]; + /* param_table[3] = &psc4_param[0]; */ + param_table[4] = &psc5_param[0]; + param_table[5] = &psc6_param[0]; + + mac_irqs[2] = &psc3_irqs[0]; + /* mac_irqs[3] = &psc4_irqs[0]; */ + mac_irqs[4] = &psc5_irqs[0]; + mac_irqs[5] = &psc6_irqs[0]; + + sys_request_irq(3, psc_irq, IRQ_FLG_STD, "PSC3", psc_irq); + sys_request_irq(4, psc_irq, IRQ_FLG_STD, "PSC4", psc_irq); + sys_request_irq(5, psc_irq, IRQ_FLG_STD, "PSC5", psc_irq); + sys_request_irq(6, psc_irq, IRQ_FLG_STD, "PSC6", psc_irq); + } - mac_debugging_penguin(7); #ifdef DEBUG_MACINTS printk("Mac interrupt init done!\n"); #endif @@ -284,7 +389,7 @@ void mac_init_IRQ(void) * We have no machine specific interrupts on a macintoy * Yet, we need to register/unregister interrupts ... :-) * Currently unimplemented: Test for valid irq number, chained irqs, - * Nubus interrupts. + * Nubus interrupts (use nubus_request_irq!). */ int mac_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *), @@ -315,8 +420,8 @@ int mac_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_re return -EINVAL; } - /* figure out if SCC pseudo-irq */ - if (irq >= IRQ_IDX(IRQ_SCC) && irq < IRQ_IDX(IRQ_NUBUS_1)) { + /* figure out if SCC pseudo-irq (redundant ??) */ + if (irq >= IRQ_IDX(IRQ_SCC) && irq < IRQ_IDX(IRQ_PSC5_0)) { /* set specific SCC handler */ scc_handler[irqidx].handler = handler; scc_handler[irqidx].dev_id = dev_id; @@ -326,6 +431,8 @@ int mac_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_re return 0; } + /* add similar hack for Nubus pseudo-irq here - hide nubus_request_irq */ + via = (volatile unsigned char *) via_table[srcidx]; if (!via) return -EINVAL; @@ -341,9 +448,11 @@ int mac_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_re via_param[irqidx].flags = flags; via_param[irqidx].devname = devname; - /* and turn it on ... */ + /* and turn it on ... careful, that's VIA only ... */ if (srcidx == SRC_VIA2 && via2_is_rbv) via_write(via, rIER, via_read(via, rIER)|0x80|(1<<(irqidx))); + else if (srcidx == SRC_VIA2 && via2_is_oss) + via_write(oss_regp, oss_map[irqidx]+8, 2); else via_write(via, vIER, via_read(via, vIER)|0x80|(1<<(irqidx))); @@ -351,8 +460,18 @@ int mac_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_re if (irq == IRQ_IDX(IRQ_MAC_SCSI)) { /* * Set vPCR for SCSI interrupts. (what about RBV here?) + * 980429 MS: RBV is ok, OSS seems to be differentt */ - via_write(via, vPCR, 0x66); + if (!via2_is_oss) + /* CB2 (IRQ) indep. interrupt input, positive edge */ + /* CA2 (DRQ) indep. interrupt input, positive edge */ + via_write(via, vPCR, 0x66); +#if 0 + else + /* CB2 (IRQ) indep. interrupt input, negative edge */ + /* CA2 (DRQ) indep. interrupt input, negative edge */ + via_write(via, vPCR, 0x22); +#endif } return 0; @@ -382,7 +501,7 @@ void mac_free_irq (unsigned int irq, void *dev_id) cli(); /* figure out if SCC pseudo-irq */ - if (irq >= IRQ_IDX(IRQ_SCC) && irq < IRQ_IDX(IRQ_NUBUS_1)) { + if (irq >= IRQ_IDX(IRQ_SCC) && irq < IRQ_IDX(IRQ_PSC5_0)) { /* clear specific SCC handler */ scc_handler[irqidx].handler = mac_default_handler; scc_handler[irqidx].dev_id = NULL; @@ -411,6 +530,8 @@ void mac_free_irq (unsigned int irq, void *dev_id) /* and turn it off */ if (srcidx == SRC_VIA2 && via2_is_rbv) via_write(via, rIER, (via_read(via, rIER)&(1<<irqidx))); + else if (srcidx == SRC_VIA2 && via2_is_oss) + via_write(oss_regp, oss_map[irqidx]+8, 0); else via_write(via, vIER, (via_read(via, vIER)&(1<<irqidx))); @@ -453,8 +574,8 @@ not_found: void mac_enable_irq (unsigned int irq) { - int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; - int irqidx = (irq & IRQ_IDX_MASK); + int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; + int irqidx = (irq & IRQ_IDX_MASK); irq_flags[srcidx].disabled &= ~(1<<irqidx); /* @@ -468,8 +589,8 @@ void mac_enable_irq (unsigned int irq) void mac_disable_irq (unsigned int irq) { - int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; - int irqidx = (irq & IRQ_IDX_MASK); + int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; + int irqidx = (irq & IRQ_IDX_MASK); irq_flags[srcidx].disabled |= (1<<irqidx); } @@ -481,8 +602,8 @@ void mac_disable_irq (unsigned int irq) void mac_turnon_irq( unsigned int irq ) { - int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; - int irqidx = (irq & IRQ_IDX_MASK); + int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; + int irqidx = (irq & IRQ_IDX_MASK); volatile unsigned char *via; via = (volatile unsigned char *) via_table[srcidx]; @@ -491,6 +612,11 @@ void mac_turnon_irq( unsigned int irq ) if (srcidx == SRC_VIA2 && via2_is_rbv) via_write(via, rIER, via_read(via, rIER)|0x80|(1<<(irqidx))); + else if (srcidx == SRC_VIA2 && via2_is_oss) + via_write(oss_regp, oss_map[irqidx]+8, 2); + else if (srcidx >= SRC_VIA2) + via_write(via, (0x104 + 0x10*srcidx), + via_read(via, (0x104 + 0x10*srcidx))|0x80|(1<<(irqidx))); else via_write(via, vIER, via_read(via, vIER)|0x80|(1<<(irqidx))); @@ -498,8 +624,8 @@ void mac_turnon_irq( unsigned int irq ) void mac_turnoff_irq( unsigned int irq ) { - int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; - int irqidx = (irq & IRQ_IDX_MASK); + int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; + int irqidx = (irq & IRQ_IDX_MASK); volatile unsigned char *via; via = (volatile unsigned char *) via_table[srcidx]; @@ -508,6 +634,11 @@ void mac_turnoff_irq( unsigned int irq ) if (srcidx == SRC_VIA2 && via2_is_rbv) via_write(via, rIER, (via_read(via, rIER)&(1<<irqidx))); + else if (srcidx == SRC_VIA2 && via2_is_oss) + via_write(oss_regp, oss_map[irqidx]+8, 0); + else if (srcidx >= SRC_VIA2) + via_write(via, (0x104 + 0x10*srcidx), + via_read(via, (0x104 + 0x10*srcidx))|(1<<(irqidx))); else via_write(via, vIER, (via_read(via, vIER)&(1<<irqidx))); } @@ -522,23 +653,109 @@ void mac_turnoff_irq( unsigned int irq ) void mac_clear_pending_irq( unsigned int irq ) { - int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; - int irqidx = (irq & IRQ_IDX_MASK); + int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; + int irqidx = (irq & IRQ_IDX_MASK); irq_flags[srcidx].pending &= ~(1<<irqidx); } int mac_irq_pending( unsigned int irq ) { - int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; - int irqidx = (irq & IRQ_IDX_MASK); + int pending = 0; + volatile unsigned char *via; + + int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; + int irqidx = (irq & IRQ_IDX_MASK); - return (irq_flags[srcidx].pending & (1<<irqidx)); + pending = irq_flags[srcidx].pending & (1<<irqidx); + + via = (volatile unsigned char *) via_table[srcidx]; + if (!via) + return (pending); + + if (srcidx == SRC_VIA2 && via2_is_rbv) + pending |= via_read(via, rIFR)&(1<<irqidx); + else if (srcidx == SRC_VIA2 && via2_is_oss) + pending |= via_read(via, oIFR)&0x03&(1<<oss_map[irqidx]); + else if (srcidx >= SRC_VIA2) + pending |= via_read(via, (0x100 + 0x10*srcidx))&(1<<irqidx); + else + pending |= via_read(via, vIFR)&(1<<irqidx); + + return (pending); } int mac_get_irq_list (char *buf) { - return 0; + int i, len = 0; + int srcidx, irqidx; + + for (i = VIA1_SOURCE_BASE; i < NUM_MAC_SOURCES+8; ++i) { + srcidx = ((i & IRQ_SRC_MASK)>>3) - 1; + irqidx = (i & IRQ_IDX_MASK); + + /* + * Not present: skip + */ + + if (mac_irqs[srcidx] == NULL) + continue; + + /* + * never used by VIAs, unused by others so far, counts + * the magic 'nothing pending' cases ... + */ + if (irqidx == 7 && mac_irqs[srcidx][irqidx]) { + len += sprintf(buf+len, "Level %01d: %10lu (spurious) \n", + srcidx, + mac_irqs[srcidx][irqidx]); + continue; + } + + /* + * Nothing registered for this IPL: skip + */ + + if (handler_table[srcidx] == NULL) + continue; + + /* + * No handler installed: skip + */ + + if (handler_table[srcidx][irqidx].handler == mac_default_handler || + handler_table[srcidx][irqidx].handler == nubus_wtf) + continue; + + + if (i < VIA2_SOURCE_BASE) + len += sprintf(buf+len, "via1 %01d: %10lu ", + irqidx, + mac_irqs[srcidx][irqidx]); + else if (i < RBV_SOURCE_BASE) + len += sprintf(buf+len, "via2 %01d: %10lu ", + irqidx, + mac_irqs[srcidx][irqidx]); + else if (i < MAC_SCC_SOURCE_BASE) + len += sprintf(buf+len, "rbv %01d: %10lu ", + irqidx, + mac_irqs[srcidx][irqidx]); + else if (i < NUBUS_SOURCE_BASE) + len += sprintf(buf+len, "scc %01d: %10lu ", + irqidx, + mac_irqs[srcidx][irqidx]); + else /* Nubus */ + len += sprintf(buf+len, "nubus %01d: %10lu ", + irqidx, + mac_irqs[srcidx][irqidx]); + + len += sprintf(buf+len, "%s\n", + param_table[srcidx][irqidx].devname); + + } + if (num_spurious) + len += sprintf(buf+len, "spurio.: %10u\n", num_spurious); + return len; } void via_scsi_clear(void) @@ -547,6 +764,9 @@ void via_scsi_clear(void) if (via2_is_rbv) { via_write(rbv_regp, rIFR, (1<<3)|(1<<0)|0x80); deep_magic = via_read(rbv_regp, rBufB); + } else if (via2_is_oss) { + /* nothing */ + /* via_write(oss_regp, 9, 0) */; } else deep_magic = via_read(via2_regp, vBufB); mac_enable_irq( IRQ_IDX(IRQ_MAC_SCSI) ); @@ -570,12 +790,45 @@ void mac_debug_handler(int irq, void *dev_id, struct pt_regs *regs) } } +void scsi_mac_debug(void); +void scsi_mac_polled(void); + +static int in_nmi = 0; +static volatile int nmi_hold = 0; + void mac_nmi_handler(int irq, void *dev_id, struct pt_regs *fp) { + int i; /* * generate debug output on NMI switch if 'debug' kernel option given * (only works with Penguin!) */ + + in_nmi++; +#if 0 + scsi_mac_debug(); + printk("PC: %08lx\nSR: %04x SP: %p\n", fp->pc, fp->sr, fp); +#endif + for (i=0; i<100; i++) + udelay(1000); + + if (in_nmi == 1) { + nmi_hold = 1; + printk("... pausing, press NMI to resume ..."); + } else { + printk(" ok!\n"); + nmi_hold = 0; + } + + barrier(); + + while (nmi_hold == 1) + udelay(1000); + +#if 0 + scsi_mac_polled(); +#endif + if ( console_loglevel >= 8 ) { #if 0 show_state(); @@ -595,6 +848,7 @@ void mac_nmi_handler(int irq, void *dev_id, struct pt_regs *fp) /* printk("NMI "); */ #endif } + in_nmi--; } /* @@ -610,6 +864,7 @@ static void via_irq(unsigned char *via, int *viaidx, struct pt_regs *regs) int ct = 0; struct irqhandler *via_handler = handler_table[*viaidx]; struct irqparam *via_param = param_table[*viaidx]; + unsigned long *via_irqs = mac_irqs[*viaidx]; /* to be changed, possibly: for each non'masked', enabled IRQ, read * flag bit, ack and call handler ... @@ -626,7 +881,12 @@ static void via_irq(unsigned char *via, int *viaidx, struct pt_regs *regs) if(events==0) { - printk("via_irq: nothing pending!\n"); +#ifdef DEBUG_VIA + /* should go away; mostly missing timer ticks and ADB events */ + printk("via%d_irq: nothing pending, flags %x mask %x!\n", + *viaidx + 1, via_read(via, vIFR), via_read(via,vIER)); +#endif + via_irqs[7]++; return; } @@ -661,9 +921,12 @@ static void via_irq(unsigned char *via, int *viaidx, struct pt_regs *regs) /* call corresponding handlers */ if (events&(1<<i)) { if (irq_flags[*viaidx].disabled & (1<<i)) { + if (!irq_flags[*viaidx].pending&(1<<i)) + via_irqs[i]++; /* irq disabled -> mark pending */ irq_flags[*viaidx].pending |= (1<<i); } else { + via_irqs[i]++; /* irq enabled -> call handler */ (via_handler[i].handler)(irq, via, regs); } @@ -686,7 +949,9 @@ static void via_irq(unsigned char *via, int *viaidx, struct pt_regs *regs) ct++; if(events && ct>8) { +#ifdef DEBUG_VIA printk("via%d: stuck events %x\n", (*viaidx)+1, events); +#endif break; } } @@ -743,6 +1008,23 @@ void rbv_irq(int irq, void *dev_id, struct pt_regs *regs) struct irqhandler *via_handler = handler_table[srcidx]; struct irqparam *via_param = param_table[srcidx]; + /* shouldn't we disable interrupts here ?? */ + + + /* + * Shouldnt happen + */ + + if(events==0) + { +#ifdef DEBUG_VIA + printk("rbv_irq: nothing pending, flags %x mask %x!\n", + via_read(via, rIFR), via_read(via,rIER)); +#endif + rbv_irqs[7]++; + return; + } + #ifdef DEBUG_VIA /* * limited verbosity for RBV interrupts (add more if needed) @@ -757,19 +1039,6 @@ void rbv_irq(int irq, void *dev_id, struct pt_regs *regs) * If ack for masked IRQ required: keep 'pending' info separate. */ - /* shouldn't we disable interrupts here ?? */ - - - /* - * Shouldnt happen - */ - - if(events==0) - { - printk("rbv_irq: nothing pending!\n"); - return; - } - do { /* * Clear the pending flag @@ -787,12 +1056,16 @@ void rbv_irq(int irq, void *dev_id, struct pt_regs *regs) int irq = (srcidx+1)* 8 + i; /* call corresponding handlers */ if (events&(1<<i)) { - if (irq_flags[srcidx].disabled & (1<<i)) + if (irq_flags[srcidx].disabled & (1<<i)) { + if (!irq_flags[srcidx].pending&(1<<i)) + rbv_irqs[i]++; /* irq disabled -> mark pending */ irq_flags[srcidx].pending |= (1<<i); - else + } else { + rbv_irqs[i]++; /* irq enabled -> call handler */ (via_handler[i].handler)(irq, via, regs); + } } /* and call handlers for pending irqs - first ?? */ if ( (irq_flags[srcidx].pending & (1<<i)) @@ -803,7 +1076,7 @@ void rbv_irq(int irq, void *dev_id, struct pt_regs *regs) irq_flags[srcidx].pending &= ~(1<<i); } } - + /* * And done ... check for more punishment! */ @@ -843,24 +1116,277 @@ void via_wtf(int slot, void *via, struct pt_regs *regs) #endif } +/* + * Nubus / SCSI interrupts; OSS style + * The OSS is even more different than the RBV. OSS appears to stand for + * Obscenely Screwed Silicon ... + * + * Latest NetBSD sources suggest the OSS should behave like a RBV, but + * that's probably true for the 0x203 offset (Nubus/ADB-SWIM IOP) at best + */ + +void oss_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + int srcidx = IRQ_IDX(irq) - 1; /* MUST be 1 !! */ + volatile unsigned char *via = oss_regp; + unsigned char events=(via_read(via, oIFR))&0x03; + unsigned char nub_ev=(via_read(via, nIFR))&0x4F; + unsigned char adb_ev; + int i; + int ct = 0; + struct irqhandler *via_handler = handler_table[srcidx]; + struct irqparam *via_param = param_table[srcidx]; + + /* shouldn't we disable interrupts here ?? */ + + adb_ev = nub_ev & 0x40; + nub_ev &= 0x3F; + + /* + * Shouldnt happen + */ + + if (events==0 && adb_ev==0 && nub_ev==0) + { + printk("oss_irq: nothing pending, flags %x %x!\n", + via_read(via, oIFR), via_read(via, nIFR)); + rbv_irqs[7]++; + return; + } + +#ifdef DEBUG_VIA + /* + * limited verbosity for RBV interrupts (add more if needed) + */ + if ( events != 1<<3 ) /* SCSI IRQ */ + printk("oss_irq: irq %d events %x %x %x !\n", irq, srcidx+1, + events, adb_ev, nub_ev); +#endif + + /* + * OSS priorities: call ADB handler first if registered, other events, + * then Nubus + * ADB: yet to be implemented! + */ + + /* + * ADB: try to shutup the IOP + */ + if (adb_ev) { + printk("Hands off ! Don't press this button ever again !!!\n"); + via_write(via, 6, 0); + } + + do { + /* + * Clear the pending flags + * How exactly is that supposed to work ?? + */ + + /* + * Now see what bits are raised + */ + + for(i=0;i<7;i++) + { + /* HACK HACK: map to bit number in OSS register */ + int irqidx = oss_map[i]; + /* determine machspec. irq no. */ + int irq = (srcidx+1)* 8 + i; + /* call corresponding handlers */ + if ( (events&(1<<irqidx)) && /* bit set*/ + (via_read(via, irqidx+8)&0x7) ) { /* irq enabled */ + if (irq_flags[srcidx].disabled & (1<<i)) { + if (!irq_flags[srcidx].pending&(1<<i)) + rbv_irqs[i]++; + /* irq disabled -> mark pending */ + irq_flags[srcidx].pending |= (1<<i); + } else { + rbv_irqs[i]++; + /* irq enabled -> call handler */ + (via_handler[i].handler)(irq, via, regs); + } + } + /* and call handlers for pending irqs - first ?? */ + if ( (irq_flags[srcidx].pending & (1<<i)) + && !(irq_flags[srcidx].disabled & (1<<i)) ) { + /* call handler for re-enabled irq */ + (via_handler[i].handler)(irq, via, regs); + /* and clear pending flag :-) */ + irq_flags[srcidx].pending &= ~(1<<i); + } + } + + /* + * And done ... check for more punishment! + */ + + events=(via_read(via, oIFR)/*&via_read(via,rIER)*/)&0x03; + ct++; + if(events && ct>8) + { + printk("oss: stuck events %x\n",events); + for(i=0;i<7;i++) + { + if(events&(1<<i)) + { + printk("oss - bashing source %d\n", + i); + /* that should disable it */ + via_write(via, 8+i, 0); + } + } + break; + } + } + while(events); +#if 0 + scsi_mac_polled(); +#endif + + if (nub_ev) + oss_do_nubus(irq, via, regs); + +} + +/* + * Unexpected slot interrupt + */ + void nubus_wtf(int slot, void *via, struct pt_regs *regs) { -#ifdef DEBUG_VIA +#ifdef DEBUG_VIA_NUBUS printk("Unexpected interrupt on nubus slot %d\n",slot); #endif } +/* + * SCC master interrupt handler; sole purpose: pass the registered + * async struct to the SCC handler proper. + */ + void mac_SCC_handler(int irq, void *dev_id, struct pt_regs *regs) { int i; - - for (i = 0; i < 8; i++) + /* 1+2: compatibility with PSC ! */ + for (i = 1; i < 3; i++) /* currently only these two used */ if (scc_handler[i].handler != mac_default_handler) (scc_handler[i].handler)(i, scc_handler[i].dev_id, regs); } /* + * PSC interrupt handler + */ + +void psc_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + int srcidx = IRQ_IDX(irq) - 1; + volatile unsigned char *via = psc_regp; + unsigned int pIFR = 0x100 + 0x10*srcidx; + unsigned int pIER = 0x104 + 0x10*srcidx; + unsigned char events=(via_read(via, pIFR)&via_read(via,pIER))&0xF; + int i; + int ct = 0; + struct irqhandler *via_handler = handler_table[srcidx]; + struct irqparam *via_param = param_table[srcidx]; + + /* shouldn't we disable interrupts here ?? */ + + + /* + * Shouldnt happen + */ + + if(events==0) + { +#ifdef DEBUG_VIA + printk("rbv_irq: nothing pending, flags %x mask %x!\n", + via_read(via, pIFR), via_read(via,pIER)); +#endif + mac_irqs[srcidx][7]++; + return; + } + +#ifdef DEBUG_VIA + /* + * limited verbosity for RBV interrupts (add more if needed) + */ + if ( srcidx == 1 && events != 1<<3 && events != 1<<1 ) /* SCSI IRQ */ + printk("psc_irq: irq %d events %x !\n", irq, srcidx+1, events); +#endif + + /* to be changed, possibly: for each non'masked', enabled IRQ, read + * flag bit, ack and call handler ... + * Currently: all pending irqs ack'ed en bloc. + * If ack for masked IRQ required: keep 'pending' info separate. + */ + + do { + /* + * Clear the pending flag + */ + + /* via_write(via, pIFR, events); */ + + /* + * Now see what bits are raised + */ + + for(i=0;i<7;i++) + { + /* determine machspec. irq no. */ + int irq = (srcidx+1)* 8 + i; + /* call corresponding handlers */ + if (events&(1<<i)) { + if (irq_flags[srcidx].disabled & (1<<i)) { + if (!irq_flags[srcidx].pending&(1<<i)) + mac_irqs[srcidx][i]++; + /* irq disabled -> mark pending */ + irq_flags[srcidx].pending |= (1<<i); + } else { + mac_irqs[srcidx][i]++; + /* irq enabled -> call handler */ + (via_handler[i].handler)(irq, via, regs); + } + } + /* and call handlers for pending irqs - first ?? */ + if ( (irq_flags[srcidx].pending & (1<<i)) + && !(irq_flags[srcidx].disabled & (1<<i)) ) { + /* call handler for re-enabled irq */ + (via_handler[i].handler)(irq, via, regs); + /* and clear pending flag :-) */ + irq_flags[srcidx].pending &= ~(1<<i); + } + } + + /* + * And done ... check for more punishment! + */ + + events=(via_read(via,pIFR)&via_read(via,pIER))&0x7F; + ct++; + if(events && ct>8) + { + printk("psc: stuck events %x\n",events); + for(i=0;i<7;i++) + { + if(events&(1<<i)) + { + printk("psc - bashing source %d\n", + i); + via_write(via, pIER, 1<<i); + /* via_write(via, pIFR, (1<<i)); */ + } + } + break; + } + } + while(events); +} + + +/* * Nubus handling * Caution: slot numbers are currently 'hardcoded' to the range 9-15! * In general, the same request_irq() functions as above can be used if @@ -869,25 +1395,26 @@ void mac_SCC_handler(int irq, void *dev_id, struct pt_regs *regs) static int nubus_active=0; -int nubus_request_irq(int slot, void (*handler)(int,void *,struct pt_regs *)) +int nubus_request_irq(int slot, void *dev_id, void (*handler)(int,void *,struct pt_regs *)) { slot-=9; /* printk("Nubus request irq for slot %d\n",slot);*/ if(nubus_handler[slot].handler!=nubus_wtf) return -EBUSY; nubus_handler[slot].handler=handler; - nubus_handler[slot].dev_id =handler; + nubus_handler[slot].dev_id =dev_id; nubus_param[slot].flags = IRQ_FLG_LOCK; - nubus_param[slot].devname = "nubus"; + nubus_param[slot].devname = "nubus slot"; /* * if no nubus int. was active previously: register the main nubus irq * handler now! */ - if (!nubus_active) - request_irq(IRQ_MAC_NUBUS, via_do_nubus, IRQ_FLG_LOCK, - "nubus dispatch", via_do_nubus); + if (!nubus_active && !via2_is_oss) { + request_irq(IRQ_MAC_NUBUS, via_do_nubus, IRQ_FLG_LOCK, + "nubus dispatch", via_do_nubus); + } nubus_active|=1<<slot; /* printk("program slot %d\n",slot);*/ @@ -897,7 +1424,9 @@ int nubus_request_irq(int slot, void (*handler)(int,void *,struct pt_regs *)) via_read(via2, vDirA)|(1<<slot)); via_write(via2, vBufA, 0); #endif - if (!via2_is_rbv) { + if (via2_is_oss) + via_write(oss_regp, slot, 2); + else if (!via2_is_rbv) { /* Make sure the bit is an input */ via_write(via2_regp, vDirA, via_read(via2_regp, vDirA)&~(1<<slot)); @@ -917,6 +1446,8 @@ int nubus_free_irq(int slot) if (via2_is_rbv) via_write(rbv_regp, rBufA, 1<<slot); + else if (via2_is_oss) + via_write(oss_regp, slot, 0); else { via_write(via2_regp, vDirA, via_read(via2_regp, vDirA)|(1<<slot)); @@ -927,6 +1458,16 @@ int nubus_free_irq(int slot) return 0; } +#ifdef CONFIG_BLK_DEV_MAC_IDE +/* + * IDE interrupt hook + */ +extern void (*mac_ide_intr_hook)(int, void *, struct pt_regs *); +#endif + +/* + * Nubus dispatch handler - VIA/RBV style + */ static void via_do_nubus(int slot, void *via, struct pt_regs *regs) { unsigned char map; @@ -941,6 +1482,14 @@ static void via_do_nubus(int slot, void *via, struct pt_regs *regs) else via_write(via2_regp, vIFR, 0x82); +#ifdef CONFIG_BLK_DEV_MAC_IDE + /* IDE hack */ + if (mac_ide_intr_hook) + /* 'slot' is lacking the machspec bit in 2.0 */ + /* need to pass proper dev_id = hwgroup here */ + mac_ide_intr_hook(IRQ_MAC_NUBUS, via, regs); +#endif + while(1) { if (via2_is_rbv) @@ -948,15 +1497,23 @@ static void via_do_nubus(int slot, void *via, struct pt_regs *regs) else map = ~via_read(via2_regp, vBufA); -#ifdef DEBUG_VIA - printk("nubus_irq: map %x mask %x\n", map, nubus_active); + if( (map = (map&nubus_active)) ==0 ) { +#ifdef DEBUG_NUBUS_INT + printk("nubus_irq: nothing pending, map %x mask %x\n", + map, nubus_active); #endif - if( (map = (map&nubus_active)) ==0 ) + nubus_irqs[7]++; break; + } +#ifdef DEBUG_NUBUS_INT + printk("nubus_irq: map %x mask %x\n", map, nubus_active); +#endif if(ct++>2) { +#ifdef DEBUG_NUBUS_INT printk("nubus stuck events - %d/%d\n", map, nubus_active); +#endif return; } @@ -964,7 +1521,8 @@ static void via_do_nubus(int slot, void *via, struct pt_regs *regs) { if(map&(1<<i)) { - (nubus_handler[i].handler)(i+9, via, regs); + nubus_irqs[i]++; + (nubus_handler[i].handler)(i+9, nubus_handler[i].dev_id, regs); } } /* clear it */ @@ -977,3 +1535,76 @@ static void via_do_nubus(int slot, void *via, struct pt_regs *regs) /* And done */ } + +/* + * Nubus dispatch handler - OSS style + */ +static void oss_do_nubus(int slot, void *via, struct pt_regs *regs) +{ + unsigned char map; + int i; + int ct=0; + +/* printk("nubus interrupt\n");*/ + +#if 0 + /* lock the nubus interrupt */ + if (via2_is_rbv) + via_write(rbv_regp, rIFR, 0x82); + else + via_write(via2_regp, vIFR, 0x82); +#endif + + /* IDE hack for Quadra: uses Nubus interrupt without any slot bit set */ +#ifdef CONFIG_BLK_DEV_MAC_IDE + if (mac_ide_intr_hook) + mac_ide_intr_hook(IRQ_MAC_NUBUS, via, regs); +#endif + + while(1) + { + /* pending events */ + map=(via_read(via, nIFR))&0x3F; + +#ifdef DEBUG_VIA_NUBUS + printk("nubus_irq: map %x mask %x\n", map, nubus_active); +#endif + if( (map = (map&nubus_active)) ==0 ) { +#ifdef CONFIG_BLK_DEV_MAC_IDE + if (!mac_ide_intr_hook) + printk("nubus_irq: nothing pending, map %x mask %x\n", + map, nubus_active); +#endif + nubus_irqs[7]++; + break; + } + + if(ct++>2) + { +#if 0 + printk("nubus stuck events - %d/%d\n", map, nubus_active); +#endif + return; + } + + for(i=0;i<7;i++) + { + if(map&(1<<i)) + { + nubus_irqs[i]++; + /* call handler */ + (nubus_handler[i].handler)((i+9), nubus_handler[i].dev_id, regs); + /* clear interrupt ?? */ +#if 0 + via_write(oss_regp, i, 0); +#endif + } + } + /* clear it */ +#if 0 + via_write(oss_regp, nIFR, map); +#endif + } + + /* And done */ +} diff --git a/arch/m68k/mac/mackeyb.c b/arch/m68k/mac/mackeyb.c index f338253f3..5946a9e8b 100644 --- a/arch/m68k/mac/mackeyb.c +++ b/arch/m68k/mac/mackeyb.c @@ -600,13 +600,13 @@ __initfunc(int mac_keyb_init(void)) volatile int ct; /* setup key map */ - memcpy (plain_map, mac_plain_map, sizeof(plain_map)); - memcpy(shift_map, mac_shift_map, sizeof(shift_map)); - memcpy(altgr_map, mac_altgr_map, sizeof(altgr_map)); - memcpy(ctrl_map, mac_ctrl_map, sizeof(ctrl_map)); - memcpy(shift_ctrl_map, mac_shift_ctrl_map, sizeof(shift_ctrl_map)); - memcpy(alt_map, mac_alt_map, sizeof(alt_map)); - memcpy(ctrl_alt_map, mac_ctrl_alt_map, sizeof(ctrl_alt_map)); + memcpy(key_maps[0], mac_plain_map, sizeof(plain_map)); + memcpy(key_maps[1], mac_shift_map, sizeof(plain_map)); + memcpy(key_maps[2], mac_altgr_map, sizeof(plain_map)); + memcpy(key_maps[4], mac_ctrl_map, sizeof(plain_map)); + memcpy(key_maps[5], mac_shift_ctrl_map, sizeof(plain_map)); + memcpy(key_maps[8], mac_alt_map, sizeof(plain_map)); + memcpy(key_maps[12], mac_ctrl_alt_map, sizeof(plain_map)); /* initialize mouse interrupt hook */ mac_mouse_interrupt_hook = NULL; @@ -642,11 +642,12 @@ __initfunc(int mac_keyb_init(void)) ct=0; while (!autopoll_req.got_reply && ++ct<1000) { - adb_poll(); udelay(10); } - if(ct==1000) + if(ct==1000) { printk("Keyboard timed out.\n"); + autopoll_req.got_reply = 1; + } } /* @@ -654,7 +655,7 @@ __initfunc(int mac_keyb_init(void)) * care of that for other Macs. */ - printk("Configuring keyboard\n"); + printk("Configuring keyboard:\n"); /* * turn on all leds - the keyboard driver will turn them back off @@ -668,17 +669,17 @@ __initfunc(int mac_keyb_init(void)) * The polling stuff should go away as soon as the ADB driver is stable */ ct = 0; - adb_poll(); while (!led_request.got_reply && ++ct<1000) { - adb_poll(); udelay(10); } - if(ct==1000) - printk("Keyboard timed out.\n"); + if(ct==1000) { + printk("keyboard timed out.\n"); + led_request.got_reply = 1; + } #if 1 - printk("Configuring coding mode ...\n"); + printk("configuring coding mode ...\n"); /* * get the keyboard to send separate codes for @@ -688,14 +689,14 @@ __initfunc(int mac_keyb_init(void)) ADB_WRITEREG(ADB_KEYBOARD, 3), 0, 3); ct=0; - adb_poll(); while (!confcod_req.got_reply && ++ct<1000) { - adb_poll(); udelay(10); } - if(ct==1000) - printk("Keyboard timed out.\n"); + if(ct==1000) { + printk("keyboard timed out.\n"); + confcod_req.got_reply = 1; + } #endif #if 0 /* seems to hurt, at least Geert's Mac */ @@ -710,10 +711,8 @@ __initfunc(int mac_keyb_init(void)) ADB_WRITEREG(ADB_MOUSE, 3), 0x23, 4 ); ct=0; - adb_poll(); while (!mouse_req.got_reply && ++ct<1000) { - adb_poll(); udelay(10); } if(ct==1000) @@ -734,19 +733,18 @@ __initfunc(int mac_keyb_init(void)) ADB_READREG(ADB_KEYBOARD, KEYB_KEYREG)); #endif - /* - * fake 'request done' for the driver if requests timed out - */ - - autopoll_req.got_reply = 1; -#if 0 - /* XXX: results in race and hang with mac_kbd_leds and serial (why ?) */ - led_request.got_reply = 1; -#endif - confcod_req.got_reply = 1; - in_keybinit = 0; - printk("Keyboard init done\n"); + printk("keyboard init done\n"); return 0; } + +/* for "kbd-reset" cmdline param */ +__initfunc(void mac_kbd_reset_setup(char *str, int *ints)) +{ +} + +/* for "kbd-reset" cmdline param */ +__initfunc(void mac_kbd_reset_setup(char *str, int *ints)) +{ +} diff --git a/arch/m68k/mac/psc.h b/arch/m68k/mac/psc.h new file mode 100644 index 000000000..964f6547c --- /dev/null +++ b/arch/m68k/mac/psc.h @@ -0,0 +1,18 @@ +/* + * Apple Peripheral System Controller (PSC) + * + * The PSC is used on the AV Macs to control IO functions not handled + * by the VIAs (Ethernet, DSP, SCC). + */ + +#define PSCBASE 0x50F31000 + +#define pIFR3 0x130 +#define pIFR4 0x140 +#define pIFR5 0x150 +#define pIFR6 0x160 + +#define pIER3 0x134 +#define pIER4 0x144 +#define pIER5 0x154 +#define pIER6 0x164 diff --git a/arch/m68k/mac/via6522.c b/arch/m68k/mac/via6522.c index d2a25ab13..c867bc96d 100644 --- a/arch/m68k/mac/via6522.c +++ b/arch/m68k/mac/via6522.c @@ -1,4 +1,3 @@ - /* * 6522 Versatile Interface Adapter (VIA) * @@ -13,75 +12,27 @@ #include <asm/macintosh.h> #include <asm/macints.h> #include "via6522.h" +#include "psc.h" volatile unsigned char *via1=(unsigned char *)VIABASE; volatile unsigned char *via2=(unsigned char *)VIABASE2; +volatile unsigned char *psc=(unsigned char *)PSCBASE; unsigned char via1_clock, via1_datab; static int rbv=0; +static int oss=0; + +extern void adb_interrupt(int slot, void *via, struct pt_regs *regs); /* - * Debugging the VBL ints + * hardware reset vector */ - -extern int console_loglevel; +static void (*rom_reset)(void); /* - * VIA1 - hardwired vectors + * Timer defs. */ - -#if 0 /* gone to macints.[ch] */ -extern void via_wtf(int slot, void *via, struct pt_regs *regs); -static void via_do_nubus(int slot, volatile void *via, struct pt_regs *regs); - -extern void adb_interrupt(int slot, void *via, struct pt_regs *regs); - -static struct via_irq_tab via1_func_tab= -{ - { - via_wtf, /* One second interrupt */ - via_wtf, /* Vblank */ - via_wtf, /* ADB data ready */ - via_wtf, /* ADB data */ - via_wtf, /* ADB clock */ - via_wtf, - via_wtf, /* Slot 6 is replaced by the timer */ - via_wtf - } -}; - -static struct via_irq_tab via2_func_tab= -{ - { - via_wtf, - via_do_nubus, - via_wtf, - via_wtf, - via_wtf, - via_wtf, - via_wtf, - via_wtf - } -}; - -static struct via_irq_tab nubus_func_tab= -{ - { - via_wtf, - via_wtf, - via_wtf, - via_wtf, - via_wtf, - via_wtf, - via_wtf, - via_wtf - } -}; -#endif - -extern void adb_interrupt(int slot, void *via, struct pt_regs *regs); - #define MAC_CLOCK_TICK (783300/HZ) /* ticks per HZ */ #define MAC_CLOCK_LOW (MAC_CLOCK_TICK&0xFF) #define MAC_CLOCK_HIGH (MAC_CLOCK_TICK>>8) @@ -91,8 +42,6 @@ void via_init_clock(void (*func)(int, void *, struct pt_regs *)) { unsigned char c; -/* mac_debugging_penguin(6);*/ - switch(macintosh_config->via_type) { /* @@ -102,6 +51,10 @@ void via_init_clock(void (*func)(int, void *, struct pt_regs *)) via1=(void *)0x50F00000; via2=(void *)0x50F26000; rbv=1; + if (macintosh_config->ident == MAC_MODEL_IIFX) { + via2=(void *)0x50F1A000; + oss=1; + } break; /* * Quadra and early MacIIs agree on the VIA locations @@ -162,7 +115,7 @@ void via_init_clock(void (*func)(int, void *, struct pt_regs *)) via_write(via2,vT2CH,0); via_write(via2,vIER, 0x7F); } - else + else if (oss==0) { /* * Init the RBV chip a bit @@ -201,30 +154,18 @@ void via_init_clock(void (*func)(int, void *, struct pt_regs *)) request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func); -/* mac_debugging_penguin(7);*/ - /* * SE/30: disable video int. * XXX: testing for SE/30 VBL */ - if (macintosh_config->ident == MAC_MODEL_SE30 - && console_loglevel != 10) { + if (macintosh_config->ident == MAC_MODEL_SE30) { c = via_read(via1, vBufB); via_write(via1, vBufB, c|(0x40)); c = via_read(via1, vDirB); via_write(via1, vDirB, c|(0x40)); } - /* - * XXX: use positive edge - */ - - if (console_loglevel == 10) { - c = via_read(via1, vPCR); - via_write(via1, vPCR, c|(0x1)); - } - #if 0 /* gone to mac_init_IRQ */ /* * Set vPCR for SCSI interrupts. @@ -237,172 +178,55 @@ void via_init_clock(void (*func)(int, void *, struct pt_regs *)) } -#if 0 /* moved to macints.c */ - -static void via_irq(volatile unsigned char *via, struct via_irq_tab *irqtab, - struct pt_regs *regs) -{ - unsigned char events=(via_read(via, vIFR)&via_read(via,vIER))&0x7F; - int i; - int ct=0; - - /* - * Shouldnt happen - */ - - if(events==0) - { - printk("via_irq: nothing pending!\n"); - return; - } - - do { - /* - * Clear the pending flag - */ - - /* HACK HACK - FIXME !!! - just testing some keyboard ideas */ - - /* events&=~(1<<4); */ - via_write(via, vIFR, events); - - /* - * Now see what bits are raised - */ - - for(i=0;i<7;i++) - { - if(events&(1<<i)) - (irqtab->vector[i])(i, via, regs); - } - - /* - * And done.. - */ - events=(via_read(via, vIFR)&via_read(via,vIER))&0x7F; - ct++; - if(events && ct>8) - { - printk("via: stuck events %x\n",events); - break; - } - } - while(events); - - scsi_mac_polled(); -} - /* - * - * The RBV is different. RBV appears to stand for randomly broken - * VIA. + * get time offset between scheduling timer ticks + * Code stolen from arch/m68k/atari/time.c; underflow check probably + * wrong. */ - -static void rbv_irq(volatile unsigned char *via, struct via_irq_tab *irqtab, - struct pt_regs *regs) +#define TICK_SIZE 10000 + +/* This is always executed with interrupts disabled. */ +unsigned long mac_gettimeoffset (void) { - unsigned char events=(via_read(via, rIFR)&via_read(via,rIER))&0x7F; - int i; - int ct=0; - - /* - * Shouldnt happen - */ - - if(events==0) - { - printk("rbv_irq: nothing pending!\n"); - return; - } - - do { - /* - * Clear the pending flag - */ - - /* HACK HACK - FIXME !!! - just testing some keyboard ideas */ - - /* events&=~(1<<4); */ - via_write(via, rIFR, events); - - /* - * Now see what bits are raised - */ - - for(i=0;i<7;i++) - { - if(events&(1<<i)) - (irqtab->vector[i])(i, via, regs); - } - - /* - * And done.. - */ - events=(via_read(via, rIFR)&via_read(via,rIER))&0x7F; - ct++; - if(events && ct>8) - { - printk("rbv: stuck events %x\n",events); - for(i=0;i<7;i++) - { - if(events&(1<<i)) - { - printk("rbv - bashing source %d\n", - i); - via_write(via, rIER, i); - via_write(via, rIFR, i); - } - } - break; - } - } - while(events); -} + unsigned long ticks, offset = 0; -/* - * System interrupts - */ + /* read VIA1 timer 2 current value */ + ticks = via_read(via1, vT1CL) + (via_read(via1, vT1CH)<<8); + /* The probability of underflow is less than 2% */ + if (ticks > MAC_CLOCK_TICK - MAC_CLOCK_TICK / 50) + /* Check for pending timer interrupt in VIA1 IFR */ + if (via_read(via1, vIFR) & 0x40) + offset = TICK_SIZE; -void via1_irq(int irq, void *dev_id, struct pt_regs *regs) -{ - via_irq(via1, &via1_func_tab, regs); -} + ticks = MAC_CLOCK_TICK - ticks; + ticks = ticks * 10000L / MAC_CLOCK_TICK; -/* - * Nubus interrupts - */ - -void via2_irq(int irq, void *dev_id, struct pt_regs *regs) -{ -/* printk("via2 interrupt\n");*/ - if(rbv) - rbv_irq(via2, &via2_func_tab, regs); - else - via_irq(via2, &via2_func_tab, regs); + return ticks + offset; } /* - * Unexpected via interrupt + * PSC (AV Macs; level 3-6): initialize interrupt enable registers */ - -void via_wtf(int slot, volatile void *via, struct pt_regs *regs) -{ - printk("Unexpected event %d on via %p\n",slot,via); -} -void nubus_wtf(int slot, volatile void *via, struct pt_regs *regs) +void psc_init(void) { - printk("Unexpected interrupt on nubus slot %d\n",slot); + via_write(psc, pIER3, 0x01); + via_write(psc, pIER4, 0x09); + via_write(psc, pIER4, 0x86); + via_write(psc, pIER5, 0x03); + via_write(psc, pIER6, 0x07); } -#endif - /* * The power switch - yes its software! */ -void mac_reset(void) +void mac_poweroff(void) { +#if 0 + /* + * Powerdown, for the Macs that support it + */ if(rbv) { via_write(via2, rBufB, via_read(via2, rBufB)&~0x04); } else { @@ -411,7 +235,38 @@ void mac_reset(void) /* Send a value of 0 on that line */ via_write(via2,vBufB,via_read(via2,vBufB)&~0x04); } +#endif + /* We should never make it this far... */ + /* XXX - delay do we need to spin here ? */ + while(1); /* Just in case .. */ +} + +/* + * Not all Macs support software power down; for the rest, just + * try the ROM reset vector ... + */ +void mac_reset(void) +{ + unsigned long flags; + unsigned long *reset_hook; + + save_flags(flags); + cli(); + +#if 0 /* need ROMBASE in booter */ +#if 0 /* works on some */ + rom_reset = (boot_info.bi_mac.rombase + 0xa); +#else /* testing, doesn't work on SE/30 either */ + reset_hook = (unsigned long *) (boot_info.bi_mac.rombase + 0x4); + printk("ROM reset hook: %p\n", *reset_hook); + rom_reset = *reset_hook; +#endif + rom_reset(); +#endif + restore_flags(flags); + /* We never make it this far... */ + printk(" reboot failed, reboot manually!\n"); /* XXX - delay do we need to spin here ? */ while(1); /* Just in case .. */ } @@ -442,140 +297,13 @@ void via1_set_head(int head) via_write(via1, vBufA, via_read(via1, vBufA)|0x20); } -#if 0 /* moved to macints.c */ - - -/* - * Set up the SCSI - */ - -void via_scsi_disable(void) -{ - if (rbv) - via_write(via2, rIER, (1<<3)|(1<<0)); - else - via_write(via2, vIER, (1<<3)|(1<<0)); -} - -void via_scsi_enable(void) -{ - if (rbv) - via_write(via2, rIER, (1<<3)|(1<<0)|0x80); - else - via_write(via2, vIER, (1<<3)|(1<<0)|0x80); -} - -void via_scsi_clear(void) -{ - if (rbv) - via_write(via2, rIFR, (1<<3)|(1<<0)|0x80); - volatile unsigned char deep_magic=via_read(via2, vBufB); - via_scsi_enable(); -} - -void via_setup_scsi(void (*handler)(int,volatile void *,struct pt_regs *)) -{ - via2_func_tab.vector[0]=handler; /* SCSI DRQ */ - via2_func_tab.vector[3]=handler; /* SCSI IRQ */ - via_write(via2, vPCR, 0x66); /* Edge direction! */ - via_scsi_enable(); -} - -/* - * Nubus handling - */ - -static int nubus_active=0; - -int nubus_request_irq(int slot, void (*handler)(int,void *,struct pt_regs *)) -{ - slot-=9; -/* printk("Nubus request irq for slot %d\n",slot);*/ - if(nubus_func_tab.vector[slot]==nubus_wtf) - return -EBUSY; - nubus_func_tab.vector[slot]=handler; - nubus_active|=1<<slot; -/* printk("program slot %d\n",slot);*/ -/* printk("via2=%p\n",via2);*/ -#if 0 - via_write(via2, vDirA, - via_read(via2, vDirA)|(1<<slot)); - via_write(via2, vBufA, 0); -#endif - if (!rbv) { - /* Make sure the bit is an input */ - via_write(via2, vDirA, - via_read(via2, vDirA)&~(1<<slot)); - } -/* printk("nubus irq on\n");*/ - return 0; -} - -int nubus_free_irq(int slot) -{ - slot-=9; - nubus_active&=~(1<<slot); - nubus_func_tab.vector[slot]=nubus_wtf; - if (rbv) { - via_write(via2, rBufA, 1<<slot); - } else { - via_write(via2, vDirA, - via_read(via2, vDirA)|(1<<slot)); - via_write(via2, vBufA, 1<<slot); - via_write(via2, vDirA, - via_read(via2, vDirA)&~(1<<slot)); - } - return 0; -} - -static void via_do_nubus(int slot, volatile void *via, struct pt_regs *regs) -{ - unsigned char map; - int i; - int ct=0; - -/* printk("nubus interrupt\n");*/ - - if (rbv) { - via_write(via2, rIFR, 0x82); /* lock the nubus interrupt */ - } else { - via_write(via2, vIFR, 0x82); /* lock the nubus interrupt */ - - while(1) - { - if(rbv) - map=~via_read(via2, rBufA); - else - map=~via_read(via2, vBufA); - if((map=(map&nubus_active))==0) - break; - if(ct++>2) - { - printk("nubus stuck events - %d/%d\n", map, nubus_active); - return; - } - for(i=0;i<7;i++) - { - if(map&(1<<i)) - { - (nubus_func_tab.vector[i])(i+9, via, regs); - } - } - if (rbv) - via_write(via2, rIFR, 0x02); /* clear it */ - else - via_write(via2, vIFR, 0x02); /* clear it */ - } - - /* And done */ -} -#endif - void nubus_init_via(void) { if (rbv) { - via_write(via2, rBufB, via_read(via2, rBufB)|0x02); - via_write(via2, rIER, 0x82); /* Interrupts on */ + if (oss==0) { + via_write(via2, rBufB, via_read(via2, rBufB)|0x02); + via_write(via2, rIER, 0x82); /* Interrupts on */ + } } else { /* Assert the nubus active */ via_write(via2, vDirB, via_read(via2, vDirB)|0x02); @@ -584,7 +312,13 @@ void nubus_init_via(void) /* via_write(via2, vDirA, 0xFF); */ via_write(via2, vIER, 0x82); /* Interrupts on */ } - printk("BTW boot via1 acr=%X datab=%X pcr=%X\n", - (int)via1_clock, (int)via1_datab, (int)via_read(via1, vPCR)); -} + printk("nubus_init_via: via1 acr=%X datab=%X pcr=%X\n", + (int)via_read(via1, vACR), (int)via_read(via1, vBufB), + (int)via_read(via1, vPCR)); + + if (rbv==0) + printk("nubus_init_via: via2 acr=%X datab=%X pcr=%X\n", + (int)via_read(via2, vACR), (int)via_read(via2, vBufB), + (int)via_read(via2, vPCR)); +} |