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