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