1 /* $OpenBSD: z8530sc.c,v 1.7 2013/04/21 14:44:16 sebastia 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/file.h> 100 #include <sys/ioctl.h> 101 #include <sys/tty.h> 102 #include <sys/time.h> 103 #include <sys/kernel.h> 104 #include <sys/syslog.h> 105 106 #include <dev/ic/z8530reg.h> 107 #include <machine/z8530var.h> 108 109 void 110 zs_break(struct zs_chanstate *cs, int set) 111 { 112 113 if (set) { 114 cs->cs_preg[5] |= ZSWR5_BREAK; 115 cs->cs_creg[5] |= ZSWR5_BREAK; 116 } else { 117 cs->cs_preg[5] &= ~ZSWR5_BREAK; 118 cs->cs_creg[5] &= ~ZSWR5_BREAK; 119 } 120 zs_write_reg(cs, 5, cs->cs_creg[5]); 121 } 122 123 124 /* 125 * drain on-chip fifo 126 */ 127 void 128 zs_iflush(struct zs_chanstate *cs) 129 { 130 uint8_t c, rr0, rr1; 131 int i; 132 133 /* 134 * Count how many times we loop. Some systems, such as some 135 * Apple PowerBooks, claim to have SCC's which they really don't. 136 */ 137 for (i = 0; i < 32; i++) { 138 /* Is there input available? */ 139 rr0 = zs_read_csr(cs); 140 if ((rr0 & ZSRR0_RX_READY) == 0) 141 break; 142 143 /* 144 * First read the status, because reading the data 145 * destroys the status of this char. 146 */ 147 rr1 = zs_read_reg(cs, 1); 148 c = zs_read_data(cs); 149 150 if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) { 151 /* Clear the receive error. */ 152 zs_write_csr(cs, ZSWR0_RESET_ERRORS); 153 } 154 } 155 } 156 157 158 /* 159 * Write the given register set to the given zs channel in the proper order. 160 * The channel must not be transmitting at the time. The receiver will 161 * be disabled for the time it takes to write all the registers. 162 * Call this with interrupts disabled. 163 */ 164 void 165 zs_loadchannelregs(struct zs_chanstate *cs) 166 { 167 uint8_t *reg, v; 168 169 zs_write_csr(cs, ZSM_RESET_ERR); /* XXX: reset error condition */ 170 171 #if 1 172 /* 173 * XXX: Is this really a good idea? 174 * XXX: Should go elsewhere! -gwr 175 */ 176 zs_iflush(cs); /* XXX */ 177 #endif 178 179 if (cs->cs_ctl_chan != NULL) 180 v = ((cs->cs_ctl_chan->cs_creg[5] & (ZSWR5_RTS | ZSWR5_DTR)) != 181 (cs->cs_ctl_chan->cs_preg[5] & (ZSWR5_RTS | ZSWR5_DTR))); 182 else 183 v = 0; 184 185 if (memcmp((void *)cs->cs_preg, (void *)cs->cs_creg, 16) == 0 && !v) 186 return; /* only change if values are different */ 187 188 /* Copy "pending" regs to "current" */ 189 memcpy((void *)cs->cs_creg, (void *)cs->cs_preg, 16); 190 reg = cs->cs_creg; /* current regs */ 191 192 /* disable interrupts */ 193 zs_write_reg(cs, 1, reg[1] & ~ZSWR1_IMASK); 194 195 /* baud clock divisor, stop bits, parity */ 196 zs_write_reg(cs, 4, reg[4]); 197 198 /* misc. TX/RX control bits */ 199 zs_write_reg(cs, 10, reg[10]); 200 201 /* char size, enable (RX/TX) */ 202 zs_write_reg(cs, 3, reg[3] & ~ZSWR3_RX_ENABLE); 203 zs_write_reg(cs, 5, reg[5] & ~ZSWR5_TX_ENABLE); 204 205 /* synchronous mode stuff */ 206 zs_write_reg(cs, 6, reg[6]); 207 if (reg[15] & ZSWR15_ENABLE_ENHANCED) 208 zs_write_reg(cs, 15, 0); 209 zs_write_reg(cs, 7, reg[7]); 210 211 #if 0 212 /* 213 * Registers 2 and 9 are special because they are 214 * actually common to both channels, but must be 215 * programmed through channel A. The "zsc" attach 216 * function takes care of setting these registers 217 * and they should not be touched thereafter. 218 */ 219 /* interrupt vector */ 220 zs_write_reg(cs, 2, reg[2]); 221 /* master interrupt control */ 222 zs_write_reg(cs, 9, reg[9]); 223 #endif 224 225 /* Shut down the BRG */ 226 zs_write_reg(cs, 14, reg[14] & ~ZSWR14_BAUD_ENA); 227 228 #ifdef ZS_MD_SETCLK 229 /* Let the MD code setup any external clock. */ 230 ZS_MD_SETCLK(cs); 231 #endif /* ZS_MD_SETCLK */ 232 233 /* clock mode control */ 234 zs_write_reg(cs, 11, reg[11]); 235 236 /* baud rate (lo/hi) */ 237 zs_write_reg(cs, 12, reg[12]); 238 zs_write_reg(cs, 13, reg[13]); 239 240 /* Misc. control bits */ 241 zs_write_reg(cs, 14, reg[14]); 242 243 /* which lines cause status interrupts */ 244 zs_write_reg(cs, 15, reg[15]); 245 246 /* 247 * Zilog docs recommend resetting external status twice at this 248 * point. Mainly as the status bits are latched, and the first 249 * interrupt clear might unlatch them to new values, generating 250 * a second interrupt request. 251 */ 252 zs_write_csr(cs, ZSM_RESET_STINT); 253 zs_write_csr(cs, ZSM_RESET_STINT); 254 255 /* char size, enable (RX/TX)*/ 256 zs_write_reg(cs, 3, reg[3]); 257 zs_write_reg(cs, 5, reg[5]); 258 259 /* Write the status bits on the alternate channel also. */ 260 if (cs->cs_ctl_chan != NULL) { 261 v = cs->cs_ctl_chan->cs_preg[5]; 262 cs->cs_ctl_chan->cs_creg[5] = v; 263 zs_write_reg(cs->cs_ctl_chan, 5, v); 264 } 265 266 /* Register 7' if applicable */ 267 if (reg[15] & ZSWR15_ENABLE_ENHANCED) 268 zs_write_reg(cs, 7, reg[16]); 269 270 /* interrupt enables: RX, TX, STATUS */ 271 zs_write_reg(cs, 1, reg[1]); 272 } 273 274 /* 275 * ZS hardware interrupt. Scan all ZS channels. NB: we know here that 276 * channels are kept in (A,B) pairs. 277 * 278 * Do just a little, then get out; set a software interrupt if more 279 * work is needed. 280 * 281 * We deliberately ignore the vectoring Zilog gives us, and match up 282 * only the number of `reset interrupt under service' operations, not 283 * the order. 284 */ 285 int 286 zsc_intr_hard(void *arg) 287 { 288 struct zsc_softc *zsc = arg; 289 struct zs_chanstate *cs0, *cs1; 290 int handled; 291 uint8_t rr3; 292 293 handled = 0; 294 295 /* First look at channel A. */ 296 cs0 = zsc->zsc_cs[0]; 297 cs1 = zsc->zsc_cs[1]; 298 299 /* 300 * We have to clear interrupt first to avoid a race condition, 301 * but it will be done in each MD handler. 302 */ 303 for (;;) { 304 /* Note: only channel A has an RR3 */ 305 rr3 = zs_read_reg(cs0, 3); 306 307 if ((rr3 & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT | 308 ZSRR3_IP_B_RX | ZSRR3_IP_B_TX | ZSRR3_IP_B_STAT)) == 0) { 309 break; 310 } 311 handled = 1; 312 313 /* First look at channel A. */ 314 if (rr3 & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT)) 315 zs_write_csr(cs0, ZSWR0_CLR_INTR); 316 317 if (rr3 & ZSRR3_IP_A_RX) 318 (*cs0->cs_ops->zsop_rxint)(cs0); 319 if (rr3 & ZSRR3_IP_A_STAT) 320 (*cs0->cs_ops->zsop_stint)(cs0, 0); 321 if (rr3 & ZSRR3_IP_A_TX) 322 (*cs0->cs_ops->zsop_txint)(cs0); 323 324 /* Now look at channel B. */ 325 if (rr3 & (ZSRR3_IP_B_RX | ZSRR3_IP_B_TX | ZSRR3_IP_B_STAT)) 326 zs_write_csr(cs1, ZSWR0_CLR_INTR); 327 328 if (rr3 & ZSRR3_IP_B_RX) 329 (*cs1->cs_ops->zsop_rxint)(cs1); 330 if (rr3 & ZSRR3_IP_B_STAT) 331 (*cs1->cs_ops->zsop_stint)(cs1, 0); 332 if (rr3 & ZSRR3_IP_B_TX) 333 (*cs1->cs_ops->zsop_txint)(cs1); 334 } 335 336 /* Note: caller will check cs_x->cs_softreq and DTRT. */ 337 return handled; 338 } 339 340 341 /* 342 * ZS software interrupt. Scan all channels for deferred interrupts. 343 */ 344 int 345 zsc_intr_soft(void *arg) 346 { 347 struct zsc_softc *zsc = arg; 348 struct zs_chanstate *cs; 349 int rval, chan; 350 351 rval = 0; 352 for (chan = 0; chan < 2; chan++) { 353 cs = zsc->zsc_cs[chan]; 354 355 /* 356 * The softint flag can be safely cleared once 357 * we have decided to call the softint routine. 358 * (No need to do splzs() first.) 359 */ 360 if (cs->cs_softreq) { 361 cs->cs_softreq = 0; 362 (*cs->cs_ops->zsop_softint)(cs); 363 rval++; 364 } 365 } 366 return (rval); 367 } 368 369 /* 370 * Provide a null zs "ops" vector. 371 */ 372 373 static void zsnull_rxint (struct zs_chanstate *); 374 static void zsnull_stint (struct zs_chanstate *, int); 375 static void zsnull_txint (struct zs_chanstate *); 376 static void zsnull_softint(struct zs_chanstate *); 377 378 static void 379 zsnull_rxint(struct zs_chanstate *cs) 380 { 381 382 /* Ask for softint() call. */ 383 cs->cs_softreq = 1; 384 } 385 386 static void 387 zsnull_stint(struct zs_chanstate *cs, int force) 388 { 389 390 /* Ask for softint() call. */ 391 cs->cs_softreq = 1; 392 } 393 394 static void 395 zsnull_txint(struct zs_chanstate *cs) 396 { 397 398 /* Ask for softint() call. */ 399 cs->cs_softreq = 1; 400 } 401 402 static void 403 zsnull_softint(struct zs_chanstate *cs) 404 { 405 406 zs_write_reg(cs, 1, 0); 407 zs_write_reg(cs, 15, 0); 408 } 409 410 struct zsops zsops_null = { 411 zsnull_rxint, /* receive char available */ 412 zsnull_stint, /* external/status */ 413 zsnull_txint, /* xmit buffer empty */ 414 zsnull_softint, /* process software interrupt */ 415 }; 416