1 /* $NetBSD: zs.c,v 1.1 2001/05/14 18:23:07 drochner Exp $ */ 2 3 /*- 4 * Copyright (c) 1996 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Gordon W. Ross. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Zilog Z8530 Dual UART driver (machine-dependent part) 41 * 42 * Runs two serial lines per chip using slave drivers. 43 * Plain tty/async lines use the zs_async slave. 44 */ 45 46 #include "opt_ddb.h" 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/conf.h> 51 #include <sys/device.h> 52 #include <sys/file.h> 53 #include <sys/ioctl.h> 54 #include <sys/kernel.h> 55 #include <sys/malloc.h> 56 #include <sys/proc.h> 57 #include <sys/tty.h> 58 #include <sys/time.h> 59 #include <sys/syslog.h> 60 61 #include <dev/cons.h> 62 #include <dev/ic/z8530reg.h> 63 64 #include <machine/cpu.h> 65 66 #include <machine/z8530var.h> 67 #include <cesfic/dev/zsvar.h> 68 69 int zs_getc __P((void*)); 70 void zs_putc __P((void*, int)); 71 72 static struct zs_chanstate zs_conschan_store; 73 static int zs_hwflags[2][2]; 74 int zs_major = 10; 75 int zssoftpending; 76 77 extern struct cfdriver zsc_cd; 78 79 u_char zs_init_reg[16] = { 80 0, /* 0: CMD (reset, etc.) */ 81 0, /* 1: No interrupts yet. */ 82 0x18 + ZSHARD_PRI, /* IVECT */ 83 ZSWR3_RX_8 | ZSWR3_RX_ENABLE, 84 ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP, 85 ZSWR5_TX_8 | ZSWR5_TX_ENABLE, 86 0, /* 6: TXSYNC/SYNCLO */ 87 0, /* 7: RXSYNC/SYNCHI */ 88 0, /* 8: alias for data port */ 89 ZSWR9_MASTER_IE, 90 0, /*10: Misc. TX/RX control bits */ 91 ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD, 92 11, /*12: BAUDLO (default=9600) */ 93 0, /*13: BAUDHI (default=9600) */ 94 ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK, 95 ZSWR15_BREAK_IE | ZSWR15_DCD_IE, 96 }; 97 98 static int zsc_print __P((void *, const char *)); 99 int zscngetc __P((dev_t)); 100 void zscnputc __P((dev_t, int)); 101 102 static struct consdev zscons = { NULL, NULL, 103 zscngetc, zscnputc, nullcnpollc, 0, NODEV, 1 }; 104 105 void 106 zs_config(zsc, base) 107 struct zsc_softc *zsc; 108 char *base; 109 { 110 struct zsc_attach_args zsc_args; 111 struct zs_chanstate *cs; 112 int zsc_unit, channel, s; 113 114 zsc_unit = zsc->zsc_dev.dv_unit; 115 printf(": Zilog 8530 SCC\n"); 116 117 /* 118 * Initialize software state for each channel. 119 */ 120 for (channel = 0; channel < 2; channel++) { 121 zsc_args.channel = channel; 122 zsc_args.hwflags = zs_hwflags[zsc_unit][channel]; 123 124 /* 125 * If we're the console, copy the channel state, and 126 * adjust the console channel pointer. 127 */ 128 if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE) { 129 cs = &zs_conschan_store; 130 } else { 131 cs = malloc(sizeof(struct zs_chanstate), 132 M_DEVBUF, M_NOWAIT); 133 if(channel==0){ 134 cs->cs_reg_csr = base+7; 135 cs->cs_reg_data = base+15; 136 } else { 137 cs->cs_reg_csr = base+3; 138 cs->cs_reg_data = base+11; 139 } 140 bcopy(zs_init_reg, cs->cs_creg, 16); 141 bcopy(zs_init_reg, cs->cs_preg, 16); 142 cs->cs_defspeed = 9600; 143 } 144 zsc->zsc_cs[channel] = cs; 145 146 cs->cs_defcflag = CREAD | CS8 | HUPCL; 147 148 /* Make these correspond to cs_defcflag (-crtscts) */ 149 cs->cs_rr0_dcd = ZSRR0_DCD; 150 cs->cs_rr0_cts = 0; 151 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; 152 cs->cs_wr5_rts = 0; 153 154 cs->cs_channel = channel; 155 cs->cs_private = NULL; 156 cs->cs_ops = &zsops_null; 157 cs->cs_brg_clk = 4000000 / 16; 158 159 /* 160 * Clear the master interrupt enable. 161 * The INTENA is common to both channels, 162 * so just do it on the A channel. 163 */ 164 if (channel == 0) { 165 zs_write_reg(cs, 9, 0); 166 } 167 168 /* 169 * Look for a child driver for this channel. 170 * The child attach will setup the hardware. 171 */ 172 if (!config_found(&zsc->zsc_dev, (void *)&zsc_args, zsc_print)) { 173 /* No sub-driver. Just reset it. */ 174 u_char reset = (channel == 0) ? 175 ZSWR9_A_RESET : ZSWR9_B_RESET; 176 s = splzs(); 177 zs_write_reg(cs, 9, reset); 178 splx(s); 179 } 180 } 181 } 182 183 static int 184 zsc_print(aux, name) 185 void *aux; 186 const char *name; 187 { 188 struct zsc_attach_args *args = aux; 189 190 if (name != NULL) 191 printf("%s: ", name); 192 193 if (args->channel != -1) 194 printf(" channel %d", args->channel); 195 196 return UNCONF; 197 } 198 199 int 200 zshard(arg) 201 void *arg; 202 { 203 register struct zsc_softc *zsc; 204 register int unit, rval; 205 206 rval = 0; 207 for (unit = 0; unit < zsc_cd.cd_ndevs; unit++) { 208 zsc = zsc_cd.cd_devs[unit]; 209 if (zsc == NULL) 210 continue; 211 rval |= zsc_intr_hard(zsc); 212 if ((zsc->zsc_cs[0]->cs_softreq) || 213 (zsc->zsc_cs[1]->cs_softreq)) 214 { 215 /* zsc_req_softint(zsc); */ 216 /* We are at splzs here, so no need to lock. */ 217 if (zssoftpending == 0) { 218 zssoftpending = 1; 219 setsoftzs(); 220 } 221 } 222 } 223 return (rval); 224 } 225 226 void 227 softzs() 228 { 229 register struct zsc_softc *zsc; 230 register int unit; 231 232 /* This is not the only ISR on this IPL. */ 233 if (zssoftpending == 0) 234 return; 235 236 /* 237 * The soft intr. bit will be set by zshard only if 238 * the variable zssoftpending is zero. 239 */ 240 zssoftpending = 0; 241 242 for (unit = 0; unit < zsc_cd.cd_ndevs; ++unit) { 243 zsc = zsc_cd.cd_devs[unit]; 244 if (zsc == NULL) 245 continue; 246 (void) zsc_intr_soft(zsc); 247 } 248 return; 249 } 250 251 u_char 252 zs_read_reg(cs, reg) 253 struct zs_chanstate *cs; 254 u_char reg; 255 { 256 u_char val; 257 258 *cs->cs_reg_csr = reg; 259 ZS_DELAY(); 260 val = *cs->cs_reg_csr; 261 ZS_DELAY(); 262 return val; 263 } 264 265 void 266 zs_write_reg(cs, reg, val) 267 struct zs_chanstate *cs; 268 u_char reg, val; 269 { 270 *cs->cs_reg_csr = reg; 271 ZS_DELAY(); 272 *cs->cs_reg_csr = val; 273 ZS_DELAY(); 274 } 275 276 u_char zs_read_csr(cs) 277 struct zs_chanstate *cs; 278 { 279 register u_char val; 280 281 val = *cs->cs_reg_csr; 282 ZS_DELAY(); 283 return val; 284 } 285 286 void zs_write_csr(cs, val) 287 struct zs_chanstate *cs; 288 u_char val; 289 { 290 *cs->cs_reg_csr = val; 291 ZS_DELAY(); 292 } 293 294 u_char zs_read_data(cs) 295 struct zs_chanstate *cs; 296 { 297 register u_char val; 298 299 val = *cs->cs_reg_data; 300 ZS_DELAY(); 301 return val; 302 } 303 304 void zs_write_data(cs, val) 305 struct zs_chanstate *cs; 306 u_char val; 307 { 308 *cs->cs_reg_data = val; 309 ZS_DELAY(); 310 } 311 312 int 313 zs_set_speed(cs, bps) 314 struct zs_chanstate *cs; 315 int bps; /* bits per second */ 316 { 317 int tconst, real_bps; 318 319 tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps); 320 321 if (tconst < 0) 322 return (EINVAL); 323 324 /* Convert back to make sure we can do it. */ 325 real_bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst); 326 #if 0 327 /* XXX - Allow some tolerance here? */ 328 if (real_bps != bps) 329 return (EINVAL); 330 #endif 331 cs->cs_preg[12] = tconst; 332 cs->cs_preg[13] = tconst >> 8; 333 334 return (0); 335 } 336 337 int 338 zs_set_modes(cs, cflag) 339 struct zs_chanstate *cs; 340 int cflag; /* bits per second */ 341 { 342 int s; 343 344 /* 345 * Output hardware flow control on the chip is horrendous: 346 * if carrier detect drops, the receiver is disabled, and if 347 * CTS drops, the transmitter is stoped IN MID CHARACTER! 348 * Therefore, NEVER set the HFC bit, and instead use the 349 * status interrupt to detect CTS changes. 350 */ 351 s = splzs(); 352 #if 0 /* XXX - See below. */ 353 if (cflag & CLOCAL) { 354 cs->cs_rr0_dcd = 0; 355 cs->cs_preg[15] &= ~ZSWR15_DCD_IE; 356 } else { 357 /* XXX - Need to notice DCD change here... */ 358 cs->cs_rr0_dcd = ZSRR0_DCD; 359 cs->cs_preg[15] |= ZSWR15_DCD_IE; 360 } 361 #endif /* XXX */ 362 if (cflag & CRTSCTS) { 363 cs->cs_wr5_dtr = ZSWR5_DTR; 364 cs->cs_wr5_rts = ZSWR5_RTS; 365 cs->cs_rr0_cts = ZSRR0_CTS; 366 cs->cs_preg[15] |= ZSWR15_CTS_IE; 367 } else { 368 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; 369 cs->cs_wr5_rts = 0; 370 cs->cs_rr0_cts = 0; 371 cs->cs_preg[15] &= ~ZSWR15_CTS_IE; 372 } 373 splx(s); 374 375 /* Caller will stuff the pending registers. */ 376 return (0); 377 } 378 379 /* 380 * Handle user request to enter kernel debugger. 381 */ 382 void 383 zs_abort(cs) 384 struct zs_chanstate *cs; 385 { 386 int rr0; 387 388 /* Wait for end of break to avoid PROM abort. */ 389 /* XXX - Limit the wait? */ 390 do { 391 rr0 = *cs->cs_reg_csr; 392 ZS_DELAY(); 393 } while (rr0 & ZSRR0_BREAK); 394 #ifdef DDB 395 console_debugger(); 396 #endif 397 } 398 399 /* 400 * Polled input char. 401 */ 402 int 403 zs_getc(arg) 404 void *arg; 405 { 406 register struct zs_chanstate *cs = arg; 407 register int s, c, rr0, stat; 408 409 s = splhigh(); 410 top: 411 /* Wait for a character to arrive. */ 412 do { 413 rr0 = *cs->cs_reg_csr; 414 ZS_DELAY(); 415 } while ((rr0 & ZSRR0_RX_READY) == 0); 416 417 /* Read error register. */ 418 stat = zs_read_reg(cs, 1) & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE); 419 if (stat) { 420 zs_write_csr(cs, ZSM_RESET_ERR); 421 goto top; 422 } 423 424 /* Read character. */ 425 c = *cs->cs_reg_data; 426 ZS_DELAY(); 427 splx(s); 428 429 return (c); 430 } 431 432 /* 433 * Polled output char. 434 */ 435 void 436 zs_putc(arg, c) 437 void *arg; 438 int c; 439 { 440 register struct zs_chanstate *cs = arg; 441 register int s, rr0; 442 443 s = splhigh(); 444 /* Wait for transmitter to become ready. */ 445 do { 446 rr0 = *cs->cs_reg_csr; 447 ZS_DELAY(); 448 } while ((rr0 & ZSRR0_TX_READY) == 0); 449 450 *cs->cs_reg_data = c; 451 ZS_DELAY(); 452 splx(s); 453 } 454 455 int zscngetc(dev) 456 dev_t dev; 457 { 458 register struct zs_chanstate *cs = &zs_conschan_store; 459 register int c; 460 461 c = zs_getc(cs); 462 return (c); 463 } 464 465 void zscnputc(dev, c) 466 dev_t dev; 467 int c; 468 { 469 register struct zs_chanstate *cs = &zs_conschan_store; 470 471 zs_putc(cs, c); 472 } 473 474 /* 475 * Common parts of console init. 476 */ 477 void 478 zs_cninit(base) 479 void *base; 480 { 481 struct zs_chanstate *cs; 482 /* 483 * Pointer to channel state. Later, the console channel 484 * state is copied into the softc, and the console channel 485 * pointer adjusted to point to the new copy. 486 */ 487 cs = &zs_conschan_store; 488 zs_hwflags[0][0] = ZS_HWFLAG_CONSOLE; 489 490 /* Setup temporary chanstate. */ 491 cs->cs_reg_csr = base+7; 492 cs->cs_reg_data = base+15; 493 494 /* Initialize the pending registers. */ 495 bcopy(zs_init_reg, cs->cs_preg, 16); 496 cs->cs_preg[5] |= (ZSWR5_DTR | ZSWR5_RTS); 497 498 /* XXX: Preserve BAUD rate from boot loader. */ 499 /* XXX: Also, why reset the chip here? -gwr */ 500 /* cs->cs_defspeed = zs_get_speed(cs); */ 501 cs->cs_defspeed = 9600; /* XXX */ 502 503 /* Clear the master interrupt enable. */ 504 zs_write_reg(cs, 9, 0); 505 506 /* Reset the whole SCC chip. */ 507 zs_write_reg(cs, 9, ZSWR9_HARD_RESET); 508 509 /* Copy "pending" to "current" and H/W. */ 510 zs_loadchannelregs(cs); 511 512 /* Point the console at the SCC. */ 513 cn_tab = &zscons; 514 } 515