1 /* $NetBSD: dz_vsbus.c,v 1.51 2025/03/04 15:34:42 hans Exp $ */ 2 /* 3 * Copyright (c) 1998 Ludd, University of Lule}, Sweden. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __KERNEL_RCSID(0, "$NetBSD: dz_vsbus.c,v 1.51 2025/03/04 15:34:42 hans Exp $"); 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/conf.h> 33 #include <sys/cpu.h> 34 #include <sys/device.h> 35 #include <sys/file.h> 36 #include <sys/ioctl.h> 37 #include <sys/proc.h> 38 #include <sys/tty.h> 39 40 #include <dev/cons.h> 41 42 #include <machine/sid.h> 43 #include <machine/vsbus.h> 44 #include <machine/scb.h> 45 46 #include <arch/vax/vax/gencons.h> 47 48 #include <dev/dec/dzreg.h> 49 #include <dev/dec/dzvar.h> 50 51 #include "ioconf.h" 52 #include "locators.h" 53 #include "dzkbd.h" 54 #include "dzms.h" 55 #include "opt_cputype.h" 56 57 #if NDZKBD > 0 || NDZMS > 0 58 #include <dev/dec/dzkbdvar.h> 59 60 #if 0 61 static struct dz_linestate dz_conslinestate = { NULL, -1, NULL, NULL, NULL }; 62 #endif 63 #endif 64 65 static int dz_vsbus_match(device_t, cfdata_t, void *); 66 static void dz_vsbus_attach(device_t, device_t, void *); 67 #if NDZKBD > 0 || NDZMS > 0 68 static void dz_vsbus_attach_deferred(device_t); 69 #endif 70 71 static vaddr_t dz_regs; /* Used for console */ 72 73 CFATTACH_DECL_NEW(dz_vsbus, sizeof(struct dz_softc), 74 dz_vsbus_match, dz_vsbus_attach, NULL, NULL); 75 76 #define REG(name) short name; short X##name##X; 77 static volatile struct ss_dz {/* base address of DZ-controller: 0x200A0000 */ 78 REG(csr); /* 00 Csr: control/status register */ 79 REG(rbuf); /* 04 Rbuf/Lpr: receive buffer/line param reg. */ 80 REG(tcr); /* 08 Tcr: transmit console register */ 81 REG(tdr); /* 0C Msr/Tdr: modem status reg/transmit data reg */ 82 REG(lpr0); /* 10 Lpr0: */ 83 REG(lpr1); /* 14 Lpr0: */ 84 REG(lpr2); /* 18 Lpr0: */ 85 REG(lpr3); /* 1C Lpr0: */ 86 } *dz; 87 #undef REG 88 89 cons_decl(dz); 90 91 #if NDZKBD > 0 || NDZMS > 0 92 static int 93 dz_print(void *aux, const char *name) 94 { 95 struct dzkm_attach_args *daa = aux; 96 97 aprint_normal (" line %d", daa->daa_line); 98 99 return (QUIET); 100 } 101 #endif 102 103 static int 104 dz_vsbus_match(device_t parent, cfdata_t cf, void *aux) 105 { 106 struct vsbus_attach_args * const va = aux; 107 volatile struct ss_dz *dzP; 108 short i; 109 110 #if VAX53 || VAX49 || VAXANY 111 if (vax_boardtype == VAX_BTYP_53 || vax_boardtype == VAX_BTYP_49) 112 if (cf->cf_loc[VSBUSCF_CSR] != DZ_CSR_KA49) 113 return 0; /* Ugly */ 114 #endif 115 116 dzP = (struct ss_dz *)va->va_addr; 117 i = dzP->tcr; 118 dzP->csr = DZ_CSR_MSE|DZ_CSR_TXIE; 119 dzP->tcr = 0; 120 DELAY(1000); 121 dzP->tcr = 1; 122 DELAY(100000); 123 dzP->tcr = i; 124 125 /* If the device doesn't exist, no interrupt has been generated */ 126 return 1; 127 } 128 129 static void 130 dz_vsbus_attach(device_t parent, device_t self, void *aux) 131 { 132 struct dz_softc * const sc = device_private(self); 133 struct vsbus_attach_args * const va = aux; 134 extern const struct cdevsw dz_cdevsw; 135 int s, consline; 136 137 sc->sc_dev = self; 138 /* 139 * XXX - This is evil and ugly, but... 140 * due to the nature of how bus_space_* works on VAX, this will 141 * be perfectly good until everything is converted. 142 */ 143 if (major(cn_tab->cn_dev) != cdevsw_lookup_major(&dz_cdevsw)) { 144 dz_regs = vax_map_physmem(va->va_paddr, 1); 145 consline = -1; 146 } else 147 consline = minor(cn_tab->cn_dev); 148 sc->sc_ioh = dz_regs; 149 sc->sc_dr.dr_csr = 0; 150 sc->sc_dr.dr_rbuf = 4; 151 sc->sc_dr.dr_dtr = 9; 152 sc->sc_dr.dr_break = 13; 153 sc->sc_dr.dr_tbuf = 12; 154 sc->sc_dr.dr_tcr = 8; 155 sc->sc_dr.dr_dcd = 13; 156 sc->sc_dr.dr_ring = 13; 157 158 sc->sc_dr.dr_firstreg = 0; 159 sc->sc_dr.dr_winsize = 14; 160 161 sc->sc_type = DZ_DZV; 162 163 sc->sc_dsr = 0x0f; /* XXX check if VS has modem ctrl bits */ 164 165 scb_vecalloc(va->va_cvec, dzxint, sc, SCB_ISTACK, &sc->sc_tintrcnt); 166 scb_vecalloc(va->va_cvec - 4, dzrint, sc, SCB_ISTACK, &sc->sc_rintrcnt); 167 168 aprint_normal("\n"); 169 aprint_normal_dev(self, "4 lines"); 170 if (consline != -1) 171 aprint_normal(", console on line %d", consline); 172 173 dzattach(sc, NULL, consline); 174 DELAY(10000); 175 176 if (consline != -1) 177 cn_set_magic("\033D"); /* set VAX DDB escape sequence */ 178 179 s = spltty(); 180 dzrint(sc); 181 dzxint(sc); 182 splx(s); 183 184 #if NDZKBD > 0 || NDZMS > 0 185 config_defer(self, dz_vsbus_attach_deferred); 186 #endif 187 } 188 189 #if NDZKBD > 0 || NDZMS > 0 190 static void 191 dz_vsbus_attach_deferred(device_t self) 192 { 193 struct dzkm_attach_args daa; 194 #if NDZKBD > 0 195 extern const struct cdevsw dz_cdevsw; 196 197 /* Don't touch this port if this is the console */ 198 if (cn_tab->cn_dev != makedev(cdevsw_lookup_major(&dz_cdevsw), 0)) { 199 dz->rbuf = DZ_LPR_RX_ENABLE | (DZ_LPR_B4800 << 8) 200 | DZ_LPR_8_BIT_CHAR | 0 /* line */; 201 daa.daa_line = 0; 202 daa.daa_flags = 203 (cn_tab->cn_pri == CN_INTERNAL ? DZKBD_CONSOLE : 0); 204 config_found(self, &daa, dz_print, CFARGS_NONE); 205 } 206 #endif 207 #if NDZMS > 0 208 dz->rbuf = DZ_LPR_RX_ENABLE | (DZ_LPR_B4800 << 8) | DZ_LPR_8_BIT_CHAR \ 209 | DZ_LPR_PARENB | DZ_LPR_OPAR | 1 /* line */; 210 daa.daa_line = 1; 211 daa.daa_flags = 0; 212 config_found(self, &daa, dz_print, CFARGS_NONE); 213 #endif 214 } 215 #endif 216 217 int 218 dzcngetc(dev_t dev) 219 { 220 int c = 0, s; 221 int mino = minor(dev); 222 u_short rbuf; 223 224 s = spltty(); 225 do { 226 while ((dz->csr & 0x80) == 0) 227 ; /* Wait for char */ 228 rbuf = dz->rbuf; 229 if (((rbuf >> 8) & 3) != mino) 230 continue; 231 c = rbuf & 0x7f; 232 } while (c == 17 || c == 19); /* ignore XON/XOFF */ 233 splx(s); 234 235 if (c == 13) 236 c = 10; 237 238 return (c); 239 } 240 241 void 242 dzcnprobe(struct consdev *cndev) 243 { 244 extern vaddr_t iospace; 245 int diagcons; 246 paddr_t ioaddr = 0x200A0000; 247 extern const struct cdevsw dz_cdevsw; 248 249 switch (vax_boardtype) { 250 case VAX_BTYP_410: 251 case VAX_BTYP_420: 252 case VAX_BTYP_43: 253 diagcons = (vax_confdata & 0x20 ? 3 : 0); 254 break; 255 256 case VAX_BTYP_46: 257 case VAX_BTYP_48: 258 diagcons = (vax_confdata & 0x100 ? 3 : 0); 259 break; 260 261 case VAX_BTYP_49: 262 ioaddr = DZ_CSR_KA49; 263 diagcons = (vax_confdata & 8 ? 3 : 0); 264 break; 265 266 case VAX_BTYP_53: 267 ioaddr = DZ_CSR_KA49; 268 diagcons = 3; 269 break; 270 271 default: 272 cndev->cn_pri = CN_DEAD; 273 return; 274 } 275 if (diagcons) 276 cndev->cn_pri = CN_REMOTE; 277 else 278 cndev->cn_pri = CN_NORMAL; 279 cndev->cn_dev = makedev(cdevsw_lookup_major(&dz_cdevsw), diagcons); 280 dz_regs = iospace; 281 dz = (void *)dz_regs; 282 ioaccess(iospace, ioaddr, 1); 283 dz->csr = 0; /* Disable scanning until initting is done */ 284 dz->tcr = (1 << minor(cndev->cn_dev)); /* Turn on xmitter */ 285 dz->csr = 0x20; /* Turn scanning back on */ 286 } 287 288 void 289 dzcninit(struct consdev *cndev) 290 { 291 dz = (void*)dz_regs; 292 293 dz->csr = 0; /* Disable scanning until initting is done */ 294 dz->tcr = (1 << minor(cndev->cn_dev)); /* Turn on xmitter */ 295 dz->csr = 0x20; /* Turn scanning back on */ 296 } 297 298 299 void 300 dzcnputc(dev_t dev, int ch) 301 { 302 int timeout = 1<<15; /* don't hang the machine! */ 303 int mino = minor(dev); 304 int s; 305 u_short tcr; 306 307 if (mfpr(PR_MAPEN) == 0) 308 return; 309 310 s = spltty(); 311 tcr = dz->tcr; /* remember which lines to scan */ 312 dz->tcr = (1 << mino); 313 314 while ((dz->csr & 0x8000) == 0) /* Wait until ready */ 315 if (--timeout < 0) 316 break; 317 dz->tdr = ch; /* Put the character */ 318 timeout = 1<<15; 319 while ((dz->csr & 0x8000) == 0) /* Wait until ready */ 320 if (--timeout < 0) 321 break; 322 323 dz->tcr = tcr; 324 splx(s); 325 } 326 327 void 328 dzcnpollc(dev_t dev, int pollflag) 329 { 330 static u_char mask; 331 332 if (pollflag) 333 mask = vsbus_setmask(0); 334 else 335 vsbus_setmask(mask); 336 } 337 338 #if NDZKBD > 0 || NDZMS > 0 339 int 340 dzgetc(struct dz_linestate *ls) 341 { 342 int line = 0; 343 int s; 344 u_short rbuf; 345 346 if (ls != NULL) 347 line = ls->dz_line; 348 349 s = spltty(); 350 for (;;) { 351 for(; (dz->csr & DZ_CSR_RX_DONE) == 0;); 352 rbuf = dz->rbuf; 353 if (((rbuf >> 8) & 3) == line) { 354 splx(s); 355 return (rbuf & 0xff); 356 } 357 } 358 } 359 360 void 361 dzputc(struct dz_linestate *ls, int ch) 362 { 363 int line; 364 u_short tcr; 365 int s; 366 extern const struct cdevsw dz_cdevsw; 367 368 /* if the dz has already been attached, the MI 369 driver will do the transmitting: */ 370 if (ls && ls->dz_sc) { 371 s = spltty(); 372 line = ls->dz_line; 373 putc(ch, &ls->dz_tty->t_outq); 374 tcr = dz->tcr; 375 if (!(tcr & (1 << line))) 376 dz->tcr = tcr | (1 << line); 377 dzxint(ls->dz_sc); 378 splx(s); 379 return; 380 } 381 382 /* use dzcnputc to do the transmitting: */ 383 dzcnputc(makedev(cdevsw_lookup_major(&dz_cdevsw), 0), ch); 384 } 385 #endif /* NDZKBD > 0 || NDZMS > 0 */ 386