1/* $NetBSD: dz_ibus.c,v 1.14 2021/08/07 16:19:02 thorpej 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.14 2021/08/07 16:19:02 thorpej 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 97int dz_ibus_match(device_t, cfdata_t, void *); 98void dz_ibus_attach(device_t, device_t, void *); 99int dz_ibus_intr(void *); 100void dz_ibus_cnsetup(paddr_t); 101int dz_ibus_cngetc(dev_t); 102void dz_ibus_cnputc(dev_t, int); 103void dz_ibus_cnpollc(dev_t, int); 104int dz_ibus_getmajor(void); 105int dz_ibus_print(void *, const char *); 106 107int dzgetc(struct dz_linestate *); 108void dzputc(struct dz_linestate *, int); 109 110CFATTACH_DECL_NEW(dz_ibus, sizeof(struct dz_softc), 111 dz_ibus_match, dz_ibus_attach, NULL, NULL); 112 113struct 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 118struct 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 132int dz_ibus_iscn; 133int dz_ibus_consln = -1; 134 135int 136dz_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 151void 152dz_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_iot = normal_memt; 172 sc->sc_ioh = (bus_space_handle_t)MIPS_PHYS_TO_KSEG1(iba->ia_addr); 173 174 sc->sc_dr.dr_csr = 0; 175 sc->sc_dr.dr_rbuf = 8; 176 sc->sc_dr.dr_dtr = 17; 177 sc->sc_dr.dr_break = 25; 178 sc->sc_dr.dr_tbuf = 24; 179 sc->sc_dr.dr_tcr = 16; 180 sc->sc_dr.dr_dcd = 25; 181 sc->sc_dr.dr_ring = 24; 182 183 sc->sc_dr.dr_firstreg = 0; 184 sc->sc_dr.dr_winsize = sizeof(struct dzregs); 185 186 sc->sc_type = DZ_DZV; 187 188 dz = (volatile struct dzregs *)sc->sc_ioh; 189 i = dz->tcr; 190 dz->csr = DZ_CSR_MSE | DZ_CSR_TXIE; 191 dz->tcr = 0; 192 wbflush(); 193 DELAY(1000); 194 dz->tcr = 1; 195 wbflush(); 196 DELAY(100000); 197 dz->tcr = i; 198 wbflush(); 199 200 sc->sc_dsr = 0x0f; /* XXX check if VS has modem ctrl bits */ 201 202 aprint_normal(": DC-7085, 4 lines"); 203 ibus_intr_establish(parent, (void *)iba->ia_cookie, IPL_TTY, 204 dz_ibus_intr, sc); 205 dzattach(sc, NULL, dz_ibus_consln); 206 DELAY(10000); 207 208 if (systype == DS_PMAX || systype == DS_3MAX) { 209#if NDZKBD > 0 210 if (!dz_ibus_iscn) 211 dz->rbuf = DZ_LPR_RX_ENABLE | (DZ_LPR_B4800 << 8) | 212 DZ_LPR_8_BIT_CHAR | DZ_LINE_KBD; 213 daa.daa_line = DZ_LINE_KBD; 214 daa.daa_flags = (dz_ibus_iscn ? 0 : DZKBD_CONSOLE); 215 config_found(self, &daa, dz_ibus_print, CFARGS_NONE); 216#endif 217#if NDZMS > 0 218 dz->rbuf = DZ_LPR_RX_ENABLE | (DZ_LPR_B4800 << 8) | 219 DZ_LPR_8_BIT_CHAR | DZ_LPR_PARENB | DZ_LPR_OPAR | 220 DZ_LINE_MOUSE; 221 daa.daa_line = DZ_LINE_MOUSE; 222 daa.daa_flags = 0; 223 config_found(self, &daa, dz_ibus_print, CFARGS_NONE); 224#endif 225 } 226} 227 228int 229dz_ibus_getmajor(void) 230{ 231 extern const struct cdevsw dz_cdevsw; 232 static int cache = -1; 233 234 if (cache != -1) 235 return (cache); 236 237 return (cache = cdevsw_lookup_major(&dz_cdevsw)); 238} 239 240int 241dz_ibus_intr(void *cookie) 242{ 243 struct dz_softc *sc; 244 volatile struct dzregs *dzr; 245 unsigned csr; 246 247 sc = cookie; 248 dzr = (volatile struct dzregs *)sc->sc_ioh; 249 250 while (((csr = dzr->csr) & (DZ_CSR_RX_DONE | DZ_CSR_TX_READY)) != 0) { 251 if ((csr & DZ_CSR_RX_DONE) != 0) 252 dzrint(sc); 253 if ((csr & DZ_CSR_TX_READY) != 0) 254 dzxint(sc); 255 } 256 257 return (0); 258} 259 260void 261dz_ibus_cnsetup(paddr_t addr) 262{ 263 264 dzcn = (void *)MIPS_PHYS_TO_KSEG1(addr); 265} 266 267void 268dz_ibus_cnattach(int line) 269{ 270 271 switch (line) { 272 case 0: 273 line = DZ_LINE_KBD; 274 break; 275 case 4: 276 line = DZ_LINE_CONSOLE; 277 break; 278 default: 279 line = DZ_LINE_AUX; 280 break; 281 } 282 283 dz_ibus_iscn = 1; 284 dz_ibus_consln = line; 285 286 /* Disable scanning until init is done. */ 287 dzcn->csr = 0; 288 wbflush(); 289 DELAY(1000); 290 291 /* Turn on transmitter for the console. */ 292 dzcn->tcr = (1 << line); 293 wbflush(); 294 DELAY(1000); 295 296 /* Turn scanning back on. */ 297 dzcn->csr = 0x20; 298 wbflush(); 299 DELAY(1000); 300 301 /* 302 * Point the console at the DZ-11. 303 */ 304 cn_tab = &dz_ibus_consdev; 305 cn_tab->cn_pri = CN_REMOTE; 306 cn_tab->cn_dev = makedev(dz_ibus_getmajor(), line); 307} 308 309int 310dz_ibus_cngetc(dev_t dev) 311{ 312 int c, line, s; 313 uint16_t rbuf; 314 315 c = 0; 316 line = minor(dev); 317 s = spltty(); 318 319 do { 320 while ((dzcn->csr & DZ_CSR_RX_DONE) == 0) 321 DELAY(10); 322 DELAY(10); 323 rbuf = dzcn->rbuf; 324 if (((rbuf >> 8) & 3) != line) 325 continue; 326 c = rbuf & 0x7f; 327 } while (c == 17 || c == 19); /* ignore XON/XOFF */ 328 329 splx(s); 330 if (c == 13) 331 c = 10; 332 return (c); 333} 334 335void 336dz_ibus_cnputc(dev_t dev, int ch) 337{ 338 int timeout, s; 339 uint16_t tcr; 340 341 s = spltty(); 342 343 /* Don't hang the machine! */ 344 timeout = 1 << 15; 345 346 /* Remember which lines to scan */ 347 tcr = dzcn->tcr; 348 dzcn->tcr = (1 << minor(dev)); 349 wbflush(); 350 DELAY(10); 351 352 /* Wait until ready */ 353 while ((dzcn->csr & 0x8000) == 0) 354 if (--timeout < 0) 355 break; 356 DELAY(10); 357 358 /* Put the character */ 359 dzcn->tdr = ch; 360 timeout = 1 << 15; 361 wbflush(); 362 DELAY(10); 363 364 /* Wait until ready */ 365 while ((dzcn->csr & 0x8000) == 0) 366 if (--timeout < 0) 367 break; 368 369 DELAY(10); 370 dzcn->tcr = tcr; 371 wbflush(); 372 DELAY(10); 373 splx(s); 374} 375 376void 377dz_ibus_cnpollc(dev_t dev, int pollflag) 378{ 379 380} 381 382#if NDZKBD > 0 || NDZMS > 0 383int 384dz_ibus_print(void *aux, const char *pnp) 385{ 386 struct dzkm_attach_args *daa; 387 388 daa = aux; 389 if (pnp != NULL) 390 aprint_normal("lkkbd/vsms at %s", pnp); 391 aprint_normal(" line %d", daa->daa_line); 392 return (UNCONF); 393} 394 395int 396dzgetc(struct dz_linestate *ls) 397{ 398 volatile struct dzregs *dzr; 399 int line, s; 400 uint16_t rbuf; 401 402 if (ls == NULL) { 403 /* 404 * dzkbd is the only thing that should put us here. 405 */ 406 line = DZ_LINE_KBD; 407 dzr = dzcn; 408 } else { 409 line = ls->dz_line; 410 dzr = (volatile struct dzregs *)ls->dz_sc->sc_ioh; 411 } 412 413 s = spltty(); 414 for (;;) { 415 while ((dzr->csr & DZ_CSR_RX_DONE) == 0) 416 DELAY(10); 417 DELAY(10); 418 rbuf = dzr->rbuf; 419 DELAY(10); 420 if (((rbuf >> 8) & 3) == line) 421 return (rbuf & 0xff); 422 } 423 splx(s); 424} 425 426void 427dzputc(struct dz_linestate *ls, int ch) 428{ 429 volatile struct dzregs *dzr; 430 int line; 431 uint16_t tcr; 432 int s; 433 434 /* 435 * If the dz has already been attached, the MI driver will do the 436 * transmitting: 437 */ 438 if (ls != NULL && ls->dz_sc != NULL) { 439 line = ls->dz_line; 440 dzr = (volatile struct dzregs *)ls->dz_sc->sc_ioh; 441 s = spltty(); 442 putc(ch, &ls->dz_tty->t_outq); 443 tcr = dzr->tcr; 444 if ((tcr & (1 << line)) == 0) { 445 dzr->tcr = tcr | (1 << line); 446 wbflush(); 447 DELAY(10); 448 } 449 dzxint(ls->dz_sc); 450 splx(s); 451 return; 452 } 453 454 /* Use dzcnputc to do the transmitting. */ 455 dz_ibus_cnputc(makedev(dz_ibus_getmajor(), DZ_LINE_KBD), ch); 456} 457#endif /* NDZKBD > 0 || NDZMS > 0 */ 458