summaryrefslogtreecommitdiff
path: root/sys/arch/mac68k
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/mac68k')
-rw-r--r--sys/arch/mac68k/conf/GENERIC3
-rw-r--r--sys/arch/mac68k/conf/GENERICSBC3
-rw-r--r--sys/arch/mac68k/conf/files.mac68k3
-rw-r--r--sys/arch/mac68k/dev/adb_direct.c14
-rw-r--r--sys/arch/mac68k/dev/pm_direct.c9
-rw-r--r--sys/arch/mac68k/dev/z8530reg.h51
-rw-r--r--sys/arch/mac68k/dev/z8530sc.c152
-rw-r--r--sys/arch/mac68k/dev/z8530sc.h128
-rw-r--r--sys/arch/mac68k/dev/z8530tty.c764
-rw-r--r--sys/arch/mac68k/dev/z8530tty.h140
-rw-r--r--sys/arch/mac68k/dev/zs.c905
-rw-r--r--sys/arch/mac68k/include/intr.h9
-rw-r--r--sys/arch/mac68k/include/z8530var.h106
-rw-r--r--sys/arch/mac68k/mac68k/intr.c194
-rw-r--r--sys/arch/mac68k/mac68k/locore.s70
-rw-r--r--sys/arch/mac68k/mac68k/machdep.c32
-rw-r--r--sys/arch/mac68k/mac68k/pmap_bootstrap.c7
-rw-r--r--sys/arch/mac68k/mac68k/psc.c76
-rw-r--r--sys/arch/mac68k/mac68k/vectors.s12
-rw-r--r--sys/arch/mac68k/mac68k/via.c31
20 files changed, 1395 insertions, 1314 deletions
diff --git a/sys/arch/mac68k/conf/GENERIC b/sys/arch/mac68k/conf/GENERIC
index 0ed58cf74e6..0ea7da7ea81 100644
--- a/sys/arch/mac68k/conf/GENERIC
+++ b/sys/arch/mac68k/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.34 2004/09/16 09:14:03 mickey Exp $
+# $OpenBSD: GENERIC,v 1.35 2004/11/25 18:32:06 miod Exp $
# $NetBSD: GENERIC,v 1.52 1997/01/13 23:34:07 scottr Exp $
#
# GENERIC - an all-in-one kernel for the mac68k
@@ -14,7 +14,6 @@ option M68020 # Must have 68851 PMMU
option FPSP
option FPU_EMULATE
option COMPAT_SUNOS # SunOS m68k binary compatibility
-option ZS_CONSOLE_ABORT
option DISABLE_EXT_CACHE # Don't use IIci external cache
option DISABLE_ADB_WITH_SERIAL_CONSOLE
#option MRG_ADB # Use ROM-based ADB driver
diff --git a/sys/arch/mac68k/conf/GENERICSBC b/sys/arch/mac68k/conf/GENERICSBC
index 20b9c1bbe5e..cbde64ba41b 100644
--- a/sys/arch/mac68k/conf/GENERICSBC
+++ b/sys/arch/mac68k/conf/GENERICSBC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERICSBC,v 1.18 2004/09/16 09:14:03 mickey Exp $
+# $OpenBSD: GENERICSBC,v 1.19 2004/11/25 18:32:06 miod Exp $
# $NetBSD: GENERIC,v 1.52 1997/01/13 23:34:07 scottr Exp $
#
# GENERICSBC --- our generic kernel using the SBC SCSI driver
@@ -14,7 +14,6 @@ option M68020 # Must have 68851 PMMU
option FPSP
option FPU_EMULATE
option COMPAT_SUNOS # SunOS m68k binary compatibility
-option ZS_CONSOLE_ABORT
option DISABLE_EXT_CACHE # Don't use IIci external cache
option DISABLE_ADB_WITH_SERIAL_CONSOLE
#option MRG_ADB # Use ROM-based ADB driver
diff --git a/sys/arch/mac68k/conf/files.mac68k b/sys/arch/mac68k/conf/files.mac68k
index 726f03adcda..015308f2bf0 100644
--- a/sys/arch/mac68k/conf/files.mac68k
+++ b/sys/arch/mac68k/conf/files.mac68k
@@ -1,4 +1,4 @@
-# $OpenBSD: files.mac68k,v 1.31 2004/10/08 13:04:36 grange Exp $
+# $OpenBSD: files.mac68k,v 1.32 2004/11/25 18:32:06 miod Exp $
# $NetBSD: files.mac68k,v 1.61 1997/03/01 20:22:16 scottr Exp $
# mac68k-specific configuration info
@@ -104,6 +104,7 @@ file arch/mac68k/mac68k/bus_space.c
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/machdep.c
file arch/mac68k/mac68k/macrom.c
file arch/mac68k/mac68k/macromasm.s
diff --git a/sys/arch/mac68k/dev/adb_direct.c b/sys/arch/mac68k/dev/adb_direct.c
index 3200c91a940..73214a76ef9 100644
--- a/sys/arch/mac68k/dev/adb_direct.c
+++ b/sys/arch/mac68k/dev/adb_direct.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: adb_direct.c,v 1.13 2003/11/03 06:43:02 david Exp $ */
+/* $OpenBSD: adb_direct.c,v 1.14 2004/11/25 18:32:10 miod Exp $ */
/* $NetBSD: adb_direct.c,v 1.5 1997/04/21 18:04:28 scottr Exp $ */
/* From: adb_direct.c 2.02 4/18/97 jpw */
@@ -204,8 +204,6 @@ int ADBNumDevices; /* num. of ADB devices found with ADBReInit */
extern struct mac68k_machine_S mac68k_machine;
-int zshard(int);
-
void pm_setup_adb(void);
void pm_check_adb_devices(int);
void pm_intr(void);
@@ -1073,7 +1071,7 @@ switch_start:
ADB_SET_STATE_ACKON(); /* start ACK to ADB chip */
delay(ADB_DELAY); /* delay */
ADB_SET_STATE_ACKOFF(); /* end ACK to ADB chip */
- zshard(0); /* grab any serial interrupts */
+ (void)intr_dispatch(0x70);
break;
case ADB_ACTION_IN:
@@ -1087,7 +1085,7 @@ switch_start:
ADB_SET_STATE_ACKON(); /* start ACK to ADB chip */
delay(ADB_DELAY); /* delay */
ADB_SET_STATE_ACKOFF(); /* end ACK to ADB chip */
- zshard(0); /* grab any serial interrupts */
+ (void)intr_dispatch(0x70);
if (1 == ending) { /* end of message? */
ADB_SET_STATE_INACTIVE(); /* signal end of frame */
@@ -1148,7 +1146,7 @@ switch_start:
adbActionState = ADB_ACTION_OUT; /* set next state */
delay(ADB_DELAY); /* delay */
- zshard(0); /* grab any serial interrupts */
+ (void)intr_dispatch(0x70);
if (ADB_INTR_IS_ON) { /* ADB intr low during
* write */
@@ -1189,13 +1187,13 @@ switch_start:
adbWriteDelay = 1; /* must retry when done with
* read */
delay(ADB_DELAY); /* delay */
- zshard(0); /* grab any serial interrupts */
+ (void)intr_dispatch(0x70);
goto switch_start; /* process next state right
* now */
break;
}
delay(ADB_DELAY); /* required delay */
- zshard(0); /* grab any serial interrupts */
+ (void)intr_dispatch(0x70);
if (adbOutputBuffer[0] == adbSentChars) { /* check for done */
if (0 == adb_cmd_result(adbOutputBuffer)) { /* do we expect data
diff --git a/sys/arch/mac68k/dev/pm_direct.c b/sys/arch/mac68k/dev/pm_direct.c
index 9602a3e5741..3ed9b2ae26e 100644
--- a/sys/arch/mac68k/dev/pm_direct.c
+++ b/sys/arch/mac68k/dev/pm_direct.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pm_direct.c,v 1.6 2003/03/14 10:47:36 miod Exp $ */
+/* $OpenBSD: pm_direct.c,v 1.7 2004/11/25 18:32:10 miod Exp $ */
/* pm_direct.c 1.22 01/09/97 Takashi Hamada */
/*
@@ -173,7 +173,6 @@ extern int adbStarting; /* doing ADB reinit, so do "polling" differently */
/*
* Define the external functions
*/
-extern int zshard(int); /* from zs.c */
extern void adb_comp_exec(void); /* from adb_direct.c */
@@ -255,7 +254,7 @@ pm_wait_busy(delay)
{
while(PM_IS_ON) {
#ifdef PM_GRAB_SI
- zshard(0); /* grab any serial interrupts */
+ (void)intr_dispatch(0x70);
#endif
if ((--delay) < 0)
return( 1 ); /* timeout */
@@ -273,7 +272,7 @@ pm_wait_free(delay)
{
while(PM_IS_OFF) {
#ifdef PM_GRAB_SI
- zshard(0); /* grab any serial interrupts */
+ (void)intr_dispatch(0x70);
#endif
if ((--delay) < 0)
return( 0 ); /* timeout */
@@ -980,7 +979,7 @@ pm_adb_op(buffer, compRout, data, command)
if ((via_reg(VIA1, vIFR) & 0x10) == 0x10)
pm_intr();
#ifdef PM_GRAB_SI
- zshard(0); /* grab any serial interrupts */
+ (void)intr_dispatch(0x70);
#endif
if ((--delay) < 0)
return( -1 );
diff --git a/sys/arch/mac68k/dev/z8530reg.h b/sys/arch/mac68k/dev/z8530reg.h
index cc3224ba9d5..57a1cc636cf 100644
--- a/sys/arch/mac68k/dev/z8530reg.h
+++ b/sys/arch/mac68k/dev/z8530reg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: z8530reg.h,v 1.4 2003/06/02 23:27:49 millert Exp $ */
-/* $NetBSD: z8530reg.h,v 1.3 1996/05/18 18:54:23 briggs Exp $ */
+/* $OpenBSD: z8530reg.h,v 1.5 2004/11/25 18:32:10 miod Exp $ */
+/* $NetBSD: z8530reg.h,v 1.7 1996/10/23 00:32:31 gwr Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -60,29 +60,12 @@
* registers 2 and 9 across both channels, and reads registers 2 and 3
* differently for the two channels. We can, however, ignore this much
* of the time.
- */
-
-/*
+ *
* This file also includes flags for the Z85C30 and Z85230 enhanced scc.
* The CMOS 8530 includes extra SDLC functionality, and is used in a
* number of Macs (often in the Z85C80, an 85C30 combined w/ a SCSI
* controller). -wrs
- */
-#if 0 /* Example only! */
-/*
- * The layout of this structure is hardware-dependent!
- * Define these in some machine-dependent place.
- */
-struct zschan {
- volatile u_char zc_csr; /* ctrl, status, or reg. number */
- volatile u_char zc_data; /* data or numbered register */
-};
-struct zsdevice {
- struct zschan zs_chan[2];
-};
-#endif /* Example only! */
-
-/*
+ *
* Some of the names in this files were chosen to make the hsis driver
* work unchanged (which means that they will match some in SunOS).
*
@@ -91,9 +74,7 @@ struct zsdevice {
* framing error (missing stop bit, etc)
* end of frame (in synchronous modes)
* parity error (when `parity error is S.C.' is set)
- */
-
-/*
+ *
* Registers with only a single `numeric value' get a name.
* Other registers hold bits and are only numbered; the bit
* definitions imply the register number (see below).
@@ -181,6 +162,8 @@ struct zsdevice {
#define ZSWR1_TIE 0x02 /* transmit interrupt enable */
#define ZSWR1_SIE 0x01 /* external/status interrupt enable */
+#define ZSWR1_IMASK 0x1F /* mask of all itr. enable bits. */
+
/* HSIS compat */
#define ZSWR1_REQ_ENABLE (ZSWR1_REQ_WAIT | ZSWR1_REQ_TX)
@@ -197,6 +180,7 @@ struct zsdevice {
#define ZSWR3_RX_7 0x40 /* receive 7 bits per char */
#define ZSWR3_RX_6 0x80 /* receive 6 bits per char */
#define ZSWR3_RX_8 0xc0 /* receive 8 bits per char */
+#define ZSWR3_RXSIZE 0xc0 /* receive char size mask */
#define ZSWR3_HFC 0x20 /* hardware flow control */
#define ZSWR3_HUNT 0x10 /* enter hunt mode */
@@ -213,19 +197,23 @@ struct zsdevice {
#define ZSWR4_CLK_X16 0x40 /* clock divisor = 16 */
#define ZSWR4_CLK_X32 0x80 /* clock divisor = 32 */
#define ZSWR4_CLK_X64 0xc0 /* clock divisor = 64 */
+#define ZSWR4_CLK_MASK 0xc0 /* clock divisor mask */
#define ZSWR4_MONOSYNC 0x00 /* 8 bit sync char (sync only) */
#define ZSWR4_BISYNC 0x10 /* 16 bit sync char (sync only) */
-#define ZSWR4_SDLC 0x20 /* SDLC mode */
+#define ZSWR4_SDLC 0x20 /* SDLC mode */
#define ZSWR4_EXTSYNC 0x30 /* external sync mode */
+#define ZSWR4_SYNC_MASK 0x30 /* sync mode bit mask */
-#define ZSWR4_SYNCMODE 0x00 /* one of the above sync modes */
-#define ZSWR4_ONESB 0x04 /* 1 stop bit */
-#define ZSWR4_1P5SB 0x08 /* 1.5 stop bits (clk cannot be 1x) */
-#define ZSWR4_TWOSB 0x0c /* 2 stop bits */
+#define ZSWR4_SYNCMODE 0x00 /* no stop bit (sync mode only) */
+#define ZSWR4_ONESB 0x04 /* 1 stop bit */
+#define ZSWR4_1P5SB 0x08 /* 1.5 stop bits (clk cannot be 1x) */
+#define ZSWR4_TWOSB 0x0c /* 2 stop bits */
+#define ZSWR4_SBMASK 0x0c /* mask of all stop bits */
-#define ZSWR4_EVENP 0x02 /* check for even parity */
+#define ZSWR4_EVENP 0x02 /* check for even parity */
#define ZSWR4_PARENB 0x01 /* enable parity checking */
+#define ZSWR4_PARMASK 0x03 /* mask of all parity bits */
/*
* Bits in Write Register 5 (`Transmit Parameter and Controls').
@@ -238,6 +226,7 @@ struct zsdevice {
#define ZSWR5_TX_7 0x20 /* transmit 7 bits */
#define ZSWR5_TX_6 0x40 /* transmit 6 bits */
#define ZSWR5_TX_8 0x60 /* transmit 8 bits */
+#define ZSWR5_TXSIZE 0x60 /* transmit char size mask */
#define ZSWR5_BREAK 0x10 /* send break (continuous 0s) */
#define ZSWR5_TX_ENABLE 0x08 /* enable transmitter */
@@ -340,7 +329,7 @@ struct zsdevice {
* 2 bps
*
* rounded down to an integer. This can be computed entirely
- * in integer arithemtic as:
+ * in integer arithmetic as:
*
* f + bps
* ------- - 2
diff --git a/sys/arch/mac68k/dev/z8530sc.c b/sys/arch/mac68k/dev/z8530sc.c
index acded984c68..6ec3fef5ac6 100644
--- a/sys/arch/mac68k/dev/z8530sc.c
+++ b/sys/arch/mac68k/dev/z8530sc.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: z8530sc.c,v 1.6 2004/08/03 12:10:47 todd Exp $ */
-/* $NetBSD: z8530sc.c,v 1.1 1996/05/18 18:54:28 briggs Exp $ */
+/* $OpenBSD: z8530sc.c,v 1.7 2004/11/25 18:32:10 miod Exp $ */
+/* $NetBSD: z8530sc.c,v 1.5 1996/12/17 20:42:40 gwr Exp $ */
/*
* Copyright (c) 1994 Gordon W. Ross
@@ -61,11 +61,13 @@
#include <sys/kernel.h>
#include <sys/syslog.h>
-/* #include <dev/ic/z8530reg.h> */
-#include "z8530reg.h"
+#include <mac68k/dev/z8530reg.h>
#include <machine/z8530var.h>
-int
+static void zsnull_intr(struct zs_chanstate *);
+static void zsnull_softint(struct zs_chanstate *);
+
+void
zs_break(cs, set)
struct zs_chanstate *cs;
int set;
@@ -82,26 +84,10 @@ zs_break(cs, set)
}
zs_write_reg(cs, 5, cs->cs_creg[5]);
splx(s);
-
- return 0;
}
/*
- * Compute the current baud rate given a ZSCC channel.
- */
-int
-zs_getspeed(cs)
- struct zs_chanstate *cs;
-{
- int tconst;
-
- tconst = zs_read_reg(cs, 12);
- tconst |= zs_read_reg(cs, 13) << 8;
- return (TCONST_TO_BPS(cs->cs_pclk_div16, tconst));
-}
-
-/*
* drain on-chip fifo
*/
void
@@ -130,49 +116,6 @@ zs_iflush(cs)
}
}
-/*
- * Figure out if a chip is an NMOS 8530, a CMOS 8530,
- * or an 85230. We use a form of the test in the Zilog SCC
- * users manual.
- */
-int
-zs_checkchip(cs)
- struct zs_chanstate *cs;
-{
- char r1, r2, r3;
- int chip;
-
- /* we assume we can write to the chip */
-
- r1=cs->cs_creg[15]; /* see if bit 0 sticks */
- zs_write_reg(cs, 15, (r1 | ZSWR15_ENABLE_ENHANCED));
- if ((zs_read_reg(cs, 15) & ZSWR15_ENABLE_ENHANCED) != 0) {
- /* we have either an 8580 or 85230. NB Zilog says we should only
- * have an 85230 at this point, but the 8580 seems to pass this
- * test too. To test, we try to write to WR7', and see if we
- * loose sight of RR14. */
- r2=cs->cs_creg[14];
- r3=(r2 != 0x47) ? 0x47 : 0x40;
- /* unique bit pattern to turn on reading of WR7' at RR14 */
- zs_write_reg(cs, 7, ~r2);
- if (zs_read_reg(cs, ZSRR_ENHANCED) != r2) {
- chip = ZS_CHIP_ESCC;
- zs_write_reg(cs, 7, cs->cs_creg[ZS_ENHANCED_REG]);
- } else {
- chip = ZS_CHIP_8580;
- zs_write_reg(cs, 7, cs->cs_creg[7]);
- }
- zs_write_reg(cs, 15, r1);
- } else { /* now we have to tell an NMOS from a CMOS; does WR15 D2 work? */
- zs_write_reg(cs, 15, (r1 | ZSWR15_SDLC_FIFO));
- r2=cs->cs_creg[2];
- zs_write_reg(cs, 2, (r2 | 0x80));
- chip = (zs_read_reg(cs, 6) & 0x80) ? ZS_CHIP_NMOS : ZS_CHIP_CMOS;
- zs_write_reg(cs, 2, r2);
- }
- zs_write_reg(cs, 15, r1);
- return chip;
-}
/*
* Write the given register set to the given zs channel in the proper order.
@@ -201,8 +144,7 @@ zs_loadchannelregs(cs)
#endif
/* disable interrupts */
- zs_write_reg(cs, 1, reg[1] &
- ~(ZSWR1_RIE_SPECIAL_ONLY | ZSWR1_TIE | ZSWR1_SIE));
+ zs_write_reg(cs, 1, reg[1] & ~ZSWR1_IMASK);
/* baud clock divisor, stop bits, parity */
zs_write_reg(cs, 4, reg[4]);
@@ -234,11 +176,11 @@ zs_loadchannelregs(cs)
/* Shut down the BRG */
zs_write_reg(cs, 14, reg[14] & ~ZSWR14_BAUD_ENA);
-
- if ((cs->cs_cclk_flag & ZSC_EXTERN) ||
- (cs->cs_pclk_flag & ZSC_EXTERN))
- zsmd_setclock(cs);
- /* the md layer wants to do something; let it. */
+
+#ifdef ZS_MD_SETCLK
+ /* Let the MD code setup any external clock. */
+ ZS_MD_SETCLK(cs);
+#endif /* ZS_MD_SETCLK */
/* clock mode control */
zs_write_reg(cs, 11, reg[11]);
@@ -253,7 +195,8 @@ zs_loadchannelregs(cs)
/* which lines cause status interrupts */
zs_write_reg(cs, 15, reg[15]);
- /* Zilog docs recommend resetting external status twice at this
+ /*
+ * Zilog docs recommend resetting external status twice at this
* point. Mainly as the status bits are latched, and the first
* interrupt clear might unlatch them to new values, generating
* a second interrupt request.
@@ -265,11 +208,8 @@ zs_loadchannelregs(cs)
zs_write_reg(cs, 3, reg[3]);
zs_write_reg(cs, 5, reg[5]);
- /* interrupt enables: TX, TX, STATUS */
+ /* interrupt enables: RX, TX, STATUS */
zs_write_reg(cs, 1, reg[1]);
-
- cs->cs_cclk_flag = cs->cs_pclk_flag;
- cs->cs_csource = cs->cs_psource;
}
@@ -293,53 +233,37 @@ zsc_intr_hard(arg)
register struct zs_chanstate *cs_b;
register int rval;
register u_char rr3, rr3a;
-#ifdef DIAGNOSTIC
- register int loopcount;
- loopcount = ZS_INTERRUPT_CNT;
-#endif
- cs_a = &zsc->zsc_cs[0];
- cs_b = &zsc->zsc_cs[1];
+ cs_a = zsc->zsc_cs[0];
+ cs_b = zsc->zsc_cs[1];
rval = 0;
rr3a = 0;
/* Note: only channel A has an RR3 */
- rr3 = zs_read_reg(cs_a, 3);
-
- while ((rr3 = zs_read_reg(cs_a, ZSRR_IPEND))
-#ifdef DIAGNOSTIC
- && --loopcount
-#endif
- ) {
+ while ((rr3 = zs_read_reg(cs_a, 3)) != 0) {
/* Handle receive interrupts first. */
if (rr3 & ZSRR3_IP_A_RX)
(*cs_a->cs_ops->zsop_rxint)(cs_a);
if (rr3 & ZSRR3_IP_B_RX)
- (*cs_b->cs_ops->zsop_rxint)(cs_b);
+ (*cs_b->cs_ops->zsop_stint)(cs_b);
/* Handle status interrupts (i.e. flow control). */
if (rr3 & ZSRR3_IP_A_STAT)
(*cs_a->cs_ops->zsop_stint)(cs_a);
if (rr3 & ZSRR3_IP_B_STAT)
(*cs_b->cs_ops->zsop_stint)(cs_b);
-
+
/* Handle transmit done interrupts. */
if (rr3 & ZSRR3_IP_A_TX)
(*cs_a->cs_ops->zsop_txint)(cs_a);
if (rr3 & ZSRR3_IP_B_TX)
(*cs_b->cs_ops->zsop_txint)(cs_b);
-
+
+ /* Accumulate so we know what needs to be cleared. */
rr3a |= rr3;
}
-#ifdef DIAGNOSTIC
- if (loopcount == 0) {
- if (rr3 & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT))
- cs_a->cs_flags |= ZS_FLAGS_INTERRUPT_OVERRUN;
- if (rr3 & (ZSRR3_IP_B_RX | ZSRR3_IP_B_TX | ZSRR3_IP_B_STAT))
- cs_b->cs_flags |= ZS_FLAGS_INTERRUPT_OVERRUN;
- }
-#endif
+
/* Clear interrupt. */
if (rr3a & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT)) {
@@ -351,11 +275,7 @@ zsc_intr_hard(arg)
rval |= 2;
}
- if ((cs_a->cs_softreq) || (cs_b->cs_softreq)) {
- /* This is a machine-dependent function (or macro). */
- zsc_req_softint(zsc);
- }
-
+ /* Note: caller will check cs_x->cs_softreq and DTRT. */
return (rval);
}
@@ -369,11 +289,11 @@ zsc_intr_soft(arg)
{
register struct zsc_softc *zsc = arg;
register struct zs_chanstate *cs;
- register int rval, unit;
+ register int rval, chan;
rval = 0;
- for (unit = 0; unit < 2; unit++) {
- cs = &zsc->zsc_cs[unit];
+ for (chan = 0; chan < 2; chan++) {
+ cs = zsc->zsc_cs[chan];
/*
* The softint flag can be safely cleared once
@@ -383,27 +303,33 @@ zsc_intr_soft(arg)
if (cs->cs_softreq) {
cs->cs_softreq = 0;
(*cs->cs_ops->zsop_softint)(cs);
- rval = 1;
+ rval++;
}
}
return (rval);
}
-static void zsnull_intr(struct zs_chanstate *);
-static void zsnull_softint(struct zs_chanstate *);
+/*
+ * Provide a null zs "ops" vector.
+ */
+
+static void zsnull_intr(struct zs_chanstate *);
+static void zsnull_softint(struct zs_chanstate *);
static void
zsnull_intr(cs)
struct zs_chanstate *cs;
{
- zs_write_reg(cs, 1, 0);
- zs_write_reg(cs, 15, 0);
+ /* Ask for softint() call. */
+ cs->cs_softreq = 1;
}
static void
zsnull_softint(cs)
struct zs_chanstate *cs;
{
+ zs_write_reg(cs, 1, 0);
+ zs_write_reg(cs, 15, 0);
}
struct zsops zsops_null = {
diff --git a/sys/arch/mac68k/dev/z8530sc.h b/sys/arch/mac68k/dev/z8530sc.h
index cbde3c453ed..6604c744bff 100644
--- a/sys/arch/mac68k/dev/z8530sc.h
+++ b/sys/arch/mac68k/dev/z8530sc.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: z8530sc.h,v 1.5 2003/06/02 23:27:49 millert Exp $ */
-/* $NetBSD: z8530sc.h,v 1.1 1996/05/18 18:54:30 briggs Exp $ */
+/* $OpenBSD: z8530sc.h,v 1.6 2004/11/25 18:32:10 miod Exp $ */
+/* $NetBSD: z8530sc.h,v 1.5 1996/12/17 20:42:42 gwr Exp $ */
/*
* Copyright (c) 1994 Gordon W. Ross
@@ -44,33 +44,6 @@
/*
- * Clock source info structure
- */
-struct zsclksrc {
- long clk; /* clock rate, in MHz, present on signal line */
- int flags; /* Specifies how this source can be used
- (RTxC divided, RTxC BRG, PCLK BRG, TRxC divided)
- and also if the source is "external" and if it
- is changeable (by an ioctl ex.). The
- source usage flags are used by the tty
- child. The other bits tell zsloadchannelregs
- if it should call an md signal source
- changing routine. ZSC_VARIABLE says if
- an ioctl should be able to cahnge the
- clock rate.*/
-};
-#define ZSC_PCLK 0x01
-#define ZSC_RTXBRG 0x02
-#define ZSC_RTXDIV 0x04
-#define ZSC_TRXDIV 0x08
-#define ZSC_VARIABLE 0x40
-#define ZSC_EXTERN 0x80
-
-#define ZSC_BRG 0x03
-#define ZSC_DIV 0x0c
-
-
-/*
* Software state, per zs channel.
*/
struct zs_chanstate {
@@ -80,16 +53,13 @@ struct zs_chanstate {
volatile u_char *cs_reg_data; /* data or numbered register */
int cs_channel; /* sub-unit number */
- void *cs_private; /* sub-driver data pointer */
+ void *cs_private; /* sub-driver data pointer */
struct zsops *cs_ops;
- int cs_clock_count; /* how many signal sources available */
- struct zsclksrc cs_clocks[4]; /* info on available signal sources */
- int cs_defspeed; /* default baud rate (from PROM) */
- int cs_pclk_div16; /* PCLK / 16 used by zs children w/o multiple
- * baud support - some ports have only
- * one clock source, and some children (kbd & ms)
- * are fixed baud rate */
+ int cs_brg_clk; /* BAUD Rate Generator clock
+ * (usually PCLK / 16) */
+ int cs_defspeed; /* default baud rate */
+ int cs_defcflag; /* default cflag */
/*
* We must keep a copy of the write registers as they are
@@ -106,38 +76,28 @@ struct zs_chanstate {
*/
u_char cs_creg[16]; /* current values */
u_char cs_preg[16]; /* pending values */
- long cs_cclk_flag; /* flag for current clock source */
- long cs_pclk_flag; /* flag for pending clock source */
- int cs_csource; /* current source # */
- int cs_psource; /* pending source # */
+ int cs_heldchange; /* change pending (creg != preg) */
- u_char cs_heldchange; /* change pending (creg != preg) */
u_char cs_rr0; /* last rr0 processed */
- u_char cs_rr0_changes; /* rr0 changes noted in status int. */
+ u_char cs_rr0_delta; /* rr0 changes at status intr. */
+ u_char cs_rr0_dcd; /* which bit to read as DCD */
+ u_char cs_rr0_cts; /* which bit to read as CTS */
+ /* the above is set only while CRTSCTS is enabled. */
+
+ u_char cs_wr5_dtr; /* which bit to write as DTR */
+ u_char cs_wr5_rts; /* which bit to write as RTS */
+ /* the above is set only while CRTSCTS is enabled. */
char cs_softreq; /* need soft interrupt call */
- char cs_chip; /* type of chip */
- char cs_flags; /* misc. flags */
+ char cs_pad[1];
+ /* MD code might define a larger variant of this. */
};
-#define ZS_INTERRUPT_CNT 10
-#define ZS_FLAGS_INTERRUPT_OVERRUN 0x01
-#define ZS_FLAGS_DEBUG1 0x10
- /* The interrupt service routine will now look to see if more interrupts
- * come in while servicing an interrupt. If so, it keeps servicing
- * them either to exhaustion or until it's tried ZS_INTERRUPT_CNT times.
- * If it tries too many times, it flags a ZS_FLAGS_INTERRUPT_OVERRUN.
- * It shouldn't, but w/o a counter of sorts, we could get hung in an
- * infinite loop because of sick hardware, or because there's a data
- * clock fed on one of the inputs. The DEBUG flag is for testing and has
- * no permanant definition. */
-#define ZS_ENHANCED_REG 8
- /* cs_Xreg which is used to hold WR7' data; reg 8 is an alias to the
- * data port, so we won't miss its loss. */
/*
* Function vector - per channel
*/
-typedef void (*zsop_t)(register struct zs_chanstate *);
+struct zs_chanstate;
+typedef void (*zsop_t) (struct zs_chanstate *);
struct zsops {
zsop_t zsop_rxint; /* receive char available */
zsop_t zsop_stint; /* external/status */
@@ -147,38 +107,24 @@ struct zsops {
extern struct zsops zsops_null;
-struct zsc_softc {
- struct device zsc_dev; /* required first: base device */
- struct zs_chanstate zsc_cs[2]; /* channel A and B soft state */
-};
-
struct zsc_attach_args {
int channel; /* two serial channels per zsc */
int hwflags;
};
-#define ZS_HWFLAG_CONSOLE 1
-#define ZS_HWFLAG_CONABRT 2
-#define ZS_HWFLAG_RAW 4
-#define ZS_HWFLAG_IGCTS 16
-#define ZS_HWFLAG_IGDCD 32
-/* _CONSOLE says this port is the console, _CONABRT says a Break sequence acts as
- an abort, and _RAW recomends "raw" mode defaults on a tty.
- _CONABRT is turned off if an overly-long break is received.
- _IGCTS and _IGDCD tell the tty layer to ignore CTS or DCD. Assume
- whatever's least supprising (CTS and DCD present). Used mainly for
- external clock support on mac68k. The DCD and CTS pins are used also
- for clock inputs; not good for the UNIX I/O model! */
-
-#define ZS_CHIP_NMOS 0
-#define ZS_CHIP_CMOS 1
-#define ZS_CHIP_8580 2
-#define ZS_CHIP_ESCC 3
-
-void zs_loadchannelregs(struct zs_chanstate *);
-int zsc_intr_soft(void *);
-int zsc_intr_hard(void *);
-int zs_checkchip(struct zs_chanstate *);
-int zs_break(struct zs_chanstate *, int);
-int zs_getspeed(struct zs_chanstate *);
-void zs_iflush(struct zs_chanstate *);
-
+#define ZS_HWFLAG_CONSOLE 1
+#define ZS_HWFLAG_NO_DCD 2 /* Ignore the DCD bit */
+#define ZS_HWFLAG_NO_CTS 4 /* Ignore the CTS bit */
+#define ZS_HWFLAG_RAW 8 /* advise raw mode */
+
+int zsc_intr_hard(void *);
+int zsc_intr_soft(void *);
+
+void zs_abort(struct zs_chanstate *);
+void zs_break(struct zs_chanstate *, int);
+void zs_iflush (struct zs_chanstate *);
+void zs_loadchannelregs(struct zs_chanstate *);
+int zs_set_speed (struct zs_chanstate *, int);
+int zs_set_modes (struct zs_chanstate *, int);
+int zs_getspeed(struct zs_chanstate *);
+
+extern int zs_major;
diff --git a/sys/arch/mac68k/dev/z8530tty.c b/sys/arch/mac68k/dev/z8530tty.c
index 975e36851b8..e2bc82c2f67 100644
--- a/sys/arch/mac68k/dev/z8530tty.c
+++ b/sys/arch/mac68k/dev/z8530tty.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: z8530tty.c,v 1.15 2003/11/03 06:43:02 david Exp $ */
-/* $NetBSD: z8530tty.c,v 1.10 1996/12/18 05:17:44 scottr Exp $ */
+/* $OpenBSD: z8530tty.c,v 1.16 2004/11/25 18:32:10 miod Exp $ */
+/* $NetBSD: z8530tty.c,v 1.14 1996/12/17 20:42:43 gwr Exp $ */
/*
* Copyright (c) 1994 Gordon W. Ross
@@ -47,6 +47,19 @@
*
* This is the "slave" driver that will be attached to
* the "zsc" driver for plain "tty" async. serial lines.
+ *
+ * Credits, history:
+ *
+ * The original version of this code was the sparc/dev/zs.c driver
+ * as distributed with the Berkeley 4.4 Lite release. Since then,
+ * Gordon Ross reorganized the code into the current parent/child
+ * driver scheme, separating the Sun keyboard and mouse support
+ * into independent child drivers.
+ *
+ * RTS/CTS flow-control support was a collaboration of:
+ * Gordon Ross <gwr@netbsd.org>,
+ * Bill Studenmund <wrstuden@loki.stanford.edu>
+ * Ian Dall <Ian.Dall@dsto.defence.gov.au>
*/
#include <sys/param.h>
@@ -62,8 +75,7 @@
#include <sys/kernel.h>
#include <sys/syslog.h>
-/* #include <dev/ic/z8530reg.h> */
-#include "z8530reg.h"
+#include <mac68k/dev/z8530reg.h>
#include <machine/z8530var.h>
#ifdef KGDB
@@ -71,6 +83,15 @@ extern int zs_check_kgdb();
#endif
/*
+ * How many input characters we can buffer.
+ * The port-specific var.h may override this.
+ * Note: must be a power of two!
+ */
+#ifndef ZSTTY_RING_SIZE
+#define ZSTTY_RING_SIZE 2048
+#endif
+
+/*
* Make this an option variable one can patch.
* But be warned: this must be a power of 2!
*/
@@ -79,7 +100,50 @@ int zstty_rbuf_size = ZSTTY_RING_SIZE;
/* This should usually be 3/4 of ZSTTY_RING_SIZE */
int zstty_rbuf_hiwat = (ZSTTY_RING_SIZE - (ZSTTY_RING_SIZE >> 2));
-struct zstty_stats z8530tty_stats;
+struct zstty_softc {
+ struct device zst_dev; /* required first: base device */
+ struct tty *zst_tty;
+ struct zs_chanstate *zst_cs;
+
+ int zst_hwflags; /* see z8530var.h */
+ int zst_swflags; /* TIOCFLAG_SOFTCAR, ... <ttycom.h> */
+
+ /*
+ * Printing an overrun error message often takes long enough to
+ * cause another overrun, so we only print one per second.
+ */
+ long zst_rotime; /* time of last ring overrun */
+ long zst_fotime; /* time of last fifo overrun */
+
+ /*
+ * The receive ring buffer.
+ */
+ int zst_rbget; /* ring buffer `get' index */
+ volatile int zst_rbput; /* ring buffer `put' index */
+ int zst_ringmask;
+ int zst_rbhiwat;
+
+ u_short *zst_rbuf; /* rr1, data pairs */
+
+ /*
+ * The transmit byte count and address are used for pseudo-DMA
+ * output in the hardware interrupt code. PDMA can be suspended
+ * to get pending changes done; heldtbc is used for this. It can
+ * also be stopped for ^S; this sets TS_TTSTOP in tp->t_state.
+ */
+ int zst_tbc; /* transmit byte count */
+ caddr_t zst_tba; /* transmit buffer address */
+ int zst_heldtbc; /* held tbc while xmission stopped */
+
+ /* Flags to communicate with zstty_softint() */
+ volatile char zst_rx_blocked; /* input block at ring */
+ volatile char zst_rx_overrun; /* ring overrun */
+ volatile char zst_tx_busy; /* working on an output chunk */
+ volatile char zst_tx_done; /* done with one output chunk */
+ volatile char zst_tx_stopped; /* H/W level stop (lost CTS) */
+ volatile char zst_st_check; /* got a status interrupt */
+ char pad[2];
+};
/* Definition of the driver for autoconfig. */
@@ -104,21 +168,20 @@ static int zsparam(struct tty *, struct termios *);
static void zs_modem(struct zstty_softc *zst, int onoff);
static int zshwiflow(struct tty *, int);
static void zs_hwiflow(struct zstty_softc *, int);
-static int zsgetbaud(register struct zs_chanstate *,
- register int *rate, register int *tc, register u_char *rr4,
- register u_char *rr11, register u_char *rr14,
- register int *source, register int *sourceflag);
-
+static void zstty_rxint(register struct zs_chanstate *);
+static void zstty_txint(register struct zs_chanstate *);
+static void zstty_stint(register struct zs_chanstate *);
+static void zstty_softint(struct zs_chanstate *);
+static void zsoverrun(struct zstty_softc *, long *, char *);
/*
* zstty_match: how is this zs channel configured?
*/
int
-zstty_match(parent, vcf, aux)
+zstty_match(parent, match, aux)
struct device *parent;
- void *vcf;
- void *aux;
+ void *match, *aux;
{
- struct cfdata *cf = (struct cfdata *) vcf;
+ struct cfdata *cf = match;
struct zsc_attach_args *args = aux;
/* Exact match is better than wildcard. */
@@ -147,31 +210,22 @@ zstty_attach(parent, self, aux)
int channel, tty_unit;
dev_t dev;
- cf = zst->zst_dev.dv_cfdata;
tty_unit = zst->zst_dev.dv_unit;
channel = args->channel;
- cs = &zsc->zsc_cs[channel];
+ cs = zsc->zsc_cs[channel];
cs->cs_private = zst;
cs->cs_ops = &zsops_tty;
zst->zst_cs = cs;
zst->zst_swflags = cf->cf_flags; /* softcar, etc. */
zst->zst_hwflags = args->hwflags;
-
- zst->zst_cflag = ZSTTY_DEF_CFLAG; /* set up defaults */
- zst->zst_iflag = TTYDEF_IFLAG; /* an ioctl can change */
- zst->zst_lflag = TTYDEF_LFLAG; /* these values, modifying */
- zst->zst_oflag = TTYDEF_OFLAG; /* initial defaults */
- zst->zst_ispeed = zst->zst_ospeed = cs->cs_defspeed;
- /* zst_cc set after tty is malloc'd */
-
- dev = makedev(ZSTTY_MAJOR, tty_unit);
+ dev = makedev(zs_major, tty_unit);
if (zst->zst_swflags)
printf(" flags 0x%x", zst->zst_swflags);
if (zst->zst_hwflags & ZS_HWFLAG_CONSOLE)
- printf(" (console)");
+ printf(": console");
else {
#ifdef KGDB
/*
@@ -189,50 +243,39 @@ zstty_attach(parent, self, aux)
}
#endif
}
+ printf("\n");
tp = ttymalloc();
tp->t_dev = dev;
tp->t_oproc = zsstart;
tp->t_param = zsparam;
tp->t_hwiflow = zshwiflow;
- ttychars(tp);
- bcopy(tp->t_cc, zst->zst_cc, sizeof(tp->t_cc));
zst->zst_tty = tp;
zst->zst_rbhiwat = zstty_rbuf_size; /* impossible value */
zst->zst_ringmask = zstty_rbuf_size - 1;
zst->zst_rbuf = malloc(zstty_rbuf_size * sizeof(zst->zst_rbuf[0]),
M_DEVBUF, M_WAITOK);
+ /* XXX - Do we need an MD hook here? */
- zstty_mdattach(zsc, zst, cs, tp); /*let the md code customize stuff */
-
- if (zst->zst_hwflags & (ZS_HWFLAG_IGCTS | ZS_HWFLAG_IGDCD)) {
- printf("\n Ignoring ");
- switch (zst->zst_hwflags & (ZS_HWFLAG_IGCTS | ZS_HWFLAG_IGDCD)) {
- case ZS_HWFLAG_IGCTS:
- printf("CTS line "); break;
- case ZS_HWFLAG_IGDCD:
- printf("DCD line "); break;
- default:
- printf("CTS and DCD lines ");
- }
- }
-
- printf("\n");
/*
* Hardware init
*/
if (zst->zst_hwflags & ZS_HWFLAG_CONSOLE) {
- /* This unit is the console. */
+ /* Call zsparam similar to open. */
+ struct termios t;
+
+ /* Make console output work while closed. */
zst->zst_swflags |= TIOCFLAG_SOFTCAR;
- /* Call _param so interrupts get enabled. */
- bcopy(&zst->zst_termios, &tp->t_termios, sizeof(struct termios));
- /* copy the whole termios in as the first "first open" won't
- * do it since the speed != 0 */
- cs->cs_defspeed = zs_getspeed(cs);
- tp->t_ispeed = cs->cs_defspeed;
- tp->t_ospeed = cs->cs_defspeed;
- (void) zsparam(tp, &tp->t_termios);
+ /* Setup the "new" parameters in t. */
+ bzero((void*)&t, sizeof(t));
+ t.c_cflag = cs->cs_defcflag;
+ t.c_ospeed = cs->cs_defspeed;
+ /* Enable interrupts. */
+ cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_SIE;
+ /* Make sure zsparam will see changes. */
+ tp->t_ospeed = 0;
+ (void) zsparam(tp, &t);
} else {
/* Not the console; may need reset. */
int reset, s;
@@ -296,10 +339,6 @@ zsopen(dev, flags, mode, p)
tp = zst->zst_tty;
cs = zst->zst_cs;
-#ifdef ZSTTYDEBUG
- zsprintf("zs_open to channel at %p\n",cs->cs_reg_csr);
-#endif
-
/* If KGDB took the line, then tp==NULL */
if (tp == NULL)
return (EBUSY);
@@ -315,57 +354,78 @@ zsopen(dev, flags, mode, p)
s = spltty();
if ((tp->t_state & TS_ISOPEN) == 0) {
- if ((tp->t_ispeed == 0) || (zst->zst_resetdef)) {
- /* First open. Executed if either the tty
- * was uninitialized, or if we choose to
- * reset defaults w/ each open. */
- bcopy(&zst->zst_termios, &tp->t_termios,
- sizeof(struct termios));
- if (zst->zst_swflags & TIOCFLAG_CLOCAL)
- tp->t_cflag |= CLOCAL;
- if (zst->zst_swflags & TIOCFLAG_CRTSCTS)
- tp->t_cflag |= CRTSCTS;
- if (zst->zst_swflags & TIOCFLAG_MDMBUF)
- tp->t_cflag |= MDMBUF;
+ /* First open. */
+ struct termios t;
+
+ /*
+ * Setup the "new" parameters in t.
+ * Can not use tp->t because zsparam
+ * deals only with what has changed.
+ */
+ bzero((void*)&t, sizeof(t));
+ t.c_cflag = cs->cs_defcflag;
+ if (zst->zst_swflags & TIOCFLAG_CLOCAL)
+ t.c_cflag |= CLOCAL;
+ if (zst->zst_swflags & TIOCFLAG_CRTSCTS)
+ t.c_cflag |= CRTSCTS;
+ if (zst->zst_swflags & TIOCFLAG_MDMBUF)
+ t.c_cflag |= MDMBUF;
+ t.c_ospeed = cs->cs_defspeed;
+ /* Enable interrupts. */
+ cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_SIE;
+ /* Make sure zsparam will see changes. */
+ tp->t_ospeed = 0;
+ (void) zsparam(tp, &t);
+ /*
+ * Note: zsparam has done: cflag, ispeed, ospeed
+ * so we just need to do: iflag, oflag, lflag, cc
+ * For "raw" mode, just leave all zeros.
+ */
+ if ((zst->zst_hwflags & ZS_HWFLAG_RAW) == 0) {
+ tp->t_iflag = TTYDEF_IFLAG;
+ tp->t_oflag = TTYDEF_OFLAG;
+ tp->t_lflag = TTYDEF_LFLAG;
+ ttychars(tp);
}
- (void) zsparam(tp, &tp->t_termios);
ttsetwater(tp);
/* Flush any pending input. */
zst->zst_rbget = zst->zst_rbput;
zs_iflush(cs); /* XXX */
- /* Turn on DTR */
- zs_modem(zst, 1);
+ /* DTR was turned on by zsparam. */
if (zst->zst_swflags & TIOCFLAG_SOFTCAR) {
tp->t_state |= TS_CARR_ON;
}
+ /* XXX - The MD code could just force CLOCAL instead. */
+ if (zst->zst_hwflags & ZS_HWFLAG_NO_DCD) {
+ tp->t_state |= TS_CARR_ON;
+ }
}
error = 0;
- /* Wait for carrier. */
-#ifdef ZSTTYDEBUG
- zsprintf("wait for carrier...\n");
-#endif
- for (;;) {
+ /* In this section, we may touch the chip. */
+ (void)splzs();
- if (zst->zst_hwflags & ZS_HWFLAG_IGDCD) {
- tp->t_state |= TS_CARR_ON;
- break;
- }
+ /*
+ * Get initial value of RR0. This is done after we
+ * raise DTR in case the cable loops DTR back to CTS.
+ */
+ cs->cs_rr0 = zs_read_csr(cs);
- /* Might never get status intr if carrier already on. */
- cs->cs_rr0 = zs_read_csr(cs);
- if (cs->cs_rr0 & ZSRR0_DCD) {
+ /*
+ * Wait for DCD (if necessary). Note that we might
+ * never get status interrupt if DCD is already on.
+ */
+ for (;;) {
+ /* Check the DCD bit (if we have one). */
+ if (cs->cs_rr0 & cs->cs_rr0_dcd)
tp->t_state |= TS_CARR_ON;
- break;
- }
if ((tp->t_state & TS_CARR_ON) ||
(tp->t_cflag & CLOCAL) ||
(flags & O_NONBLOCK) )
- {
break;
- }
+ /* Sleep waiting for a status interrupt. */
tp->t_state |= TS_WOPEN;
error = ttysleep(tp, (caddr_t)&tp->t_rawq,
TTIPRI | PCATCH, ttopen, 0);
@@ -378,18 +438,12 @@ zsopen(dev, flags, mode, p)
}
break;
}
+ /* The status interrupt changed cs->cs_rr0 */
}
splx(s);
-
-#ifdef ZSTTYDEBUG
- zsprintf("...carrier %s\n",
- (tp->t_state & TS_CARR_ON) ? "on" : "off");
-#endif
-
if (error == 0)
error = linesw[tp->t_line].l_open(dev, tp);
-
return (error);
}
@@ -406,11 +460,7 @@ zsclose(dev, flags, mode, p)
struct zstty_softc *zst;
register struct zs_chanstate *cs;
register struct tty *tp;
- int hup;
-
-#ifdef ZSTTYDEBUG
- zsprintf("zs_close\n");
-#endif
+ int hup, s;
zst = zstty_cd.cd_devs[minor(dev)];
cs = zst->zst_cs;
@@ -421,6 +471,14 @@ zsclose(dev, flags, mode, p)
return 0;
(*linesw[tp->t_line].l_close)(tp, flags);
+
+ /* Disable interrupts. */
+ s = splzs();
+ cs->cs_creg[1] = cs->cs_preg[1] = 0;
+ zs_write_reg(cs, 1, cs->cs_creg[1]);
+ splx(s);
+
+ /* Maybe do "hangup" (drop DTR). */
hup = tp->t_cflag & HUPCL;
if (zst->zst_swflags & TIOCFLAG_SOFTCAR)
hup = 0;
@@ -432,7 +490,6 @@ zsclose(dev, flags, mode, p)
if (cs->cs_creg[5] & ZSWR5_BREAK) {
zs_break(cs, 0);
}
- /* XXX - turn off interrupts? */
ttyclose(tp);
return (0);
@@ -495,9 +552,12 @@ zsioctl(dev, cmd, data, flag, p)
error = ttioctl(tp, cmd, data, flag, p);
if (error >= 0)
return (error);
- error = zsmdioctl(tp, cmd, data, flag, p);
- if (error >= 0)
- return (error);
+
+ #ifdef ZS_MD_IOCTL
+ error = ZS_MD_IOCTL;
+ if (error >= 0)
+ return (error);
+ #endif /* ZS_MD_IOCTL */
switch (cmd) {
@@ -536,30 +596,6 @@ zsioctl(dev, cmd, data, flag, p)
zs_modem(zst, 0);
break;
-#if 0
- case SetSafeOpen:
- error = suser(p, 0);
- if (error != 0)
- return (EPERM);
- zst->zst_resetdef = 1;
- break;
-
- case ClearSafeOpen:
- error = suser(p, 0);
- if (error != 0)
- return (EPERM);
- zst->zst_resetdef = 0;
- break;
-
- case SetOpenDefaults:
- error = suser(p, 0);
- if (error != 0)
- return (EPERM);
- bcopy(&tp->t_termios, &zst->zst_termios, \
- sizeof(struct termios));
- break;
-#endif
-
case TIOCMSET:
case TIOCMBIS:
case TIOCMBIC:
@@ -594,10 +630,10 @@ zsstart(tp)
/*
* If under CRTSCTS hfc and halted, do nothing
+ * This flag can only be set with CRTSCTS.
*/
- if (tp->t_cflag & CRTSCTS)
- if (zst->zst_tx_stopped)
- goto out;
+ if (zst->zst_tx_stopped)
+ goto out;
/*
* If there are sleepers, and output has drained below low
@@ -611,15 +647,15 @@ zsstart(tp)
selwakeup(&tp->t_wsel);
}
+ nch = ndqb(&tp->t_outq, 0); /* XXX */
(void) splzs();
- nch = ndqb(&tp->t_outq, 0); /* XXX */
if (nch) {
register char *p = tp->t_outq.c_cf;
/* mark busy, enable tx done interrupts, & send first byte */
tp->t_state |= TS_BUSY;
-
+ zst->zst_tx_busy = 1;
cs->cs_preg[1] |= ZSWR1_TIE;
cs->cs_creg[1] = cs->cs_preg[1];
zs_write_reg(cs, 1, cs->cs_creg[1]);
@@ -658,144 +694,15 @@ zsstop(tp, flag)
if (tp->t_state & TS_BUSY) {
/*
* Device is transmitting; must stop it.
+ * Also clear _heldtbc to prevent any
+ * flow-control event from resuming.
*/
zst->zst_tbc = 0;
- zst->zst_heldtbc = 0; /* XXX */
+ zst->zst_heldtbc = 0;
if ((tp->t_state & TS_TTSTOP) == 0)
tp->t_state |= TS_FLUSH;
}
splx(s);
- return(0);
-}
-
-#ifndef ZS_TOLERANCE
-#define ZS_TOLERANCE 50
-/* 5% in tenths of a % */
-#endif
-
-/*
- * Search through the signal sources in the channel, and
- * pick the best one for the baud rate requested. Return
- * a -1 if not achievable in tolerance. Otherwise ret 0
- * and fill in the values.
- *
- * This routine draws inspiration from the Atari port's zs.c
- * driver in NetBSD1.1 which did the same type of source switching.
- * Tolerance code inspired by comspeed routine in isa/com.c.
- *
- * By Bill Studenmund, 1996-05-12
- */
-static int
-zsgetbaud(cs, rate, tc, rr4, rr11, rr14, source, sourceflag)
- register struct zs_chanstate *cs;
- register int *rate, *tc, *source, *sourceflag;
- register u_char *rr4, *rr11, *rr14;
-{
- int i, tc0, tc1, s, sf, rate0, rate1, err, tol;
-
- s = -1; /* no valid source yet */
- tol = ZS_TOLERANCE;
-
- sf = 0; tc0 = 0; rate0 = 0; /* XXX Kill gcc warning */
-
- /*
- * Step through all the sources and see which one matches
- * the best. A source has to match BETTER than tol to be chosen.
- * Thus if two sources give the same error, the first one will be
- * chosen. Also, allow for the possability that one source might run
- * both the BRG and the direct divider (i.e. RTxC).
- */
- for (i=0; i< cs->cs_clock_count; i++) {
- if (cs->cs_clocks[i].clk <= 0)
- continue; /* skip non-existent or bad clocks */
- if (cs->cs_clocks[i].flags & ZSC_BRG) {
- /* check out BRG at /16 */
- tc1 = BPS_TO_TCONST(cs->cs_clocks[i].clk >> 4, rate[0]);
- if (tc1 >= 0) {
- rate1 = TCONST_TO_BPS(cs->cs_clocks[i].clk >> 4, tc1);
- err = abs(((rate1 - rate[0])*1000)/rate[0]);
- if (err < tol) {
- tol = err;
- s = i;
- sf = cs->cs_clocks[i].flags & ~ZSC_DIV;
- tc0 = tc1;
- rate0 = rate1;
- }
- }
- }
- if (cs->cs_clocks[i].flags & ZSC_DIV) {
- /*
- * Check out either /1, /16, /32, or /64
- * Note: for /1, you'd better be using a synchronized
- * clock!
- */
- int b0 = cs->cs_clocks[i].clk, e0 = abs(b0-rate[0]);
- int b1 = b0 >> 4, e1 = abs(b1-rate[0]);
- int b2 = b1 >> 1, e2 = abs(b2-rate[0]);
- int b3 = b2 >> 1, e3 = abs(b3-rate[0]);
-
- if (e0 < e1 && e0 < e2 && e0 < e3) {
- err = e0;
- rate1 = b0;
- tc1 = ZSWR4_CLK_X1;
- } else if (e0 > e1 && e1 < e2 && e1 < e3) {
- err = e1;
- rate1 = b1;
- tc1 = ZSWR4_CLK_X16;
- } else if (e0 > e2 && e1 > e2 && e2 < e3) {
- err = e2;
- rate1 = b2;
- tc1 = ZSWR4_CLK_X32;
- } else {
- err = e3;
- rate1 = b3;
- tc1 = ZSWR4_CLK_X64;
- }
-
- err = (err * 1000)/rate[0];
- if (err < tol) {
- tol = err;
- s = i;
- sf = cs->cs_clocks[i].flags & ~ZSC_BRG;
- tc0 = tc1;
- rate0 = rate1;
- }
- }
- }
-#ifdef ZSTTYDEBUG
- zsprintf("Checking for rate %d. Found source #%d.\n",rate[0], s);
-#endif
- if (s == -1) return (-1);
- /*
- * Now we have a source, so set it up.
- */
- *source = s;
- *sourceflag = sf;
- rate[0] = rate0;
- if (sf & ZSC_BRG) {
- *rr4 = ZSWR4_CLK_X16;
- *rr11= ZSWR11_RXCLK_BAUD | ZSWR11_TXCLK_BAUD;
- if (sf & ZSC_PCLK) {
- *rr14 = ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK;
- } else {
- *rr14 = ZSWR14_BAUD_ENA;
- }
- *tc = tc0;
- } else {
- *rr4 = tc0;
- if (sf & ZSC_RTXDIV) {
- *rr11 = ZSWR11_RXCLK_RTXC | ZSWR11_TXCLK_RTXC;
- } else {
- *rr11 = ZSWR11_RXCLK_TRXC | ZSWR11_TXCLK_TRXC;
- }
- *rr14= 0;
- *tc = 0xffff;
- }
-#ifdef ZSTTYDEBUG
- zsprintf("Rate is %7d, tc is %7d, source no. %2d, flags %4x\n", \
- *rate, *tc, *source, *sourceflag);
- zsprintf("Registers are: 4 %x, 11 %x, 14 %x\n\n", *rr4, *rr11, *rr14);
-#endif
return (0);
}
@@ -803,154 +710,146 @@ zsgetbaud(cs, rate, tc, rr4, rr11, rr14, source, sourceflag)
* Set ZS tty parameters from termios.
* XXX - Should just copy the whole termios after
* making sure all the changes could be done.
- * XXX - Only whack the UART when params change...
*/
static int
zsparam(tp, t)
register struct tty *tp;
register struct termios *t;
{
- register struct zstty_softc *zst;
- register struct zs_chanstate *cs;
- register int s, cflag, hfc;
- u_char tmp3, tmp4, tmp5, tmp11, tmp14;
- int bps, tconst, src, srcflag;
+ struct zstty_softc *zst;
+ struct zs_chanstate *cs;
+ int s, bps, cflag, error;
+ u_char tmp3, tmp4, tmp5;
zst = zstty_cd.cd_devs[minor(tp->t_dev)];
cs = zst->zst_cs;
-
bps = t->c_ospeed;
+ cflag = t->c_cflag;
+
if (bps < 0 || (t->c_ispeed && t->c_ispeed != bps))
return (EINVAL);
- if (bps == 0) {
- /* stty 0 => drop DTR and RTS */
- zs_modem(zst, 0);
+
+ /*
+ * Only whack the UART when params change.
+ * Some callers need to clear tp->t_ospee
+ * to make sure initialization gets done.
+ */
+ if ((tp->t_ospeed == bps) &&
+ (tp->t_cflag == cflag) )
return (0);
- }
- if (0 > zsgetbaud(cs, &bps, &tconst, &tmp4, &tmp11, &tmp14,
- &src, &srcflag))
- return (EINVAL);
-
- tp->t_ispeed = tp->t_ospeed = bps;
- cs->cs_psource = src;
- cs->cs_pclk_flag = srcflag;
-
- cflag = t->c_cflag;
/*
- * Make sure we don't enable hfc on a signal line we're ignoring
- *
- * As we enable CTS interrupts only if we have CRTSCTS, this code
- * also effectivly turns off ZSWR15_CTS_IE.
+ * Call MD functions to deal with changed
+ * clock modes or H/W flow control modes.
+ * The BRG divisor is set now. (reg 12,13
*/
- if (zst->zst_hwflags & ZS_HWFLAG_IGDCD)
- cflag &= ~MDMBUF;
- if (zst->zst_hwflags & ZS_HWFLAG_IGCTS)
- cflag &= ~CRTSCTS;
+ error = zs_set_speed(cs, bps);
+ if (error)
+ return (error);
+ error = zs_set_modes(cs, cflag);
+ if (error)
+ return (error);
+
+ /* OK, we are now committed to do it. */
tp->t_cflag = cflag;
+ tp->t_ospeed = bps;
+ tp->t_ispeed = bps;
+
/*
* Block interrupts so that state will not
* be altered until we are done setting it up.
- */
- s = splzs();
-
- /*
+ *
* Initial values in cs_preg are set before
* our attach routine is called. The master
* interrupt enable is handled by zsc.c
*/
+ s = splzs();
- cs->cs_preg[12] = tconst & 255;
- cs->cs_preg[13] = tconst >> 8;
-
+ /* Recompute character size bits. */
+ tmp3 = cs->cs_preg[3] & ~ZSWR3_RXSIZE;
+ tmp5 = cs->cs_preg[5] & ~ZSWR5_TXSIZE;
switch (cflag & CSIZE) {
case CS5:
- tmp3 = ZSWR3_RX_5;
- tmp5 = ZSWR5_TX_5;
+ /* These are |= 0 but let the optimizer deal with it. */
+ tmp3 |= ZSWR3_RX_5;
+ tmp5 |= ZSWR5_TX_5;
break;
case CS6:
- tmp3 = ZSWR3_RX_6;
- tmp5 = ZSWR5_TX_6;
+ tmp3 |= ZSWR3_RX_6;
+ tmp5 |= ZSWR5_TX_6;
break;
case CS7:
- tmp3 = ZSWR3_RX_7;
- tmp5 = ZSWR5_TX_7;
+ tmp3 |= ZSWR3_RX_7;
+ tmp5 |= ZSWR5_TX_7;
break;
case CS8:
default:
- tmp3 = ZSWR3_RX_8;
- tmp5 = ZSWR5_TX_8;
+ tmp3 |= ZSWR3_RX_8;
+ tmp5 |= ZSWR5_TX_8;
break;
}
+ /* Raise or lower DTR and RTS as appropriate. */
+ if (bps) {
+ /* Raise DTR and RTS */
+ tmp5 |= cs->cs_wr5_dtr;
+ } else {
+ /* Drop DTR and RTS */
+ /* XXX: Should SOFTCAR prevent this? */
+ tmp5 &= ~(cs->cs_wr5_dtr);
+ }
+ cs->cs_preg[3] = tmp3;
+ cs->cs_preg[5] = tmp5;
- cs->cs_preg[3] = tmp3 | ZSWR3_RX_ENABLE;
- cs->cs_preg[5] = tmp5 | ZSWR5_TX_ENABLE | ZSWR5_DTR | ZSWR5_RTS;
-
- tmp4 |= (cflag & CSTOPB ? ZSWR4_TWOSB : ZSWR4_ONESB);
+ /*
+ * Recompute the stop bits and parity bits. Note that
+ * zs_set_speed() may have set clock selection bits etc.
+ * in wr4, so those must preserved.
+ */
+ tmp4 = cs->cs_preg[4];
+ /* Recompute stop bits. */
+ tmp4 &= ~ZSWR4_SBMASK;
+ tmp4 |= (cflag & CSTOPB) ?
+ ZSWR4_TWOSB : ZSWR4_ONESB;
+ /* Recompute parity bits. */
+ tmp4 &= ~ZSWR4_PARMASK;
if ((cflag & PARODD) == 0)
tmp4 |= ZSWR4_EVENP;
if (cflag & PARENB)
tmp4 |= ZSWR4_PARENB;
cs->cs_preg[4] = tmp4;
- /*
- * Output hardware flow control on the chip is horrendous:
- * if carrier detect drops, the receiver is disabled and if
- * CTS drops, the transmitter is stoped IN MID CHARACTER!
- * Therefore, do not set the HFC bit, and instead use
- * the status interrupts to detect CTS changes.
- */
- if (cflag & CRTSCTS) {
- zst->zst_rbhiwat = zstty_rbuf_hiwat;
- cs->cs_preg[15] |= ZSWR15_CTS_IE;
- } else {
- zst->zst_rbhiwat = zstty_rbuf_size; /* impossible value */
- cs->cs_preg[15] &= ~ZSWR15_CTS_IE;
- }
- /* Shouldn't the zst_rbhiwat stuff be if (cflag & CHWFLOW) ? wrs */
-
- /*
- * Disable DCD interrupts if we've been told to ignore
- * the DCD pin. Happens on mac68k because the input line for
- * DCD can also be used as a clock input.
- */
- if (zst->zst_hwflags & ZS_HWFLAG_IGDCD)
- cs->cs_preg[15] &= ~ZSWR15_DCD_IE;
- else
- cs->cs_preg[15] |= ZSWR15_DCD_IE;
-
- /*
- * now find out which line to change for input flow control.
- * Important as some ports (mac68k) don't always have input
- * flow control when they have output flow control (RTS actually
- * controls buffers on the Xmitter output).
- */
- hfc = (cflag & CRTSCTS) ? 1 : 0;
- hfc |= (cflag & MDMBUF) ? 2 : 0;
-
- zst->zst_hwimask = zst->zst_hwimasks[hfc];
- if ((zst->zst_rx_blocked) && (zst->zst_hwimask))
- cs->cs_preg[5] &= ~zst->zst_hwimask;
- /* make sure we enforce halted-ness */
-
- /* XXX check for loss of output blocking if loosing hwi ability? */
+ /* The MD function zs_set_modes handled CRTSCTS, etc. */
/*
* If nothing is being transmitted, set up new current values,
* else mark them as pending.
*/
if (cs->cs_heldchange == 0) {
- if (tp->t_state & TS_BUSY) {
+ if (zst->zst_tx_busy) {
zst->zst_heldtbc = zst->zst_tbc;
zst->zst_tbc = 0;
- cs->cs_heldchange = 0xFF;
+ cs->cs_heldchange = 0xFFFF;
} else {
zs_loadchannelregs(cs);
}
}
splx(s);
- /* check for ttstart if lost output flow control? XXX */
+
+ /* If we can throttle input, enable "high water" detection. */
+ if (cflag & CHWFLOW) {
+ zst->zst_rbhiwat = zstty_rbuf_hiwat;
+ } else {
+ /* This impossible value prevents a "high water" trigger. */
+ zst->zst_rbhiwat = zstty_rbuf_size;
+ /* XXX: Lost hwi ability, so unblock and restart. */
+ zst->zst_rx_blocked = 0;
+ if (zst->zst_tx_stopped) {
+ zst->zst_tx_stopped = 0;
+ zsstart(tp);
+ }
+ }
+
return (0);
}
@@ -964,23 +863,25 @@ zs_modem(zst, onoff)
int onoff;
{
struct zs_chanstate *cs;
- struct tty *tp;
- int s, bis, and;
+ int s, clr, set;
cs = zst->zst_cs;
- tp = zst->zst_tty;
+ if (cs->cs_wr5_dtr == 0)
+ return;
if (onoff) {
- bis = ZSWR5_DTR | ZSWR5_RTS;
- and = ~0;
+ clr = 0;
+ set = cs->cs_wr5_dtr;
} else {
- bis = 0;
- and = ~(ZSWR5_DTR | ZSWR5_RTS);
+ clr = cs->cs_wr5_dtr;
+ set = 0;
}
+
s = splzs();
- cs->cs_preg[5] = (cs->cs_preg[5] | bis) & and;
+ cs->cs_preg[5] &= ~clr;
+ cs->cs_preg[5] |= set;
if (cs->cs_heldchange == 0) {
- if (tp->t_state & TS_BUSY) {
+ if (zst->zst_tx_busy) {
zst->zst_heldtbc = zst->zst_tbc;
zst->zst_tbc = 0;
cs->cs_heldchange = (1<<5);
@@ -1004,20 +905,16 @@ zshwiflow(tp, stop)
int stop;
{
register struct zstty_softc *zst;
+ register struct zs_chanstate *cs;
int s;
zst = zstty_cd.cd_devs[minor(tp->t_dev)];
+ cs = zst->zst_cs;
+
+ /* Can not do this without some bit assigned as RTS. */
+ if (cs->cs_wr5_rts == 0)
+ return (0);
- /*
- * This loop checks to see that we can in fact control input.
- * If not, then do little except tell the upper layer the truth.
- */
- if (zst->zst_hwimask == 0) {
- if (stop)
- return 0;
- else
- return 1; /* yes, w/o hwi we can unblock input. ;-) */
- }
s = splzs();
if (stop) {
/*
@@ -1027,14 +924,12 @@ zshwiflow(tp, stop)
if (zst->zst_rx_blocked)
goto out;
zst->zst_rx_blocked = 1;
- z8530tty_stats.tty_block++;
} else {
/*
* The tty layer is asking us to resume input.
* The input ring is always empty by now.
*/
zst->zst_rx_blocked = 0;
- z8530tty_stats.tty_unblock++;
}
zs_hwiflow(zst, stop);
out:
@@ -1052,25 +947,27 @@ zs_hwiflow(zst, stop)
int stop;
{
register struct zs_chanstate *cs;
- register struct tty *tp;
- register int bis, and;
+ register int clr, set;
cs = zst->zst_cs;
- tp = zst->zst_tty;
+
+ if (cs->cs_wr5_rts == 0)
+ return;
if (stop) {
/* Block input (Lower RTS) */
- bis = 0;
- and = ~zst->zst_hwimask;
+ clr = cs->cs_wr5_rts;
+ set = 0;
} else {
/* Unblock input (Raise RTS) */
- bis = zst->zst_hwimask;
- and = ~0;
+ clr = 0;
+ set = cs->cs_wr5_rts;
}
- cs->cs_preg[5] = (cs->cs_preg[5] | bis) & and;
+ cs->cs_preg[5] &= ~clr;
+ cs->cs_preg[5] |= set;
if (cs->cs_heldchange == 0) {
- if (tp->t_state & TS_BUSY) {
+ if (zst->zst_tx_busy) {
zst->zst_heldtbc = zst->zst_tbc;
zst->zst_tbc = 0;
cs->cs_heldchange = (1<<5);
@@ -1086,14 +983,9 @@ zs_hwiflow(zst, stop)
* Interface to the lower layer (zscc)
****************************************************************/
-static void zstty_rxint(register struct zs_chanstate *);
-static void zstty_txint(register struct zs_chanstate *);
-static void zstty_stint(register struct zs_chanstate *);
-static void zsoverrun(struct zstty_softc *, long *, char *);
-static void zstty_softint(struct zs_chanstate *);
-/*
- * XXX: need to do input flow-control to avoid ring overrun.
- */
+static void zstty_rxint (struct zs_chanstate *);
+static void zstty_txint (struct zs_chanstate *);
+static void zstty_stint (struct zs_chanstate *);
/*
* receiver ready interrupt.
@@ -1157,7 +1049,6 @@ nextchar:
if ((cc > zst->zst_rbhiwat) && (zst->zst_rx_blocked == 0)) {
zst->zst_rx_blocked = 1;
zs_hwiflow(zst, 1);
- z8530tty_stats.ring_block++;
}
/* Ask for softint() call. */
@@ -1211,7 +1102,8 @@ zstty_txint(cs)
zs_write_csr(cs, ZSWR0_RESET_TXINT);
/* Ask the softint routine for more output. */
- zst->zst_tx_empty = 1;
+ zst->zst_tx_busy = 0;
+ zst->zst_tx_done = 1;
cs->cs_softreq = 1;
}
@@ -1223,11 +1115,9 @@ zstty_stint(cs)
register struct zs_chanstate *cs;
{
register struct zstty_softc *zst;
- register struct tty *tp;
- register u_char rr0;
+ register u_char rr0, delta;
zst = cs->cs_private;
- tp = zst->zst_tty;
rr0 = zs_read_csr(cs);
zs_write_csr(cs, ZSWR0_RESET_STATUS);
@@ -1236,27 +1126,38 @@ zstty_stint(cs)
* Check here for console break, so that we can abort
* even when interrupts are locking up the machine.
*/
- if ((rr0 & ZSRR0_BREAK))
+ if ((rr0 & ZSRR0_BREAK) &&
+ (zst->zst_hwflags & ZS_HWFLAG_CONSOLE))
{
- zs_abort(zst);
+ zs_abort(cs);
return;
}
/*
+ * We have to accumulate status line changes here.
+ * Otherwise, if we get multiple status interrupts
+ * before the softint runs, we could fail to notice
+ * some status line changes in the softint routine.
+ * Fix from Bill Studenmund, October 1996.
+ */
+ delta = (cs->cs_rr0 ^ rr0);
+ cs->cs_rr0_delta |= delta;
+ cs->cs_rr0 = rr0;
+
+ /*
* Need to handle CTS output flow control here.
* Output remains stopped as long as either the
* zst_tx_stopped or TS_TTSTOP flag is set.
* Never restart here; the softint routine will
* do that after things are ready to move.
*/
- if (((rr0 & ZSRR0_CTS) == 0) && (tp->t_cflag & CRTSCTS)) {
+ if ((delta & cs->cs_rr0_cts) &&
+ ((rr0 & cs->cs_rr0_cts) == 0))
+ {
zst->zst_tbc = 0;
zst->zst_heldtbc = 0;
zst->zst_tx_stopped = 1;
}
-
- cs->cs_rr0_changes |= cs->cs_rr0 ^ rr0;
- cs->cs_rr0 = rr0;
zst->zst_st_check = 1;
/* Ask for softint() call. */
@@ -1273,8 +1174,8 @@ zsoverrun(zst, ptime, what)
char *what;
{
- if (*ptime != time.tv_sec) {
- *ptime = time.tv_sec;
+ if (*ptime != time_second) {
+ *ptime = time_second;
log(LOG_WARNING, "%s: %s overrun\n",
zst->zst_dev.dv_xname, what);
}
@@ -1302,7 +1203,7 @@ zstty_softint(cs)
register int get, c, s;
int ringmask, overrun;
register u_short ring_data;
- register u_char rr0, delta, flag;
+ register u_char rr0, delta;
zst = cs->cs_private;
tp = zst->zst_tty;
@@ -1319,12 +1220,6 @@ zstty_softint(cs)
zst->zst_rx_overrun = 0;
zsoverrun(zst, &zst->zst_rotime, "ring");
}
- if (cs->cs_flags & ZS_FLAGS_INTERRUPT_OVERRUN) {
- (void) splzs();
- cs->cs_flags &= ~ZS_FLAGS_INTERRUPT_OVERRUN;
- (void) spltty();
- zsoverrun(zst, &zst->zst_intotime, "interrupt");
- }
/*
* Copy data from the receive ring into the tty layer.
@@ -1366,7 +1261,6 @@ zstty_softint(cs)
(void) splzs();
zst->zst_rx_blocked = 0;
zs_hwiflow(zst, 0); /* unblock input */
- z8530tty_stats.ring_unblock++;
(void) spltty();
}
@@ -1378,50 +1272,41 @@ zstty_softint(cs)
if (zst->zst_st_check) {
zst->zst_st_check = 0;
+ (void) splzs();
rr0 = cs->cs_rr0;
- delta = cs->cs_rr0_changes;
- cs->cs_rr0_changes = 0;
- if ((delta & ZSRR0_DCD) &&
- ~(zst->zst_hwflags & ZS_HWFLAG_IGDCD)) {
- c = ((rr0 & ZSRR0_DCD) != 0);
- if ((tp->t_cflag & CHWFLOW) == CHWFLOW) {
- flag = 1;
- tp->t_cflag &= ~MDMBUF;
- } else
- flag = 0;
+ delta = cs->cs_rr0_delta;
+ cs->cs_rr0_delta = 0;
+ (void) spltty();
+
+ /* Note, the MD code may use DCD for something else. */
+ if (delta & cs->cs_rr0_dcd) {
+ c = ((rr0 & cs->cs_rr0_dcd) != 0);
if (line->l_modem(tp, c) == 0)
zs_modem(zst, c);
- if (flag)
- tp->t_cflag |= MDMBUF;
- /*
- * The above trick hides MDMBUF from the tty layer
- * if we also have CRTSCTS; Used as mac68k takes
- * the two of them as meaning do CRTSCTS with DCD
- * as the hwi line. Just CRTSCTS doesn't have a
- * hwi line.
- */
}
- if ((delta & ZSRR0_CTS) && (tp->t_cflag & CRTSCTS)) {
+
+ /* Note, cs_rr0_cts is set only with H/W flow control. */
+ if (delta & cs->cs_rr0_cts) {
/*
* Only do restart here. Stop is handled
* at the h/w interrupt level.
*/
- if (rr0 & ZSRR0_CTS) {
+ if (rr0 & cs->cs_rr0_cts) {
zst->zst_tx_stopped = 0;
- tp->t_state &= ~TS_TTSTOP;
+ /* tp->t_state &= ~TS_TTSTOP; */
(*line->l_start)(tp);
}
}
}
- if (zst->zst_tx_empty) {
- zst->zst_tx_empty = 0;
+ if (zst->zst_tx_done) {
+ zst->zst_tx_done = 0;
tp->t_state &= ~TS_BUSY;
if (tp->t_state & TS_FLUSH)
tp->t_state &= ~TS_FLUSH;
else
ndflush(&tp->t_outq, zst->zst_tba -
- (caddr_t) tp->t_outq.c_cf);
+ (caddr_t) tp->t_outq.c_cf);
line->l_start(tp);
}
@@ -1435,4 +1320,3 @@ struct zsops zsops_tty = {
zstty_softint, /* process software interrupt */
};
-
diff --git a/sys/arch/mac68k/dev/z8530tty.h b/sys/arch/mac68k/dev/z8530tty.h
deleted file mode 100644
index ba602c6c178..00000000000
--- a/sys/arch/mac68k/dev/z8530tty.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/* $OpenBSD: z8530tty.h,v 1.3 2003/06/02 23:27:49 millert Exp $ */
-/* $NetBSD: z8530tty.h,v 1.1 1996/05/18 18:54:35 briggs Exp $ */
-
-/*
- * Copyright (c) 1994 Gordon W. Ross
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This software was developed by the Computer Systems Engineering group
- * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
- * contributed to Berkeley.
- *
- * All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Lawrence Berkeley Laboratory.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)zs.c 8.1 (Berkeley) 7/19/93
- */
-
-/*
- * Zilog Z8530 Dual UART driver (tty interface)
- *
- * This is the "slave" driver that will be attached to
- * the "zsc" driver for plain "tty" async. serial lines.
- */
-
-
-/*
- * Allow the MD var.h to override the default CFLAG so that
- * console messages during boot come out with correct parity.
- */
-#ifndef ZSTTY_DEF_CFLAG
-#define ZSTTY_DEF_CFLAG TTYDEF_CFLAG
-#endif
-
-/*
- * How many input characters we can buffer.
- * The port-specific var.h may override this.
- * Note: must be a power of two!
- */
-#ifndef ZSTTY_RING_SIZE
-#define ZSTTY_RING_SIZE 2048
-#endif
-
-struct zstty_stats {
- int ring_block;
- int ring_unblock;
- int tty_block;
- int tty_unblock;
-};
-
-struct zstty_softc {
- struct device zst_dev; /* required first: base device */
- struct tty *zst_tty;
- struct zs_chanstate *zst_cs;
-
- int zst_hwflags; /* see z8530var.h */
- int zst_swflags; /* TIOCFLAG_SOFTCAR, ... <ttycom.h> */
-
- /*
- * Printing an overrun error message often takes long enough to
- * cause another overrun, so we only print one per second.
- */
- long zst_rotime; /* time of last ring overrun */
- long zst_fotime; /* time of last fifo overrun */
- long zst_intotime; /* time of last interrupt overrun */
-
- /*
- * The receive ring buffer.
- */
- int zst_rbget; /* ring buffer `get' index */
- volatile int zst_rbput; /* ring buffer `put' index */
- int zst_ringmask;
- int zst_rbhiwat;
-
- u_short *zst_rbuf; /* rr1, data pairs */
-
- /*
- * The transmit byte count and address are used for pseudo-DMA
- * output in the hardware interrupt code. PDMA can be suspended
- * to get pending changes done; heldtbc is used for this. It can
- * also be stopped for ^S; this sets TS_TTSTOP in tp->t_state.
- */
- int zst_tbc; /* transmit byte count */
- caddr_t zst_tba; /* transmit buffer address */
- int zst_heldtbc; /* held tbc while xmission stopped */
-
- /* Flags to communicate with zstty_softint() */
- volatile char zst_rx_blocked;
- volatile char zst_rx_overrun;
- volatile char zst_tx_stopped;
- volatile char zst_tx_empty;
- volatile char zst_st_check;
- char pad[3];
-
- struct termios zst_termios; /* default values for tty flags */
-#define zst_cflag zst_termios.c_cflag
-#define zst_iflag zst_termios.c_iflag
-#define zst_lflag zst_termios.c_lflag
-#define zst_oflag zst_termios.c_oflag
-#define zst_cc zst_termios.c_cc
-#define zst_ispeed zst_termios.c_ispeed
-#define zst_ospeed zst_termios.c_ospeed
-
- char zst_resetdef; /* !=0 means reset tty defs. on open */
- char zst_hwimask; /* bits to keep low for hwiflow */
-
- char zst_hwimasks[4]; /* masks for hwiflow for HFC modes */
-};
-
-#define ZSTTY_RAW_CFLAG (CS8 | CREAD | HUPCL )
-#define ZSTTY_RAW_IFLAG (IXANY | IMAXBEL)
-#define ZSTTY_RAW_LFLAG (ECHOE|ECHOKE|ECHOCTL)
-#define ZSTTY_RAW_OFLAG (ONLCR | OXTABS)
-/* Above taken from looking at a tty after a stty raw */
diff --git a/sys/arch/mac68k/dev/zs.c b/sys/arch/mac68k/dev/zs.c
index ab82e6d875c..e8f6f83416b 100644
--- a/sys/arch/mac68k/dev/zs.c
+++ b/sys/arch/mac68k/dev/zs.c
@@ -1,7 +1,8 @@
-/* $OpenBSD: zs.c,v 1.15 2004/03/09 21:46:47 xsa Exp $ */
-/* $NetBSD: zs.c,v 1.12 1996/12/18 05:04:22 scottr Exp $ */
+/* $OpenBSD: zs.c,v 1.16 2004/11/25 18:32:10 miod Exp $ */
+/* $NetBSD: zs.c,v 1.19 1998/01/12 19:22:18 thorpej Exp $ */
/*
+ * Copyright (c) 1996-1998 Bill Studenmund
* Copyright (c) 1995 Gordon W. Ross
* All rights reserved.
*
@@ -37,6 +38,19 @@
* Runs two serial lines per chip using slave drivers.
* Plain tty/async lines use the zs_async slave.
* Sun keyboard/mouse uses the zs_kbd/zs_ms slaves.
+ * Other ports use their own mice & keyboard slaves.
+ *
+ * Credits & history:
+ *
+ * With NetBSD 1.1, port-mac68k started using a port of the port-sparc
+ * (port-sun3?) zs.c driver (which was in turn based on code in the
+ * Berkeley 4.4 Lite release). Bill Studenmund did the port, with
+ * help from Allen Briggs and Gordon Ross <gwr@netbsd.org>. Noud de
+ * Brouwer field-tested the driver at a local ISP.
+ *
+ * Bill Studenmund and Gordon Ross then ported the machine-independant
+ * z8530 driver to work with port-mac68k. NetBSD 1.2 contained an
+ * intermediate version (mac68k using a local, patched version of
*/
#include <sys/param.h>
@@ -52,47 +66,62 @@
#include <sys/syslog.h>
#include <dev/cons.h>
-#include "z8530reg.h"
+
+#include <mac68k/dev/z8530reg.h>
#include <machine/z8530var.h>
#include <machine/autoconf.h>
#include <machine/cpu.h>
+#include <machine/psc.h>
#include <machine/viareg.h>
+#ifdef DDB
#include <ddb/db_var.h>
+#endif
+
+/* Are these in a header file anywhere? */
+/* Booter flags interface */
+#define ZSMAC_RAW 0x01
+#define ZSMAC_LOCALTALK 0x02
+#define ZS_STD_BRG (57600*4)
+
+#include "zsc.h" /* get the # of zs chips defined */
/*
- * XXX: Hard code this to make console init easier...
+ * Some warts needed by z8530tty.c -
*/
-#define NZSC 1 /* XXX */
+int zs_def_cflag = (CREAD | CS8 | HUPCL);
+int zs_major = 12;
+
+/*
+ * abort detection on console will now timeout after iterating on a loop
+ * the following # of times. Cheep hack. Also, abort detection is turned
+ * off after a timeout (i.e. maybe there's not a terminal hooked up).
+ */
+#define ZSABORT_DELAY 3000000
/*
* Define interrupt levels.
*/
-#define ZSHARD_PRI 6 /* Wired on the CPU board... */
-#define ZSSOFT_PRI 3 /* Want tty pri (4) but this is OK. */
+#define ZSHARD_PRI 4 /* Wired on the CPU board... */
+/*
+ * Serial port cards with zs chips on them are actually at the
+ * NuBus interrupt level, which is lower than 4. But blocking
+ * level 4 interrupts will block those interrupts too, so level
+ * 4 is fine.
+ */
/* The layout of this is hardware-dependent (padding, order). */
struct zschan {
volatile u_char zc_csr; /* ctrl,status, and indirect access */
u_char zc_xxx0;
- u_char zc_xxx1;
- u_char zc_xxx2;
+ u_char zc_xxx1; /* part of the other channel lives here!*/
+ u_char zc_xxx2; /* Yea Apple! */
volatile u_char zc_data; /* data */
u_char zc_xxx3;
u_char zc_xxx4;
u_char zc_xxx5;
};
-/*
- * The zsdevice structure is not used on the mac68k port as the
- * chip is wired up weird. Channel B & A are interspersed with
- * the data & control bytes
-struct zsdevice {
- /! Yes, they are backwards. !/
- struct zschan zs_chan_b;
- struct zschan zs_chan_a;
-};
-*/
/* Saved PROM mappings */
static char *zsaddr[NZSC]; /* See zs_init() */
@@ -103,16 +132,19 @@ static int zs_defspeed[NZSC][2] = {
{ 9600, /* tty00 */
9600 }, /* tty01 */
};
-/* console stuff */
-void *zs_conschan = 0;
-int zs_consunit;
-/* device that the console is attached to--if serial. */
+void *zs_conschan = 0;
+int zs_consunit;
+/* device to which the console is attached--if serial. */
dev_t mac68k_zsdev;
-/* Mac stuff, some vestages of old mac serial driver here */
+/* Mac stuff */
volatile unsigned char *sccA = 0;
+int nzsc_attached = 0; /* needed as long as we have spurious
+ * interupt problems.
+ */
static struct zschan *zs_get_chan_addr(int zsc_unit, int channel);
void zs_init(void);
+int zs_cn_check_speed(int bps);
static struct zschan *
zs_get_chan_addr(zsc_unit, channel)
@@ -137,7 +169,7 @@ zs_get_chan_addr(zsc_unit, channel)
/* Find PROM mappings (for console support). */
-static int zsinited = 0; /* 0 = not, 1 = inited, not attached, 2= attached */
+int zsinited = 0; /* 0 = not, 1 = inited, not attached, 2= attached */
void
zs_init()
@@ -187,7 +219,7 @@ static u_char zs_init_reg[16] = {
/* Definition of the driver for autoconfig. */
static int zsc_match(struct device *, void *, void *);
static void zsc_attach(struct device *, struct device *, void *);
-static int zsc_print(void *aux, const char *name);
+static int zsc_print(void *, const char *name);
struct cfattach zsc_ca = {
sizeof(struct zsc_softc), zsc_match, zsc_attach
@@ -197,8 +229,8 @@ struct cfdriver zsc_cd = {
NULL, "zsc", DV_DULL
};
-int zshard(void *);
-int zssoft(void *);
+int zshard(void *);
+int zssoft(void *);
/*
@@ -213,22 +245,6 @@ zsc_match(parent, vcf, aux)
return 1;
}
-static int
-zsc_print(aux, name)
- void *aux;
- const char *name;
-{
- struct zsc_attach_args *args = aux;
-
- if (name != NULL)
- printf("%s: ", name);
-
- if (args->channel != -1)
- printf(" channel %d", args->channel);
-
- return UNCONF;
-}
-
/*
* Attach a found zs.
*
@@ -244,12 +260,13 @@ zsc_attach(parent, self, aux)
struct zsc_softc *zsc = (void *) self;
struct zsc_attach_args zsc_args;
volatile struct zschan *zc;
+ struct xzs_chanstate *xcs;
struct zs_chanstate *cs;
int zsc_unit, channel;
- int reset, s;
- int chip = 0; /* XXX quiet bogus gcc warning */
+ int s, chip, theflags;
- if (!zsinited) zs_init();
+ if (!zsinited)
+ zs_init();
zsinited = 2;
zsc_unit = zsc->zsc_dev.dv_unit;
@@ -258,52 +275,138 @@ zsc_attach(parent, self, aux)
if (zsaddr[zsc_unit] == NULL)
panic("zs_attach: zs%d not mapped", zsc_unit);
+ chip = 0;
+#ifdef DEBUG
+ printf(" chip type %d",chip);
+#endif
+ printf("\n");
+
/*
* Initialize software state for each channel.
*/
for (channel = 0; channel < 2; channel++) {
- cs = &zsc->zsc_cs[channel];
-
- zc = zs_get_chan_addr(zsc_unit, channel);
- cs->cs_reg_csr = &zc->zc_csr;
- cs->cs_reg_data = &zc->zc_data;
+ zsc_args.channel = channel;
+ zsc_args.hwflags = zs_hwflags[zsc_unit][channel];
+ xcs = &zsc->xzsc_xcs_store[channel];
+ cs = &xcs->xzs_cs;
+ zsc->zsc_cs[channel] = cs;
cs->cs_channel = channel;
cs->cs_private = NULL;
cs->cs_ops = &zsops_null;
- /* Define BAUD rate clock for the MI code. */
- cs->cs_pclk_div16 = mac68k_machine.sccClkConst*2;
- cs->cs_csource = 0;
- cs->cs_psource = 0;
+ zc = zs_get_chan_addr(zsc_unit, channel);
+ cs->cs_reg_csr = &zc->zc_csr;
+ cs->cs_reg_data = &zc->zc_data;
- cs->cs_defspeed = zs_defspeed[zsc_unit][channel];
+ if (channel == 0) /* Double check interupts are off */
+ zs_write_reg(cs, 9, 0);
bcopy(zs_init_reg, cs->cs_creg, 16);
bcopy(zs_init_reg, cs->cs_preg, 16);
- /*
- * Clear the master interrupt enable.
- * The INTENA is common to both channels,
- * so just do it on the A channel.
- */
+ /* Current BAUD rate generator clock. */
+ cs->cs_brg_clk = ZS_STD_BRG; /* RTxC is 230400*16, so use 230400 */
+ cs->cs_defspeed = zs_defspeed[zsc_unit][channel];
+ cs->cs_defcflag = zs_def_cflag;
+
+ /* Make these correspond to cs_defcflag (-crtscts) */
+ cs->cs_rr0_dcd = ZSRR0_DCD;
+ cs->cs_rr0_cts = 0;
+ cs->cs_wr5_dtr = ZSWR5_DTR;
+ cs->cs_wr5_rts = 0;
+
+#ifdef __notyet__
+ cs->cs_slave_type = ZS_SLAVE_NONE;
+#endif
+
+ /* Define BAUD rate stuff. */
+ xcs->cs_clocks[0].clk = ZS_STD_BRG * 16;
+ xcs->cs_clocks[0].flags = ZSC_RTXBRG;
+ xcs->cs_clocks[1].flags =
+ ZSC_RTXBRG | ZSC_RTXDIV | ZSC_VARIABLE | ZSC_EXTERN;
+ xcs->cs_clocks[2].flags = ZSC_TRXDIV | ZSC_VARIABLE;
+ xcs->cs_clock_count = 3;
+
if (channel == 0) {
- zs_write_reg(cs, 9, 0);
+ theflags = mac68k_machine.modem_flags;
+ xcs->cs_clocks[1].clk = mac68k_machine.modem_dcd_clk;
+ xcs->cs_clocks[2].clk = mac68k_machine.modem_cts_clk;
+ } else {
+ theflags = mac68k_machine.print_flags;
+ xcs->cs_clocks[1].flags = ZSC_VARIABLE;
+ /*
+ * Yes, we aren't defining ANY clock source enables for
+ * the printer's DCD clock in. The hardware won't let
+ * us use it. But a clock will freak out the chip, so
+ * we let you set it, telling us to bar interrupts on
+ * the line.
+ */
+ xcs->cs_clocks[1].clk = mac68k_machine.print_dcd_clk;
+ xcs->cs_clocks[2].clk = mac68k_machine.print_cts_clk;
+ }
+ if (xcs->cs_clocks[1].clk)
+ zsc_args.hwflags |= ZS_HWFLAG_NO_DCD;
+ if (xcs->cs_clocks[2].clk)
+ zsc_args.hwflags |= ZS_HWFLAG_NO_CTS;
+
+#ifdef DEBUG
+ printf("zsc%d channel %d: d_speed %6d DCD clk %ld CTS clk %ld",
+ zsc_unit, channel, cs->cs_defspeed,
+ xcs->cs_clocks[1].clk, xcs->cs_clocks[2].clk);
+#endif
+
+ /* Set defaults in our "extended" chanstate. */
+ xcs->cs_csource = 0;
+ xcs->cs_psource = 0;
+ xcs->cs_cclk_flag = 0; /* Nothing fancy by default */
+ xcs->cs_pclk_flag = 0;
+
+ if (theflags & ZSMAC_RAW) {
+ zsc_args.hwflags |= ZS_HWFLAG_RAW;
+#ifdef DEBUG
+ printf(" (raw defaults)");
+#endif
+ }
- chip = 0; /* We'll turn chip checking on post 1.2 */
- printf(" chip type %d \n",chip);
+ /*
+ * XXX - This might be better done with a "stub" driver
+ * (to replace zstty) that ignores LocalTalk for now.
+ */
+ if (theflags & ZSMAC_LOCALTALK) {
+ printf(" shielding from LocalTalk");
+ cs->cs_defspeed = 1;
+ cs->cs_creg[ZSRR_BAUDLO] = cs->cs_preg[ZSRR_BAUDLO] = 0xff;
+ cs->cs_creg[ZSRR_BAUDHI] = cs->cs_preg[ZSRR_BAUDHI] = 0xff;
+ zs_write_reg(cs, ZSRR_BAUDLO, 0xff);
+ zs_write_reg(cs, ZSRR_BAUDHI, 0xff);
+ /*
+ * If we might have LocalTalk, then make sure we have
+ * the Baud rate low-enough to not do any damage.
+ */
}
- cs->cs_chip = chip;
+
+ /*
+ * We used to disable chip interrupts here, but we now
+ * do that in zscnprobe, just in case MacOS left the chip on.
+ */
+
+ xcs->cs_chip = chip;
+
+ /* Stash away a copy of the final H/W flags. */
+ xcs->cs_hwflags = zsc_args.hwflags;
+
+#ifdef DEBUG
+ printf("\n");
+#endif
/*
* Look for a child driver for this channel.
* The child attach will setup the hardware.
*/
- zsc_args.channel = channel;
- zsc_args.hwflags = zs_hwflags[zsc_unit][channel];
- if (!config_found(self, (void *) &zsc_args, zsc_print)) {
+ if (!config_found(self, (void *)&zsc_args, zsc_print)) {
/* No sub-driver. Just reset it. */
- reset = (channel == 0) ?
+ u_char reset = (channel == 0) ?
ZSWR9_A_RESET : ZSWR9_B_RESET;
s = splzs();
zs_write_reg(cs, 9, reset);
@@ -311,161 +414,111 @@ zsc_attach(parent, self, aux)
}
}
+ if (current_mac_model->class == MACH_CLASSAV) {
+ add_psc_lev4_intr(2, zshard, zsc);
+ add_psc_lev4_intr(3, zshard, zsc);
+ } else {
+ intr_establish(zshard, zsc, ZSHARD_PRI);
+ }
+
+ /* XXX - Now safe to install interrupt handlers. */
+
/*
* Set the master interrupt enable and interrupt vector.
* (common to both channels, do it on A)
*/
- cs = &zsc->zsc_cs[0];
+ cs = zsc->zsc_cs[0];
s = splzs();
/* interrupt vector */
zs_write_reg(cs, 2, zs_init_reg[2]);
/* master interrupt control (enable) */
zs_write_reg(cs, 9, zs_init_reg[9]);
+ nzsc_attached++;
splx(s);
}
-void
-zstty_mdattach(zsc, zst, cs, tp)
- struct zsc_softc *zsc;
- struct zstty_softc *zst;
- struct zs_chanstate *cs;
- struct tty *tp;
+static int
+zsc_print(aux, name)
+ void *aux;
+ const char *name;
{
- int theflags;
-
- zst->zst_resetdef = 0;
- cs->cs_clock_count = 3; /* internal + externals */
- cs->cs_cclk_flag = 0; /* Not doing anything fancy by default */
- cs->cs_pclk_flag = 0;
- cs->cs_clocks[0].clk = mac68k_machine.sccClkConst*32;
- cs->cs_clocks[0].flags = ZSC_RTXBRG; /* allowing divide by 16 will
- melt the driver! */
-
- cs->cs_clocks[1].flags = ZSC_RTXBRG | ZSC_RTXDIV | ZSC_VARIABLE | ZSC_EXTERN;
- cs->cs_clocks[2].flags = ZSC_TRXDIV | ZSC_VARIABLE;
- if (zst->zst_dev.dv_unit == 0) {
- theflags = mac68k_machine.modem_flags;
- cs->cs_clocks[1].clk = mac68k_machine.modem_dcd_clk;
- cs->cs_clocks[2].clk = mac68k_machine.modem_cts_clk;
- } else if (zst->zst_dev.dv_unit == 1) {
- theflags = mac68k_machine.print_flags;
- cs->cs_clocks[1].flags = ZSC_VARIABLE;
- /*
- * Yes, we aren't defining ANY clock source enables for the
- * printer's DCD clock in. The hardware won't let us
- * use it. But a clock will freak out the chip, so we
- * let you set it, telling us to bar interrupts on the line.
- */
- cs->cs_clocks[1].clk = mac68k_machine.print_dcd_clk;
- cs->cs_clocks[2].clk = mac68k_machine.print_cts_clk;
- } else
- theflags = 0;
-
- if (cs->cs_clocks[1].clk)
- zst->zst_hwflags |= ZS_HWFLAG_IGDCD;
- if (cs->cs_clocks[2].clk)
- zst->zst_hwflags |= ZS_HWFLAG_IGCTS;
-
- if (theflags & ZSMAC_RAW) {
- zst->zst_cflag = ZSTTY_RAW_CFLAG;
- zst->zst_iflag = ZSTTY_RAW_IFLAG;
- zst->zst_lflag = ZSTTY_RAW_LFLAG;
- zst->zst_oflag = ZSTTY_RAW_OFLAG;
- printf(" (raw defaults)");
- }
- if (theflags & ZSMAC_LOCALTALK) {
- printf(" shielding from LocalTalk");
- zst->zst_ospeed = tp->t_ospeed = 1;
- zst->zst_ispeed = tp->t_ispeed = 1;
- cs->cs_defspeed = 1;
- cs->cs_creg[ZSRR_BAUDLO] = cs->cs_preg[ZSRR_BAUDLO] = 0xff;
- cs->cs_creg[ZSRR_BAUDHI] = cs->cs_preg[ZSRR_BAUDHI] = 0xff;
- zs_write_reg(cs, ZSRR_BAUDLO, 0xff);
- zs_write_reg(cs, ZSRR_BAUDHI, 0xff);
- /*
- * If we might have LocalTalk, then make sure we have the
- * Baud rate low-enough to not do any damage.
- */
- }
+ struct zsc_attach_args *args = aux;
- /* For the mac, we have rtscts = check CTS for output control, no
- * input control. mdmbuf means check DCD for output, and use DTR
- * for input control. mdmbuf & rtscts means use CTS for output
- * control, and DTR for input control. */
+ if (name != NULL)
+ printf("%s: ", name);
- zst->zst_hwimasks[1] = 0;
- zst->zst_hwimasks[2] = ZSWR5_DTR;
- zst->zst_hwimasks[3] = ZSWR5_DTR;
+ if (args->channel != -1)
+ printf(" channel %d", args->channel);
+ return UNCONF;
}
int
-zsmdioctl(tp, com, data, flag, p)
- struct tty *tp;
- u_long com;
+zsmdioctl(cs, cmd, data)
+ struct zs_chanstate *cs;
+ u_long cmd;
caddr_t data;
- int flag;
- struct proc *p;
{
- return (-1);
+ switch (cmd) {
+ default:
+ return (-1);
+ }
+ return (0);
}
void
zsmd_setclock(cs)
struct zs_chanstate *cs;
{
+ struct xzs_chanstate *xcs = (void *)cs;
+
if (cs->cs_channel != 0)
return;
+
/*
* If the new clock has the external bit set, then select the
* external source.
*/
- via_set_modem((cs->cs_pclk_flag & ZSC_EXTERN) ? 1 : 0);
+ via_set_modem((xcs->cs_pclk_flag & ZSC_EXTERN) ? 1 : 0);
}
+static int zssoftpending;
+
+/*
+ * Do the minimum work to pull data off of the chip and queue it up
+ * for later processing.
+ */
int
zshard(arg)
void *arg;
{
- struct zsc_softc *zsc;
- int unit, rval;
-#ifdef ZSMACDEBUG
- itecnputc(mac68k_zsdev, 'Z');
-#endif
-
- rval = 0;
- unit = zsc_cd.cd_ndevs;
- while (--unit >= 0) {
- zsc = zsc_cd.cd_devs[unit];
- if (zsc != NULL) {
- rval |= zsc_intr_hard(zsc);
- }
- }
-#ifdef ZSMACDEBUG
- itecnputc(mac68k_zsdev, '\n');
-#endif
- return (rval);
-}
+ struct zsc_softc *zsc = (struct zsc_softc *)arg;
+ int rval;
-int zssoftpending;
+ if (zsc == NULL)
+ return 0;
-void
-zsc_req_softint(zsc)
- struct zsc_softc *zsc;
-{
- if (zssoftpending == 0) {
+ rval = 0;
+ rval |= zsc_intr_hard(zsc);
+ if ((zsc->zsc_cs[0]->cs_softreq) || (zsc->zsc_cs[1]->cs_softreq)) {
+ /* zsc_req_softint(zsc); */
/* We are at splzs here, so no need to lock. */
- zssoftpending = ZSSOFT_PRI;
- /* isr_soft_request(ZSSOFT_PRI); */
- setsoftserial();
+ if (zssoftpending == 0) {
+ zssoftpending = 1;
+ setsoftserial();
+ }
}
+ return (rval);
}
+/*
+ * Similar scheme as for zshard (look at all of them)
+ */
int
zssoft(arg)
void *arg;
{
- struct zsc_softc *zsc;
- int unit;
+ register struct zsc_softc *zsc;
+ register int unit;
/* This is not the only ISR on this IPL. */
if (zssoftpending == 0)
@@ -473,32 +526,290 @@ zssoft(arg)
/*
* The soft intr. bit will be set by zshard only if
- * the variable zssoftpending is zero. The order of
- * these next two statements prevents our clearing
- * the soft intr bit just after zshard has set it.
+ * the variable zssoftpending is zero.
*/
-/* isr_soft_clear(ZSSOFT_PRI); */
zssoftpending = 0;
- /* Do ttya/ttyb first, because they go faster. */
- unit = zsc_cd.cd_ndevs;
- while (--unit >= 0) {
+ for (unit = 0; unit < zsc_cd.cd_ndevs; ++unit) {
zsc = zsc_cd.cd_devs[unit];
- if (zsc != NULL) {
- (void) zsc_intr_soft(zsc);
- }
+ if (zsc == NULL)
+ continue;
+ (void) zsc_intr_soft(zsc);
}
return (1);
}
+#ifndef ZS_TOLERANCE
+#define ZS_TOLERANCE 51
+/* 5% in tenths of a %, plus 1 so that exactly 5% will be ok. */
+#endif
+
/*
- * Read or write the chip with suitable delays.
+ * check out a rate for acceptability from the internal clock
+ * source. Used in console config to validate a requested
+ * default speed. Placed here so that all the speed checking code is
+ * in one place.
+ *
+ * != 0 means ok.
*/
-#define ZS_DELAY()
+int
+zs_cn_check_speed(bps)
+ int bps; /* target rate */
+{
+ int tc, rate;
+
+ tc = BPS_TO_TCONST(ZS_STD_BRG, bps);
+ if (tc < 0)
+ return 0;
+ rate = TCONST_TO_BPS(ZS_STD_BRG, tc);
+ if (ZS_TOLERANCE > abs(((rate - bps)*1000)/bps))
+ return 1;
+ else
+ return 0;
+}
+
/*
- * MacII hardware has the delay built in. No need for extra delay. :-)
+ * Search through the signal sources in the channel, and
+ * pick the best one for the baud rate requested. Return
+ * a -1 if not achievable in tolerance. Otherwise return 0
+ * and fill in the values.
+ *
+ * This routine draws inspiration from the Atari port's zs.c
+ * driver in NetBSD 1.1 which did the same type of source switching.
+ * Tolerance code inspired by comspeed routine in isa/com.c.
+ *
+ * By Bill Studenmund, 1996-05-12
*/
+int
+zs_set_speed(cs, bps)
+ struct zs_chanstate *cs;
+ int bps; /* bits per second */
+{
+ struct xzs_chanstate *xcs = (void *) cs;
+ int i, tc, tc0 = 0, tc1, s, sf = 0;
+ int src, rate0, rate1, err, tol;
+
+ if (bps == 0)
+ return (0);
+
+ src = -1; /* no valid source yet */
+ tol = ZS_TOLERANCE;
+
+ /*
+ * Step through all the sources and see which one matches
+ * the best. A source has to match BETTER than tol to be chosen.
+ * Thus if two sources give the same error, the first one will be
+ * chosen. Also, allow for the possability that one source might run
+ * both the BRG and the direct divider (i.e. RTxC).
+ */
+ for (i=0; i < xcs->cs_clock_count; i++) {
+ if (xcs->cs_clocks[i].clk <= 0)
+ continue; /* skip non-existant or bad clocks */
+ if (xcs->cs_clocks[i].flags & ZSC_BRG) {
+ /* check out BRG at /16 */
+ tc1 = BPS_TO_TCONST(xcs->cs_clocks[i].clk >> 4, bps);
+ if (tc1 >= 0) {
+ rate1 = TCONST_TO_BPS(xcs->cs_clocks[i].clk >> 4, tc1);
+ err = abs(((rate1 - bps)*1000)/bps);
+ if (err < tol) {
+ tol = err;
+ src = i;
+ sf = xcs->cs_clocks[i].flags & ~ZSC_DIV; tc0 = tc1;
+ rate0 = rate1;
+ }
+ }
+ }
+ if (xcs->cs_clocks[i].flags & ZSC_DIV) {
+ /*
+ * Check out either /1, /16, /32, or /64
+ * Note: for /1, you'd better be using a synchronized
+ * clock!
+ */
+ int b0 = xcs->cs_clocks[i].clk, e0 = abs(b0-bps);
+ int b1 = b0 >> 4, e1 = abs(b1-bps);
+ int b2 = b1 >> 1, e2 = abs(b2-bps);
+ int b3 = b2 >> 1, e3 = abs(b3-bps);
+
+ if (e0 < e1 && e0 < e2 && e0 < e3) {
+ err = e0;
+ rate1 = b0;
+ tc1 = ZSWR4_CLK_X1;
+ } else if (e0 > e1 && e1 < e2 && e1 < e3) {
+ err = e1;
+ rate1 = b1;
+ tc1 = ZSWR4_CLK_X16;
+ } else if (e0 > e2 && e1 > e2 && e2 < e3) {
+ err = e2;
+ rate1 = b2;
+ tc1 = ZSWR4_CLK_X32;
+ } else {
+ err = e3;
+ rate1 = b3;
+ tc1 = ZSWR4_CLK_X64;
+ }
+
+ err = (err * 1000)/bps;
+ if (err < tol) {
+ tol = err;
+ src = i;
+ sf = xcs->cs_clocks[i].flags & ~ZSC_BRG;
+ tc0 = tc1;
+ rate0 = rate1;
+ }
+ }
+ }
+#ifdef ZSMACDEBUG
+ zsprintf("Checking for rate %d. Found source #%d.\n",bps, src);
+#endif
+ if (src == -1)
+ return (EINVAL); /* no can do */
+
+ /*
+ * The M.I. layer likes to keep cs_brg_clk current, even though
+ * we are the only ones who should be touching the BRG's rate.
+ *
+ * Note: we are assuming that any ZSC_EXTERN signal source comes in
+ * on the RTxC pin. Correct for the mac68k obio zsc.
+ */
+ if (sf & ZSC_EXTERN)
+ cs->cs_brg_clk = xcs->cs_clocks[i].clk >> 4;
+ else
+ cs->cs_brg_clk = ZS_STD_BRG;
+
+ /*
+ * Now we have a source, so set it up.
+ */
+ s = splzs();
+ xcs->cs_psource = src;
+ xcs->cs_pclk_flag = sf;
+ bps = rate0;
+ if (sf & ZSC_BRG) {
+ cs->cs_preg[4] = ZSWR4_CLK_X16;
+ cs->cs_preg[11]= ZSWR11_RXCLK_BAUD | ZSWR11_TXCLK_BAUD;
+ if (sf & ZSC_PCLK) {
+ cs->cs_preg[14] = ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK;
+ } else {
+ cs->cs_preg[14] = ZSWR14_BAUD_ENA;
+ }
+ tc = tc0;
+ } else {
+ cs->cs_preg[4] = tc0;
+ if (sf & ZSC_RTXDIV) {
+ cs->cs_preg[11] = ZSWR11_RXCLK_RTXC | ZSWR11_TXCLK_RTXC; } else {
+ cs->cs_preg[11] = ZSWR11_RXCLK_TRXC | ZSWR11_TXCLK_TRXC; }
+ cs->cs_preg[14]= 0;
+ tc = 0xffff;
+ }
+ /* Set the BAUD rate divisor. */
+ cs->cs_preg[12] = tc;
+ cs->cs_preg[13] = tc >> 8;
+ splx(s);
+
+#ifdef ZSMACDEBUG
+ zsprintf("Rate is %7d, tc is %7d, source no. %2d, flags %4x\n", \
+ bps, tc, src, sf);
+ zsprintf("Registers are: 4 %x, 11 %x, 14 %x\n\n",
+ cs->cs_preg[4], cs->cs_preg[11], cs->cs_preg[14]);
+#endif
+
+ cs->cs_preg[5] |= ZSWR5_RTS; /* Make sure the drivers are on! */
+
+ /* Caller will stuff the pending registers. */
+ return (0);
+}
+
+int
+zs_set_modes(cs, cflag)
+ struct zs_chanstate *cs;
+ int cflag; /* bits per second */
+{
+ struct xzs_chanstate *xcs = (void*)cs;
+ int s;
+
+ /*
+ * Make sure we don't enable hfc on a signal line we're ignoring.
+ * As we enable CTS interrupts only if we have CRTSCTS or CDTRCTS,
+ * this code also effectivly turns off ZSWR15_CTS_IE.
+ *
+ * Also, disable DCD interrupts if we've been told to ignore
+ * the DCD pin. Happens on mac68k because the input line for
+ * DCD can also be used as a clock input. (Just set CLOCAL.)
+ *
+ * If someone tries to turn an invalid flow mode on, Just Say No
+ * (Suggested by gwr)
+ */
+#if 0
+ if ((cflag & CDTRCTS) && (cflag & (CRTSCTS | MDMBUF)))
+ return (EINVAL);
+#endif
+ if (xcs->cs_hwflags & ZS_HWFLAG_NO_DCD) {
+ if (cflag & MDMBUF)
+ return (EINVAL);
+ cflag |= CLOCAL;
+ }
+#if 0
+ if ((xcs->cs_hwflags & ZS_HWFLAG_NO_CTS) && (cflag & (CRTSCTS | CDTRCTS)))
+ return (EINVAL);
+#endif
+
+ /*
+ * Output hardware flow control on the chip is horrendous:
+ * if carrier detect drops, the receiver is disabled, and if
+ * CTS drops, the transmitter is stoped IN MID CHARACTER!
+ * Therefore, NEVER set the HFC bit, and instead use the
+ * status interrupt to detect CTS changes.
+ */
+ s = splzs();
+ if ((cflag & (CLOCAL | MDMBUF)) != 0)
+ cs->cs_rr0_dcd = 0;
+ else
+ cs->cs_rr0_dcd = ZSRR0_DCD;
+ /*
+ * The mac hardware only has one output, DTR (HSKo in Mac
+ * parlance). In HFC mode, we use it for the functions
+ * typically served by RTS and DTR on other ports, so we
+ * have to fake the upper layer out some.
+ *
+ * CRTSCTS we use CTS as an input which tells us when to shut up.
+ * We make no effort to shut up the other side of the connection.
+ * DTR is used to hang up the modem.
+ *
+ * In CDTRCTS, we use CTS to tell us to stop, but we use DTR to
+ * shut up the other side.
+ */
+ if ((cflag & CRTSCTS) != 0){
+ cs->cs_wr5_dtr = ZSWR5_DTR;
+ cs->cs_wr5_rts = 0;
+ cs->cs_rr0_cts = ZSRR0_CTS;
+#if 0
+ } else if ((cflag & CDTRCTS) != 0) {
+ cs->cs_wr5_dtr = 0;
+ cs->cs_wr5_rts = ZSWR5_DTR;
+ cs->cs_rr0_cts = ZSRR0_CTS;
+#endif
+ } else if ((cflag & MDMBUF) != 0) {
+ cs->cs_wr5_dtr = 0;
+ cs->cs_wr5_rts = ZSWR5_DTR;
+ cs->cs_rr0_cts = ZSRR0_DCD;
+ } else {
+ cs->cs_wr5_dtr = ZSWR5_DTR;
+ cs->cs_wr5_rts = 0;
+ cs->cs_rr0_cts = 0;
+ }
+ splx(s);
+
+ /* Caller will stuff the pending registers. */
+ return(0);
+}
+
+/*
+ * Read or write the chip with suitable delays.
+ * MacII hardware has the delay built in.
+ * No need for extra delay. :-) However, some clock-chiped
+ * macs, or zsc's on serial add-on boards might need it.
+ */
+#define ZS_DELAY()
u_char
zs_read_reg(cs, reg)
@@ -528,30 +839,32 @@ zs_write_reg(cs, reg, val)
u_char zs_read_csr(cs)
struct zs_chanstate *cs;
{
- register u_char v;
+ u_char val;
- v = (*cs->cs_reg_csr) ^ ZSRR0_CTS;
- /* make up for the fact CTS is wired backwards */
+ val = *cs->cs_reg_csr;
ZS_DELAY();
- return v;
+ /* make up for the fact CTS is wired backwards */
+ val ^= ZSRR0_CTS;
+ return val;
}
-u_char zs_read_data(cs)
+void zs_write_csr(cs, val)
struct zs_chanstate *cs;
+ register u_char val;
{
- register u_char v;
-
- v = *cs->cs_reg_data;
+ /* Note, the csr does not write CTS... */
+ *cs->cs_reg_csr = val;
ZS_DELAY();
- return v;
}
-void zs_write_csr(cs, val)
+u_char zs_read_data(cs)
struct zs_chanstate *cs;
- u_char val;
{
- *cs->cs_reg_csr = val;
+ register u_char val;
+
+ val = *cs->cs_reg_data;
ZS_DELAY();
+ return val;
}
void zs_write_data(cs, val)
@@ -563,8 +876,11 @@ void zs_write_data(cs, val)
}
/****************************************************************
- * Console support functions (Originally Sun3 specific!)
- * Now works w/ just mac68k port!
+ * Console support functions (mac68k specific!)
+ * Note: this code is allowed to know about the layout of
+ * the chip registers, and uses that to keep things simple.
+ * XXX - I think I like the mvme167 code better. -gwr
+ * XXX - Well :-P :-) -wrs
****************************************************************/
#define zscnpollc nullcnpollc
@@ -587,27 +903,38 @@ extern int zsopen( dev_t dev, int flags, int mode, struct proc *p);
static void
zscnsetup()
{
- struct zs_chanstate cs;
+ struct xzs_chanstate xcs;
+ struct zs_chanstate *cs;
struct zschan *zc;
int tconst, s;
/* Setup temporary chanstate. */
- bzero((caddr_t)&cs, sizeof(cs));
+ bzero((caddr_t)&xcs, sizeof(xcs));
+ cs = &xcs.xzs_cs;
zc = zs_conschan;
- cs.cs_reg_csr = &zc->zc_csr;
- cs.cs_reg_data = &zc->zc_data;
- cs.cs_channel = zs_consunit;
-
- bcopy(zs_init_reg, cs.cs_preg, 16);
- tconst = BPS_TO_TCONST(mac68k_machine.sccClkConst*2, zs_defspeed[0][zs_consunit]);
- cs.cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS;
- cs.cs_preg[1] = 0; /* don't enable interrupts */
- cs.cs_preg[12] = tconst;
- cs.cs_preg[13] = tconst >> 8;
-
- s = splhigh();
- zs_loadchannelregs(&cs);
- splx(s);
+ cs->cs_reg_csr = &zc->zc_csr;
+ cs->cs_reg_data = &zc->zc_data;
+ cs->cs_channel = zs_consunit;
+ cs->cs_brg_clk = ZS_STD_BRG;
+
+ bcopy(zs_init_reg, cs->cs_preg, 16);
+ cs->cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS;
+ cs->cs_preg[15] = ZSWR15_BREAK_IE;
+ tconst = BPS_TO_TCONST(cs->cs_brg_clk,
+ zs_defspeed[0][zs_consunit]);
+ cs->cs_preg[12] = tconst;
+ cs->cs_preg[13] = tconst >> 8;
+ /* can't use zs_set_speed as we haven't set up the
+ * signal sources, and it's not worth it for now
+ */
+
+ /*
+ * As zs_loadchannelregs doesn't touch reg 9 (interupt control),
+ * we won't accidentally turn on interupts below
+ */
+ s = splhigh();
+ zs_loadchannelregs(cs);
+ splx(s);
}
/*
@@ -620,81 +947,85 @@ zscnsetup()
* (the video, better than CN_NORMAL), and CN_REMOTE (pick me!)
*
* As the mac's a bit different, we do extra work here. We mainly check
- * to see if we have serial echo going on, and if the tty's are supposed
- * to default to raw or not.
+ * to see if we have serial echo going on. Also chould check for default
+ * speeds.
*/
void
zscnprobe(struct consdev * cp)
{
- extern u_long IOBase;
- int maj, unit;
-
- for (maj = 0; maj < nchrdev; maj++) {
- if (cdevsw[maj].d_open == zsopen) {
- break;
- }
- }
- if (maj == nchrdev) {
- /* no console entry for us */
- if (mac68k_machine.serial_boot_echo) {
- mac68k_set_io_offsets(IOBase);
- zs_conschan = (struct zschan *) -1; /* dummy flag for zs_init() */
- zs_consunit = 1;
- zs_hwflags[0][zs_consunit] = ZS_HWFLAG_CONSOLE;
- zs_init();
- zscnsetup();
- }
- return;
- }
-
- cp->cn_pri = CN_NORMAL; /* Lower than CN_INTERNAL */
- if (mac68k_machine.serial_console != 0) {
- cp->cn_pri = CN_REMOTE; /* Higher than CN_INTERNAL */
- mac68k_machine.serial_boot_echo =0;
- }
-
- unit = (mac68k_machine.serial_console == 1) ? 0 : 1;
- zs_consunit = unit;
-
- mac68k_zsdev = cp->cn_dev = makedev(maj, unit);
-
- if (mac68k_machine.serial_boot_echo) {
- /*
- * at this point, we know that we don't have a serial
- * console, but are doing echo
- */
- mac68k_set_io_offsets(IOBase);
- zs_conschan = (struct zschan *) -1; /* dummy flag for zs_init() */
+ extern u_long IOBase;
+ int maj, unit, i;
+
+ for (maj = 0; maj < nchrdev; maj++) {
+ if (cdevsw[maj].d_open == zsopen) {
+ break;
+ }
+ }
+ if (maj != nchrdev) {
+ cp->cn_pri = CN_NORMAL; /* Lower than CN_INTERNAL */
+ if (mac68k_machine.serial_console != 0) {
+ cp->cn_pri = CN_REMOTE; /* Higher than CN_INTERNAL */
+ mac68k_machine.serial_boot_echo =0;
+ }
+
+ unit = (mac68k_machine.serial_console == 1) ? 0 : 1;
+ zs_consunit = unit;
+ zs_conschan = (struct zschan *) -1; /* dummy flag for zs_init() */
+
+ mac68k_zsdev = cp->cn_dev = makedev(maj, unit);
+ }
+ if (mac68k_machine.serial_boot_echo) {
+ /*
+ * at this point, we know that we don't have a serial
+ * console, but are doing echo
+ */
+ zs_conschan = (struct zschan *) -1; /* dummy flag for zs_init() */
zs_consunit = 1;
zs_hwflags[0][zs_consunit] = ZS_HWFLAG_CONSOLE;
- zs_init();
- zscnsetup();
- }
- return;
+ }
+
+ if ((i = mac68k_machine.modem_d_speed) > 0) {
+ if (zs_cn_check_speed(i))
+ zs_defspeed[0][0] = i;
+ }
+ if ((i = mac68k_machine.print_d_speed) > 0) {
+ if (zs_cn_check_speed(i))
+ zs_defspeed[0][1] = i;
+ }
+ mac68k_set_io_offsets(IOBase);
+ zs_init();
+ /*
+ * zsinit will set up the addresses of the scc. It will also, if
+ * zs_conschan != 0, calculate the new address of the conschan for
+ * unit zs_consunit. So if we are (or think we are) going to use the
+ * chip for console I/O, we just set up the internal addresses for it.
+ *
+ * Now turn off interrupts for the chip. Note: this code piece is the
+ * only vestage of the NetBSD 1.0 ser driver. :-)
+ */
+ unit = sccA[2]; /* reset reg. access */
+ unit = sccA[0];
+ sccA[2] = 9; sccA[2] = 0; /* write 0 to reg. 9, clearing MIE */
+ sccA[2] = ZSWR0_CLR_INTR; unit = sccA[2]; /* reset any pending ints. */
+ sccA[0] = ZSWR0_CLR_INTR; unit = sccA[0];
+
+ if (mac68k_machine.serial_boot_echo)
+ zscnsetup();
+ return;
}
void
zscninit(struct consdev * cp)
{
- extern u_long IOBase;
- int chan = minor(cp->cn_dev & 1);
-
- mac68k_set_io_offsets(IOBase);
- zs_conschan = (struct zschan *) -1;
- zs_consunit = chan;
zs_hwflags[0][zs_consunit] = ZS_HWFLAG_CONSOLE;
-#ifdef ZS_CONSOLE_ABORT
- zs_hwflags[0][zs_consunit] |= ZS_HWFLAG_CONABRT;
-#endif
- zs_init();
- /*
+ /*
* zsinit will set up the addresses of the scc. It will also, if
* zs_conschan != 0, calculate the new address of the conschan for
* unit zs_consunit. So zs_init implicitly sets zs_conschan to the right
* number. :-)
- */
- zscnsetup();
- printf("\nOpenBSD/mac68k console\n");
+ */
+ zscnsetup();
+ printf("\nOpenBSD/mac68k console\n");
}
@@ -784,27 +1115,21 @@ zscnputc(dev, c)
* Handle user request to enter kernel debugger.
*/
void
-zs_abort(zst)
- register struct zstty_softc *zst;
+zs_abort(cs)
+ struct zs_chanstate *cs;
{
- register volatile struct zschan *zc = zs_conschan;
+ volatile struct zschan *zc = zs_conschan;
int rr0;
register long wait = 0;
- if ((zst->zst_hwflags & ZS_HWFLAG_CONABRT) == 0)
- return;
-
/* Wait for end of break to avoid PROM abort. */
- /* XXX - Limit the wait? */
do {
rr0 = zc->zc_csr;
ZS_DELAY();
} while ((rr0 & ZSRR0_BREAK) && (wait++ < ZSABORT_DELAY));
- if (wait > ZSABORT_DELAY) {
- if (zst != NULL) zst->zst_hwflags &= ~ZS_HWFLAG_CONABRT;
- /* If we time out, turn off the abort ability! */
- }
+ if (wait > ZSABORT_DELAY)
+ return; /* XXX */
#ifdef DDB
if (db_console)
Debugger();
diff --git a/sys/arch/mac68k/include/intr.h b/sys/arch/mac68k/include/intr.h
index f96958e377c..37ee5df76b7 100644
--- a/sys/arch/mac68k/include/intr.h
+++ b/sys/arch/mac68k/include/intr.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: intr.h,v 1.8 2003/01/05 01:51:27 miod Exp $ */
-/* $NetBSD: intr.h,v 1.8 1997/11/07 07:33:18 scottr Exp $ */
+/* $OpenBSD: intr.h,v 1.9 2004/11/25 18:32:10 miod Exp $ */
+/* $NetBSD: intr.h,v 1.9 1998/08/12 06:58:42 scottr Exp $ */
/*
* Copyright (C) 1997 Scott Reynolds
@@ -156,6 +156,11 @@ extern volatile u_int8_t ssir;
#define setsoftdtmgr() siron(SIR_DTMGR)
#define setsoftadb() siron(SIR_ADB)
+/* intr.c */
+void intr_establish (int (*)(void *), void *, int);
+void intr_disestablish (int);
+void intr_dispatch (int);
+
/* locore.s */
int spl0(void);
#endif /* _KERNEL */
diff --git a/sys/arch/mac68k/include/z8530var.h b/sys/arch/mac68k/include/z8530var.h
index 590f646a581..5bf9a0bb3a4 100644
--- a/sys/arch/mac68k/include/z8530var.h
+++ b/sys/arch/mac68k/include/z8530var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: z8530var.h,v 1.6 2003/06/02 23:27:49 millert Exp $ */
+/* $OpenBSD: z8530var.h,v 1.7 2004/11/25 18:32:10 miod Exp $ */
/* $NetBSD: z8530var.h,v 1.2 1996/06/07 10:27:19 briggs Exp $ */
/*
@@ -46,8 +46,58 @@
#define _MAC68K_Z8530VAR_H_
#ifdef _KERNEL
-#include <arch/mac68k/dev/z8530sc.h>
-#include <arch/mac68k/dev/z8530tty.h>
+#include <mac68k/dev/z8530sc.h>
+
+/*
+ * Clock source info structure, added here so xzs_chanstate works
+ */
+struct zsclksrc {
+ long clk; /* clock rate, in MHz, present on signal line */
+ int flags; /* Specifies how this source can be used
+ (RTxC divided, RTxC BRG, PCLK BRG, TRxC divided) and also if the source is "external" and if it
+ is changeable (by an ioctl ex.). The
+ source usage flags are used by the tty
+ child. The other bits tell zsloadchannelregs
+ if it should call an md signal source
+ changing routine. ZSC_VARIABLE says if
+ an ioctl should be able to change the
+ clock rate.*/
+};
+#define ZSC_PCLK 0x01
+#define ZSC_RTXBRG 0x02
+#define ZSC_RTXDIV 0x04
+#define ZSC_TRXDIV 0x08
+#define ZSC_VARIABLE 0x40
+#define ZSC_EXTERN 0x80
+
+#define ZSC_BRG 0x03
+#define ZSC_DIV 0x0c
+
+/*
+ * These are the machine-dependent (extended) variants of
+ * struct zs_chanstate and struct zsc_softc
+ */
+struct xzs_chanstate {
+ /* machine-independent part (First!)*/
+ struct zs_chanstate xzs_cs;
+ /* machine-dependent extensions */
+ int cs_hwflags;
+ int cs_chip; /* type of chip */
+ /* Clock source info... */
+ int cs_clock_count; /* how many signal sources available */
+ struct zsclksrc cs_clocks[4]; /* info on available signal sources */
+ long cs_cclk_flag; /* flag for current clock source */
+ long cs_pclk_flag; /* flag for pending clock source */
+ int cs_csource; /* current source # */
+ int cs_psource; /* pending source # */
+};
+
+struct zsc_softc {
+ struct device zsc_dev; /* required first: base device */
+ struct zs_chanstate *zsc_cs[2]; /* channel A and B soft state */
+ /* Machine-dependent part follows... */
+ struct xzs_chanstate xzsc_xcs_store[2];
+};
/*
* Functions to read and write individual registers in a channel.
@@ -65,54 +115,14 @@ void zs_write_csr(struct zs_chanstate *cs, u_char val);
void zs_write_data(struct zs_chanstate *cs, u_char val);
#endif /* _KERNEL */
-/*
- * abort detection on console will now timeout after iterating on a loop
- * the following # of times. Cheep hack. Also, abort detection is turned
- * off after a timeout (i.e. maybe there's not a terminal hooked up).
- */
-#define ZSABORT_DELAY 3000000
-
-/*
- * How to request a "soft" interrupt.
- * This could be a macro if you like.
- */
-#ifdef _KERNEL
-void zsc_req_softint(struct zsc_softc *zsc);
-
-/* Handle user request to enter kernel debugger. */
-void zs_abort(struct zstty_softc *zst);
+/* XXX - Could define splzs() here instead of in psl.h */
/* Hook for MD ioctl support */
-int zsmdioctl(struct tty *tp, u_long com, caddr_t data, int flag,
- struct proc *p);
-
-/* Clean up at end of tty attach */
-void zstty_mdattach(struct zsc_softc *zsc, struct zstty_softc *zst,
- struct zs_chanstate *cs, struct tty *tp);
+int zsmdioctl (struct zs_chanstate *cs, u_long cmd, caddr_t data);
+/* XXX - This is a bit gross... */
+#define ZS_MD_IOCTL zsmdioctl(cs, cmd, data)
/* Callback for "external" clock sources */
void zsmd_setclock(struct zs_chanstate *cs);
+#define ZS_MD_SETCLK(cs) zsmd_setclock(cs)
#endif /* _KERNEL */
-
-/*
- * Some warts needed by z8530tty.c -
- */
-#define ZSTTY_MAJOR 12 /* XXX */
-#undef ZSTTY_DEF_CFLAG
-#define ZSTTY_DEF_CFLAG (CREAD | CS8 | HUPCL)
-
-#define ZSTTY_RAW_CFLAG (CS8 | CREAD | HUPCL )
-#define ZSTTY_RAW_IFLAG (IXANY | IMAXBEL)
-#define ZSTTY_RAW_LFLAG (ECHOE|ECHOKE|ECHOCTL)
-#define ZSTTY_RAW_OFLAG (ONLCR | OXTABS)
-/* Above taken from looking at a tty after a stty raw */
-
-/* Booter flags interface */
-#define ZSMAC_RAW 0x01
-#define ZSMAC_LOCALTALK 0x02
-
-#ifdef _KERNEL
-#define zsprintf printf
-#endif /* _KERNEL */
-
-#endif /* _MAC68K_Z8530VAR_H_ */
diff --git a/sys/arch/mac68k/mac68k/intr.c b/sys/arch/mac68k/mac68k/intr.c
new file mode 100644
index 00000000000..e1f5641620e
--- /dev/null
+++ b/sys/arch/mac68k/mac68k/intr.c
@@ -0,0 +1,194 @@
+/* $OpenBSD: intr.c,v 1.1 2004/11/25 18:32:10 miod Exp $ */
+/* $NetBSD: intr.c,v 1.2 1998/08/25 04:03:56 scottr Exp $ */
+
+/*-
+ * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Adam Glass, Gordon W. Ross, and Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Link and dispatch interrupts.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/vmmeter.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <net/netisr.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#define NISR 8
+#define ISRLOC 0x18
+
+static int intr_noint (void *);
+void netintr (void);
+
+static int ((*intr_func[NISR]) (void *)) = {
+ intr_noint,
+ intr_noint,
+ intr_noint,
+ intr_noint,
+ intr_noint,
+ intr_noint,
+ intr_noint,
+ intr_noint
+};
+static void *intr_arg[NISR] = {
+ (void *)0,
+ (void *)1,
+ (void *)2,
+ (void *)3,
+ (void *)4,
+ (void *)5,
+ (void *)6,
+ (void *)7
+};
+
+#ifdef DEBUG
+int intr_debug = 0;
+#endif
+
+extern int intrcnt[]; /* from locore.s */
+
+/*
+ * Establish an autovectored interrupt handler.
+ * Called by driver attach functions.
+ *
+ * XXX Warning! DO NOT use Macintosh ROM traps from an interrupt handler
+ * established by this routine, either directly or indirectly, without
+ * properly saving and restoring all registers. If not, chaos _will_
+ * ensue! (sar 19980806)
+ */
+void
+intr_establish(func, arg, ipl)
+ int (*func) (void *);
+ void *arg;
+ int ipl;
+{
+ if ((ipl < 0) || (ipl >= NISR))
+ panic("intr_establish: bad ipl %d", ipl);
+
+#ifdef DIAGNOSTIC
+ if (intr_func[ipl] != intr_noint)
+ printf("intr_establish: attempt to share ipl %d\n", ipl);
+#endif
+
+ intr_func[ipl] = func;
+ intr_arg[ipl] = arg;
+}
+
+/*
+ * Disestablish an interrupt handler.
+ */
+void
+intr_disestablish(ipl)
+ int ipl;
+{
+ if ((ipl < 0) || (ipl >= NISR))
+ panic("intr_disestablish: bad ipl %d", ipl);
+
+ intr_func[ipl] = intr_noint;
+ intr_arg[ipl] = (void *)ipl;
+}
+
+/*
+ * This is the dispatcher called by the low-level
+ * assembly language interrupt routine.
+ *
+ * XXX Note: see the warning in intr_establish()
+ */
+void
+intr_dispatch(evec)
+ int evec; /* format | vector offset */
+{
+ int ipl, vec;
+
+ vec = (evec & 0xfff) >> 2;
+#ifdef DIAGNOSTIC
+ if ((vec < ISRLOC) || (vec >= (ISRLOC + NISR)))
+ panic("intr_dispatch: bad vec 0x%x\n", vec);
+#endif
+ ipl = vec - ISRLOC;
+
+ intrcnt[ipl]++;
+ uvmexp.intrs++;
+
+ (void)(*intr_func[ipl])(intr_arg[ipl]);
+}
+
+/*
+ * Default interrupt handler: do nothing.
+ */
+static int
+intr_noint(arg)
+ void *arg;
+{
+#ifdef DEBUG
+ if (intr_debug)
+ printf("intr_noint: ipl %d\n", (int)arg);
+#endif
+ return 0;
+}
+
+int netisr;
+
+void
+netintr()
+{
+ int s, isr;
+
+ for (;;) {
+ s = splimp();
+ isr = netisr;
+ netisr = 0;
+ splx(s);
+
+ if (isr == 0)
+ return;
+
+#define DONETISR(bit, fn) do { \
+ if (isr & (1 << bit)) \
+ (fn)(); \
+} while (0)
+
+#include <net/netisr_dispatch.h>
+
+#undef DONETISR
+ }
+}
diff --git a/sys/arch/mac68k/mac68k/locore.s b/sys/arch/mac68k/mac68k/locore.s
index 7d8cd45dece..3a0a11cfe22 100644
--- a/sys/arch/mac68k/mac68k/locore.s
+++ b/sys/arch/mac68k/mac68k/locore.s
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.s,v 1.35 2004/07/02 17:33:43 miod Exp $ */
+/* $OpenBSD: locore.s,v 1.36 2004/11/25 18:32:10 miod Exp $ */
/* $NetBSD: locore.s,v 1.103 1998/07/09 06:02:50 scottr Exp $ */
/*
@@ -227,9 +227,11 @@ Lstart2:
jra Lstart3
Lget040TC:
+#if 0
movl _C_LABEL(current_mac_model),a1 | if an AV Mac, save current
cmpl #MACH_CLASSAV,a1@(CPUINFO_CLASS) | TC so internal video will
jne LnotAV | get configured
+#endif
.long 0x4e7a0003 | movc tc,d0
jra LsaveTC
LnotAV:
@@ -823,6 +825,9 @@ Lbrkpt3:
* Level 7: NMIs: parity errors?, RESET button
*/
+#define INTERRUPT_SAVEREG moveml #0xC0C0,sp@-
+#define INTERRUPT_RESTOREREG moveml sp@+,#0x0303
+
ENTRY_NOPROFILE(spurintr)
addql #1,_C_LABEL(intrcnt)+0
addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS
@@ -853,63 +858,14 @@ ENTRY_NOPROFILE(lev2intr)
addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS
jra _ASM_LABEL(rei)
-ENTRY_NOPROFILE(lev3intr)
- addql #1,_C_LABEL(intrcnt)+24
- clrl sp@-
- moveml #0xFFFF,sp@-
- movl sp, sp@-
- movl _C_LABEL(lev3_intrvec),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(lev4intr)
- addql #1,_C_LABEL(intrcnt)+12
- clrl sp@-
- moveml #0xFFFF,sp@-
- movl sp, sp@-
- movl _C_LABEL(lev4_intrvec),a2
- jbsr a2@
- addql #4,sp
- tstl d0
- beq normal_rei
- moveml sp@+, #0xFFFF
- addql #4,sp
- rte
-normal_rei:
- moveml sp@+, #0xFFFF
- addql #4,sp
- addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS
- jra _ASM_LABEL(rei)
-
-ENTRY_NOPROFILE(lev5intr)
- addql #1,_C_LABEL(intrcnt)+28
- clrl sp@-
- moveml #0xFFFF,sp@-
- movl sp, sp@-
- movl _C_LABEL(lev5_intrvec),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(lev6intr)
- addql #1,_C_LABEL(intrcnt)+32
- clrl sp@-
- moveml #0xFFFF,sp@-
- movl sp, sp@-
- movl _C_LABEL(lev6_intrvec),a2
- jbsr a2@
- addql #4,sp
- moveml sp@+, #0xFFFF
+ENTRY_NOPROFILE(intrhand) /* levels 3 through 6 */
+ INTERRUPT_SAVEREG
+ movw sp@(22),sp@- | push exception vector info
+ clrw sp@-
+ jbsr _C_LABEL(intr_dispatch) | call dispatch routine
addql #4,sp
- addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS
- jra _ASM_LABEL(rei)
+ INTERRUPT_RESTOREREG
+ jra _ASM_LABEL(rei) | all done
ENTRY_NOPROFILE(lev7intr)
addql #1,_C_LABEL(intrcnt)+16
diff --git a/sys/arch/mac68k/mac68k/machdep.c b/sys/arch/mac68k/mac68k/machdep.c
index f3b77460ead..b394f5eff9d 100644
--- a/sys/arch/mac68k/mac68k/machdep.c
+++ b/sys/arch/mac68k/mac68k/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.112 2004/03/10 23:02:53 tom Exp $ */
+/* $OpenBSD: machdep.c,v 1.113 2004/11/25 18:32:11 miod Exp $ */
/* $NetBSD: machdep.c,v 1.207 1998/07/08 04:39:34 thorpej Exp $ */
/*
@@ -1030,22 +1030,6 @@ badladdr(addr)
return (0);
}
-int netisr;
-
-void
-netintr()
-{
-#define DONETISR(bit, fn) \
- do { \
- if (netisr & (1 << (bit))) { \
- netisr &= ~(1 << (bit)); \
- (fn)(); \
- } \
- } while (0)
-#include <net/netisr_dispatch.h>
-#undef DONETISR
-}
-
/*
* Level 7 interrupts can be caused by the keyboard or parity errors.
*/
@@ -1171,7 +1155,6 @@ getenvvars(flag, buf)
/* We need these for pre-mapping graybars & echo, but probably */
/* only on MacII or LC. -- XXX */
/* videoaddr = getenv("MACOS_VIDEO"); */
- /* sccaddr = getenv("MACOS_SCC"); */
/*
* The following are not in a structure so that they can be
@@ -1195,9 +1178,11 @@ getenvvars(flag, buf)
mac68k_machine.modem_flags = getenv("SERIAL_MODEM_FLAGS");
mac68k_machine.modem_cts_clk = getenv("SERIAL_MODEM_HSKICLK");
mac68k_machine.modem_dcd_clk = getenv("SERIAL_MODEM_GPICLK");
+ mac68k_machine.modem_flags = getenv("SERIAL_MODEM_DSPEED");
mac68k_machine.print_flags = getenv("SERIAL_PRINT_FLAGS");
mac68k_machine.print_cts_clk = getenv("SERIAL_PRINT_HSKICLK");
mac68k_machine.print_dcd_clk = getenv("SERIAL_PRINT_GPICLK");
+ mac68k_machine.print_d_speed = getenv("SERIAL_PRINT_DSPEED");
mac68k_machine.booter_version = getenv("BOOTERVER");
/*
@@ -2003,7 +1988,6 @@ struct cpu_model_info cpu_models[] = {
{MACH_MACQ650, "Quadra", " 650", MACH_CLASSQ, &romvecs[6]},
{MACH_MACC650, "Centris", " 650", MACH_CLASSQ, &romvecs[6]},
{MACH_MACQ605, "Quadra", " 605", MACH_CLASSQ, &romvecs[9]},
- {MACH_MACQ605_33, "Quadra", " 605/33", MACH_CLASSQ, &romvecs[9]},
{MACH_MACC610, "Centris", " 610", MACH_CLASSQ, &romvecs[6]},
{MACH_MACQ610, "Quadra", " 610", MACH_CLASSQ, &romvecs[6]},
{MACH_MACQ630, "Quadra", " 630", MACH_CLASSQ2, &romvecs[13]},
@@ -2043,7 +2027,6 @@ struct cpu_model_info cpu_models[] = {
{MACH_MACLCII, "LC", " II", MACH_CLASSLC, &romvecs[3]},
{MACH_MACLCIII, "LC", " III", MACH_CLASSLC, &romvecs[14]},
{MACH_MACLC475, "LC", " 475", MACH_CLASSQ, &romvecs[9]},
- {MACH_MACLC475_33, "LC", " 475/33", MACH_CLASSQ, &romvecs[9]},
{MACH_MACLC520, "LC", " 520", MACH_CLASSLC, &romvecs[15]},
{MACH_MACLC575, "LC", " 575", MACH_CLASSQ2, &romvecs[16]},
{MACH_MACCCLASSIC, "Color Classic", "", MACH_CLASSLC, &romvecs[3]},
@@ -2317,7 +2300,6 @@ setmachdep()
Via1Base = (volatile u_char *)IOBase;
mac68k_machine.scsi80 = 1;
mac68k_machine.zs_chip = 0;
- mac68k_machine.sccClkConst = 115200;
via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
via_reg(VIA2, vIER) = 0x7f; /* disable VIA2 int */
setup_mrg_vectors = 1;
@@ -2328,7 +2310,6 @@ setmachdep()
Via1Base = (volatile u_char *)IOBase;
mac68k_machine.scsi80 = 1;
mac68k_machine.zs_chip = 0;
- mac68k_machine.sccClkConst = 115200;
/* Disable everything but PM; we need it. */
via_reg(VIA1, vIER) = 0x6f; /* disable VIA1 int */
/* Are we disabling something important? */
@@ -2347,7 +2328,6 @@ setmachdep()
Via1Base = (volatile u_char *)IOBase;
mac68k_machine.scsi80 = 1;
mac68k_machine.zs_chip = 0;
- mac68k_machine.sccClkConst = 115200;
/* Disable everything but PM; we need it. */
via_reg(VIA1, vIER) = 0x6f; /* disable VIA1 int */
/* Are we disabling something important? */
@@ -2363,7 +2343,6 @@ setmachdep()
Via1Base = (volatile u_char *)IOBase;
mac68k_machine.scsi96 = 1;
mac68k_machine.zs_chip = 0;
- mac68k_machine.sccClkConst = 115200;
via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
via_reg(VIA2, vIER) = 0x7f; /* disable VIA2 int */
break;
@@ -2373,7 +2352,6 @@ setmachdep()
Via1Base = (volatile u_char *)IOBase;
mac68k_machine.scsi80 = 1;
mac68k_machine.zs_chip = 0;
- mac68k_machine.sccClkConst = 115200;
via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
via_reg(VIA2, rIER) = 0x7f; /* disable RBV int */
break;
@@ -2383,7 +2361,6 @@ setmachdep()
Via1Base = (volatile u_char *)IOBase;
mac68k_machine.scsi80 = 1;
mac68k_machine.zs_chip = 0;
- mac68k_machine.sccClkConst = 115200;
via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
via_reg(VIA2, rIER) = 0x7f; /* disable RBV int */
break;
@@ -2393,7 +2370,6 @@ setmachdep()
Via1Base = (volatile u_char *)IOBase;
mac68k_machine.scsi80 = 1;
mac68k_machine.zs_chip = 0;
- mac68k_machine.sccClkConst = 115200;
via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
via_reg(VIA2, rIER) = 0x7f; /* disable RBV int */
break;
@@ -2403,7 +2379,6 @@ setmachdep()
Via1Base = (volatile u_char *)IOBase;
mac68k_machine.scsi80 = 1;
mac68k_machine.zs_chip = 0;
- mac68k_machine.sccClkConst = 115200;
via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
via_reg(VIA2, rIER) = 0x7f; /* disable RBV int */
break;
@@ -2413,7 +2388,6 @@ setmachdep()
Via1Base = (volatile u_char *)IOBase;
mac68k_machine.scsi80 = 1;
mac68k_machine.zs_chip = 0;
- mac68k_machine.sccClkConst = 115200; /* XXX unverified */
via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
break;
default:
diff --git a/sys/arch/mac68k/mac68k/pmap_bootstrap.c b/sys/arch/mac68k/mac68k/pmap_bootstrap.c
index 2752c54eb96..9e024a0336e 100644
--- a/sys/arch/mac68k/mac68k/pmap_bootstrap.c
+++ b/sys/arch/mac68k/mac68k/pmap_bootstrap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap_bootstrap.c,v 1.25 2003/06/02 23:27:49 millert Exp $ */
+/* $OpenBSD: pmap_bootstrap.c,v 1.26 2004/11/25 18:32:11 miod Exp $ */
/* $NetBSD: pmap_bootstrap.c,v 1.50 1999/04/07 06:14:33 scottr Exp $ */
/*
@@ -56,6 +56,8 @@
#include <mac68k/mac68k/clockreg.h>
#include <mac68k/mac68k/macrom.h>
+extern int zsinited;
+
/*
* These are used to map the RAM:
*/
@@ -269,8 +271,7 @@ bootstrap_mac68k(tc)
* of this function (where we start using the MMU, so the new
* address is correct.
*/
- if ( (mac68k_machine.serial_boot_echo)
- || (mac68k_machine.serial_console))
+ if (zsinited != 0)
zs_init();
videoaddr = newvideoaddr;
diff --git a/sys/arch/mac68k/mac68k/psc.c b/sys/arch/mac68k/mac68k/psc.c
index 27a0d9c8fa9..4f4f3bce156 100644
--- a/sys/arch/mac68k/mac68k/psc.c
+++ b/sys/arch/mac68k/mac68k/psc.c
@@ -1,5 +1,6 @@
-/* $OpenBSD: psc.c,v 1.2 2002/03/14 01:26:36 millert Exp $ */
-/* $NetBSD: psc.c,v 1.4 1998/04/24 05:27:26 scottr Exp $ */
+/* $OpenBSD: psc.c,v 1.3 2004/11/25 18:32:11 miod Exp $ */
+/* $NetBSD: psc.c,v 1.5 1998/08/12 05:42:46 scottr Exp $ */
+
/*-
* Copyright (c) 1997 David Huang <khym@bga.com>
@@ -39,30 +40,22 @@
#include <machine/cpu.h>
#include <machine/psc.h>
-void psc_lev3_intr(struct frame *);
+int psc_lev3_intr(void *);
static void psc_lev3_noint(void *);
-int psc_lev4_intr(struct frame *);
+int psc_lev4_intr(void *);
static int psc_lev4_noint(void *);
-void psc_lev5_intr(struct frame *);
+int psc_lev5_intr(void *);
static void psc_lev5_noint(void *);
-void psc_lev6_intr(struct frame *);
+int psc_lev6_intr(void *);
static void psc_lev6_noint(void *);
-void psc_spurintr(struct frame *);
-
-void (*lev3_intrvec)(struct frame *);
-int (*lev4_intrvec)(struct frame *);
-void (*lev5_intrvec)(struct frame *);
-void (*lev6_intrvec)(struct frame *);
-
-extern int zshard(void *); /* from zs.c */
void (*psc3_ihandler)(void *) = psc_lev3_noint;
void *psc3_iarg;
int (*psc4_itab[4])(void *) = {
- psc_lev4_noint, /* 0 */
- zshard, /* 1 */
- zshard, /* 2 */
+ psc_lev4_noint, /* 0 */
+ psc_lev4_noint, /* 1 */
+ psc_lev4_noint, /* 2 */
psc_lev4_noint /* 3 */
};
@@ -96,32 +89,21 @@ void
psc_init()
{
/*
- * Only Quadra AVs have a PSC. On other machines, point the
- * level 4 interrupt to zshard(), and levels 3, 5, and 6 to
- * psc_spurintr().
+ * Only Quadra AVs have a PSC.
*/
if (current_mac_model->class == MACH_CLASSAV) {
- lev3_intrvec = psc_lev3_intr;
- lev4_intrvec = psc_lev4_intr;
- lev5_intrvec = psc_lev5_intr;
- lev6_intrvec = psc_lev6_intr;
+ intr_establish(psc_lev3_intr, NULL, 3);
+ intr_establish(psc_lev4_intr, NULL, 4);
+ intr_establish(psc_lev5_intr, NULL, 5);
+ intr_establish(psc_lev6_intr, NULL, 6);
psc_reg1(PSC_LEV3_IER) = 0x01; /* disable level 3 interrupts */
psc_reg1(PSC_LEV4_IER) = 0x09; /* disable level 4 interrupts */
psc_reg1(PSC_LEV4_IER) = 0x86; /* except for SCC */
psc_reg1(PSC_LEV5_IER) = 0x03; /* disable level 5 interrupts */
psc_reg1(PSC_LEV6_IER) = 0x07; /* disable level 6 interrupts */
- } else {
- lev3_intrvec = lev5_intrvec = lev6_intrvec = psc_spurintr;
- lev4_intrvec = (int (*)(struct frame *))zshard;
}
}
-void
-psc_spurintr(fp)
- struct frame *fp;
-{
-}
-
int
add_psc_lev3_intr(handler, arg)
void (*handler)(void *);
@@ -145,9 +127,9 @@ remove_psc_lev3_intr()
return add_psc_lev3_intr(psc_lev3_noint, (void *)0);
}
-void
-psc_lev3_intr(fp)
- struct frame *fp;
+int
+psc_lev3_intr(arg)
+ void *arg;
{
u_int8_t intbits;
@@ -157,6 +139,8 @@ psc_lev3_intr(fp)
if (intbits)
psc3_ihandler(psc3_iarg);
+
+ return 0;
}
static void
@@ -167,8 +151,8 @@ psc_lev3_noint(arg)
}
int
-psc_lev4_intr(fp)
- struct frame *fp;
+psc_lev4_intr(arg)
+ void * arg;
{
u_int8_t intbits, bitnum;
u_int mask;
@@ -224,9 +208,9 @@ psc_lev4_noint(arg)
return 0;
}
-void
-psc_lev5_intr(fp)
- struct frame *fp;
+int
+psc_lev5_intr(arg)
+ void *arg;
{
u_int8_t intbits, bitnum;
u_int mask;
@@ -242,6 +226,8 @@ psc_lev5_intr(fp)
psc5_itab[bitnum](psc5_iarg[bitnum]);
mask <<= 1;
} while (intbits >= mask && ++bitnum);
+
+ return 0;
}
int
@@ -279,9 +265,9 @@ psc_lev5_noint(arg)
printf("psc_lev5_noint: device %d\n", (int)arg);
}
-void
-psc_lev6_intr(fp)
- struct frame *fp;
+int
+psc_lev6_intr(arg)
+ void *arg;
{
u_int8_t intbits, bitnum;
u_int mask;
@@ -297,6 +283,8 @@ psc_lev6_intr(fp)
psc6_itab[bitnum](psc6_iarg[bitnum]);
mask <<= 1;
} while (intbits >= mask && ++bitnum);
+
+ return 0;
}
int
diff --git a/sys/arch/mac68k/mac68k/vectors.s b/sys/arch/mac68k/mac68k/vectors.s
index 6747505c8c7..08594c8cd43 100644
--- a/sys/arch/mac68k/mac68k/vectors.s
+++ b/sys/arch/mac68k/mac68k/vectors.s
@@ -1,5 +1,5 @@
-/* $OpenBSD: vectors.s,v 1.6 2004/01/27 16:16:27 miod Exp $ */
-| $NetBSD: vectors.s,v 1.9 1997/09/03 06:16:24 scottr Exp $
+/* $OpenBSD: vectors.s,v 1.7 2004/11/25 18:32:11 miod Exp $ */
+| $NetBSD: vectors.s,v 1.10 1998/08/12 06:58:42 scottr Exp $
| Copyright (c) 1988 University of Utah
| Copyright (c) 1990 Regents of the University of California.
@@ -75,10 +75,10 @@ GLOBAL(vectab)
VECTOR(spurintr) /* 24: spurious interrupt */
VECTOR(lev1intr) /* 25: level 1 interrupt autovector */
VECTOR(lev2intr) /* 26: level 2 interrupt autovector */
- VECTOR(lev3intr) /* 27: level 3 interrupt autovector */
- VECTOR(lev4intr) /* 28: level 4 interrupt autovector */
- VECTOR(lev5intr) /* 29: level 5 interrupt autovector */
- VECTOR(lev6intr) /* 30: level 6 interrupt autovector */
+ VECTOR(intrhand) /* 27: level 3 interrupt autovector */
+ VECTOR(intrhand) /* 28: level 4 interrupt autovector */
+ VECTOR(intrhand) /* 29: level 5 interrupt autovector */
+ VECTOR(intrhand) /* 30: level 6 interrupt autovector */
VECTOR(lev7intr) /* 31: level 7 interrupt autovector */
VECTOR(trap0) /* 32: syscalls */
VECTOR(trap1) /* 33: sigreturn syscall or breakpoint */
diff --git a/sys/arch/mac68k/mac68k/via.c b/sys/arch/mac68k/mac68k/via.c
index 09e5fcc7e8e..10445242ff5 100644
--- a/sys/arch/mac68k/mac68k/via.c
+++ b/sys/arch/mac68k/mac68k/via.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: via.c,v 1.17 2002/03/14 01:26:36 millert Exp $ */
-/* $NetBSD: via.c,v 1.58 1997/03/04 04:11:52 scottr Exp $ */
+/* $OpenBSD: via.c,v 1.18 2004/11/25 18:32:11 miod Exp $ */
+/* $NetBSD: via.c,v 1.62 1997/09/10 04:38:48 scottr Exp $ */
/*-
* Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo,
@@ -87,6 +87,7 @@ void *via2iarg[7] = {
void via2_intr(struct frame *);
void rbv_intr(struct frame *);
+void oss_intr(struct frame *);
void (*real_via2_intr)(struct frame *);
@@ -169,6 +170,8 @@ via_init()
real_via2_intr = via2_intr;
via2itab[1] = via2_nubus_intr;
+ } else if (current_mac_model->class == MACH_CLASSIIfx) { /* OSS */
+ real_via2_intr = oss_intr;
} else { /* RBV */
if (current_mac_model->class == MACH_CLASSIIci) {
/*
@@ -250,6 +253,30 @@ via2_intr(fp)
}
void
+oss_intr(fp)
+ struct frame *fp;
+{
+ u_int8_t intbits, bitnum;
+ u_int mask;
+
+ intbits = via2_reg(vIFR + rIFR);
+
+ if (intbits == 0)
+ return;
+
+ intbits &= 0x7f;
+ mask =1 ;
+ bitnum = 0;
+ do {
+ if (intbits & mask) {
+ (*slotitab[bitnum])(slotptab[bitnum], bitnum+9);
+ via2_reg(rIFR) = mask;
+ }
+ mask <<= 1;
+ } while (intbits >= mask && ++bitnum);
+}
+
+void
rbv_intr(fp)
struct frame *fp;
{