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.
This commit is contained in:
briggs 1999-06-28 01:56:55 +00:00
parent f9de07203c
commit 71a4446b04
16 changed files with 972 additions and 137 deletions

View File

@ -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

View File

@ -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:

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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)
*/

View File

@ -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)))

View File

@ -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);
extern long intrnames;
char *inames, *g_inames;
/* Non-standard interrupt priority */
mac68k_audioipl = (PSL_S | PSL_IPL2);
g_inames = (char *) &intrnames;
if (mac68k_machine.aux_interrupts) {
if (current_mac_model->class == MACH_CLASSAV)
mac68k_bioipl = mac68k_netipl = (PSL_S | PSL_IPL4);
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();
}

View File

@ -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;
}

View File

@ -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

View File

@ -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:

View File

@ -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;

View File

@ -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 */

View File

@ -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

View File

@ -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
}

View File

@ -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