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