diff options
Diffstat (limited to 'sys/arch/mac68k')
-rw-r--r-- | sys/arch/mac68k/conf/GENERIC | 3 | ||||
-rw-r--r-- | sys/arch/mac68k/conf/GENERICSBC | 3 | ||||
-rw-r--r-- | sys/arch/mac68k/conf/files.mac68k | 3 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/adb_direct.c | 14 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/pm_direct.c | 9 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/z8530reg.h | 51 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/z8530sc.c | 152 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/z8530sc.h | 128 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/z8530tty.c | 764 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/z8530tty.h | 140 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/zs.c | 905 | ||||
-rw-r--r-- | sys/arch/mac68k/include/intr.h | 9 | ||||
-rw-r--r-- | sys/arch/mac68k/include/z8530var.h | 106 | ||||
-rw-r--r-- | sys/arch/mac68k/mac68k/intr.c | 194 | ||||
-rw-r--r-- | sys/arch/mac68k/mac68k/locore.s | 70 | ||||
-rw-r--r-- | sys/arch/mac68k/mac68k/machdep.c | 32 | ||||
-rw-r--r-- | sys/arch/mac68k/mac68k/pmap_bootstrap.c | 7 | ||||
-rw-r--r-- | sys/arch/mac68k/mac68k/psc.c | 76 | ||||
-rw-r--r-- | sys/arch/mac68k/mac68k/vectors.s | 12 | ||||
-rw-r--r-- | sys/arch/mac68k/mac68k/via.c | 31 |
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; { |