summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorbriggs <briggs@NetBSD.org>1999-06-28 01:56:55 +0000
committerbriggs <briggs@NetBSD.org>1999-06-28 01:56:55 +0000
commit71a4446b0474dfb2e3ef955bb14bd11faed1a970 (patch)
tree92eeac468ef562a1106d9c1f13638b8d752eab0f /sys
parentf9de07203c7aaa21be218345abfdb6879edc67be (diff)
Unfortunately, several changes that are intermingled:
- Add initial IOP support. ADB doesn't work yet for me, but it's here so that others will be encouraged to work on it. ADB_HW_IOP basically is configured as a NOP so that serial consoles will continue to work. - Roll via1_intr and via2_intr into the intr.c scheme--this also required changing rtclock_intr to grovel the stack differently so that hardclock gets the right arguments and softclock() doesn't get all reentrant. - Make via1 interrupts parallel to via2 interrupts--handlers get a pass- through pointer and we can register handlers. Register via1 interrupt with intr_establish()--normally level 1, level 6 for A/UX scheme. - Use intr_establish() to set real via2 interrupt handler instead of the hacked function pointer. - Reorganize adb-direct interrupts so that a function call is removed. - Implement A/UX interrupts for all Quadras right now. We may need to special case some Quadras, but Linux folks are reporting success on several models. - Fix intrnames to be accurate for the normal, PSC, and A/UX interrupt configurations.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/mac68k/conf/files.mac68k3
-rw-r--r--sys/arch/mac68k/dev/adb_direct.c175
-rw-r--r--sys/arch/mac68k/dev/adbvar.h5
-rw-r--r--sys/arch/mac68k/dev/pm_direct.c43
-rw-r--r--sys/arch/mac68k/include/cpu.h6
-rw-r--r--sys/arch/mac68k/include/iopreg.h149
-rw-r--r--sys/arch/mac68k/include/viareg.h18
-rw-r--r--sys/arch/mac68k/mac68k/intr.c70
-rw-r--r--sys/arch/mac68k/mac68k/iop.c441
-rw-r--r--sys/arch/mac68k/mac68k/locore.s65
-rw-r--r--sys/arch/mac68k/mac68k/machdep.c38
-rw-r--r--sys/arch/mac68k/mac68k/pram.c4
-rw-r--r--sys/arch/mac68k/mac68k/vectors.s6
-rw-r--r--sys/arch/mac68k/mac68k/via.c74
-rw-r--r--sys/arch/mac68k/obio/asc.c8
-rw-r--r--sys/arch/mac68k/obio/if_sn_obio.c8
16 files changed, 974 insertions, 139 deletions
diff --git a/sys/arch/mac68k/conf/files.mac68k b/sys/arch/mac68k/conf/files.mac68k
index 77cfe3ded2b..ec3e28bbc26 100644
--- a/sys/arch/mac68k/conf/files.mac68k
+++ b/sys/arch/mac68k/conf/files.mac68k
@@ -1,4 +1,4 @@
-# $NetBSD: files.mac68k,v 1.90 1999/06/07 20:31:31 thorpej Exp $
+# $NetBSD: files.mac68k,v 1.91 1999/06/28 01:56:55 briggs Exp $
# mac68k-specific configuration info
@@ -136,6 +136,7 @@ file arch/mac68k/mac68k/clock.c
file arch/mac68k/mac68k/conf.c
file arch/mac68k/mac68k/disksubr.c disk
file arch/mac68k/mac68k/intr.c
+file arch/mac68k/mac68k/iop.c
file arch/mac68k/mac68k/kgdb_machdep.c kgdb
file arch/mac68k/mac68k/machdep.c
file arch/mac68k/mac68k/macrom.c
diff --git a/sys/arch/mac68k/dev/adb_direct.c b/sys/arch/mac68k/dev/adb_direct.c
index a8c251f9cc4..19ae8c714c2 100644
--- a/sys/arch/mac68k/dev/adb_direct.c
+++ b/sys/arch/mac68k/dev/adb_direct.c
@@ -1,4 +1,4 @@
-/* $NetBSD: adb_direct.c,v 1.23 1999/05/15 19:29:12 scottr Exp $ */
+/* $NetBSD: adb_direct.c,v 1.24 1999/06/28 01:56:56 briggs Exp $ */
/* From: adb_direct.c 2.02 4/18/97 jpw */
@@ -70,6 +70,7 @@
#include <machine/param.h>
#include <machine/cpu.h>
#include <machine/adbsys.h> /* required for adbvar.h */
+#include <machine/iopreg.h> /* required for IOP support */
#include <mac68k/mac68k/macrom.h>
#include <mac68k/dev/adbvar.h>
@@ -100,6 +101,7 @@
#define ADB_ACTION_OUT 0x3 /* sending out a command */
#define ADB_ACTION_IN 0x4 /* receiving data */
#define ADB_ACTION_POLLING 0x5 /* polling - II only */
+#define ADB_ACTION_RUNNING 0x6 /* running - IOP only */
/*
* These describe the state of the ADB bus itself, although they
@@ -210,6 +212,7 @@ char *adbHardwareDescr[MAX_ADB_HW + 1] = {
"IIsi series",
"PowerBook",
"Cuda",
+ "IOP",
};
/*
@@ -265,8 +268,9 @@ extern struct mac68k_machine_S mac68k_machine;
extern int ite_polling; /* Are we polling? (Debugger mode) */
void pm_setup_adb __P((void));
+void pm_hw_setup __P((void));
void pm_check_adb_devices __P((int));
-void pm_intr __P((void));
+void pm_intr __P((void *));
int pm_adb_op __P((u_char *, void *, void *, int));
void pm_init_adb_device __P((void));
@@ -276,10 +280,10 @@ void pm_init_adb_device __P((void));
#ifdef ADB_DEBUG
void print_single __P((u_char *));
#endif
-void adb_intr __P((void));
-void adb_intr_II __P((void));
-void adb_intr_IIsi __P((void));
-void adb_intr_cuda __P((void));
+void adb_intr __P((void *));
+void adb_intr_II __P((void *));
+void adb_intr_IIsi __P((void *));
+void adb_intr_cuda __P((void *));
void adb_soft_intr __P((void));
int send_adb_II __P((u_char *, u_char *, void *, void *, int));
int send_adb_IIsi __P((u_char *, u_char *, void *, void *, int));
@@ -307,6 +311,8 @@ int adb_prog_switch_enable __P((void));
int adb_prog_switch_disable __P((void));
/* we should create this and it will be the public version */
int send_adb __P((u_char *, void *, void *));
+void adb_iop_recv __P((IOP *, struct iop_msg *));
+int send_adb_iop __P((int, u_char *, void *, void *));
#ifdef ADB_DEBUG
/*
@@ -374,7 +380,7 @@ adb_cuda_tickle(void)
* grab serial interrupts?
*/
void
-adb_intr_cuda(void)
+adb_intr_cuda(void *arg)
{
volatile int i, ending;
volatile unsigned int s;
@@ -682,7 +688,7 @@ send_adb_cuda(u_char * in, u_char * buffer, void *compRout, void *data, int
while ((adbActionState != ADB_ACTION_IDLE) || (ADB_INTR_IS_ON)
|| (adbWaiting == 1))
if (ADB_SR_INTR_IS_ON) { /* wait for "interrupt" */
- adb_intr_cuda(); /* process it */
+ adb_intr_cuda(NULL); /* process it */
adb_soft_intr();
}
@@ -691,7 +697,7 @@ send_adb_cuda(u_char * in, u_char * buffer, void *compRout, void *data, int
void
-adb_intr_II(void)
+adb_intr_II(void *arg)
{
struct adbCommand packet;
int i, intr_on = 0;
@@ -706,6 +712,8 @@ adb_intr_II(void)
ADB_VIA_INTR_DISABLE(); /* disable ADB interrupt on IIs. */
delay(ADB_DELAY); /* yuck (don't remove) */
+
+if (!mac68k_machine.aux_interrupts)
(void)intr_dispatch(0x70); /* grab any serial interrupts */
if (ADB_INTR_IS_ON)
@@ -753,6 +761,7 @@ switch_start:
adbActionState = ADB_ACTION_IN;
}
delay(ADB_DELAY);
+if (!mac68k_machine.aux_interrupts)
(void)intr_dispatch(0x70); /* grab any serial interrupts */
goto switch_start;
break;
@@ -1123,7 +1132,7 @@ send_adb_II(u_char * in, u_char * buffer, void *compRout, void *data, int comman
while ((adbActionState != ADB_ACTION_IDLE) || (ADB_INTR_IS_ON)
|| (adbWaiting == 1))
if (ADB_SR_INTR_IS_ON) { /* wait for "interrupt" */
- adb_intr_II(); /* go process "interrupt" */
+ adb_intr_II(NULL); /* go process "interrupt" */
adb_soft_intr();
}
@@ -1187,22 +1196,25 @@ adb_guess_next_device(void)
* code for the machine we are running on.
*/
void
-adb_intr(void)
+adb_intr(void *arg)
{
switch (adbHardware) {
case ADB_HW_II:
- adb_intr_II();
+ adb_intr_II(arg);
break;
case ADB_HW_IISI:
- adb_intr_IIsi();
+ adb_intr_IIsi(arg);
break;
- case ADB_HW_PB:
+ case ADB_HW_PB: /* Should not come through here. */
break;
case ADB_HW_CUDA:
- adb_intr_cuda();
+ adb_intr_cuda(arg);
+ break;
+
+ case ADB_HW_IOP: /* Should not come through here. */
break;
case ADB_HW_UNKNOWN:
@@ -1218,7 +1230,7 @@ adb_intr(void)
*
*/
void
-adb_intr_IIsi(void)
+adb_intr_IIsi(void *arg)
{
struct adbCommand packet;
int i, ending;
@@ -1502,13 +1514,77 @@ send_adb_IIsi(u_char * in, u_char * buffer, void *compRout, void *data, int
while ((adbActionState != ADB_ACTION_IDLE) || (ADB_INTR_IS_ON)
|| (adbWaiting == 1))
if (ADB_SR_INTR_IS_ON) { /* wait for "interrupt" */
- adb_intr_IIsi(); /* process it */
+ adb_intr_IIsi(NULL); /* process it */
adb_soft_intr();
}
return 0;
} /* send_adb_IIsi */
+void
+adb_iop_recv(IOP *iop, struct iop_msg *msg)
+{
+ struct adbCommand pkt;
+ unsigned flags;
+
+ if (adbActionState != ADB_ACTION_RUNNING)
+ return;
+
+ switch (msg->status) {
+ case IOP_MSGSTAT_SENT:
+ if (0 == adb_cmd_result(msg->msg + 1)) {
+ adbWaiting = 1;
+ adbWaitingCmd = msg->msg[2];
+ }
+ break;
+ case IOP_MSGSTAT_RECEIVED:
+ case IOP_MSGSTAT_UNEXPECTED:
+ flags = msg->msg[0];
+ if (flags != 0) {
+ printf("ADB FLAGS 0x%x", flags);
+ break;
+ }
+ if (adbWaiting &&
+ (msg->msg[2] == adbWaitingCmd)) {
+ pkt.saveBuf = msg->msg + 1;
+ pkt.compRout = adbCompRout;
+ pkt.compData = adbCompData;
+ pkt.unsol = 0;
+ pkt.ack_only = 0;
+ adb_pass_up(&pkt);
+
+ adbWaitingCmd = 0;
+ adbWaiting = 0;
+ } else {
+ pkt.unsol = 1;
+ pkt.ack_only = 0;
+ adb_pass_up(&pkt);
+ }
+ break;
+ default:
+ return;
+ }
+}
+
+int
+send_adb_iop(int cmd, u_char * buffer, void *compRout, void *data)
+{
+ u_char buff[32];
+ int i, cnt;
+
+ if (adbActionState != ADB_ACTION_RUNNING)
+ return -1;
+
+ buff[0] = IOP_ADB_FL_EXPLICIT;
+ buff[1] = buffer[0];
+ buff[2] = cmd;
+ cnt = (int) buff[1];
+ for (i=0; i<cnt ; i++) {
+ buff[i+3] = buffer[i+1];
+ }
+ return iop_send_msg(ISM_IOP, IOP_CHAN_ADB, buff, cnt+3,
+ adb_iop_recv, NULL);
+}
/*
* adb_pass_up is called by the interrupt-time routines.
@@ -1559,6 +1635,7 @@ adb_pass_up(struct adbCommand *in)
start = 0;
} else {
switch (adbHardware) {
+ case ADB_HW_IOP:
case ADB_HW_II:
cmd = in->data[1];
if (in->data[0] < 2)
@@ -1776,6 +1853,17 @@ adb_op(Ptr buffer, Ptr compRout, Ptr data, short command)
return -1;
break;
+ case ADB_HW_IOP:
+#if 0
+ result = send_adb_iop((int)command, (u_char *)buffer,
+ (void *)compRout, (void *)data);
+ if (result == 0)
+ return 0;
+ else
+#endif
+ return -1;
+ break;
+
case ADB_HW_IISI:
result = send_adb_IIsi((u_char *)0, (u_char *)buffer,
(void *)compRout, (void *)data, (int)command);
@@ -1831,6 +1919,8 @@ adb_hw_setup(void)
switch (adbHardware) {
case ADB_HW_II:
+ via1_register_irq(2, adb_intr_II, NULL);
+
via_reg(VIA1, vDirB) |= 0x30; /* register B bits 4 and 5:
* outputs */
via_reg(VIA1, vDirB) &= 0xf7; /* register B bit 3: input */
@@ -1847,7 +1937,14 @@ adb_hw_setup(void)
ADB_VIA_CLR_INTR(); /* clear interrupt */
break;
+ case ADB_HW_IOP:
+ /* adbActionState = ADB_ACTION_RUNNING; */
+ via_reg(VIA1, vIER) = 0x84;
+ via_reg(VIA1, vIFR) = 0x04;
+ break;
+
case ADB_HW_IISI:
+ via1_register_irq(2, adb_intr_IIsi, NULL);
via_reg(VIA1, vDirB) |= 0x30; /* register B bits 4 and 5:
* outputs */
via_reg(VIA1, vDirB) &= 0xf7; /* register B bit 3: input */
@@ -1882,10 +1979,11 @@ adb_hw_setup(void)
* XXX - really PM_VIA_CLR_INTR - should we put it in
* pm_direct.h?
*/
- via_reg(VIA1, vIFR) = 0x90; /* clear interrupt */
+ pm_hw_setup();
break;
case ADB_HW_CUDA:
+ via1_register_irq(2, adb_intr_cuda, NULL);
via_reg(VIA1, vDirB) |= 0x30; /* register B bits 4 and 5:
* outputs */
via_reg(VIA1, vDirB) &= 0xf7; /* register B bit 3: input */
@@ -2013,7 +2111,8 @@ adb_reinit(void)
(void)(&s); /* work around lame GCC bug */
/* Make sure we are not interrupted while building the table. */
- if (adbHardware != ADB_HW_PB) /* ints must be on for PB? */
+ /* ints must be on for PB & IOP (at least, for now) */
+ if (adbHardware != ADB_HW_PB && adbHardware != ADB_HW_IOP)
s = splhigh();
ADBNumDevices = 0; /* no devices yet */
@@ -2034,7 +2133,7 @@ adb_reinit(void)
/* send an ADB reset first */
adb_op_sync((Ptr)0, (Ptr)0, (Ptr)0, (short)0x00);
- delay(3000);
+ delay(4000);
/*
* Probe for ADB devices. Probe devices 1-15 quickly to determine
@@ -2198,7 +2297,8 @@ adb_reinit(void)
if (adbHardware == ADB_HW_CUDA)
timeout((void *)adb_cuda_tickle, 0, ADB_TICKLE_TICKS);
- if (adbHardware != ADB_HW_PB) /* ints must be on for PB? */
+ /* ints must be on for PB & IOP (at least, for now) */
+ if (adbHardware != ADB_HW_PB && adbHardware != ADB_HW_IOP)
splx(s);
return;
@@ -2255,6 +2355,7 @@ int
adb_cmd_result(u_char *in)
{
switch (adbHardware) {
+ case ADB_HW_IOP:
case ADB_HW_II:
/* was it an ADB talk command? */
if ((in[1] & 0x0c) == 0x0c)
@@ -2294,7 +2395,8 @@ int
adb_cmd_extra(u_char *in)
{
switch (adbHardware) {
- case ADB_HW_II:
+ case ADB_HW_II:
+ case ADB_HW_IOP:
if ((in[1] & 0x0c) == 0x08) /* was it a listen command? */
return 0;
return 1;
@@ -2401,8 +2503,6 @@ adb_setup_hw_type(void)
case MACH_MACIIVX: /* IIvx */
case MACH_MACP460: /* Performa 460/465/467 */
case MACH_MACP600: /* Performa 600 */
- case MACH_MACQ900: /* Quadra 900 - XXX not sure */
- case MACH_MACQ950: /* Quadra 950 - XXX not sure */
adbHardware = ADB_HW_IISI;
#ifdef ADB_DEBUG
if (adb_debug)
@@ -2461,6 +2561,18 @@ adb_setup_hw_type(void)
printf_intr("adb: using Cuda series hardware support\n");
#endif
break;
+
+ case MACH_MACQ900: /* Quadra 900 */
+ case MACH_MACQ950: /* Quadra 950 */
+ case MACH_MACIIFX: /* Mac IIfx */
+ adbHardware = ADB_HW_IOP;
+ iop_register_listener(ISM_IOP, IOP_CHAN_ADB, adb_iop_recv, NULL);
+#ifdef ADB_DEBUG
+ if (adb_debug)
+ printf_intr("adb: using IOP-based ADB\n");
+#endif
+ break;
+
default:
adbHardware = ADB_HW_UNKNOWN;
#ifdef ADB_DEBUG
@@ -2488,8 +2600,6 @@ adb_setup_hw_type(void)
case MACH_MACP600: /* Performa 600 */
case MACH_MACQ630: /* LC 630, Performa 630, Quadra 630 */
case MACH_MACQ840AV: /* Quadra 840AV */
- case MACH_MACQ900: /* Quadra 900 - XXX not sure */
- case MACH_MACQ950: /* Quadra 950 - XXX not sure */
adbSoftPower = 1;
break;
}
@@ -2576,14 +2686,14 @@ set_adb_info(ADBSetInfoBlock * info, int adbAddr)
long
mrg_adbintr(void)
{
- adb_intr();
+ adb_intr(NULL);
return 1; /* mimic mrg_adbintr in macrom.h just in case */
}
long
mrg_pmintr(void)
{
- pm_intr();
+ pm_intr(NULL);
return 1; /* mimic mrg_pmintr in macrom.h just in case */
}
@@ -2600,6 +2710,9 @@ adb_read_date_time(unsigned long *time)
case ADB_HW_II:
return -1;
+ case ADB_HW_IOP:
+ return -1;
+
case ADB_HW_IISI:
output[0] = 0x02; /* 2 byte message */
output[1] = 0x01; /* to pram/rtc device */
@@ -2652,6 +2765,9 @@ adb_set_date_time(unsigned long time)
case ADB_HW_II:
return -1;
+ case ADB_HW_IOP:
+ return -1;
+
case ADB_HW_IISI:
output[0] = 0x06; /* 6 byte message */
output[1] = 0x01; /* to pram/rtc device */
@@ -2738,6 +2854,7 @@ adb_poweroff(void)
return 0;
case ADB_HW_II: /* II models don't do ADB soft power */
+ case ADB_HW_IOP: /* IOP models don't do ADB soft power */
case ADB_HW_UNKNOWN:
default:
return -1;
@@ -2771,6 +2888,7 @@ adb_prog_switch_enable(void)
return -1;
case ADB_HW_II: /* II models don't do prog. switch */
+ case ADB_HW_IOP: /* IOP models don't do prog. switch */
case ADB_HW_CUDA: /* cuda doesn't do prog. switch TO DO: verify this */
case ADB_HW_UNKNOWN:
default:
@@ -2805,6 +2923,7 @@ adb_prog_switch_disable(void)
return -1;
case ADB_HW_II: /* II models don't do prog. switch */
+ case ADB_HW_IOP: /* IOP models don't do prog. switch */
case ADB_HW_CUDA: /* cuda doesn't do prog. switch */
case ADB_HW_UNKNOWN:
default:
diff --git a/sys/arch/mac68k/dev/adbvar.h b/sys/arch/mac68k/dev/adbvar.h
index 6d8996a1a32..a767f3b634e 100644
--- a/sys/arch/mac68k/dev/adbvar.h
+++ b/sys/arch/mac68k/dev/adbvar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: adbvar.h,v 1.14 1999/02/11 06:41:08 ender Exp $ */
+/* $NetBSD: adbvar.h,v 1.15 1999/06/28 01:56:56 briggs Exp $ */
/*
* Copyright (C) 1994 Bradley A. Grantham
@@ -84,7 +84,8 @@ void extdms_complete __P((void));
#define ADB_HW_IISI 0x2 /* Mac IIsi series */
#define ADB_HW_PB 0x3 /* PowerBook series */
#define ADB_HW_CUDA 0x4 /* Machines with a Cuda chip */
-#define MAX_ADB_HW 4 /* Number of ADB hardware types */
+#define ADB_HW_IOP 0x5 /* Machines with an IOP */
+#define MAX_ADB_HW 5 /* Number of ADB hardware types */
#ifndef MRG_ADB
/* adb_direct.c */
diff --git a/sys/arch/mac68k/dev/pm_direct.c b/sys/arch/mac68k/dev/pm_direct.c
index fed597c2adf..7b348a3abed 100644
--- a/sys/arch/mac68k/dev/pm_direct.c
+++ b/sys/arch/mac68k/dev/pm_direct.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pm_direct.c,v 1.8 1999/03/05 06:45:41 scottr Exp $ */
+/* $NetBSD: pm_direct.c,v 1.9 1999/06/28 01:56:56 briggs Exp $ */
/*
* Copyright (C) 1997 Takashi Hamada
@@ -173,13 +173,13 @@ int pm_wait_free __P((int));
int pm_receive_pm1 __P((u_char *));
int pm_send_pm1 __P((u_char,int));
int pm_pmgrop_pm1 __P((PMData *));
-void pm_intr_pm1 __P((void));
+void pm_intr_pm1 __P((void *));
/* these functions are for the PB Duo series and the PB 5XX series */
int pm_receive_pm2 __P((u_char *));
int pm_send_pm2 __P((u_char));
int pm_pmgrop_pm2 __P((PMData *));
-void pm_intr_pm2 __P((void));
+void pm_intr_pm2 __P((void *));
/* this function is MRG-Based (for testing) */
int pm_pmgrop_mrg __P((PMData *));
@@ -187,8 +187,9 @@ int pm_pmgrop_mrg __P((PMData *));
/* these functions are called from adb_direct.c */
void pm_setup_adb __P((void));
void pm_check_adb_devices __P((int));
-void pm_intr __P((void));
+void pm_intr __P((void *));
int pm_adb_op __P((u_char *, void *, void *, int));
+void pm_hw_setup __P((void));
/* these functions also use the variables of adb_direct.c */
void pm_adb_get_TALK_result __P((PMData *));
@@ -558,7 +559,8 @@ pm_pmgrop_pm1(pmdata)
* My PM interrupt routine for PB1XX series
*/
void
-pm_intr_pm1()
+pm_intr_pm1(arg)
+ void *arg;
{
int s;
int rval;
@@ -827,7 +829,8 @@ pm_pmgrop_pm2(pmdata)
* My PM interrupt routine for the PB Duo series and the PB 5XX series
*/
void
-pm_intr_pm2()
+pm_intr_pm2(arg)
+ void *arg;
{
int s;
int rval;
@@ -952,14 +955,15 @@ pmgrop(pmdata)
* My PM interrupt routine
*/
void
-pm_intr()
+pm_intr(arg)
+ void *arg;
{
switch (pmHardware) {
case PM_HW_PB1XX:
- pm_intr_pm1();
+ pm_intr_pm1(arg);
break;
case PM_HW_PB5XX:
- pm_intr_pm2();
+ pm_intr_pm2(arg);
break;
default:
break;
@@ -967,6 +971,23 @@ pm_intr()
}
+void
+pm_hw_setup()
+{
+ switch (pmHardware) {
+ case PM_HW_PB1XX:
+ via1_register_irq(4, pm_intr_pm1, (void *)0);
+ PM_VIA_CLR_INTR();
+ break;
+ case PM_HW_PB5XX:
+ via1_register_irq(4, pm_intr_pm2, (void *)0);
+ PM_VIA_CLR_INTR();
+ break;
+ default:
+ break;
+ }
+}
+
/*
* Synchronous ADBOp routine for the Power Manager
@@ -1019,7 +1040,7 @@ pm_adb_op(buffer, compRout, data, command)
pmdata.data[2] = 0;
if ((command & 0xc) != 0xc) { /* if the command is not TALK */
- /* set up stuff for adb_pass_up */
+ /* set up stuff fNULLor adb_pass_up */
packet.data[0] = 1 + pmdata.data[2];
packet.data[1] = command;
for (i = 0; i < pmdata.data[2]; i++)
@@ -1048,7 +1069,7 @@ pm_adb_op(buffer, compRout, data, command)
delay = 0x80000;
while (adbWaiting == 1) {
if ((via_reg(VIA1, vIFR) & 0x10) == 0x10)
- pm_intr();
+ pm_intr((void *)0);
#ifdef PM_GRAB_SI
#if 0
zshard(0); /* grab any serial interrupts */
diff --git a/sys/arch/mac68k/include/cpu.h b/sys/arch/mac68k/include/cpu.h
index 208a968f674..9f0f12b4958 100644
--- a/sys/arch/mac68k/include/cpu.h
+++ b/sys/arch/mac68k/include/cpu.h
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.h,v 1.61 1999/04/06 03:40:23 scottr Exp $ */
+/* $NetBSD: cpu.h,v 1.62 1999/06/28 01:56:57 briggs Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@@ -246,6 +246,10 @@ struct mac68k_machine_S {
int scsi96; /* Has NCR 53C96 */
int scsi96_2; /* Has 2nd 53C96 */
int sonic; /* Has SONIC e-net */
+
+ int via1_ipl;
+ int via2_ipl;
+ int aux_interrupts;
};
/* What kind of model is this */
diff --git a/sys/arch/mac68k/include/iopreg.h b/sys/arch/mac68k/include/iopreg.h
new file mode 100644
index 00000000000..c2161cbfce8
--- /dev/null
+++ b/sys/arch/mac68k/include/iopreg.h
@@ -0,0 +1,149 @@
+/* $NetBSD: iopreg.h,v 1.1 1999/06/28 01:56:57 briggs Exp $ */
+
+#include <sys/pool.h>
+#include <sys/queue.h>
+
+#define IOP1_BASE 0x00004000
+
+#define SCC_IOP 0
+#define ISM_IOP 1
+
+#define IOP_CS_BYPASS 0x01
+#define IOP_CS_AUTOINC 0x02
+#define IOP_CS_RUN 0x04
+#define IOP_CS_IRQ 0x08
+#define IOP_CS_INT0 0x10
+#define IOP_CS_INT1 0x20
+#define IOP_CS_HWINT 0x40
+#define IOP_CS_DMAINACT 0x80
+
+#define IOP_RESET (IOP_CS_DMAINACT | IOP_CS_AUTOINC)
+#define IOP_BYPASS \
+ (IOP_CS_BYPASS | IOP_CS_AUTOINC | IOP_CS_RUN | IOP_CS_DMAINACT)
+#define IOP_INTERRUPT (IOP_CS_INT0 | IOP_CS_INT1)
+
+#define OSS_INTLEVEL_OFFSET 0x0001A006
+
+typedef struct {
+ volatile u_char ram_hi;
+ u_char pad0;
+ volatile u_char ram_lo;
+ u_char pad1;
+ volatile u_char control_status;
+ u_char pad2[3];
+ volatile u_char data;
+ u_char pad3[23];
+ union {
+ struct {
+ volatile u_char sccb_cmd;
+ u_char pad0;
+ volatile u_char scca_cmd;
+ u_char pad1;
+ volatile u_char sccb_data;
+ u_char pad2;
+ volatile u_char scca_data;
+ u_char pad3;
+ } scc;
+ struct {
+ volatile u_char wdata;
+ u_char pad0;
+ /* etc... */
+ } iwm;
+ } bypass;
+} IOPHW;
+
+#define IOP_MAXCHAN 7
+#define IOP_MAXMSG 8
+#define IOP_MSGLEN 32
+#define IOP_MSGBUFLEN (IOP_MSGLEN * IOP_MAXCHAN)
+
+#define IOP_MSG_IDLE 0 /* idle */
+#define IOP_MSG_NEW 1 /* new message sent */
+#define IOP_MSG_RECEIVED 2 /* message received; processing */
+#define IOP_MSG_COMPLETE 3 /* message processing complete */
+
+#define IOP_ADDR_MAX_SEND_CHAN 0x200
+#define IOP_ADDR_SEND_STATE 0x201
+#define IOP_ADDR_PATCH_CTRL 0x21F
+#define IOP_ADDR_SEND_MSG 0x220
+#define IOP_ADDR_MAX_RECV_CHAN 0x300
+#define IOP_ADDR_RECV_STATE 0x301
+#define IOP_ADDR_ALIVE 0x31F
+#define IOP_ADDR_RECV_MSG 0x320
+
+typedef struct {
+ u_char pad1[0x200];
+ u_char max_send_chan; /* maximum send channel # */
+ u_char send_state[IOP_MAXCHAN]; /* send channel states */
+ u_char pad2[23];
+ u_char patch_ctrl; /* patch control flag */
+ u_char send_msg[IOP_MSGBUFLEN]; /* send channel message data */
+ u_char max_recv_chan; /* max. receive channel # */
+ u_char recv_state[IOP_MAXCHAN]; /* receive channel states */
+ u_char pad3[23];
+ u_char alive; /* IOP alive flag */
+ u_char recv_msg[IOP_MSGBUFLEN]; /* receive channel msg data */
+} IOPK;
+
+struct iop_msg;
+struct _s_IOP;
+
+typedef void (*iop_msg_handler)(struct _s_IOP *iop, struct iop_msg *);
+
+struct iop_msg {
+ SIMPLEQ_ENTRY(iop_msg) iopm;
+ int channel;
+ int status;
+ u_char msg[IOP_MSGLEN];
+
+ /* The routine that will handle the message */
+ iop_msg_handler handler;
+ void *user_data;
+};
+
+#define IOP_MSGSTAT_IDLE 0 /* Message unused (invalid) */
+#define IOP_MSGSTAT_QUEUED 1 /* Message queued for send */
+#define IOP_MSGSTAT_SENDING 2 /* Message on IOP */
+#define IOP_MSGSTAT_SENT 3 /* Message complete */
+#define IOP_MSGSTAT_RECEIVING 4 /* Top of receive queue */
+#define IOP_MSGSTAT_RECEIVED 5 /* Msg received */
+#define IOP_MSGSTAT_UNEXPECTED 6 /* Unexpected msg received */
+
+typedef struct _s_IOP {
+ IOPHW *iop;
+ struct pool pool;
+ SIMPLEQ_HEAD(, iop_msg) sendq[IOP_MAXCHAN];
+ SIMPLEQ_HEAD(, iop_msg) recvq[IOP_MAXCHAN];
+ iop_msg_handler listeners[IOP_MAXCHAN];
+ void *listener_data[IOP_MAXCHAN];
+ struct iop_msg unsolicited_msg;
+} IOP;
+
+#define IOP_LOADADDR(ioph,addr) (ioph->ram_lo = addr & 0xff, \
+ ioph->ram_hi = (addr >> 8) & 0xff)
+
+void iop_init __P((int fullinit));
+void iop_upload __P((int iop, u_char *mem, u_long nb, u_long iopbase));
+void iop_download __P((int iop, u_char *mem, u_long nb, u_long iopbase));
+int iop_send_msg __P((int iopn, int chan, u_char *msg, int msglen,
+ iop_msg_handler handler, void *udata));
+int iop_queue_receipt __P((int iopn, int chan, iop_msg_handler handler,
+ void *user_data));
+int iop_register_listener __P((int iopn, int chan, iop_msg_handler handler,
+ void *user_data));
+
+/* ADB support */
+#define IOP_CHAN_ADB 2
+
+#define IOP_ADB_FL_EXPLICIT 0x80 /* Non-zero if explicit command */
+#define IOP_ADB_FL_AUTOPOLL 0x40 /* Auto/SRQ polling enabled */
+#define IOP_ADB_FL_SRQ 0x04 /* SRQ detected */
+#define IOP_ADB_FL_TIMEOUT 0x02 /* Non-zero if timeout */
+
+/*
+ * The structure of an ADB packet to/from the IOP is:
+ * Flag byte (values above)
+ * Count of bytes in data
+ * Command byte
+ * Data (optional)
+ */
diff --git a/sys/arch/mac68k/include/viareg.h b/sys/arch/mac68k/include/viareg.h
index 6f021e375af..300a4d94683 100644
--- a/sys/arch/mac68k/include/viareg.h
+++ b/sys/arch/mac68k/include/viareg.h
@@ -1,4 +1,4 @@
-/* $NetBSD: viareg.h,v 1.11 1999/02/20 09:57:35 scottr Exp $ */
+/* $NetBSD: viareg.h,v 1.12 1999/06/28 01:56:57 briggs Exp $ */
/*-
* Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo,
@@ -57,6 +57,7 @@
#define DB1I_Par_Err 0x80
#define DB1O_vSndEnb 0x80
#define DB1O_Par_Enb 0x40
+#define DB1O_AuxIntEnb 0x40 /* 0 = enabled, 1 = disabled */
#define DB1O_vFDesk2 0x20
#define DB1O_vFDesk1 0x10
#define DB1I_vFDBInt 0x08
@@ -143,8 +144,10 @@
extern volatile unsigned char *Via1Base;
extern volatile unsigned char *Via2Base; /* init in VIA_Initialize */
#define VIA1_addr Via1Base /* at PA 0x50f00000 */
-#define VIA2OFF 1 /* VIA2 addr = VIA1_addr * 0x2000 */
-#define RBVOFF 0x13 /* RBV addr = VIA1_addr * 0x13000 */
+
+#define VIA2OFF 1 /* VIA2 addr = VIA1_addr + 0x2000 */
+#define RBVOFF 0x13 /* RBV addr = VIA1_addr + 0x26000 */
+#define OSSOFF 0xd /* OSS addr = VIA1_addr + 0x1A000 */
#define VIA1 0
extern int VIA2;
@@ -160,7 +163,7 @@ extern int VIA2;
#define vT1LH 0x0e00
#define vT2C 0x1000
#define vT2CH 0x1200
-#define vSR 0x1400 /* shift register */
+#define vSR 0x1400 /* shift register */
#define vACR 0x1600 /* aux control register */
#define vPCR 0x1800 /* peripheral control register */
#define vIFR 0x1a00 /* interrupt flag register */
@@ -184,6 +187,13 @@ extern int VIA2;
#define RBVMonIDStd 0x30 /* 12 inch BW or 13 inch color */
#define RBVMonIDNone 0x38 /* No monitor connected */
+ /* OSS registers */
+#define OSS_IFR 0x202
+#define OSS_PENDING_IRQ (*(volatile u_short *)(Via2Base + (OSS_IFR)))
+
+#define OSS_oRCR 0x204
+#define OSS_POWEROFF 0x80
+
#define via_reg(v, r) (*(Via1Base+(v)*0x2000+(r)))
#define via2_reg(r) (*(Via2Base+(r)))
diff --git a/sys/arch/mac68k/mac68k/intr.c b/sys/arch/mac68k/mac68k/intr.c
index 24fd578066d..62c84911b07 100644
--- a/sys/arch/mac68k/mac68k/intr.c
+++ b/sys/arch/mac68k/mac68k/intr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: intr.c,v 1.4 1999/03/24 05:51:03 mrg Exp $ */
+/* $NetBSD: intr.c,v 1.5 1999/06/28 01:56:57 briggs Exp $ */
/*-
* Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
@@ -92,8 +92,8 @@ int intr_debug = 0;
/*
* Some of the below are not used yet, but might be used someday on the
- * Q700/900/950 where the interrupt controller may be reprogrammed to
- * interrupt on different levels as listed in locore.s
+ * IIfx/Q700/900/950/etc. where the interrupt controller may be reprogrammed
+ * to interrupt on different levels as listed in locore.s
*/
u_short mac68k_ttyipl;
u_short mac68k_bioipl;
@@ -108,23 +108,59 @@ extern int intrcnt[]; /* from locore.s */
void intr_computeipl __P((void));
+#define MAX_INAME_LENGTH 53
+#define STD_INAMES \
+ "spur\0via1\0via2\0unused1\0scc\0unused2\0unused3\0nmi\0clock\0"
+#define AUX_INAMES \
+ "spur\0soft\0via2\0ethernet\0scc\0sound\0via1\0nmi\0clock\0 "
+#define AV_INAMES \
+ "spur\0via1\0via2\0ethernet\0scc\0dsp\0unused1\0nmi\0clock\0 "
+
void
intr_init()
{
- /* Standard spl(9) interrupt priorities */
- mac68k_ttyipl = (PSL_S | PSL_IPL1);
- mac68k_bioipl = (PSL_S | PSL_IPL2);
- mac68k_netipl = (PSL_S | PSL_IPL2);
- mac68k_impipl = (PSL_S | PSL_IPL2);
- mac68k_statclockipl = (PSL_S | PSL_IPL2);
- mac68k_clockipl = (PSL_S | PSL_IPL2);
- mac68k_schedipl = (PSL_S | PSL_IPL3);
-
- /* Non-standard interrupt priority */
- mac68k_audioipl = (PSL_S | PSL_IPL2);
-
- if (current_mac_model->class == MACH_CLASSAV)
- mac68k_bioipl = mac68k_netipl = (PSL_S | PSL_IPL4);
+ extern long intrnames;
+ char *inames, *g_inames;
+
+ g_inames = (char *) &intrnames;
+ if (mac68k_machine.aux_interrupts) {
+
+ inames = AUX_INAMES;
+
+ /* Standard spl(9) interrupt priorities */
+ mac68k_ttyipl = (PSL_S | PSL_IPL1);
+ mac68k_bioipl = (PSL_S | PSL_IPL2);
+ mac68k_netipl = (PSL_S | PSL_IPL3);
+ mac68k_impipl = (PSL_S | PSL_IPL6);
+ mac68k_statclockipl = (PSL_S | PSL_IPL6);
+ mac68k_clockipl = (PSL_S | PSL_IPL6);
+ mac68k_schedipl = (PSL_S | PSL_IPL4);
+
+ /* Non-standard interrupt priority */
+ mac68k_audioipl = (PSL_S | PSL_IPL5);
+
+ } else {
+ inames = STD_INAMES;
+
+ /* Standard spl(9) interrupt priorities */
+ mac68k_ttyipl = (PSL_S | PSL_IPL1);
+ mac68k_bioipl = (PSL_S | PSL_IPL2);
+ mac68k_netipl = (PSL_S | PSL_IPL2);
+ mac68k_impipl = (PSL_S | PSL_IPL2);
+ mac68k_statclockipl = (PSL_S | PSL_IPL2);
+ mac68k_clockipl = (PSL_S | PSL_IPL2);
+ mac68k_schedipl = (PSL_S | PSL_IPL3);
+
+ /* Non-standard interrupt priority */
+ mac68k_audioipl = (PSL_S | PSL_IPL2);
+
+ if (current_mac_model->class == MACH_CLASSAV) {
+ inames = AV_INAMES;
+ mac68k_bioipl = mac68k_netipl = (PSL_S | PSL_IPL4);
+ }
+ }
+
+ memcpy(g_inames, inames, MAX_INAME_LENGTH);
intr_computeipl();
}
diff --git a/sys/arch/mac68k/mac68k/iop.c b/sys/arch/mac68k/mac68k/iop.c
new file mode 100644
index 00000000000..82bf7ed8811
--- /dev/null
+++ b/sys/arch/mac68k/mac68k/iop.c
@@ -0,0 +1,441 @@
+/* $NetBSD: iop.c,v 1.1 1999/06/28 01:56:57 briggs Exp $ */
+
+/*
+ * This code handles VIA, RBV, and OSS functionality.
+ */
+
+#include "opt_mac68k.h"
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/pool.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+
+#include <machine/cpu.h>
+#include <machine/frame.h>
+
+#include <machine/iopreg.h>
+#include <machine/viareg.h>
+
+static IOP mac68k_iops[2];
+
+static void iopism_hand __P((void *arg));
+static void load_msg_to_iop __P((IOPHW *ioph, struct iop_msg *msg));
+static void iop_message_sent __P((IOP *iop, int chan));
+static void receive_iop_message __P((IOP *iop, int chan));
+static void default_listener __P((IOP *iop, struct iop_msg *msg));
+
+static __inline__ int iop_read1 __P((IOPHW *ioph, u_long addr));
+static __inline__ void iop_write1 __P((IOPHW *ioph, u_long addr, u_char data));
+static __inline__ void _iop_upload __P((IOPHW *, u_char *, u_long, u_long));
+static __inline__ void _iop_download __P((IOPHW *, u_char *, u_long, u_long));
+
+static __inline__ int
+iop_read1(ioph, iopbase)
+ IOPHW *ioph;
+ u_long iopbase;
+{
+ IOP_LOADADDR(ioph, iopbase);
+ return ioph->data;
+}
+
+static __inline__ void
+iop_write1(ioph, iopbase, data)
+ IOPHW *ioph;
+ u_long iopbase;
+ u_char data;
+{
+ IOP_LOADADDR(ioph, iopbase);
+ ioph->data = data;
+}
+
+static void
+default_listener(iop, msg)
+ IOP *iop;
+ struct iop_msg *msg;
+{
+ printf("unsolicited message on channel %d.\n", msg->channel);
+}
+
+void
+iop_init(fullinit)
+ int fullinit;
+{
+ IOPHW *ioph;
+ IOP *iop;
+ int i, ii;
+
+ switch (current_mac_model->machineid) {
+ default:
+ return;
+ case MACH_MACQ900:
+ case MACH_MACQ950:
+ mac68k_iops[SCC_IOP].iop = (IOPHW *)
+ ((u_char *)IOBase + 0xc000);
+ mac68k_iops[ISM_IOP].iop = (IOPHW *)
+ ((u_char *)IOBase + 0x1e000);
+ break;
+ case MACH_MACIIFX:
+ mac68k_iops[SCC_IOP].iop = (IOPHW *)
+ ((u_char *)IOBase + 0x4000);
+ mac68k_iops[ISM_IOP].iop = (IOPHW *)
+ ((u_char *)IOBase + 0x12000);
+ break;
+ }
+
+ ioph = mac68k_iops[SCC_IOP].iop;
+ ioph->control_status = 0x82; /* Reset */
+ ioph->control_status = IOP_BYPASS; /* Set to bypass */
+
+ ioph = mac68k_iops[ISM_IOP].iop;
+ ioph->control_status = 0x82; /* Reset */
+
+ if (!fullinit) {
+ return;
+ }
+
+ for (ii = 0 ; ii < 2 ; ii++) {
+ iop = &mac68k_iops[ii];
+ ioph = iop->iop;
+ for (i = 0; i < IOP_MAXCHAN; i++) {
+ SIMPLEQ_INIT(&iop->sendq[i]);
+ SIMPLEQ_INIT(&iop->recvq[i]);
+ iop->listeners[i] = default_listener;
+ iop->listener_data[i] = NULL;
+ }
+ IOP_LOADADDR(ioph, 0x200);
+ for (i = 0x200; i > 0; i--) {
+ ioph->data = 0;
+ }
+ }
+
+ switch (current_mac_model->machineid) {
+ default:
+ return;
+ case MACH_MACQ900:
+ case MACH_MACQ950:
+#ifdef notyet_maybe_not_ever
+ iop = &mac68k_iops[SCC_IOP];
+ intr_establish(iopscc_hand, iop, 4);
+#endif
+ iop = &mac68k_iops[ISM_IOP];
+ via1_register_irq(2, iopism_hand, iop);
+ via_reg(VIA1, vIER) = 0x84;
+ via_reg(VIA1, vIFR) = 0x04;
+ break;
+ case MACH_MACIIFX:
+ /* oss_register_irq(2, iopism_hand, &ioph); */
+ break;
+ }
+
+ iop = &mac68k_iops[SCC_IOP];
+ ioph = iop->iop;
+ printf("SCC IOP base: 0x%x\n", (unsigned) ioph);
+ pool_init(&iop->pool, sizeof(struct iop_msg), 0, 0, 0, "mac68k_iop1",
+ 0, NULL, NULL, M_DEVBUF);
+ ioph->control_status = 0x80 | IOP_BYPASS;
+
+ iop = &mac68k_iops[ISM_IOP];
+ ioph = iop->iop;
+ printf("ISM IOP base: 0x%x\n", (unsigned) ioph);
+ pool_init(&iop->pool, sizeof(struct iop_msg), 0, 0, 0, "mac68k_iop2",
+ 0, NULL, NULL, M_DEVBUF);
+ iop_write1(ioph, IOP_ADDR_ALIVE, 0);
+
+ printf("OLD cs0: 0x%x\n", (unsigned) ioph->control_status);
+
+ iop_write1(ioph, IOP_ADDR_MAX_SEND_CHAN, 7);
+ iop_write1(ioph, IOP_ADDR_MAX_RECV_CHAN, 7);
+ ioph->control_status = 0x80 | IOP_CS_RUN | IOP_CS_AUTOINC;
+ iop_write1(ioph, IOP_ADDR_ALIVE, 0);
+{unsigned cs, c2;
+ cs = (unsigned) ioph->control_status;
+ printf("OLD cs1: 0x%x\n", cs);
+ cs = 0;
+ do { c2 = iop_read1(ioph, IOP_ADDR_ALIVE); cs++; } while (c2 != 0xff);
+ printf("OLD cs2: 0x%x (i = %d)\n", (unsigned) ioph->control_status, cs);
+}
+}
+
+static __inline__ void
+_iop_upload(ioph, mem, nb, iopbase)
+ IOPHW *ioph;
+ u_char *mem;
+ u_long nb, iopbase;
+{
+ IOP_LOADADDR(ioph, iopbase);
+ while (nb--) {
+ ioph->data = *mem++;
+ }
+}
+
+void
+iop_upload(iopn, mem, nb, iopbase)
+ int iopn;
+ u_char *mem;
+ u_long nb, iopbase;
+{
+ IOPHW *ioph;
+
+ if (iopn & ~1) return;
+ ioph = mac68k_iops[iopn].iop;
+ if (!ioph) return;
+
+ _iop_upload(ioph, mem, nb, iopbase);
+}
+
+static __inline__ void
+_iop_download(ioph, mem, nb, iopbase)
+ IOPHW *ioph;
+ u_char *mem;
+ u_long nb, iopbase;
+{
+ IOP_LOADADDR(ioph, iopbase);
+ while (nb--) {
+ *mem++ = ioph->data;
+ }
+}
+
+void
+iop_download(iopn, mem, nb, iopbase)
+ int iopn;
+ u_char *mem;
+ u_long nb, iopbase;
+{
+ IOPHW *ioph;
+
+ if (iopn & ~1) return;
+ ioph = mac68k_iops[iopn].iop;
+ if (!ioph) return;
+
+ _iop_download(ioph, mem, nb, iopbase);
+}
+
+static void
+iopism_hand(arg)
+ void *arg;
+{
+ IOP *iop;
+ IOPHW *ioph;
+ u_char cs;
+ u_char m, s;
+ int i;
+
+ iop = (IOP *) arg;
+ ioph = iop->iop;
+ cs = ioph->control_status;
+
+printf("iopism_hand.\n");
+
+#if DIAGNOSTIC
+ if ((cs & IOP_INTERRUPT) == 0) {
+ printf("IOP_ISM interrupt--no interrupt!? (cs 0x%x)\n",
+ (u_int) cs);
+ }
+#endif
+
+ /*
+ * Scan send queues for complete messages.
+ */
+ if (cs & IOP_CS_INT0) {
+ ioph->control_status |= IOP_CS_INT0;
+ m = iop_read1(ioph, IOP_ADDR_MAX_SEND_CHAN);
+ for (i = 0; i < m; i++) {
+ s = iop_read1(ioph, IOP_ADDR_SEND_STATE + i);
+ if (s == IOP_MSG_COMPLETE) {
+ iop_message_sent(iop, i);
+ }
+ }
+ }
+
+ /*
+ * Scan receive queue for new messages.
+ */
+ if (cs & IOP_CS_INT1) {
+ ioph->control_status |= IOP_CS_INT1;
+ m = iop_read1(ioph, IOP_ADDR_MAX_RECV_CHAN);
+ for (i = 0; i < m; i++) {
+ s = iop_read1(ioph, IOP_ADDR_RECV_STATE + i);
+ if (s == IOP_MSG_NEW) {
+ receive_iop_message(iop, i);
+ }
+ }
+ }
+}
+
+static void
+load_msg_to_iop(ioph, msg)
+ IOPHW *ioph;
+ struct iop_msg *msg;
+{
+ int offset;
+
+ msg->status = IOP_MSGSTAT_SENDING;
+ offset = IOP_ADDR_SEND_MSG + msg->channel * IOP_MSGLEN;
+ _iop_upload(ioph, msg->msg, IOP_MSGLEN, offset);
+ iop_write1(ioph, IOP_ADDR_SEND_STATE + msg->channel, IOP_MSG_NEW);
+
+ /* ioph->control_status |= IOP_CS_IRQ; */
+ ioph->control_status = (ioph->control_status & 0xfe) | IOP_CS_IRQ;
+}
+
+static void
+iop_message_sent(iop, chan)
+ IOP *iop;
+ int chan;
+{
+ IOPHW *ioph;
+ struct iop_msg *msg;
+
+ ioph = iop->iop;
+
+ msg = SIMPLEQ_FIRST(&iop->sendq[chan]);
+ msg->status = IOP_MSGSTAT_SENT;
+ SIMPLEQ_REMOVE_HEAD(&iop->sendq[chan], msg, iopm);
+
+ msg->handler(iop, msg);
+
+ pool_put(&iop->pool, msg);
+
+ if (!(msg = SIMPLEQ_FIRST(&iop->sendq[chan]))) {
+ iop_write1(ioph, IOP_ADDR_SEND_STATE + chan, IOP_MSG_IDLE);
+ } else {
+ load_msg_to_iop(ioph, msg);
+ }
+}
+
+static void
+receive_iop_message(iop, chan)
+ IOP *iop;
+ int chan;
+{
+ IOPHW *ioph;
+ struct iop_msg *msg;
+ int offset;
+
+ msg = SIMPLEQ_FIRST(&iop->recvq[chan]);
+ if (msg) {
+ SIMPLEQ_REMOVE_HEAD(&iop->recvq[chan], msg, iopm);
+ } else {
+ msg = &iop->unsolicited_msg;
+ msg->channel = chan;
+ msg->handler = iop->listeners[chan];
+ msg->user_data = iop->listener_data[chan];
+ }
+
+ offset = IOP_ADDR_RECV_MSG + chan * IOP_MSGLEN;
+ _iop_download(ioph, msg->msg, IOP_MSGLEN, offset);
+ msg->status = IOP_MSGSTAT_RECEIVED;
+
+ msg->handler(iop, msg);
+
+ if (msg != &iop->unsolicited_msg)
+ pool_put(&iop->pool, msg);
+
+ iop_write1(ioph, IOP_ADDR_RECV_STATE + chan, IOP_MSG_COMPLETE);
+ ioph->control_status |= IOP_CS_IRQ;
+
+ if ((msg = SIMPLEQ_FIRST(&iop->recvq[chan])) != NULL) {
+ msg->status = IOP_MSGSTAT_RECEIVING;
+ }
+}
+
+int
+iop_send_msg(iopn, chan, mesg, msglen, handler, user_data)
+ int iopn, chan, msglen;
+ u_char *mesg;
+ iop_msg_handler handler;
+ void *user_data;
+{
+ struct iop_msg *msg;
+ IOP *iop;
+ int s;
+
+ if (iopn & ~1) return -1;
+ iop = &mac68k_iops[iopn];
+ if (!iop) return -1;
+ if (msglen > IOP_MSGLEN) return -1;
+
+ msg = (struct iop_msg *) pool_get(&iop->pool, PR_WAITOK);
+ if (msg == NULL) return -1;
+printf("have msg buffer for IOP: %#x\n", (unsigned) iop->iop);
+ msg->channel = chan;
+ if (msglen < IOP_MSGLEN) memset(msg->msg, '\0', IOP_MSGLEN);
+ memcpy(msg->msg, mesg, msglen);
+ msg->handler = handler;
+ msg->user_data = user_data;
+
+ msg->status = IOP_MSGSTAT_QUEUED;
+
+ s = splhigh();
+ SIMPLEQ_INSERT_TAIL(&iop->sendq[chan], msg, iopm);
+ if (msg == SIMPLEQ_FIRST(&iop->sendq[chan])) {
+ msg->status = IOP_MSGSTAT_SENDING;
+printf("loading msg to iop: cs: 0x%x V1-%x- ", (unsigned) iop->iop->control_status, (unsigned)via_reg(VIA1, vIFR));
+ load_msg_to_iop(iop->iop, msg);
+printf("msg loaded to iop: cs: 0x%x V1-%x- ", (unsigned) iop->iop->control_status, (unsigned)via_reg(VIA1, vIFR));
+ }
+
+{int i; for (i=0;i<100;i++) {
+printf(" cs: 0x%x V1-%x- ", (unsigned) iop->iop->control_status, (unsigned)via_reg(VIA1, vIFR));
+delay(1000);
+}}
+ splx(s);
+
+ return 0;
+}
+
+int
+iop_queue_receipt(iopn, chan, handler, user_data)
+ int iopn, chan;
+ iop_msg_handler handler;
+ void *user_data;
+{
+ struct iop_msg *msg;
+ IOP *iop;
+ int s;
+
+ if (iopn & ~1) return -1;
+ iop = &mac68k_iops[iopn];
+ if (!iop) return -1;
+
+ msg = (struct iop_msg *) pool_get(&iop->pool, PR_WAITOK);
+ if (msg == NULL) return -1;
+ msg->channel = chan;
+ msg->handler = handler;
+ msg->user_data = user_data;
+
+ msg->status = IOP_MSGSTAT_QUEUED;
+
+ s = splhigh();
+ SIMPLEQ_INSERT_TAIL(&iop->recvq[chan], msg, iopm);
+ if (msg == SIMPLEQ_FIRST(&iop->recvq[chan])) {
+ msg->status = IOP_MSGSTAT_RECEIVING;
+ }
+ splx(s);
+
+ return 0;
+}
+
+int
+iop_register_listener(iopn, chan, handler, user_data)
+ int iopn, chan;
+ iop_msg_handler handler;
+ void *user_data;
+{
+ IOP *iop;
+ int s;
+
+ if (iopn & ~1) return -1;
+ iop = &mac68k_iops[iopn];
+ if (!iop) return -1;
+
+ s = splhigh();
+ iop->listeners[chan] = handler;
+ iop->listener_data[chan] = user_data;
+ splx(s);
+
+ return 0;
+}
diff --git a/sys/arch/mac68k/mac68k/locore.s b/sys/arch/mac68k/mac68k/locore.s
index 5467ec862ee..43fb23144dc 100644
--- a/sys/arch/mac68k/mac68k/locore.s
+++ b/sys/arch/mac68k/mac68k/locore.s
@@ -1,4 +1,4 @@
-/* $NetBSD: locore.s,v 1.117 1999/06/11 06:51:39 scottr Exp $ */
+/* $NetBSD: locore.s,v 1.118 1999/06/28 01:56:57 briggs Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@@ -811,31 +811,6 @@ ENTRY_NOPROFILE(spurintr)
addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS
jra _ASM_LABEL(rei)
-ENTRY_NOPROFILE(lev1intr)
- addql #1,_C_LABEL(intrcnt)+4
- clrl sp@-
- moveml #0xFFFF,sp@-
- movl sp, sp@-
- jbsr _C_LABEL(via1_intr)
- addql #4,sp
- moveml sp@+,#0xFFFF
- addql #4,sp
- addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS
- jra _ASM_LABEL(rei)
-
-ENTRY_NOPROFILE(lev2intr)
- addql #1,_C_LABEL(intrcnt)+8
- clrl sp@-
- moveml #0xFFFF,sp@-
- movl sp, sp@-
- movl _C_LABEL(real_via2_intr),a2
- jbsr a2@
- addql #4,sp
- moveml sp@+,#0xFFFF
- addql #4,sp
- addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS
- jra _ASM_LABEL(rei)
-
ENTRY_NOPROFILE(intrhand) /* levels 3 through 6 */
INTERRUPT_SAVEREG
movw sp@(22),sp@- | push exception vector info
@@ -867,19 +842,21 @@ ENTRY_NOPROFILE(lev7intr)
ENTRY_NOPROFILE(rtclock_intr)
movl d2,sp@- | save d2
movw sr,d2 | save SPL
- movw #SPL2,sr | raise SPL to splclock()
- movl a6@(8),a1 | get pointer to frame in via1_intr
- movl a1@(64),sp@- | push ps
- movl a1@(68),sp@- | push pc
- movl sp,sp@- | push pointer to ps, pc
+ movw _C_LABEL(mac68k_clockipl),sr
+ | raise SPL to splclock()
+ movl a6@,a1 | unwind to frame in intr_dispatch
+ lea a1@(28),a1 | push pointer to interrupt frame
+ movl a1,sp@- | 28 = 16 for regs in intrhand,
+ | + 4 for args to intr_dispatch
+ | + 4 for return address to intrhand
+ | + 4 for value of A6
jbsr _C_LABEL(hardclock) | call generic clock int routine
- lea sp@(12),sp | pop params
+ addql #4,sp | pop param
jbsr _C_LABEL(mrg_VBLQueue) | give programs in the VBLqueue a chance
- addql #1,_C_LABEL(intrcnt)+20
+ addql #1,_C_LABEL(intrcnt)+32
addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS
movw d2,sr | restore SPL
movl sp@+,d2 | restore d2
- movl #1,d0 | clock taken care of
rts | go back from whence we came
/*
@@ -1917,18 +1894,18 @@ ASGLOBAL(fullcflush)
.long 0
#endif
-/* interrupt counters */
+/* interrupt counters -- leave some space for overriding the names */
GLOBAL(intrnames)
- .asciz "spur"
- .asciz "via1"
- .asciz "via2"
- .asciz "scc"
- .asciz "nmi"
- .asciz "clock"
- .asciz "unused1"
- .asciz "unused2"
- .asciz "unused3"
+ .asciz "spur "
+ .asciz "via1 "
+ .asciz "via2 "
+ .asciz "unused1 "
+ .asciz "scc "
+ .asciz "unused2 "
+ .asciz "unused3 "
+ .asciz "nmi "
+ .asciz "clock "
GLOBAL(eintrnames)
.even
diff --git a/sys/arch/mac68k/mac68k/machdep.c b/sys/arch/mac68k/mac68k/machdep.c
index 89b76d76d87..7a4f548c06c 100644
--- a/sys/arch/mac68k/mac68k/machdep.c
+++ b/sys/arch/mac68k/mac68k/machdep.c
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.236 1999/06/26 18:29:28 briggs Exp $ */
+/* $NetBSD: machdep.c,v 1.237 1999/06/28 01:56:57 briggs Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@@ -129,6 +129,7 @@
#include <dev/cons.h>
+#include <machine/iopreg.h>
#include <machine/psc.h>
#include <machine/viareg.h>
#include <mac68k/mac68k/macrom.h>
@@ -266,6 +267,9 @@ mac68k_init()
/* Initialize the VIAs */
via_init();
+ /* Initialize the IOPs (if present) */
+ iop_init(1);
+
/* Initialize the PSC (if present) */
psc_init();
@@ -2076,6 +2080,10 @@ setmachdep()
cpui = &(cpu_models[mac68k_machine.cpu_model_index]);
current_mac_model = cpui;
+ mac68k_machine.via1_ipl = 1;
+ mac68k_machine.via2_ipl = 2;
+ mac68k_machine.aux_interrupts = 0;
+
/*
* Set up any machine specific stuff that we have to before
* ANYTHING else happens
@@ -2122,7 +2130,33 @@ setmachdep()
break;
case MACH_CLASSQ:
case MACH_CLASSQ2:
+ VIA2 = 1;
+ IOBase = 0x50f00000;
+ Via1Base = (volatile u_char *)IOBase;
mac68k_machine.sonic = 1;
+ mac68k_machine.scsi96 = 1;
+ mac68k_machine.zs_chip = 0;
+ via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
+ via_reg(VIA2, vIER) = 0x7f; /* disable VIA2 int */
+
+#if 1
+ switch (current_mac_model->machineid) {
+ default:
+ /* case MACH_MACQ900: These three, at least, support the
+ case MACH_MACQ950: A/UX interrupts. What Quadras don't?
+ case MACH_MACQ700: */
+ /* Enable A/UX interrupt scheme */
+ mac68k_machine.aux_interrupts = 1;
+
+ via_reg(VIA1, vBufB) &= (0xff ^ DB1O_AuxIntEnb);
+ via_reg(VIA1, vDirB) |= DB1O_AuxIntEnb;
+ mac68k_machine.via1_ipl = 6;
+ mac68k_machine.via2_ipl = 2;
+ break;
+ }
+#endif
+
+ break;
case MACH_CLASSAV:
case MACH_CLASSP580:
VIA2 = 1;
@@ -2214,6 +2248,7 @@ mac68k_set_io_offsets(base)
case MACH_MACQ950:
mac68k_machine.scsi96_2 = 1;
sccA = (volatile u_char *)base + 0xc020;
+ iop_init(0); /* For console */
break;
case MACH_MACQ700:
break;
@@ -2267,6 +2302,7 @@ mac68k_set_io_offsets(base)
Via1Base = (volatile u_char *)base;
sccA = (volatile u_char *)base + 0x4020;
SCSIBase = base;
+ iop_init(0); /* For console */
break;
default:
case MACH_CLASSH:
diff --git a/sys/arch/mac68k/mac68k/pram.c b/sys/arch/mac68k/mac68k/pram.c
index 613e0526622..a1da80b4284 100644
--- a/sys/arch/mac68k/mac68k/pram.c
+++ b/sys/arch/mac68k/mac68k/pram.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pram.c,v 1.17 1998/02/21 00:37:08 scottr Exp $ */
+/* $NetBSD: pram.c,v 1.18 1999/06/28 01:56:58 briggs Exp $ */
/*-
* Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo,
@@ -176,6 +176,7 @@ getPramTime(void)
unsigned long time;
switch (adbHardware) {
+ case ADB_HW_IOP:
case ADB_HW_II: /* access PRAM via VIA interface */
time = (long)getPramTimeII();
return time;
@@ -207,6 +208,7 @@ void
setPramTime(unsigned long time)
{
switch (adbHardware) {
+ case ADB_HW_IOP:
case ADB_HW_II: /* access PRAM via ADB interface */
setPramTimeII(time);
return;
diff --git a/sys/arch/mac68k/mac68k/vectors.s b/sys/arch/mac68k/mac68k/vectors.s
index 0496412b29b..91508258f9c 100644
--- a/sys/arch/mac68k/mac68k/vectors.s
+++ b/sys/arch/mac68k/mac68k/vectors.s
@@ -1,4 +1,4 @@
-| $NetBSD: vectors.s,v 1.13 1998/10/04 23:38:56 thorpej Exp $
+| $NetBSD: vectors.s,v 1.14 1999/06/28 01:56:58 briggs Exp $
| Copyright (c) 1988 University of Utah
| Copyright (c) 1990 Regents of the University of California.
@@ -76,8 +76,8 @@ GLOBAL(vectab)
VECTOR(badtrap) /* 22: unassigned, reserved */
VECTOR(badtrap) /* 23: unassigned, reserved */
VECTOR(spurintr) /* 24: spurious interrupt */
- VECTOR(lev1intr) /* 25: level 1 interrupt autovector */
- VECTOR(lev2intr) /* 26: level 2 interrupt autovector */
+ VECTOR(intrhand) /* 25: level 1 interrupt autovector */
+ VECTOR(intrhand) /* 26: level 2 interrupt autovector */
VECTOR(intrhand) /* 27: level 3 interrupt autovector */
VECTOR(intrhand) /* 28: level 4 interrupt autovector */
VECTOR(intrhand) /* 29: level 5 interrupt autovector */
diff --git a/sys/arch/mac68k/mac68k/via.c b/sys/arch/mac68k/mac68k/via.c
index 42d52ab52c9..e678017a740 100644
--- a/sys/arch/mac68k/mac68k/via.c
+++ b/sys/arch/mac68k/mac68k/via.c
@@ -1,4 +1,4 @@
-/* $NetBSD: via.c,v 1.69 1999/02/20 09:57:35 scottr Exp $ */
+/* $NetBSD: via.c,v 1.70 1999/06/28 01:56:58 briggs Exp $ */
/*-
* Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo,
@@ -46,6 +46,7 @@
#include <sys/systm.h>
#include <machine/cpu.h>
#include <machine/frame.h>
+#include <machine/intr.h>
#include <machine/viareg.h>
void mrg_adbintr __P((void *));
@@ -53,10 +54,10 @@ void mrg_pmintr __P((void *));
void rtclock_intr __P((void *));
void profclock __P((void *));
-void via1_intr __P((struct frame *));
-void via2_intr __P((struct frame *));
-void rbv_intr __P((struct frame *));
-void oss_intr __P((struct frame *));
+void via1_intr __P((void *));
+void via2_intr __P((void *));
+void rbv_intr __P((void *));
+void oss_intr __P((void *));
void via2_nubus_intr __P((void *));
void rbv_nubus_intr __P((void *));
@@ -66,7 +67,6 @@ static void slot_ignore __P((void *));
static void slot_noint __P((void *));
int VIA2 = 1; /* default for II, IIx, IIcx, SE/30. */
-void (*real_via2_intr) __P((struct frame *));
/* VIA1 interrupt handler table */
void (*via1itab[7]) __P((void *)) = {
@@ -79,6 +79,17 @@ void (*via1itab[7]) __P((void *)) = {
rtclock_intr,
};
+/* Arg array for VIA1 interrupts. */
+void *via1iarg[7] = {
+ (void *)0,
+ (void *)1,
+ (void *)2,
+ (void *)3,
+ (void *)4,
+ (void *)5,
+ (void *)6
+};
+
/* VIA2 interrupt handler table */
void (*via2itab[7]) __P((void *)) = {
via2_noint,
@@ -144,6 +155,8 @@ via_init()
/* turn off timer latch */
via_reg(VIA1, vACR) &= 0x3f;
+ intr_establish((int (*)(void *)) via1_intr, NULL, mac68k_machine.via1_ipl);
+
if (VIA2 == VIA2OFF) {
/* Initialize VIA2 */
via2_reg(vT1L) = 0;
@@ -185,10 +198,15 @@ via_init()
break;
}
- real_via2_intr = via2_intr;
+ intr_establish((int (*)(void*))via2_intr, NULL,
+ mac68k_machine.via2_ipl);
via2itab[1] = via2_nubus_intr;
} else if (current_mac_model->class == MACH_CLASSIIfx) { /* OSS */
- real_via2_intr = oss_intr;
+ volatile u_char *ossintr;
+ ossintr = (volatile u_char *)IOBase + 0x1a006;
+ *ossintr = 0;
+ intr_establish((int (*)(void*))oss_intr, NULL,
+ mac68k_machine.via2_ipl);
} else { /* RBV */
#ifdef DISABLE_EXT_CACHE
if (current_mac_model->class == MACH_CLASSIIci) {
@@ -198,7 +216,8 @@ via_init()
via2_reg(rBufB) |= DB2O_CEnable;
}
#endif
- real_via2_intr = rbv_intr;
+ intr_establish((int (*)(void*))rbv_intr, NULL,
+ mac68k_machine.via2_ipl);
via2itab[1] = rbv_nubus_intr;
add_nubus_intr(0, slot_ignore, NULL);
}
@@ -219,8 +238,8 @@ via_set_modem(onoff)
}
void
-via1_intr(fp)
- struct frame *fp;
+via1_intr(intr_arg)
+ void *intr_arg;
{
u_int8_t intbits, bitnum;
u_int mask;
@@ -242,16 +261,17 @@ via1_intr(fp)
bitnum = 0;
do {
if (intbits & mask) {
- via1itab[bitnum]((void *)((int)bitnum));
+ via1itab[bitnum](via1iarg[bitnum]);
/* via_reg(VIA1, vIFR) = mask; */
}
mask <<= 1;
- } while (intbits >= mask && ++bitnum);
+ ++bitnum;
+ } while (intbits >= mask);
}
void
-via2_intr(fp)
- struct frame *fp;
+via2_intr(intr_arg)
+ void *intr_arg;
{
u_int8_t intbits, bitnum;
u_int mask;
@@ -276,8 +296,8 @@ via2_intr(fp)
}
void
-rbv_intr(fp)
- struct frame *fp;
+rbv_intr(intr_arg)
+ void *intr_arg;
{
u_int8_t intbits, bitnum;
u_int mask;
@@ -301,8 +321,8 @@ rbv_intr(fp)
}
void
-oss_intr(fp)
- struct frame *fp;
+oss_intr(intr_arg)
+ void *intr_arg;
{
u_int8_t intbits, bitnum;
u_int mask;
@@ -461,8 +481,15 @@ via_powerdown()
if (VIA2 == VIA2OFF) {
via2_reg(vDirB) |= 0x04; /* Set write for bit 2 */
via2_reg(vBufB) &= ~0x04; /* Shut down */
- } else if (VIA2 == RBVOFF)
+ } else if (VIA2 == RBVOFF) {
via2_reg(rBufB) &= ~0x04;
+ } else if (VIA2 == OSSOFF) {
+ /*
+ * Thanks to Brad Boyer <flar@cegt201.bradley.edu> for the
+ * Linux/mac68k code that I derived this from.
+ */
+ via2_reg(OSS_oRCR) |= OSS_POWEROFF;
+ }
}
void
@@ -471,10 +498,13 @@ via1_register_irq(irq, irq_func, client_data)
void (*irq_func)(void *);
void *client_data;
{
- if (irq_func)
+ if (irq_func) {
via1itab[irq] = irq_func;
- else
+ via1iarg[irq] = client_data;
+ } else {
via1itab[irq] = via1_noint;
+ via1iarg[irq] = (void *)0;
+ }
}
void
diff --git a/sys/arch/mac68k/obio/asc.c b/sys/arch/mac68k/obio/asc.c
index a025781cfbc..0bffff4f41a 100644
--- a/sys/arch/mac68k/obio/asc.c
+++ b/sys/arch/mac68k/obio/asc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: asc.c,v 1.31 1999/04/22 18:00:34 ender Exp $ */
+/* $NetBSD: asc.c,v 1.32 1999/06/28 01:56:58 briggs Exp $ */
/*
* Copyright (C) 1997 Scott Reynolds
@@ -189,7 +189,11 @@ ascattach(parent, self, aux)
mac68k_set_bell_callback(asc_ring_bell, sc);
#if __notyet__
- via2_register_irq(VIA2_ASC, asc_intr, sc);
+ if (mac68k_machine.aux_interrupts) {
+ intr_establish((int (*)(void *))asc_intr, sc, 5);
+ } else {
+ via2_register_irq(VIA2_ASC, asc_intr, sc);
+ }
asc_intr_enable();
#endif
}
diff --git a/sys/arch/mac68k/obio/if_sn_obio.c b/sys/arch/mac68k/obio/if_sn_obio.c
index 237644272e8..90caf74bf22 100644
--- a/sys/arch/mac68k/obio/if_sn_obio.c
+++ b/sys/arch/mac68k/obio/if_sn_obio.c
@@ -1,4 +1,4 @@
-/* $NetBSD: if_sn_obio.c,v 1.17 1998/07/05 00:51:10 jonathan Exp $ */
+/* $NetBSD: if_sn_obio.c,v 1.18 1999/06/28 01:56:58 briggs Exp $ */
/*
* Copyright (C) 1997 Allen Briggs
@@ -186,7 +186,11 @@ sn_obio_attach(parent, self, aux)
return;
}
- add_nubus_intr(sc->slotno, snintr, (void *)sc);
+ if (mac68k_machine.aux_interrupts) {
+ intr_establish((int (*)(void *))snintr, (void *)sc, 3);
+ } else {
+ add_nubus_intr(sc->slotno, snintr, (void *)sc);
+ }
}
static int