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