1 /* $NetBSD: dz_ibus.c,v 1.11 2011/07/09 17:32:29 matt Exp $ */ 2 3 /*- 4 * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Doran. 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 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1998 Ludd, University of Lule}, Sweden. 34 * All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed at Ludd, University of 47 * Lule}, Sweden and its contributors. 48 * 4. The name of the author may not be used to endorse or promote products 49 * derived from this software without specific prior written permission 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 52 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 53 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 54 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 55 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 56 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 57 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 58 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 59 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 60 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 61 */ 62 63 #include <sys/cdefs.h> 64 __KERNEL_RCSID(0, "$NetBSD: dz_ibus.c,v 1.11 2011/07/09 17:32:29 matt Exp $"); 65 66 #include "dzkbd.h" 67 #include "dzms.h" 68 69 #include <sys/param.h> 70 #include <sys/bus.h> 71 #include <sys/conf.h> 72 #include <sys/device.h> 73 #include <sys/file.h> 74 #include <sys/ioctl.h> 75 #include <sys/proc.h> 76 #include <sys/reboot.h> 77 #include <sys/systm.h> 78 #include <sys/tty.h> 79 80 #include <dev/cons.h> 81 82 #include <dev/tc/tcvar.h> /* tc_addr_t */ 83 84 #include <dev/dec/dzreg.h> 85 #include <dev/dec/dzvar.h> 86 #include <dev/dec/dzkbdvar.h> 87 88 #include <pmax/ibus/ibusvar.h> 89 #include <pmax/pmax/pmaxtype.h> 90 #include <pmax/pmax/cons.h> 91 92 #define DZ_LINE_KBD 0 93 #define DZ_LINE_MOUSE 1 94 #define DZ_LINE_CONSOLE 2 95 #define DZ_LINE_AUX 3 96 97 int dz_ibus_match(device_t, cfdata_t, void *); 98 void dz_ibus_attach(device_t, device_t, void *); 99 int dz_ibus_intr(void *); 100 void dz_ibus_cnsetup(paddr_t); 101 int dz_ibus_cngetc(dev_t); 102 void dz_ibus_cnputc(dev_t, int); 103 void dz_ibus_cnpollc(dev_t, int); 104 int dz_ibus_getmajor(void); 105 int dz_ibus_print(void *, const char *); 106 107 int dzgetc(struct dz_linestate *); 108 void dzputc(struct dz_linestate *, int); 109 110 CFATTACH_DECL_NEW(dz_ibus, sizeof(struct dz_softc), 111 dz_ibus_match, dz_ibus_attach, NULL, NULL); 112 113 struct consdev dz_ibus_consdev = { 114 NULL, NULL, dz_ibus_cngetc, dz_ibus_cnputc, 115 dz_ibus_cnpollc, NULL, NULL, NULL, NODEV, CN_NORMAL, 116 }; 117 118 struct dzregs { 119 uint16_t csr; /* 00 Csr: control/status */ 120 uint16_t p0[3]; 121 122 uint16_t rbuf; /* 08 Rbuf/Lpr: receive buffer/line param */ 123 uint16_t p1[3]; 124 125 uint16_t tcr; /* 10 Tcr: transmit console */ 126 uint16_t p2[3]; 127 128 uint16_t tdr; /* 18 Msr/Tdr: modem status reg/xmit data */ 129 uint16_t p3[3]; 130 } volatile *dzcn; 131 132 int dz_ibus_iscn; 133 int dz_ibus_consln = -1; 134 135 int 136 dz_ibus_match(device_t parent, cfdata_t cf, void *aux) 137 { 138 struct ibus_attach_args *iba = aux; 139 140 if (strcmp(iba->ia_name, "dc") != 0 && 141 strcmp(iba->ia_name, "mdc") != 0 && 142 strcmp(iba->ia_name, "dc7085") != 0) 143 return (0); 144 145 if (badaddr((void *)iba->ia_addr, 2)) 146 return (0); 147 148 return (1); 149 } 150 151 void 152 dz_ibus_attach(device_t parent, device_t self, void *aux) 153 { 154 struct ibus_attach_args *iba = aux; 155 struct dz_softc *sc = device_private(self); 156 volatile struct dzregs *dz; 157 #if NDZMS > 0 || NDZKBD > 0 158 struct dzkm_attach_args daa; 159 #endif 160 int i; 161 162 163 DELAY(100000); 164 165 sc->sc_dev = self; 166 167 /* 168 * XXX - This is evil and ugly, but... due to the nature of how 169 * bus_space_* works on pmax it will do for the time being. 170 */ 171 sc->sc_ioh = (bus_space_handle_t)MIPS_PHYS_TO_KSEG1(iba->ia_addr); 172 173 sc->sc_dr.dr_csr = 0; 174 sc->sc_dr.dr_rbuf = 8; 175 sc->sc_dr.dr_dtr = 17; 176 sc->sc_dr.dr_break = 25; 177 sc->sc_dr.dr_tbuf = 24; 178 sc->sc_dr.dr_tcr = 16; 179 sc->sc_dr.dr_dcd = 25; 180 sc->sc_dr.dr_ring = 24; 181 182 sc->sc_dr.dr_firstreg = 0; 183 sc->sc_dr.dr_winsize = sizeof(struct dzregs); 184 185 sc->sc_type = DZ_DZV; 186 187 dz = (volatile struct dzregs *)sc->sc_ioh; 188 i = dz->tcr; 189 dz->csr = DZ_CSR_MSE | DZ_CSR_TXIE; 190 dz->tcr = 0; 191 wbflush(); 192 DELAY(1000); 193 dz->tcr = 1; 194 wbflush(); 195 DELAY(100000); 196 dz->tcr = i; 197 wbflush(); 198 199 sc->sc_dsr = 0x0f; /* XXX check if VS has modem ctrl bits */ 200 201 aprint_normal(": DC-7085, 4 lines"); 202 ibus_intr_establish(parent, (void *)iba->ia_cookie, IPL_TTY, 203 dz_ibus_intr, sc); 204 dzattach(sc, NULL, dz_ibus_consln); 205 DELAY(10000); 206 207 if (systype == DS_PMAX || systype == DS_3MAX) { 208 #if NDZKBD > 0 209 if (!dz_ibus_iscn) 210 dz->rbuf = DZ_LPR_RX_ENABLE | (DZ_LPR_B4800 << 8) | 211 DZ_LPR_8_BIT_CHAR | DZ_LINE_KBD; 212 daa.daa_line = DZ_LINE_KBD; 213 daa.daa_flags = (dz_ibus_iscn ? 0 : DZKBD_CONSOLE); 214 config_found(self, &daa, dz_ibus_print); 215 #endif 216 #if NDZMS > 0 217 dz->rbuf = DZ_LPR_RX_ENABLE | (DZ_LPR_B4800 << 8) | 218 DZ_LPR_8_BIT_CHAR | DZ_LPR_PARENB | DZ_LPR_OPAR | 219 DZ_LINE_MOUSE; 220 daa.daa_line = DZ_LINE_MOUSE; 221 daa.daa_flags = 0; 222 config_found(self, &daa, dz_ibus_print); 223 #endif 224 } 225 } 226 227 int 228 dz_ibus_getmajor(void) 229 { 230 extern const struct cdevsw dz_cdevsw; 231 static int cache = -1; 232 233 if (cache != -1) 234 return (cache); 235 236 return (cache = cdevsw_lookup_major(&dz_cdevsw)); 237 } 238 239 int 240 dz_ibus_intr(void *cookie) 241 { 242 struct dz_softc *sc; 243 volatile struct dzregs *dzr; 244 unsigned csr; 245 246 sc = cookie; 247 dzr = (volatile struct dzregs *)sc->sc_ioh; 248 249 while (((csr = dzr->csr) & (DZ_CSR_RX_DONE | DZ_CSR_TX_READY)) != 0) { 250 if ((csr & DZ_CSR_RX_DONE) != 0) 251 dzrint(sc); 252 if ((csr & DZ_CSR_TX_READY) != 0) 253 dzxint(sc); 254 } 255 256 return (0); 257 } 258 259 void 260 dz_ibus_cnsetup(paddr_t addr) 261 { 262 263 dzcn = (void *)MIPS_PHYS_TO_KSEG1(addr); 264 } 265 266 void 267 dz_ibus_cnattach(int line) 268 { 269 270 switch (line) { 271 case 0: 272 line = DZ_LINE_KBD; 273 break; 274 case 4: 275 line = DZ_LINE_CONSOLE; 276 break; 277 default: 278 line = DZ_LINE_AUX; 279 break; 280 } 281 282 dz_ibus_iscn = 1; 283 dz_ibus_consln = line; 284 285 /* Disable scanning until init is done. */ 286 dzcn->csr = 0; 287 wbflush(); 288 DELAY(1000); 289 290 /* Turn on transmitter for the console. */ 291 dzcn->tcr = (1 << line); 292 wbflush(); 293 DELAY(1000); 294 295 /* Turn scanning back on. */ 296 dzcn->csr = 0x20; 297 wbflush(); 298 DELAY(1000); 299 300 /* 301 * Point the console at the DZ-11. 302 */ 303 cn_tab = &dz_ibus_consdev; 304 cn_tab->cn_pri = CN_REMOTE; 305 cn_tab->cn_dev = makedev(dz_ibus_getmajor(), line); 306 } 307 308 int 309 dz_ibus_cngetc(dev_t dev) 310 { 311 int c, line, s; 312 uint16_t rbuf; 313 314 c = 0; 315 line = minor(dev); 316 s = spltty(); 317 318 do { 319 while ((dzcn->csr & DZ_CSR_RX_DONE) == 0) 320 DELAY(10); 321 DELAY(10); 322 rbuf = dzcn->rbuf; 323 if (((rbuf >> 8) & 3) != line) 324 continue; 325 c = rbuf & 0x7f; 326 } while (c == 17 || c == 19); /* ignore XON/XOFF */ 327 328 splx(s); 329 if (c == 13) 330 c = 10; 331 return (c); 332 } 333 334 void 335 dz_ibus_cnputc(dev_t dev, int ch) 336 { 337 int timeout, s; 338 uint16_t tcr; 339 340 s = spltty(); 341 342 /* Don't hang the machine! */ 343 timeout = 1 << 15; 344 345 /* Remember which lines to scan */ 346 tcr = dzcn->tcr; 347 dzcn->tcr = (1 << minor(dev)); 348 wbflush(); 349 DELAY(10); 350 351 /* Wait until ready */ 352 while ((dzcn->csr & 0x8000) == 0) 353 if (--timeout < 0) 354 break; 355 DELAY(10); 356 357 /* Put the character */ 358 dzcn->tdr = ch; 359 timeout = 1 << 15; 360 wbflush(); 361 DELAY(10); 362 363 /* Wait until ready */ 364 while ((dzcn->csr & 0x8000) == 0) 365 if (--timeout < 0) 366 break; 367 368 DELAY(10); 369 dzcn->tcr = tcr; 370 wbflush(); 371 DELAY(10); 372 splx(s); 373 } 374 375 void 376 dz_ibus_cnpollc(dev_t dev, int pollflag) 377 { 378 379 } 380 381 #if NDZKBD > 0 || NDZMS > 0 382 int 383 dz_ibus_print(void *aux, const char *pnp) 384 { 385 struct dzkm_attach_args *daa; 386 387 daa = aux; 388 if (pnp != NULL) 389 aprint_normal("lkkbd/vsms at %s", pnp); 390 aprint_normal(" line %d", daa->daa_line); 391 return (UNCONF); 392 } 393 394 int 395 dzgetc(struct dz_linestate *ls) 396 { 397 volatile struct dzregs *dzr; 398 int line, s; 399 uint16_t rbuf; 400 401 if (ls == NULL) { 402 /* 403 * dzkbd is the only thing that should put us here. 404 */ 405 line = DZ_LINE_KBD; 406 dzr = dzcn; 407 } else { 408 line = ls->dz_line; 409 dzr = (volatile struct dzregs *)ls->dz_sc->sc_ioh; 410 } 411 412 s = spltty(); 413 for (;;) { 414 while ((dzr->csr & DZ_CSR_RX_DONE) == 0) 415 DELAY(10); 416 DELAY(10); 417 rbuf = dzr->rbuf; 418 DELAY(10); 419 if (((rbuf >> 8) & 3) == line) 420 return (rbuf & 0xff); 421 } 422 splx(s); 423 } 424 425 void 426 dzputc(struct dz_linestate *ls, int ch) 427 { 428 volatile struct dzregs *dzr; 429 int line; 430 uint16_t tcr; 431 int s; 432 433 /* 434 * If the dz has already been attached, the MI driver will do the 435 * transmitting: 436 */ 437 if (ls != NULL && ls->dz_sc != NULL) { 438 line = ls->dz_line; 439 dzr = (volatile struct dzregs *)ls->dz_sc->sc_ioh; 440 s = spltty(); 441 putc(ch, &ls->dz_tty->t_outq); 442 tcr = dzr->tcr; 443 if ((tcr & (1 << line)) == 0) { 444 dzr->tcr = tcr | (1 << line); 445 wbflush(); 446 DELAY(10); 447 } 448 dzxint(ls->dz_sc); 449 splx(s); 450 return; 451 } 452 453 /* Use dzcnputc to do the transmitting. */ 454 dz_ibus_cnputc(makedev(dz_ibus_getmajor(), DZ_LINE_KBD), ch); 455 } 456 #endif /* NDZKBD > 0 || NDZMS > 0 */ 457