1 /* $OpenBSD: z8530sc.c,v 1.8 2017/12/30 20:46:59 guenther Exp $ */ 2 /* $NetBSD: z8530sc.c,v 1.30 2009/05/22 03:51:30 mrg Exp $ */ 3 4 /* 5 * Copyright (c) 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This software was developed by the Computer Systems Engineering group 9 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 10 * contributed to Berkeley. 11 * 12 * All advertising materials mentioning features or use of this software 13 * must display the following acknowledgement: 14 * This product includes software developed by the University of 15 * California, Lawrence Berkeley Laboratory. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions 19 * are met: 20 * 1. Redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer. 22 * 2. Redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution. 25 * 3. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * @(#)zs.c 8.1 (Berkeley) 7/19/93 42 */ 43 44 /* 45 * Copyright (c) 1994 Gordon W. Ross 46 * 47 * This software was developed by the Computer Systems Engineering group 48 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 49 * contributed to Berkeley. 50 * 51 * All advertising materials mentioning features or use of this software 52 * must display the following acknowledgement: 53 * This product includes software developed by the University of 54 * California, Lawrence Berkeley Laboratory. 55 * 56 * Redistribution and use in source and binary forms, with or without 57 * modification, are permitted provided that the following conditions 58 * are met: 59 * 1. Redistributions of source code must retain the above copyright 60 * notice, this list of conditions and the following disclaimer. 61 * 2. Redistributions in binary form must reproduce the above copyright 62 * notice, this list of conditions and the following disclaimer in the 63 * documentation and/or other materials provided with the distribution. 64 * 3. All advertising materials mentioning features or use of this software 65 * must display the following acknowledgement: 66 * This product includes software developed by the University of 67 * California, Berkeley and its contributors. 68 * 4. Neither the name of the University nor the names of its contributors 69 * may be used to endorse or promote products derived from this software 70 * without specific prior written permission. 71 * 72 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 73 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 74 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 75 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 76 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 77 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 78 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 79 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 80 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 81 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 82 * SUCH DAMAGE. 83 * 84 * @(#)zs.c 8.1 (Berkeley) 7/19/93 85 */ 86 87 /* 88 * Zilog Z8530 Dual UART driver (common part) 89 * 90 * This file contains the machine-independent parts of the 91 * driver common to tty and keyboard/mouse sub-drivers. 92 */ 93 94 #include <sys/param.h> 95 #include <sys/systm.h> 96 #include <sys/proc.h> 97 #include <sys/device.h> 98 #include <sys/conf.h> 99 #include <sys/ioctl.h> 100 #include <sys/tty.h> 101 #include <sys/time.h> 102 #include <sys/kernel.h> 103 #include <sys/syslog.h> 104 105 #include <dev/ic/z8530reg.h> 106 #include <machine/z8530var.h> 107 108 void 109 zs_break(struct zs_chanstate *cs, int set) 110 { 111 112 if (set) { 113 cs->cs_preg[5] |= ZSWR5_BREAK; 114 cs->cs_creg[5] |= ZSWR5_BREAK; 115 } else { 116 cs->cs_preg[5] &= ~ZSWR5_BREAK; 117 cs->cs_creg[5] &= ~ZSWR5_BREAK; 118 } 119 zs_write_reg(cs, 5, cs->cs_creg[5]); 120 } 121 122 123 /* 124 * drain on-chip fifo 125 */ 126 void 127 zs_iflush(struct zs_chanstate *cs) 128 { 129 uint8_t c, rr0, rr1; 130 int i; 131 132 /* 133 * Count how many times we loop. Some systems, such as some 134 * Apple PowerBooks, claim to have SCC's which they really don't. 135 */ 136 for (i = 0; i < 32; i++) { 137 /* Is there input available? */ 138 rr0 = zs_read_csr(cs); 139 if ((rr0 & ZSRR0_RX_READY) == 0) 140 break; 141 142 /* 143 * First read the status, because reading the data 144 * destroys the status of this char. 145 */ 146 rr1 = zs_read_reg(cs, 1); 147 c = zs_read_data(cs); 148 149 if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) { 150 /* Clear the receive error. */ 151 zs_write_csr(cs, ZSWR0_RESET_ERRORS); 152 } 153 } 154 } 155 156 157 /* 158 * Write the given register set to the given zs channel in the proper order. 159 * The channel must not be transmitting at the time. The receiver will 160 * be disabled for the time it takes to write all the registers. 161 * Call this with interrupts disabled. 162 */ 163 void 164 zs_loadchannelregs(struct zs_chanstate *cs) 165 { 166 uint8_t *reg, v; 167 168 zs_write_csr(cs, ZSM_RESET_ERR); /* XXX: reset error condition */ 169 170 #if 1 171 /* 172 * XXX: Is this really a good idea? 173 * XXX: Should go elsewhere! -gwr 174 */ 175 zs_iflush(cs); /* XXX */ 176 #endif 177 178 if (cs->cs_ctl_chan != NULL) 179 v = ((cs->cs_ctl_chan->cs_creg[5] & (ZSWR5_RTS | ZSWR5_DTR)) != 180 (cs->cs_ctl_chan->cs_preg[5] & (ZSWR5_RTS | ZSWR5_DTR))); 181 else 182 v = 0; 183 184 if (memcmp((void *)cs->cs_preg, (void *)cs->cs_creg, 16) == 0 && !v) 185 return; /* only change if values are different */ 186 187 /* Copy "pending" regs to "current" */ 188 memcpy((void *)cs->cs_creg, (void *)cs->cs_preg, 16); 189 reg = cs->cs_creg; /* current regs */ 190 191 /* disable interrupts */ 192 zs_write_reg(cs, 1, reg[1] & ~ZSWR1_IMASK); 193 194 /* baud clock divisor, stop bits, parity */ 195 zs_write_reg(cs, 4, reg[4]); 196 197 /* misc. TX/RX control bits */ 198 zs_write_reg(cs, 10, reg[10]); 199 200 /* char size, enable (RX/TX) */ 201 zs_write_reg(cs, 3, reg[3] & ~ZSWR3_RX_ENABLE); 202 zs_write_reg(cs, 5, reg[5] & ~ZSWR5_TX_ENABLE); 203 204 /* synchronous mode stuff */ 205 zs_write_reg(cs, 6, reg[6]); 206 if (reg[15] & ZSWR15_ENABLE_ENHANCED) 207 zs_write_reg(cs, 15, 0); 208 zs_write_reg(cs, 7, reg[7]); 209 210 #if 0 211 /* 212 * Registers 2 and 9 are special because they are 213 * actually common to both channels, but must be 214 * programmed through channel A. The "zsc" attach 215 * function takes care of setting these registers 216 * and they should not be touched thereafter. 217 */ 218 /* interrupt vector */ 219 zs_write_reg(cs, 2, reg[2]); 220 /* master interrupt control */ 221 zs_write_reg(cs, 9, reg[9]); 222 #endif 223 224 /* Shut down the BRG */ 225 zs_write_reg(cs, 14, reg[14] & ~ZSWR14_BAUD_ENA); 226 227 #ifdef ZS_MD_SETCLK 228 /* Let the MD code setup any external clock. */ 229 ZS_MD_SETCLK(cs); 230 #endif /* ZS_MD_SETCLK */ 231 232 /* clock mode control */ 233 zs_write_reg(cs, 11, reg[11]); 234 235 /* baud rate (lo/hi) */ 236 zs_write_reg(cs, 12, reg[12]); 237 zs_write_reg(cs, 13, reg[13]); 238 239 /* Misc. control bits */ 240 zs_write_reg(cs, 14, reg[14]); 241 242 /* which lines cause status interrupts */ 243 zs_write_reg(cs, 15, reg[15]); 244 245 /* 246 * Zilog docs recommend resetting external status twice at this 247 * point. Mainly as the status bits are latched, and the first 248 * interrupt clear might unlatch them to new values, generating 249 * a second interrupt request. 250 */ 251 zs_write_csr(cs, ZSM_RESET_STINT); 252 zs_write_csr(cs, ZSM_RESET_STINT); 253 254 /* char size, enable (RX/TX)*/ 255 zs_write_reg(cs, 3, reg[3]); 256 zs_write_reg(cs, 5, reg[5]); 257 258 /* Write the status bits on the alternate channel also. */ 259 if (cs->cs_ctl_chan != NULL) { 260 v = cs->cs_ctl_chan->cs_preg[5]; 261 cs->cs_ctl_chan->cs_creg[5] = v; 262 zs_write_reg(cs->cs_ctl_chan, 5, v); 263 } 264 265 /* Register 7' if applicable */ 266 if (reg[15] & ZSWR15_ENABLE_ENHANCED) 267 zs_write_reg(cs, 7, reg[16]); 268 269 /* interrupt enables: RX, TX, STATUS */ 270 zs_write_reg(cs, 1, reg[1]); 271 } 272 273 /* 274 * ZS hardware interrupt. Scan all ZS channels. NB: we know here that 275 * channels are kept in (A,B) pairs. 276 * 277 * Do just a little, then get out; set a software interrupt if more 278 * work is needed. 279 * 280 * We deliberately ignore the vectoring Zilog gives us, and match up 281 * only the number of `reset interrupt under service' operations, not 282 * the order. 283 */ 284 int 285 zsc_intr_hard(void *arg) 286 { 287 struct zsc_softc *zsc = arg; 288 struct zs_chanstate *cs0, *cs1; 289 int handled; 290 uint8_t rr3; 291 292 handled = 0; 293 294 /* First look at channel A. */ 295 cs0 = zsc->zsc_cs[0]; 296 cs1 = zsc->zsc_cs[1]; 297 298 /* 299 * We have to clear interrupt first to avoid a race condition, 300 * but it will be done in each MD handler. 301 */ 302 for (;;) { 303 /* Note: only channel A has an RR3 */ 304 rr3 = zs_read_reg(cs0, 3); 305 306 if ((rr3 & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT | 307 ZSRR3_IP_B_RX | ZSRR3_IP_B_TX | ZSRR3_IP_B_STAT)) == 0) { 308 break; 309 } 310 handled = 1; 311 312 /* First look at channel A. */ 313 if (rr3 & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT)) 314 zs_write_csr(cs0, ZSWR0_CLR_INTR); 315 316 if (rr3 & ZSRR3_IP_A_RX) 317 (*cs0->cs_ops->zsop_rxint)(cs0); 318 if (rr3 & ZSRR3_IP_A_STAT) 319 (*cs0->cs_ops->zsop_stint)(cs0, 0); 320 if (rr3 & ZSRR3_IP_A_TX) 321 (*cs0->cs_ops->zsop_txint)(cs0); 322 323 /* Now look at channel B. */ 324 if (rr3 & (ZSRR3_IP_B_RX | ZSRR3_IP_B_TX | ZSRR3_IP_B_STAT)) 325 zs_write_csr(cs1, ZSWR0_CLR_INTR); 326 327 if (rr3 & ZSRR3_IP_B_RX) 328 (*cs1->cs_ops->zsop_rxint)(cs1); 329 if (rr3 & ZSRR3_IP_B_STAT) 330 (*cs1->cs_ops->zsop_stint)(cs1, 0); 331 if (rr3 & ZSRR3_IP_B_TX) 332 (*cs1->cs_ops->zsop_txint)(cs1); 333 } 334 335 /* Note: caller will check cs_x->cs_softreq and DTRT. */ 336 return handled; 337 } 338 339 340 /* 341 * ZS software interrupt. Scan all channels for deferred interrupts. 342 */ 343 int 344 zsc_intr_soft(void *arg) 345 { 346 struct zsc_softc *zsc = arg; 347 struct zs_chanstate *cs; 348 int rval, chan; 349 350 rval = 0; 351 for (chan = 0; chan < 2; chan++) { 352 cs = zsc->zsc_cs[chan]; 353 354 /* 355 * The softint flag can be safely cleared once 356 * we have decided to call the softint routine. 357 * (No need to do splzs() first.) 358 */ 359 if (cs->cs_softreq) { 360 cs->cs_softreq = 0; 361 (*cs->cs_ops->zsop_softint)(cs); 362 rval++; 363 } 364 } 365 return (rval); 366 } 367 368 /* 369 * Provide a null zs "ops" vector. 370 */ 371 372 static void zsnull_rxint (struct zs_chanstate *); 373 static void zsnull_stint (struct zs_chanstate *, int); 374 static void zsnull_txint (struct zs_chanstate *); 375 static void zsnull_softint(struct zs_chanstate *); 376 377 static void 378 zsnull_rxint(struct zs_chanstate *cs) 379 { 380 381 /* Ask for softint() call. */ 382 cs->cs_softreq = 1; 383 } 384 385 static void 386 zsnull_stint(struct zs_chanstate *cs, int force) 387 { 388 389 /* Ask for softint() call. */ 390 cs->cs_softreq = 1; 391 } 392 393 static void 394 zsnull_txint(struct zs_chanstate *cs) 395 { 396 397 /* Ask for softint() call. */ 398 cs->cs_softreq = 1; 399 } 400 401 static void 402 zsnull_softint(struct zs_chanstate *cs) 403 { 404 405 zs_write_reg(cs, 1, 0); 406 zs_write_reg(cs, 15, 0); 407 } 408 409 struct zsops zsops_null = { 410 zsnull_rxint, /* receive char available */ 411 zsnull_stint, /* external/status */ 412 zsnull_txint, /* xmit buffer empty */ 413 zsnull_softint, /* process software interrupt */ 414 }; 415