1 /* $NetBSD: dz_vsbus.c,v 1.40 2008/03/15 00:57:15 matt 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.40 2008/03/15 00:57:15 matt 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 "locators.h" 62 #include "dzkbd.h" 63 #include "dzms.h" 64 #include "opt_cputype.h" 65 66 #if NDZKBD > 0 || NDZMS > 0 67 #include <dev/dec/dzkbdvar.h> 68 69 #if 0 70 static struct dz_linestate dz_conslinestate = { NULL, -1, NULL, NULL, NULL }; 71 #endif 72 #endif 73 74 static int dz_vsbus_match(device_t, cfdata_t, void *); 75 static void dz_vsbus_attach(device_t, device_t, void *); 76 77 static vaddr_t dz_regs; /* Used for console */ 78 79 CFATTACH_DECL_NEW(dz_vsbus, sizeof(struct dz_softc), 80 dz_vsbus_match, dz_vsbus_attach, NULL, NULL); 81 82 #define REG(name) short name; short X##name##X; 83 static volatile struct ss_dz {/* base address of DZ-controller: 0x200A0000 */ 84 REG(csr); /* 00 Csr: control/status register */ 85 REG(rbuf); /* 04 Rbuf/Lpr: receive buffer/line param reg. */ 86 REG(tcr); /* 08 Tcr: transmit console register */ 87 REG(tdr); /* 0C Msr/Tdr: modem status reg/transmit data reg */ 88 REG(lpr0); /* 10 Lpr0: */ 89 REG(lpr1); /* 14 Lpr0: */ 90 REG(lpr2); /* 18 Lpr0: */ 91 REG(lpr3); /* 1C Lpr0: */ 92 } *dz; 93 #undef REG 94 95 cons_decl(dz); 96 97 #if NDZKBD > 0 || NDZMS > 0 98 static int 99 dz_print(void *aux, const char *name) 100 { 101 #if 0 102 #if NDZKBD > 0 || NDZMS > 0 103 struct dz_attach_args *dz_args = aux; 104 if (name == NULL) { 105 aprint_normal (" line %d", dz_args->line); 106 if (dz_args->hwflags & DZ_HWFLAG_CONSOLE) 107 aprint_normal (" (console)"); 108 } 109 return (QUIET); 110 #else 111 if (name) 112 aprint_normal ("lkc at %s", name); 113 return (UNCONF); 114 #endif 115 #endif 116 return (UNCONF); 117 } 118 #endif 119 120 static int 121 dz_vsbus_match(device_t parent, cfdata_t cf, void *aux) 122 { 123 struct vsbus_attach_args * const va = aux; 124 struct ss_dz *dzP; 125 short i; 126 127 #if VAX53 || VAX49 || VAXANY 128 if (vax_boardtype == VAX_BTYP_53 || vax_boardtype == VAX_BTYP_49) 129 if (cf->cf_loc[VSBUSCF_CSR] != 0x25000000) 130 return 0; /* Ugly */ 131 #endif 132 133 dzP = (struct ss_dz *)va->va_addr; 134 i = dzP->tcr; 135 dzP->csr = DZ_CSR_MSE|DZ_CSR_TXIE; 136 dzP->tcr = 0; 137 DELAY(1000); 138 dzP->tcr = 1; 139 DELAY(100000); 140 dzP->tcr = i; 141 142 /* If the device doesn't exist, no interrupt has been generated */ 143 return 1; 144 } 145 146 static void 147 dz_vsbus_attach(device_t parent, device_t self, void *aux) 148 { 149 struct dz_softc * const sc = device_private(self); 150 struct vsbus_attach_args * const va = aux; 151 #if NDZKBD > 0 152 extern const struct cdevsw dz_cdevsw; 153 #endif 154 #if NDZKBD > 0 || NDZMS > 0 155 struct dzkm_attach_args daa; 156 #endif 157 int s, consline; 158 159 sc->sc_dev = self; 160 /* 161 * XXX - This is evil and ugly, but... 162 * due to the nature of how bus_space_* works on VAX, this will 163 * be perfectly good until everything is converted. 164 */ 165 if (dz_regs == 0) /* This isn't console */ { 166 dz_regs = vax_map_physmem(va->va_paddr, 1); 167 consline = -1; 168 } else 169 consline = minor(cn_tab->cn_dev); 170 sc->sc_ioh = dz_regs; 171 sc->sc_dr.dr_csr = 0; 172 sc->sc_dr.dr_rbuf = 4; 173 sc->sc_dr.dr_dtr = 9; 174 sc->sc_dr.dr_break = 13; 175 sc->sc_dr.dr_tbuf = 12; 176 sc->sc_dr.dr_tcr = 8; 177 sc->sc_dr.dr_dcd = 13; 178 sc->sc_dr.dr_ring = 13; 179 180 sc->sc_dr.dr_firstreg = 0; 181 sc->sc_dr.dr_winsize = 14; 182 183 sc->sc_type = DZ_DZV; 184 185 sc->sc_dsr = 0x0f; /* XXX check if VS has modem ctrl bits */ 186 187 scb_vecalloc(va->va_cvec, dzxint, sc, SCB_ISTACK, &sc->sc_tintrcnt); 188 scb_vecalloc(va->va_cvec - 4, dzrint, sc, SCB_ISTACK, &sc->sc_rintrcnt); 189 190 aprint_normal("\n"); 191 aprint_normal_dev(self, "4 lines"); 192 193 dzattach(sc, NULL, consline); 194 DELAY(10000); 195 196 if (consline != -1) 197 cn_set_magic("\033D"); /* set VAX DDB escape sequence */ 198 199 #if NDZKBD > 0 200 /* Don't touch this port if this is the console */ 201 if (cn_tab->cn_dev != makedev(cdevsw_lookup_major(&dz_cdevsw), 0)) { 202 dz->rbuf = DZ_LPR_RX_ENABLE | (DZ_LPR_B4800 << 8) 203 | DZ_LPR_8_BIT_CHAR; 204 daa.daa_line = 0; 205 daa.daa_flags = 206 (cn_tab->cn_pri == CN_INTERNAL ? DZKBD_CONSOLE : 0); 207 config_found(self, &daa, dz_print); 208 } 209 #endif 210 #if NDZMS > 0 211 dz->rbuf = DZ_LPR_RX_ENABLE | (DZ_LPR_B4800 << 8) | DZ_LPR_8_BIT_CHAR \ 212 | DZ_LPR_PARENB | DZ_LPR_OPAR | 1 /* line */; 213 daa.daa_line = 1; 214 daa.daa_flags = 0; 215 config_found(self, &daa, dz_print); 216 #endif 217 s = spltty(); 218 dzrint(sc); 219 dzxint(sc); 220 splx(s); 221 } 222 223 int 224 dzcngetc(dev_t dev) 225 { 226 int c = 0, s; 227 int mino = minor(dev); 228 u_short rbuf; 229 230 s = spltty(); 231 do { 232 while ((dz->csr & 0x80) == 0) 233 ; /* Wait for char */ 234 rbuf = dz->rbuf; 235 if (((rbuf >> 8) & 3) != mino) 236 continue; 237 c = rbuf & 0x7f; 238 } while (c == 17 || c == 19); /* ignore XON/XOFF */ 239 splx(s); 240 241 if (c == 13) 242 c = 10; 243 244 return (c); 245 } 246 247 void 248 dzcnprobe(struct consdev *cndev) 249 { 250 extern vaddr_t iospace; 251 int diagcons; 252 paddr_t ioaddr = 0x200A0000; 253 extern const struct cdevsw dz_cdevsw; 254 255 switch (vax_boardtype) { 256 case VAX_BTYP_410: 257 case VAX_BTYP_420: 258 case VAX_BTYP_43: 259 diagcons = (vax_confdata & 0x20 ? 3 : 0); 260 break; 261 262 case VAX_BTYP_46: 263 case VAX_BTYP_48: 264 diagcons = (vax_confdata & 0x100 ? 3 : 0); 265 break; 266 267 case VAX_BTYP_49: 268 ioaddr = 0x25000000; 269 diagcons = (vax_confdata & 8 ? 3 : 0); 270 break; 271 272 case VAX_BTYP_53: 273 ioaddr = 0x25000000; 274 diagcons = 3; 275 break; 276 277 default: 278 cndev->cn_pri = CN_DEAD; 279 return; 280 } 281 if (diagcons) 282 cndev->cn_pri = CN_REMOTE; 283 else 284 cndev->cn_pri = CN_NORMAL; 285 cndev->cn_dev = makedev(cdevsw_lookup_major(&dz_cdevsw), diagcons); 286 dz_regs = iospace; 287 dz = (void *)dz_regs; 288 ioaccess(iospace, ioaddr, 1); 289 } 290 291 void 292 dzcninit(struct consdev *cndev) 293 { 294 dz = (void*)dz_regs; 295 296 dz->csr = 0; /* Disable scanning until initting is done */ 297 dz->tcr = (1 << minor(cndev->cn_dev)); /* Turn on xmitter */ 298 dz->csr = 0x20; /* Turn scanning back on */ 299 } 300 301 302 void 303 dzcnputc(dev_t dev, int ch) 304 { 305 int timeout = 1<<15; /* don't hang the machine! */ 306 int mino = minor(dev); 307 int s; 308 u_short tcr; 309 310 if (mfpr(PR_MAPEN) == 0) 311 return; 312 313 s = spltty(); 314 tcr = dz->tcr; /* remember which lines to scan */ 315 dz->tcr = (1 << mino); 316 317 while ((dz->csr & 0x8000) == 0) /* Wait until ready */ 318 if (--timeout < 0) 319 break; 320 dz->tdr = ch; /* Put the character */ 321 timeout = 1<<15; 322 while ((dz->csr & 0x8000) == 0) /* Wait until ready */ 323 if (--timeout < 0) 324 break; 325 326 dz->tcr = tcr; 327 splx(s); 328 } 329 330 void 331 dzcnpollc(dev_t dev, int pollflag) 332 { 333 static u_char mask; 334 335 if (pollflag) 336 mask = vsbus_setmask(0); 337 else 338 vsbus_setmask(mask); 339 } 340 341 #if NDZKBD > 0 || NDZMS > 0 342 int 343 dzgetc(struct dz_linestate *ls) 344 { 345 int line = ls->dz_line; 346 int s; 347 u_short rbuf; 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