diff options
| author | briggs <briggs@NetBSD.org> | 1999-06-28 01:56:55 +0000 |
|---|---|---|
| committer | briggs <briggs@NetBSD.org> | 1999-06-28 01:56:55 +0000 |
| commit | 71a4446b0474dfb2e3ef955bb14bd11faed1a970 (patch) | |
| tree | 92eeac468ef562a1106d9c1f13638b8d752eab0f /sys | |
| parent | f9de07203c7aaa21be218345abfdb6879edc67be (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.mac68k | 3 | ||||
| -rw-r--r-- | sys/arch/mac68k/dev/adb_direct.c | 175 | ||||
| -rw-r--r-- | sys/arch/mac68k/dev/adbvar.h | 5 | ||||
| -rw-r--r-- | sys/arch/mac68k/dev/pm_direct.c | 43 | ||||
| -rw-r--r-- | sys/arch/mac68k/include/cpu.h | 6 | ||||
| -rw-r--r-- | sys/arch/mac68k/include/iopreg.h | 149 | ||||
| -rw-r--r-- | sys/arch/mac68k/include/viareg.h | 18 | ||||
| -rw-r--r-- | sys/arch/mac68k/mac68k/intr.c | 70 | ||||
| -rw-r--r-- | sys/arch/mac68k/mac68k/iop.c | 441 | ||||
| -rw-r--r-- | sys/arch/mac68k/mac68k/locore.s | 65 | ||||
| -rw-r--r-- | sys/arch/mac68k/mac68k/machdep.c | 38 | ||||
| -rw-r--r-- | sys/arch/mac68k/mac68k/pram.c | 4 | ||||
| -rw-r--r-- | sys/arch/mac68k/mac68k/vectors.s | 6 | ||||
| -rw-r--r-- | sys/arch/mac68k/mac68k/via.c | 74 | ||||
| -rw-r--r-- | sys/arch/mac68k/obio/asc.c | 8 | ||||
| -rw-r--r-- | sys/arch/mac68k/obio/if_sn_obio.c | 8 |
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 |
