summaryrefslogtreecommitdiffstats
path: root/arch/m68k/mac
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-08-25 09:12:35 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-08-25 09:12:35 +0000
commitc7fc24dc4420057f103afe8fc64524ebc25c5d37 (patch)
tree3682407a599b8f9f03fc096298134cafba1c9b2f /arch/m68k/mac
parent1d793fade8b063fde3cf275bf1a5c2d381292cd9 (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/Makefile3
-rw-r--r--arch/m68k/mac/adb-bus.c831
-rw-r--r--arch/m68k/mac/config.c308
-rw-r--r--arch/m68k/mac/debug.c234
-rw-r--r--arch/m68k/mac/mac_ksyms.c (renamed from arch/m68k/mac/ksyms.c)0
-rw-r--r--arch/m68k/mac/macints.c777
-rw-r--r--arch/m68k/mac/mackeyb.c64
-rw-r--r--arch/m68k/mac/psc.h18
-rw-r--r--arch/m68k/mac/via6522.c442
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));
+}