1 1.58 riastrad /* $NetBSD: sab.c,v 1.58 2022/10/26 23:59:36 riastradh Exp $ */ 2 1.1 petrov /* $OpenBSD: sab.c,v 1.7 2002/04/08 17:49:42 jason Exp $ */ 3 1.1 petrov 4 1.1 petrov /* 5 1.1 petrov * Copyright (c) 2001 Jason L. Wright (jason (at) thought.net) 6 1.1 petrov * All rights reserved. 7 1.1 petrov * 8 1.1 petrov * Redistribution and use in source and binary forms, with or without 9 1.1 petrov * modification, are permitted provided that the following conditions 10 1.1 petrov * are met: 11 1.1 petrov * 1. Redistributions of source code must retain the above copyright 12 1.1 petrov * notice, this list of conditions and the following disclaimer. 13 1.1 petrov * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 petrov * notice, this list of conditions and the following disclaimer in the 15 1.1 petrov * documentation and/or other materials provided with the distribution. 16 1.1 petrov * 3. All advertising materials mentioning features or use of this software 17 1.1 petrov * must display the following acknowledgement: 18 1.1 petrov * This product includes software developed by Jason L. Wright 19 1.1 petrov * 4. The name of the author may not be used to endorse or promote products 20 1.1 petrov * derived from this software without specific prior written permission. 21 1.1 petrov * 22 1.1 petrov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 1.1 petrov * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 1.1 petrov * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 1.1 petrov * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 1.1 petrov * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 1.1 petrov * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 1.1 petrov * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 1.1 petrov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 1.1 petrov * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 1.1 petrov * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 1.1 petrov * POSSIBILITY OF SUCH DAMAGE. 33 1.1 petrov * 34 1.1 petrov * Effort sponsored in part by the Defense Advanced Research Projects 35 1.1 petrov * Agency (DARPA) and Air Force Research Laboratory, Air Force 36 1.1 petrov * Materiel Command, USAF, under agreement number F30602-01-2-0537. 37 1.1 petrov * 38 1.1 petrov */ 39 1.1 petrov 40 1.1 petrov /* 41 1.1 petrov * SAB82532 Dual UART driver 42 1.1 petrov */ 43 1.14 lukem 44 1.14 lukem #include <sys/cdefs.h> 45 1.58 riastrad __KERNEL_RCSID(0, "$NetBSD: sab.c,v 1.58 2022/10/26 23:59:36 riastradh Exp $"); 46 1.1 petrov 47 1.36 martin #include "opt_kgdb.h" 48 1.1 petrov #include <sys/types.h> 49 1.1 petrov #include <sys/param.h> 50 1.1 petrov #include <sys/systm.h> 51 1.1 petrov #include <sys/device.h> 52 1.1 petrov #include <sys/conf.h> 53 1.1 petrov #include <sys/file.h> 54 1.1 petrov #include <sys/ioctl.h> 55 1.1 petrov #include <sys/kernel.h> 56 1.1 petrov #include <sys/proc.h> 57 1.1 petrov #include <sys/tty.h> 58 1.1 petrov #include <sys/syslog.h> 59 1.28 elad #include <sys/kauth.h> 60 1.36 martin #include <sys/kgdb.h> 61 1.40 ad #include <sys/intr.h> 62 1.1 petrov 63 1.1 petrov #include <machine/autoconf.h> 64 1.1 petrov #include <machine/openfirm.h> 65 1.1 petrov 66 1.1 petrov #include <dev/cons.h> 67 1.1 petrov 68 1.1 petrov #include <dev/ebus/ebusreg.h> 69 1.1 petrov #include <dev/ebus/ebusvar.h> 70 1.1 petrov #include <sparc64/dev/sab82532reg.h> 71 1.1 petrov 72 1.20 drochner #include "locators.h" 73 1.20 drochner 74 1.54 christos #define SABUNIT(x) TTUNIT(x) 75 1.54 christos #define SABDIALOUT(x) TTDIALOUT(x) 76 1.1 petrov 77 1.1 petrov #define SABTTY_RBUF_SIZE 1024 /* must be divisible by 2 */ 78 1.1 petrov 79 1.1 petrov struct sab_softc { 80 1.48 christos device_t sc_dev; 81 1.1 petrov struct intrhand * sc_ih; 82 1.1 petrov bus_space_tag_t sc_bt; 83 1.1 petrov bus_space_handle_t sc_bh; 84 1.1 petrov struct sabtty_softc * sc_child[SAB_NCHAN]; 85 1.1 petrov u_int sc_nchild; 86 1.1 petrov void * sc_softintr; 87 1.1 petrov int sc_node; 88 1.1 petrov }; 89 1.1 petrov 90 1.1 petrov struct sabtty_attach_args { 91 1.1 petrov u_int sbt_portno; 92 1.1 petrov }; 93 1.1 petrov 94 1.1 petrov struct sabtty_softc { 95 1.48 christos device_t sc_dev; 96 1.1 petrov struct sab_softc * sc_parent; 97 1.1 petrov bus_space_tag_t sc_bt; 98 1.1 petrov bus_space_handle_t sc_bh; 99 1.1 petrov struct tty * sc_tty; 100 1.1 petrov u_int sc_portno; 101 1.25 cdi uint8_t sc_pvr_dtr, sc_pvr_dsr; 102 1.25 cdi uint8_t sc_imr0, sc_imr1; 103 1.1 petrov int sc_openflags; 104 1.1 petrov u_char * sc_txp; 105 1.1 petrov int sc_txc; 106 1.1 petrov int sc_flags; 107 1.44 jdc #define SABTTYF_STOP 0x0001 108 1.44 jdc #define SABTTYF_DONE 0x0002 109 1.44 jdc #define SABTTYF_RINGOVERFLOW 0x0004 110 1.44 jdc #define SABTTYF_CDCHG 0x0008 111 1.44 jdc #define SABTTYF_CONS_IN 0x0010 112 1.44 jdc #define SABTTYF_CONS_OUT 0x0020 113 1.44 jdc #define SABTTYF_TXDRAIN 0x0040 114 1.44 jdc #define SABTTYF_DONTDDB 0x0080 115 1.44 jdc #define SABTTYF_IS_RSC 0x0100 116 1.25 cdi uint8_t sc_rbuf[SABTTY_RBUF_SIZE]; 117 1.25 cdi uint8_t *sc_rend, *sc_rput, *sc_rget; 118 1.25 cdi uint8_t sc_polling, sc_pollrfc; 119 1.1 petrov }; 120 1.1 petrov 121 1.1 petrov struct sabtty_softc *sabtty_cons_input; 122 1.1 petrov struct sabtty_softc *sabtty_cons_output; 123 1.1 petrov 124 1.1 petrov #define SAB_READ(sc,r) \ 125 1.1 petrov bus_space_read_1((sc)->sc_bt, (sc)->sc_bh, (r)) 126 1.1 petrov #define SAB_WRITE(sc,r,v) \ 127 1.1 petrov bus_space_write_1((sc)->sc_bt, (sc)->sc_bh, (r), (v)) 128 1.11 petrov #define SAB_WRITE_BLOCK(sc,r,p,c) \ 129 1.11 petrov bus_space_write_region_1((sc)->sc_bt, (sc)->sc_bh, (r), (p), (c)) 130 1.1 petrov 131 1.48 christos int sab_match(device_t, cfdata_t, void *); 132 1.48 christos void sab_attach(device_t, device_t, void *); 133 1.1 petrov int sab_print(void *, const char *); 134 1.1 petrov int sab_intr(void *); 135 1.1 petrov 136 1.1 petrov void sab_softintr(void *); 137 1.1 petrov void sab_cnputc(dev_t, int); 138 1.1 petrov int sab_cngetc(dev_t); 139 1.1 petrov void sab_cnpollc(dev_t, int); 140 1.1 petrov 141 1.48 christos int sabtty_match(device_t, cfdata_t, void *); 142 1.48 christos void sabtty_attach(device_t, device_t, void *); 143 1.1 petrov void sabtty_start(struct tty *); 144 1.1 petrov int sabtty_param(struct tty *, struct termios *); 145 1.1 petrov int sabtty_intr(struct sabtty_softc *, int *); 146 1.1 petrov void sabtty_softintr(struct sabtty_softc *); 147 1.1 petrov int sabtty_mdmctrl(struct sabtty_softc *, int, int); 148 1.1 petrov void sabtty_cec_wait(struct sabtty_softc *); 149 1.1 petrov void sabtty_tec_wait(struct sabtty_softc *); 150 1.1 petrov void sabtty_reset(struct sabtty_softc *); 151 1.1 petrov void sabtty_flush(struct sabtty_softc *); 152 1.1 petrov int sabtty_speed(int); 153 1.1 petrov void sabtty_console_flags(struct sabtty_softc *); 154 1.1 petrov void sabtty_cnpollc(struct sabtty_softc *, int); 155 1.53 nakayama bool sabtty_shutdown(device_t, int); 156 1.1 petrov int sabttyparam(struct sabtty_softc *, struct tty *, struct termios *); 157 1.1 petrov 158 1.36 martin #ifdef KGDB 159 1.36 martin int sab_kgdb_check(struct sabtty_softc *); 160 1.36 martin void sab_kgdb_init(struct sabtty_softc *); 161 1.36 martin #endif 162 1.36 martin 163 1.1 petrov void sabtty_cnputc(struct sabtty_softc *, int); 164 1.1 petrov int sabtty_cngetc(struct sabtty_softc *); 165 1.1 petrov 166 1.48 christos CFATTACH_DECL_NEW(sab, sizeof(struct sab_softc), 167 1.6 thorpej sab_match, sab_attach, NULL, NULL); 168 1.1 petrov 169 1.1 petrov extern struct cfdriver sab_cd; 170 1.1 petrov 171 1.48 christos CFATTACH_DECL_NEW(sabtty, sizeof(struct sabtty_softc), 172 1.6 thorpej sabtty_match, sabtty_attach, NULL, NULL); 173 1.1 petrov 174 1.1 petrov extern struct cfdriver sabtty_cd; 175 1.2 gehenna 176 1.2 gehenna dev_type_open(sabopen); 177 1.2 gehenna dev_type_close(sabclose); 178 1.2 gehenna dev_type_read(sabread); 179 1.2 gehenna dev_type_write(sabwrite); 180 1.2 gehenna dev_type_ioctl(sabioctl); 181 1.2 gehenna dev_type_stop(sabstop); 182 1.2 gehenna dev_type_tty(sabtty); 183 1.2 gehenna dev_type_poll(sabpoll); 184 1.2 gehenna 185 1.17 seb static struct cnm_state sabtty_cnm_state; 186 1.17 seb 187 1.2 gehenna const struct cdevsw sabtty_cdevsw = { 188 1.51 dholland .d_open = sabopen, 189 1.51 dholland .d_close = sabclose, 190 1.51 dholland .d_read = sabread, 191 1.51 dholland .d_write = sabwrite, 192 1.51 dholland .d_ioctl = sabioctl, 193 1.51 dholland .d_stop = sabstop, 194 1.51 dholland .d_tty = sabtty, 195 1.51 dholland .d_poll = sabpoll, 196 1.51 dholland .d_mmap = nommap, 197 1.51 dholland .d_kqfilter = ttykqfilter, 198 1.52 dholland .d_discard = nodiscard, 199 1.51 dholland .d_flag = D_TTY 200 1.2 gehenna }; 201 1.1 petrov 202 1.1 petrov struct sabtty_rate { 203 1.1 petrov int baud; 204 1.1 petrov int n, m; 205 1.1 petrov }; 206 1.1 petrov 207 1.1 petrov struct sabtty_rate sabtty_baudtable[] = { 208 1.1 petrov { 50, 35, 10 }, 209 1.1 petrov { 75, 47, 9 }, 210 1.1 petrov { 110, 32, 9 }, 211 1.1 petrov { 134, 53, 8 }, 212 1.1 petrov { 150, 47, 8 }, 213 1.1 petrov { 200, 35, 8 }, 214 1.1 petrov { 300, 47, 7 }, 215 1.1 petrov { 600, 47, 6 }, 216 1.1 petrov { 1200, 47, 5 }, 217 1.1 petrov { 1800, 31, 5 }, 218 1.1 petrov { 2400, 47, 4 }, 219 1.1 petrov { 4800, 47, 3 }, 220 1.1 petrov { 9600, 47, 2 }, 221 1.1 petrov { 19200, 47, 1 }, 222 1.1 petrov { 38400, 23, 1 }, 223 1.1 petrov { 57600, 15, 1 }, 224 1.1 petrov { 115200, 7, 1 }, 225 1.1 petrov { 230400, 3, 1 }, 226 1.1 petrov { 460800, 1, 1 }, 227 1.1 petrov { 76800, 11, 1 }, 228 1.1 petrov { 153600, 5, 1 }, 229 1.1 petrov { 307200, 3, 1 }, 230 1.1 petrov { 614400, 3, 0 }, 231 1.1 petrov { 921600, 0, 1 }, 232 1.1 petrov }; 233 1.1 petrov 234 1.1 petrov int 235 1.48 christos sab_match(device_t parent, cfdata_t match, void *aux) 236 1.1 petrov { 237 1.1 petrov struct ebus_attach_args *ea = aux; 238 1.1 petrov char *compat; 239 1.1 petrov 240 1.47 mrg if (strcmp(ea->ea_name, "se") == 0 || 241 1.47 mrg strcmp(ea->ea_name, "FJSV,se") == 0) 242 1.1 petrov return (1); 243 1.1 petrov 244 1.15 pk compat = prom_getpropstring(ea->ea_node, "compatible"); 245 1.1 petrov if (compat != NULL && !strcmp(compat, "sab82532")) 246 1.1 petrov return (1); 247 1.1 petrov 248 1.1 petrov return (0); 249 1.1 petrov } 250 1.1 petrov 251 1.1 petrov void 252 1.48 christos sab_attach(device_t parent, device_t self, void *aux) 253 1.1 petrov { 254 1.48 christos struct sab_softc *sc = device_private(self); 255 1.1 petrov struct ebus_attach_args *ea = aux; 256 1.25 cdi uint8_t r; 257 1.1 petrov u_int i; 258 1.22 drochner int locs[SABCF_NLOCS]; 259 1.1 petrov 260 1.48 christos sc->sc_dev = self; 261 1.1 petrov sc->sc_bt = ea->ea_bustag; 262 1.1 petrov sc->sc_node = ea->ea_node; 263 1.1 petrov 264 1.1 petrov /* Use prom mapping, if available. */ 265 1.1 petrov if (ea->ea_nvaddr) 266 1.36 martin sparc_promaddr_to_handle(sc->sc_bt, ea->ea_vaddr[0], 267 1.36 martin &sc->sc_bh); 268 1.1 petrov else if (bus_space_map(sc->sc_bt, EBUS_ADDR_FROM_REG(&ea->ea_reg[0]), 269 1.1 petrov ea->ea_reg[0].size, 0, &sc->sc_bh) != 0) { 270 1.1 petrov printf(": can't map register space\n"); 271 1.1 petrov return; 272 1.1 petrov } 273 1.1 petrov 274 1.1 petrov sc->sc_ih = bus_intr_establish(ea->ea_bustag, ea->ea_intr[0], 275 1.8 pk IPL_TTY, sab_intr, sc); 276 1.1 petrov if (sc->sc_ih == NULL) { 277 1.1 petrov printf(": can't map interrupt\n"); 278 1.1 petrov return; 279 1.1 petrov } 280 1.1 petrov 281 1.40 ad sc->sc_softintr = softint_establish(SOFTINT_SERIAL, sab_softintr, sc); 282 1.1 petrov if (sc->sc_softintr == NULL) { 283 1.1 petrov printf(": can't get soft intr\n"); 284 1.1 petrov return; 285 1.1 petrov } 286 1.1 petrov 287 1.18 heas aprint_normal(": rev "); 288 1.1 petrov r = SAB_READ(sc, SAB_VSTR) & SAB_VSTR_VMASK; 289 1.1 petrov switch (r) { 290 1.1 petrov case SAB_VSTR_V_1: 291 1.18 heas aprint_normal("1"); 292 1.1 petrov break; 293 1.1 petrov case SAB_VSTR_V_2: 294 1.18 heas aprint_normal("2"); 295 1.1 petrov break; 296 1.1 petrov case SAB_VSTR_V_32: 297 1.18 heas aprint_normal("3.2"); 298 1.1 petrov break; 299 1.1 petrov default: 300 1.18 heas aprint_normal("unknown(0x%x)", r); 301 1.1 petrov break; 302 1.1 petrov } 303 1.18 heas aprint_normal("\n"); 304 1.45 mrg aprint_naive(": Serial controller\n"); 305 1.1 petrov 306 1.11 petrov /* Let current output drain */ 307 1.11 petrov DELAY(100000); 308 1.11 petrov 309 1.1 petrov /* Set all pins, except DTR pins to be inputs */ 310 1.1 petrov SAB_WRITE(sc, SAB_PCR, ~(SAB_PVR_DTR_A | SAB_PVR_DTR_B)); 311 1.1 petrov /* Disable port interrupts */ 312 1.1 petrov SAB_WRITE(sc, SAB_PIM, 0xff); 313 1.1 petrov SAB_WRITE(sc, SAB_PVR, SAB_PVR_DTR_A | SAB_PVR_DTR_B | SAB_PVR_MAGIC); 314 1.1 petrov SAB_WRITE(sc, SAB_IPC, SAB_IPC_ICPL); 315 1.1 petrov 316 1.1 petrov for (i = 0; i < SAB_NCHAN; i++) { 317 1.21 christos struct sabtty_attach_args stax; 318 1.1 petrov 319 1.21 christos stax.sbt_portno = i; 320 1.20 drochner 321 1.22 drochner locs[SABCF_CHANNEL] = i; 322 1.20 drochner 323 1.56 thorpej sc->sc_child[i] = device_private( 324 1.56 thorpej config_found(self, &stax, sab_print, 325 1.57 thorpej CFARGS(.submatch = config_stdsubmatch, 326 1.57 thorpej .locators = locs))); 327 1.1 petrov if (sc->sc_child[i] != NULL) 328 1.1 petrov sc->sc_nchild++; 329 1.1 petrov } 330 1.1 petrov } 331 1.1 petrov 332 1.1 petrov int 333 1.25 cdi sab_print(void *args, const char *name) 334 1.1 petrov { 335 1.1 petrov struct sabtty_attach_args *sa = args; 336 1.1 petrov 337 1.1 petrov if (name) 338 1.9 thorpej aprint_normal("sabtty at %s", name); 339 1.18 heas aprint_normal(" port %u", sa->sbt_portno); 340 1.1 petrov return (UNCONF); 341 1.1 petrov } 342 1.1 petrov 343 1.1 petrov int 344 1.25 cdi sab_intr(void *vsc) 345 1.1 petrov { 346 1.1 petrov struct sab_softc *sc = vsc; 347 1.1 petrov int r = 0, needsoft = 0; 348 1.25 cdi uint8_t gis; 349 1.1 petrov 350 1.1 petrov gis = SAB_READ(sc, SAB_GIS); 351 1.1 petrov 352 1.1 petrov /* channel A */ 353 1.1 petrov if ((gis & (SAB_GIS_ISA1 | SAB_GIS_ISA0)) && sc->sc_child[0] && 354 1.1 petrov sc->sc_child[0]->sc_tty) 355 1.1 petrov r |= sabtty_intr(sc->sc_child[0], &needsoft); 356 1.1 petrov 357 1.1 petrov /* channel B */ 358 1.1 petrov if ((gis & (SAB_GIS_ISB1 | SAB_GIS_ISB0)) && sc->sc_child[1] && 359 1.1 petrov sc->sc_child[1]->sc_tty) 360 1.1 petrov r |= sabtty_intr(sc->sc_child[1], &needsoft); 361 1.1 petrov 362 1.1 petrov if (needsoft) 363 1.40 ad softint_schedule(sc->sc_softintr); 364 1.1 petrov 365 1.1 petrov return (r); 366 1.1 petrov } 367 1.1 petrov 368 1.1 petrov void 369 1.25 cdi sab_softintr(void *vsc) 370 1.1 petrov { 371 1.1 petrov struct sab_softc *sc = vsc; 372 1.1 petrov 373 1.1 petrov if (sc->sc_child[0] && sc->sc_child[0]->sc_tty) 374 1.1 petrov sabtty_softintr(sc->sc_child[0]); 375 1.1 petrov if (sc->sc_child[1] && sc->sc_child[1]->sc_tty) 376 1.1 petrov sabtty_softintr(sc->sc_child[1]); 377 1.1 petrov } 378 1.1 petrov 379 1.1 petrov int 380 1.48 christos sabtty_match(device_t parent, cfdata_t match, void *aux) 381 1.1 petrov { 382 1.1 petrov 383 1.20 drochner return (1); 384 1.1 petrov } 385 1.1 petrov 386 1.1 petrov void 387 1.48 christos sabtty_attach(device_t parent, device_t self, void *aux) 388 1.1 petrov { 389 1.48 christos struct sabtty_softc *sc = device_private(self); 390 1.1 petrov struct sabtty_attach_args *sa = aux; 391 1.1 petrov int r; 392 1.10 petrov int maj; 393 1.36 martin int is_kgdb = 0; 394 1.1 petrov 395 1.48 christos sc->sc_dev = self; 396 1.36 martin #ifdef KGDB 397 1.36 martin is_kgdb = sab_kgdb_check(sc); 398 1.36 martin #endif 399 1.36 martin 400 1.36 martin if (!is_kgdb) { 401 1.46 rmind sc->sc_tty = tty_alloc(); 402 1.36 martin if (sc->sc_tty == NULL) { 403 1.36 martin aprint_normal(": failed to allocate tty\n"); 404 1.36 martin return; 405 1.36 martin } 406 1.36 martin tty_attach(sc->sc_tty); 407 1.36 martin sc->sc_tty->t_oproc = sabtty_start; 408 1.36 martin sc->sc_tty->t_param = sabtty_param; 409 1.1 petrov } 410 1.1 petrov 411 1.48 christos sc->sc_parent = device_private(parent); 412 1.1 petrov sc->sc_bt = sc->sc_parent->sc_bt; 413 1.1 petrov sc->sc_portno = sa->sbt_portno; 414 1.1 petrov sc->sc_rend = sc->sc_rbuf + SABTTY_RBUF_SIZE; 415 1.1 petrov 416 1.1 petrov switch (sa->sbt_portno) { 417 1.1 petrov case 0: /* port A */ 418 1.1 petrov sc->sc_pvr_dtr = SAB_PVR_DTR_A; 419 1.1 petrov sc->sc_pvr_dsr = SAB_PVR_DSR_A; 420 1.1 petrov r = bus_space_subregion(sc->sc_bt, sc->sc_parent->sc_bh, 421 1.1 petrov SAB_CHAN_A, SAB_CHANLEN, &sc->sc_bh); 422 1.1 petrov break; 423 1.1 petrov case 1: /* port B */ 424 1.1 petrov sc->sc_pvr_dtr = SAB_PVR_DTR_B; 425 1.1 petrov sc->sc_pvr_dsr = SAB_PVR_DSR_B; 426 1.1 petrov r = bus_space_subregion(sc->sc_bt, sc->sc_parent->sc_bh, 427 1.1 petrov SAB_CHAN_B, SAB_CHANLEN, &sc->sc_bh); 428 1.1 petrov break; 429 1.1 petrov default: 430 1.18 heas aprint_normal(": invalid channel: %u\n", sa->sbt_portno); 431 1.1 petrov return; 432 1.1 petrov } 433 1.1 petrov if (r != 0) { 434 1.18 heas aprint_normal(": failed to allocate register subregion\n"); 435 1.1 petrov return; 436 1.1 petrov } 437 1.1 petrov 438 1.1 petrov sabtty_console_flags(sc); 439 1.1 petrov 440 1.1 petrov if (sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) { 441 1.1 petrov struct termios t; 442 1.21 christos const char *acc; 443 1.1 petrov 444 1.19 heas /* Let residual prom output drain */ 445 1.19 heas DELAY(100000); 446 1.19 heas 447 1.1 petrov switch (sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) { 448 1.1 petrov case SABTTYF_CONS_IN: 449 1.1 petrov acc = "input"; 450 1.1 petrov break; 451 1.1 petrov case SABTTYF_CONS_OUT: 452 1.1 petrov acc = "output"; 453 1.1 petrov break; 454 1.1 petrov case SABTTYF_CONS_IN|SABTTYF_CONS_OUT: 455 1.1 petrov default: 456 1.1 petrov acc = "i/o"; 457 1.1 petrov break; 458 1.1 petrov } 459 1.1 petrov 460 1.1 petrov t.c_ispeed= 0; 461 1.44 jdc if (sc->sc_flags & SABTTYF_IS_RSC) 462 1.43 jdc t.c_ospeed = 115200; 463 1.43 jdc else 464 1.43 jdc t.c_ospeed = 9600; 465 1.1 petrov t.c_cflag = CREAD | CS8 | HUPCL; 466 1.1 petrov sc->sc_tty->t_ospeed = 0; 467 1.1 petrov sabttyparam(sc, sc->sc_tty, &t); 468 1.1 petrov 469 1.1 petrov if (sc->sc_flags & SABTTYF_CONS_IN) { 470 1.1 petrov sabtty_cons_input = sc; 471 1.1 petrov cn_tab->cn_pollc = sab_cnpollc; 472 1.1 petrov cn_tab->cn_getc = sab_cngetc; 473 1.10 petrov maj = cdevsw_lookup_major(&sabtty_cdevsw); 474 1.26 thorpej cn_tab->cn_dev = makedev(maj, device_unit(self)); 475 1.53 nakayama pmf_device_register1(self, NULL, NULL, sabtty_shutdown); 476 1.17 seb cn_init_magic(&sabtty_cnm_state); 477 1.17 seb cn_set_magic("\047\001"); /* default magic is BREAK */ 478 1.1 petrov } 479 1.1 petrov 480 1.1 petrov if (sc->sc_flags & SABTTYF_CONS_OUT) { 481 1.18 heas sabtty_tec_wait(sc); 482 1.1 petrov sabtty_cons_output = sc; 483 1.1 petrov cn_tab->cn_putc = sab_cnputc; 484 1.10 petrov maj = cdevsw_lookup_major(&sabtty_cdevsw); 485 1.26 thorpej cn_tab->cn_dev = makedev(maj, device_unit(self)); 486 1.1 petrov } 487 1.18 heas aprint_normal(": console %s", acc); 488 1.1 petrov } else { 489 1.1 petrov /* Not a console... */ 490 1.1 petrov sabtty_reset(sc); 491 1.36 martin 492 1.36 martin #ifdef KGDB 493 1.36 martin if (is_kgdb) { 494 1.36 martin sab_kgdb_init(sc); 495 1.36 martin aprint_normal(": kgdb"); 496 1.36 martin } 497 1.36 martin #endif 498 1.1 petrov } 499 1.1 petrov 500 1.18 heas aprint_normal("\n"); 501 1.45 mrg aprint_naive(": Serial port\n"); 502 1.1 petrov } 503 1.1 petrov 504 1.1 petrov int 505 1.25 cdi sabtty_intr(struct sabtty_softc *sc, int *needsoftp) 506 1.1 petrov { 507 1.25 cdi uint8_t isr0, isr1; 508 1.1 petrov int i, len = 0, needsoft = 0, r = 0, clearfifo = 0; 509 1.1 petrov 510 1.1 petrov isr0 = SAB_READ(sc, SAB_ISR0); 511 1.1 petrov isr1 = SAB_READ(sc, SAB_ISR1); 512 1.1 petrov 513 1.1 petrov if (isr0 || isr1) 514 1.1 petrov r = 1; 515 1.1 petrov 516 1.1 petrov if (isr0 & SAB_ISR0_RPF) { 517 1.1 petrov len = 32; 518 1.1 petrov clearfifo = 1; 519 1.1 petrov } 520 1.1 petrov if (isr0 & SAB_ISR0_TCD) { 521 1.1 petrov len = (32 - 1) & SAB_READ(sc, SAB_RBCL); 522 1.1 petrov clearfifo = 1; 523 1.1 petrov } 524 1.1 petrov if (isr0 & SAB_ISR0_TIME) { 525 1.1 petrov sabtty_cec_wait(sc); 526 1.1 petrov SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RFRD); 527 1.1 petrov } 528 1.1 petrov if (isr0 & SAB_ISR0_RFO) { 529 1.1 petrov sc->sc_flags |= SABTTYF_RINGOVERFLOW; 530 1.1 petrov clearfifo = 1; 531 1.1 petrov } 532 1.1 petrov if (len != 0) { 533 1.25 cdi uint8_t *ptr, b; 534 1.1 petrov 535 1.1 petrov ptr = sc->sc_rput; 536 1.1 petrov for (i = 0; i < len; i++) { 537 1.17 seb b = SAB_READ(sc, SAB_RFIFO); 538 1.17 seb if (i % 2 == 0) /* skip status byte */ 539 1.17 seb cn_check_magic(sc->sc_tty->t_dev, 540 1.17 seb b, sabtty_cnm_state); 541 1.17 seb *ptr++ = b; 542 1.1 petrov if (ptr == sc->sc_rend) 543 1.1 petrov ptr = sc->sc_rbuf; 544 1.1 petrov if (ptr == sc->sc_rget) { 545 1.1 petrov if (ptr == sc->sc_rbuf) 546 1.1 petrov ptr = sc->sc_rend; 547 1.1 petrov ptr--; 548 1.1 petrov sc->sc_flags |= SABTTYF_RINGOVERFLOW; 549 1.1 petrov } 550 1.1 petrov } 551 1.1 petrov sc->sc_rput = ptr; 552 1.1 petrov needsoft = 1; 553 1.1 petrov } 554 1.1 petrov 555 1.1 petrov if (clearfifo) { 556 1.1 petrov sabtty_cec_wait(sc); 557 1.1 petrov SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RMC); 558 1.1 petrov } 559 1.1 petrov 560 1.1 petrov if (isr0 & SAB_ISR0_CDSC) { 561 1.1 petrov sc->sc_flags |= SABTTYF_CDCHG; 562 1.1 petrov needsoft = 1; 563 1.1 petrov } 564 1.1 petrov 565 1.1 petrov if (isr1 & SAB_ISR1_BRKT) 566 1.17 seb cn_check_magic(sc->sc_tty->t_dev, 567 1.17 seb CNC_BREAK, sabtty_cnm_state); 568 1.1 petrov 569 1.11 petrov if (isr1 & (SAB_ISR1_XPR | SAB_ISR1_ALLS)) { 570 1.11 petrov if ((SAB_READ(sc, SAB_STAR) & SAB_STAR_XFW) && 571 1.11 petrov (sc->sc_flags & SABTTYF_STOP) == 0) { 572 1.1 petrov if (sc->sc_txc < 32) 573 1.1 petrov len = sc->sc_txc; 574 1.1 petrov else 575 1.1 petrov len = 32; 576 1.11 petrov 577 1.11 petrov if (len > 0) { 578 1.11 petrov SAB_WRITE_BLOCK(sc, SAB_XFIFO, sc->sc_txp, len); 579 1.19 heas sc->sc_txp += len; 580 1.11 petrov sc->sc_txc -= len; 581 1.11 petrov 582 1.1 petrov sabtty_cec_wait(sc); 583 1.1 petrov SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_XF); 584 1.11 petrov 585 1.11 petrov /* 586 1.11 petrov * Prevent the false end of xmit from 587 1.11 petrov * confusing things below. 588 1.11 petrov */ 589 1.11 petrov isr1 &= ~SAB_ISR1_ALLS; 590 1.1 petrov } 591 1.1 petrov } 592 1.1 petrov 593 1.1 petrov if ((sc->sc_txc == 0) || (sc->sc_flags & SABTTYF_STOP)) { 594 1.11 petrov if ((sc->sc_imr1 & SAB_IMR1_XPR) == 0) { 595 1.11 petrov sc->sc_imr1 |= SAB_IMR1_XPR; 596 1.11 petrov sc->sc_imr1 &= ~SAB_IMR1_ALLS; 597 1.11 petrov SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 598 1.11 petrov } 599 1.1 petrov } 600 1.1 petrov } 601 1.1 petrov 602 1.11 petrov if ((isr1 & SAB_ISR1_ALLS) && ((sc->sc_txc == 0) || 603 1.11 petrov (sc->sc_flags & SABTTYF_STOP))) { 604 1.11 petrov if (sc->sc_flags & SABTTYF_TXDRAIN) 605 1.11 petrov wakeup(sc); 606 1.11 petrov sc->sc_flags &= ~SABTTYF_STOP; 607 1.11 petrov sc->sc_flags |= SABTTYF_DONE; 608 1.11 petrov sc->sc_imr1 |= SAB_IMR1_ALLS; 609 1.11 petrov SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 610 1.11 petrov needsoft = 1; 611 1.11 petrov } 612 1.11 petrov 613 1.1 petrov if (needsoft) 614 1.1 petrov *needsoftp = needsoft; 615 1.1 petrov return (r); 616 1.1 petrov } 617 1.1 petrov 618 1.1 petrov void 619 1.25 cdi sabtty_softintr(struct sabtty_softc *sc) 620 1.1 petrov { 621 1.1 petrov struct tty *tp = sc->sc_tty; 622 1.1 petrov int s, flags; 623 1.25 cdi uint8_t r; 624 1.1 petrov 625 1.1 petrov if (tp == NULL) 626 1.1 petrov return; 627 1.1 petrov 628 1.1 petrov if ((tp->t_state & TS_ISOPEN) == 0) 629 1.1 petrov return; 630 1.1 petrov 631 1.1 petrov while (sc->sc_rget != sc->sc_rput) { 632 1.1 petrov int data; 633 1.25 cdi uint8_t stat; 634 1.1 petrov 635 1.1 petrov data = sc->sc_rget[0]; 636 1.1 petrov stat = sc->sc_rget[1]; 637 1.1 petrov sc->sc_rget += 2; 638 1.1 petrov if (stat & SAB_RSTAT_PE) 639 1.1 petrov data |= TTY_PE; 640 1.1 petrov if (stat & SAB_RSTAT_FE) 641 1.1 petrov data |= TTY_FE; 642 1.1 petrov if (sc->sc_rget == sc->sc_rend) 643 1.1 petrov sc->sc_rget = sc->sc_rbuf; 644 1.1 petrov 645 1.1 petrov (*tp->t_linesw->l_rint)(data, tp); 646 1.1 petrov } 647 1.1 petrov 648 1.1 petrov s = splhigh(); 649 1.1 petrov flags = sc->sc_flags; 650 1.1 petrov sc->sc_flags &= ~(SABTTYF_DONE|SABTTYF_CDCHG|SABTTYF_RINGOVERFLOW); 651 1.1 petrov splx(s); 652 1.1 petrov 653 1.1 petrov if (flags & SABTTYF_CDCHG) { 654 1.1 petrov s = spltty(); 655 1.1 petrov r = SAB_READ(sc, SAB_VSTR) & SAB_VSTR_CD; 656 1.1 petrov splx(s); 657 1.1 petrov 658 1.1 petrov (*tp->t_linesw->l_modem)(tp, r); 659 1.1 petrov } 660 1.1 petrov 661 1.1 petrov if (flags & SABTTYF_RINGOVERFLOW) 662 1.32 martin log(LOG_WARNING, "%s: ring overflow\n", 663 1.48 christos device_xname(sc->sc_dev)); 664 1.1 petrov 665 1.1 petrov if (flags & SABTTYF_DONE) { 666 1.1 petrov ndflush(&tp->t_outq, sc->sc_txp - tp->t_outq.c_cf); 667 1.1 petrov tp->t_state &= ~TS_BUSY; 668 1.1 petrov (*tp->t_linesw->l_start)(tp); 669 1.1 petrov } 670 1.1 petrov } 671 1.1 petrov 672 1.1 petrov int 673 1.25 cdi sabopen(dev_t dev, int flags, int mode, struct lwp *l) 674 1.1 petrov { 675 1.1 petrov struct sabtty_softc *sc; 676 1.1 petrov struct tty *tp; 677 1.1 petrov int s, s1; 678 1.1 petrov 679 1.42 cegger sc = device_lookup_private(&sabtty_cd, SABUNIT(dev)); 680 1.1 petrov if (sc == NULL) 681 1.1 petrov return (ENXIO); 682 1.1 petrov 683 1.1 petrov tp = sc->sc_tty; 684 1.1 petrov tp->t_dev = dev; 685 1.1 petrov 686 1.55 martin /* 687 1.55 martin * If the device is exclusively for kernel use, deny userland 688 1.55 martin * open. 689 1.55 martin */ 690 1.55 martin if (ISSET(tp->t_state, TS_KERN_ONLY)) 691 1.55 martin return (EBUSY); 692 1.55 martin 693 1.34 elad if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 694 1.34 elad return (EBUSY); 695 1.34 elad 696 1.58 riastrad ttylock(tp); 697 1.49 mlelstv if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 698 1.1 petrov ttychars(tp); 699 1.1 petrov tp->t_iflag = TTYDEF_IFLAG; 700 1.1 petrov tp->t_oflag = TTYDEF_OFLAG; 701 1.1 petrov tp->t_cflag = TTYDEF_CFLAG; 702 1.1 petrov if (sc->sc_openflags & TIOCFLAG_CLOCAL) 703 1.1 petrov tp->t_cflag |= CLOCAL; 704 1.1 petrov if (sc->sc_openflags & TIOCFLAG_CRTSCTS) 705 1.1 petrov tp->t_cflag |= CRTSCTS; 706 1.1 petrov if (sc->sc_openflags & TIOCFLAG_MDMBUF) 707 1.1 petrov tp->t_cflag |= MDMBUF; 708 1.1 petrov tp->t_lflag = TTYDEF_LFLAG; 709 1.1 petrov tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 710 1.1 petrov 711 1.1 petrov sc->sc_rput = sc->sc_rget = sc->sc_rbuf; 712 1.1 petrov 713 1.1 petrov ttsetwater(tp); 714 1.1 petrov 715 1.1 petrov s1 = splhigh(); 716 1.1 petrov sabtty_reset(sc); 717 1.1 petrov sabtty_param(tp, &tp->t_termios); 718 1.1 petrov sc->sc_imr0 = SAB_IMR0_PERR | SAB_IMR0_FERR | SAB_IMR0_PLLA; 719 1.1 petrov SAB_WRITE(sc, SAB_IMR0, sc->sc_imr0); 720 1.1 petrov sc->sc_imr1 = SAB_IMR1_BRK | SAB_IMR1_ALLS | SAB_IMR1_XDU | 721 1.1 petrov SAB_IMR1_TIN | SAB_IMR1_CSC | SAB_IMR1_XMR | SAB_IMR1_XPR; 722 1.1 petrov SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 723 1.1 petrov SAB_WRITE(sc, SAB_CCR0, SAB_READ(sc, SAB_CCR0) | SAB_CCR0_PU); 724 1.1 petrov sabtty_cec_wait(sc); 725 1.1 petrov SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_XRES); 726 1.1 petrov sabtty_cec_wait(sc); 727 1.1 petrov SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES); 728 1.1 petrov sabtty_cec_wait(sc); 729 1.1 petrov splx(s1); 730 1.1 petrov 731 1.1 petrov sabtty_flush(sc); 732 1.1 petrov 733 1.1 petrov if ((sc->sc_openflags & TIOCFLAG_SOFTCAR) || 734 1.1 petrov (SAB_READ(sc, SAB_VSTR) & SAB_VSTR_CD)) 735 1.1 petrov tp->t_state |= TS_CARR_ON; 736 1.1 petrov else 737 1.1 petrov tp->t_state &= ~TS_CARR_ON; 738 1.1 petrov } 739 1.1 petrov 740 1.1 petrov if ((flags & O_NONBLOCK) == 0) { 741 1.1 petrov while ((tp->t_cflag & CLOCAL) == 0 && 742 1.1 petrov (tp->t_state & TS_CARR_ON) == 0) { 743 1.1 petrov int error; 744 1.1 petrov 745 1.41 ad error = ttysleep(tp, &tp->t_rawcv, true, 0); 746 1.1 petrov if (error != 0) { 747 1.58 riastrad ttyunlock(tp); 748 1.1 petrov return (error); 749 1.1 petrov } 750 1.1 petrov } 751 1.1 petrov } 752 1.1 petrov 753 1.58 riastrad ttyunlock(tp); 754 1.1 petrov 755 1.1 petrov s = (*tp->t_linesw->l_open)(dev, tp); 756 1.1 petrov if (s != 0) { 757 1.58 riastrad ttylock(tp); 758 1.38 ad if (tp->t_state & TS_ISOPEN) { 759 1.58 riastrad ttyunlock(tp); 760 1.1 petrov return (s); 761 1.38 ad } 762 1.1 petrov if (tp->t_cflag & HUPCL) { 763 1.1 petrov sabtty_mdmctrl(sc, 0, DMSET); 764 1.58 riastrad ttysleep(tp, NULL, /*catch_p*/false, hz); 765 1.1 petrov } 766 1.1 petrov 767 1.1 petrov if ((sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) == 0) { 768 1.1 petrov /* Flush and power down if we're not the console */ 769 1.1 petrov sabtty_flush(sc); 770 1.1 petrov sabtty_reset(sc); 771 1.1 petrov } 772 1.58 riastrad ttyunlock(tp); 773 1.1 petrov } 774 1.1 petrov return (s); 775 1.1 petrov } 776 1.1 petrov 777 1.1 petrov int 778 1.25 cdi sabclose(dev_t dev, int flags, int mode, struct lwp *l) 779 1.1 petrov { 780 1.42 cegger struct sabtty_softc *sc = device_lookup_private(&sabtty_cd, SABUNIT(dev)); 781 1.1 petrov struct sab_softc *bc = sc->sc_parent; 782 1.1 petrov struct tty *tp = sc->sc_tty; 783 1.1 petrov int s; 784 1.1 petrov 785 1.1 petrov (*tp->t_linesw->l_close)(tp, flags); 786 1.1 petrov 787 1.1 petrov s = spltty(); 788 1.1 petrov 789 1.1 petrov if ((tp->t_state & TS_ISOPEN) == 0) { 790 1.1 petrov /* Wait for output drain */ 791 1.1 petrov sc->sc_imr1 &= ~SAB_IMR1_ALLS; 792 1.1 petrov SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 793 1.1 petrov sc->sc_flags |= SABTTYF_TXDRAIN; 794 1.1 petrov (void)tsleep(sc, TTIPRI, ttclos, 5 * hz); 795 1.1 petrov sc->sc_imr1 |= SAB_IMR1_ALLS; 796 1.1 petrov SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 797 1.1 petrov sc->sc_flags &= ~SABTTYF_TXDRAIN; 798 1.1 petrov 799 1.1 petrov if (tp->t_cflag & HUPCL) { 800 1.1 petrov sabtty_mdmctrl(sc, 0, DMSET); 801 1.1 petrov (void)tsleep(bc, TTIPRI, ttclos, hz); 802 1.1 petrov } 803 1.1 petrov 804 1.1 petrov if ((sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) == 0) { 805 1.1 petrov /* Flush and power down if we're not the console */ 806 1.1 petrov sabtty_flush(sc); 807 1.1 petrov sabtty_reset(sc); 808 1.1 petrov } 809 1.1 petrov } 810 1.1 petrov 811 1.1 petrov ttyclose(tp); 812 1.1 petrov splx(s); 813 1.1 petrov 814 1.1 petrov return (0); 815 1.1 petrov } 816 1.1 petrov 817 1.1 petrov int 818 1.25 cdi sabread(dev_t dev, struct uio *uio, int flags) 819 1.1 petrov { 820 1.42 cegger struct sabtty_softc *sc = device_lookup_private(&sabtty_cd, SABUNIT(dev)); 821 1.1 petrov struct tty *tp = sc->sc_tty; 822 1.1 petrov 823 1.1 petrov return ((*tp->t_linesw->l_read)(tp, uio, flags)); 824 1.1 petrov } 825 1.1 petrov 826 1.1 petrov int 827 1.25 cdi sabwrite(dev_t dev, struct uio *uio, int flags) 828 1.1 petrov { 829 1.42 cegger struct sabtty_softc *sc = device_lookup_private(&sabtty_cd, SABUNIT(dev)); 830 1.1 petrov struct tty *tp = sc->sc_tty; 831 1.1 petrov 832 1.1 petrov return ((*tp->t_linesw->l_write)(tp, uio, flags)); 833 1.1 petrov } 834 1.1 petrov 835 1.1 petrov int 836 1.37 christos sabioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 837 1.1 petrov { 838 1.42 cegger struct sabtty_softc *sc = device_lookup_private(&sabtty_cd, SABUNIT(dev)); 839 1.1 petrov struct tty *tp = sc->sc_tty; 840 1.1 petrov int error; 841 1.1 petrov 842 1.24 christos error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flags, l); 843 1.1 petrov if (error >= 0) 844 1.1 petrov return (error); 845 1.1 petrov 846 1.24 christos error = ttioctl(tp, cmd, data, flags, l); 847 1.1 petrov if (error >= 0) 848 1.1 petrov return (error); 849 1.1 petrov 850 1.1 petrov error = 0; 851 1.1 petrov 852 1.1 petrov switch (cmd) { 853 1.1 petrov case TIOCSBRK: 854 1.1 petrov SAB_WRITE(sc, SAB_DAFO, 855 1.1 petrov SAB_READ(sc, SAB_DAFO) | SAB_DAFO_XBRK); 856 1.1 petrov break; 857 1.1 petrov case TIOCCBRK: 858 1.1 petrov SAB_WRITE(sc, SAB_DAFO, 859 1.1 petrov SAB_READ(sc, SAB_DAFO) & ~SAB_DAFO_XBRK); 860 1.1 petrov break; 861 1.1 petrov case TIOCSDTR: 862 1.1 petrov sabtty_mdmctrl(sc, TIOCM_DTR, DMBIS); 863 1.1 petrov break; 864 1.1 petrov case TIOCCDTR: 865 1.1 petrov sabtty_mdmctrl(sc, TIOCM_DTR, DMBIC); 866 1.1 petrov break; 867 1.1 petrov case TIOCMBIS: 868 1.1 petrov sabtty_mdmctrl(sc, *((int *)data), DMBIS); 869 1.1 petrov break; 870 1.1 petrov case TIOCMBIC: 871 1.1 petrov sabtty_mdmctrl(sc, *((int *)data), DMBIC); 872 1.1 petrov break; 873 1.1 petrov case TIOCMGET: 874 1.1 petrov *((int *)data) = sabtty_mdmctrl(sc, 0, DMGET); 875 1.1 petrov break; 876 1.1 petrov case TIOCMSET: 877 1.1 petrov sabtty_mdmctrl(sc, *((int *)data), DMSET); 878 1.1 petrov break; 879 1.1 petrov case TIOCGFLAGS: 880 1.1 petrov *((int *)data) = sc->sc_openflags; 881 1.1 petrov break; 882 1.1 petrov case TIOCSFLAGS: 883 1.35 elad if (kauth_authorize_device_tty(l->l_cred, 884 1.35 elad KAUTH_DEVICE_TTY_PRIVSET, tp)) 885 1.1 petrov error = EPERM; 886 1.1 petrov else 887 1.1 petrov sc->sc_openflags = *((int *)data) & 888 1.1 petrov (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | 889 1.1 petrov TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF); 890 1.1 petrov break; 891 1.1 petrov default: 892 1.1 petrov error = ENOTTY; 893 1.1 petrov } 894 1.1 petrov 895 1.1 petrov return (error); 896 1.1 petrov } 897 1.1 petrov 898 1.1 petrov struct tty * 899 1.25 cdi sabtty(dev_t dev) 900 1.1 petrov { 901 1.42 cegger struct sabtty_softc *sc = device_lookup_private(&sabtty_cd, SABUNIT(dev)); 902 1.1 petrov 903 1.1 petrov return (sc->sc_tty); 904 1.1 petrov } 905 1.1 petrov 906 1.1 petrov void 907 1.25 cdi sabstop(struct tty *tp, int flag) 908 1.1 petrov { 909 1.42 cegger struct sabtty_softc *sc = device_lookup_private(&sabtty_cd, SABUNIT(tp->t_dev)); 910 1.1 petrov int s; 911 1.1 petrov 912 1.1 petrov s = spltty(); 913 1.1 petrov if (tp->t_state & TS_BUSY) { 914 1.1 petrov if ((tp->t_state & TS_TTSTOP) == 0) 915 1.1 petrov tp->t_state |= TS_FLUSH; 916 1.1 petrov sc->sc_flags |= SABTTYF_STOP; 917 1.1 petrov sc->sc_imr1 &= ~SAB_IMR1_ALLS; 918 1.1 petrov SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 919 1.1 petrov } 920 1.1 petrov splx(s); 921 1.1 petrov } 922 1.1 petrov 923 1.1 petrov int 924 1.25 cdi sabpoll(dev_t dev, int events, struct lwp *l) 925 1.1 petrov { 926 1.42 cegger struct sabtty_softc *sc = device_lookup_private(&sabtty_cd, SABUNIT(dev)); 927 1.1 petrov struct tty *tp = sc->sc_tty; 928 1.1 petrov 929 1.24 christos return ((*tp->t_linesw->l_poll)(tp, events, l)); 930 1.1 petrov } 931 1.1 petrov 932 1.1 petrov int 933 1.25 cdi sabtty_mdmctrl(struct sabtty_softc *sc, int bits, int how) 934 1.1 petrov { 935 1.25 cdi uint8_t r; 936 1.1 petrov int s; 937 1.1 petrov 938 1.1 petrov s = spltty(); 939 1.1 petrov switch (how) { 940 1.1 petrov case DMGET: 941 1.1 petrov bits = 0; 942 1.1 petrov if (SAB_READ(sc, SAB_STAR) & SAB_STAR_CTS) 943 1.1 petrov bits |= TIOCM_CTS; 944 1.1 petrov if ((SAB_READ(sc, SAB_VSTR) & SAB_VSTR_CD) == 0) 945 1.1 petrov bits |= TIOCM_CD; 946 1.1 petrov 947 1.1 petrov r = SAB_READ(sc, SAB_PVR); 948 1.1 petrov if ((r & sc->sc_pvr_dtr) == 0) 949 1.1 petrov bits |= TIOCM_DTR; 950 1.1 petrov if ((r & sc->sc_pvr_dsr) == 0) 951 1.1 petrov bits |= TIOCM_DSR; 952 1.1 petrov 953 1.1 petrov r = SAB_READ(sc, SAB_MODE); 954 1.1 petrov if ((r & (SAB_MODE_RTS|SAB_MODE_FRTS)) == SAB_MODE_RTS) 955 1.1 petrov bits |= TIOCM_RTS; 956 1.1 petrov break; 957 1.1 petrov case DMSET: 958 1.1 petrov r = SAB_READ(sc, SAB_MODE); 959 1.1 petrov if (bits & TIOCM_RTS) { 960 1.1 petrov r &= ~SAB_MODE_FRTS; 961 1.1 petrov r |= SAB_MODE_RTS; 962 1.1 petrov } else 963 1.1 petrov r |= SAB_MODE_FRTS | SAB_MODE_RTS; 964 1.1 petrov SAB_WRITE(sc, SAB_MODE, r); 965 1.1 petrov 966 1.1 petrov r = SAB_READ(sc, SAB_PVR); 967 1.1 petrov if (bits & TIOCM_DTR) 968 1.1 petrov r &= ~sc->sc_pvr_dtr; 969 1.1 petrov else 970 1.1 petrov r |= sc->sc_pvr_dtr; 971 1.1 petrov SAB_WRITE(sc, SAB_PVR, r); 972 1.1 petrov break; 973 1.1 petrov case DMBIS: 974 1.1 petrov if (bits & TIOCM_RTS) { 975 1.1 petrov r = SAB_READ(sc, SAB_MODE); 976 1.1 petrov r &= ~SAB_MODE_FRTS; 977 1.1 petrov r |= SAB_MODE_RTS; 978 1.1 petrov SAB_WRITE(sc, SAB_MODE, r); 979 1.1 petrov } 980 1.1 petrov if (bits & TIOCM_DTR) { 981 1.1 petrov r = SAB_READ(sc, SAB_PVR); 982 1.1 petrov r &= ~sc->sc_pvr_dtr; 983 1.1 petrov SAB_WRITE(sc, SAB_PVR, r); 984 1.1 petrov } 985 1.1 petrov break; 986 1.1 petrov case DMBIC: 987 1.1 petrov if (bits & TIOCM_RTS) { 988 1.1 petrov r = SAB_READ(sc, SAB_MODE); 989 1.1 petrov r |= SAB_MODE_FRTS | SAB_MODE_RTS; 990 1.1 petrov SAB_WRITE(sc, SAB_MODE, r); 991 1.1 petrov } 992 1.1 petrov if (bits & TIOCM_DTR) { 993 1.1 petrov r = SAB_READ(sc, SAB_PVR); 994 1.1 petrov r |= sc->sc_pvr_dtr; 995 1.1 petrov SAB_WRITE(sc, SAB_PVR, r); 996 1.1 petrov } 997 1.1 petrov break; 998 1.1 petrov } 999 1.1 petrov splx(s); 1000 1.1 petrov return (bits); 1001 1.1 petrov } 1002 1.1 petrov 1003 1.1 petrov int 1004 1.25 cdi sabttyparam(struct sabtty_softc *sc, struct tty *tp, struct termios *t) 1005 1.1 petrov { 1006 1.1 petrov int s, ospeed; 1007 1.1 petrov tcflag_t cflag; 1008 1.25 cdi uint8_t dafo, r; 1009 1.1 petrov 1010 1.1 petrov ospeed = sabtty_speed(t->c_ospeed); 1011 1.1 petrov if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 1012 1.1 petrov return (EINVAL); 1013 1.1 petrov 1014 1.1 petrov s = spltty(); 1015 1.1 petrov 1016 1.1 petrov /* hang up line if ospeed is zero, otherwise raise dtr */ 1017 1.1 petrov sabtty_mdmctrl(sc, TIOCM_DTR, 1018 1.1 petrov (t->c_ospeed == 0) ? DMBIC : DMBIS); 1019 1.1 petrov 1020 1.1 petrov dafo = SAB_READ(sc, SAB_DAFO); 1021 1.1 petrov 1022 1.1 petrov cflag = t->c_cflag; 1023 1.1 petrov 1024 1.1 petrov if (sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) { 1025 1.1 petrov cflag |= CLOCAL; 1026 1.1 petrov cflag &= ~HUPCL; 1027 1.1 petrov } 1028 1.1 petrov 1029 1.1 petrov if (cflag & CSTOPB) 1030 1.1 petrov dafo |= SAB_DAFO_STOP; 1031 1.1 petrov else 1032 1.1 petrov dafo &= ~SAB_DAFO_STOP; 1033 1.1 petrov 1034 1.1 petrov dafo &= ~SAB_DAFO_CHL_CSIZE; 1035 1.1 petrov switch (cflag & CSIZE) { 1036 1.1 petrov case CS5: 1037 1.1 petrov dafo |= SAB_DAFO_CHL_CS5; 1038 1.1 petrov break; 1039 1.1 petrov case CS6: 1040 1.1 petrov dafo |= SAB_DAFO_CHL_CS6; 1041 1.1 petrov break; 1042 1.1 petrov case CS7: 1043 1.1 petrov dafo |= SAB_DAFO_CHL_CS7; 1044 1.1 petrov break; 1045 1.1 petrov default: 1046 1.1 petrov dafo |= SAB_DAFO_CHL_CS8; 1047 1.1 petrov break; 1048 1.1 petrov } 1049 1.1 petrov 1050 1.1 petrov dafo &= ~SAB_DAFO_PARMASK; 1051 1.1 petrov if (cflag & PARENB) { 1052 1.1 petrov if (cflag & PARODD) 1053 1.1 petrov dafo |= SAB_DAFO_PAR_ODD; 1054 1.1 petrov else 1055 1.1 petrov dafo |= SAB_DAFO_PAR_EVEN; 1056 1.1 petrov } else 1057 1.1 petrov dafo |= SAB_DAFO_PAR_NONE; 1058 1.33 martin SAB_WRITE(sc, SAB_DAFO, dafo); 1059 1.1 petrov 1060 1.44 jdc if (!(sc->sc_flags & SABTTYF_IS_RSC) && ospeed != 0) { 1061 1.1 petrov SAB_WRITE(sc, SAB_BGR, ospeed & 0xff); 1062 1.1 petrov r = SAB_READ(sc, SAB_CCR2); 1063 1.1 petrov r &= ~(SAB_CCR2_BR9 | SAB_CCR2_BR8); 1064 1.1 petrov r |= (ospeed >> 2) & (SAB_CCR2_BR9 | SAB_CCR2_BR8); 1065 1.1 petrov SAB_WRITE(sc, SAB_CCR2, r); 1066 1.1 petrov } 1067 1.1 petrov 1068 1.1 petrov r = SAB_READ(sc, SAB_MODE); 1069 1.1 petrov r |= SAB_MODE_RAC; 1070 1.1 petrov if (cflag & CRTSCTS) { 1071 1.1 petrov r &= ~(SAB_MODE_RTS | SAB_MODE_FCTS); 1072 1.1 petrov r |= SAB_MODE_FRTS; 1073 1.1 petrov sc->sc_imr1 &= ~SAB_IMR1_CSC; 1074 1.1 petrov } else { 1075 1.1 petrov r |= SAB_MODE_RTS | SAB_MODE_FCTS; 1076 1.1 petrov r &= ~SAB_MODE_FRTS; 1077 1.1 petrov sc->sc_imr1 |= SAB_IMR1_CSC; 1078 1.1 petrov } 1079 1.1 petrov SAB_WRITE(sc, SAB_MODE, r); 1080 1.1 petrov SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 1081 1.1 petrov 1082 1.1 petrov tp->t_cflag = cflag; 1083 1.1 petrov 1084 1.1 petrov splx(s); 1085 1.1 petrov return (0); 1086 1.1 petrov } 1087 1.1 petrov 1088 1.1 petrov int 1089 1.25 cdi sabtty_param(struct tty *tp, struct termios *t) 1090 1.1 petrov { 1091 1.42 cegger struct sabtty_softc *sc = device_lookup_private(&sabtty_cd, SABUNIT(tp->t_dev)); 1092 1.1 petrov 1093 1.1 petrov return (sabttyparam(sc, tp, t)); 1094 1.1 petrov } 1095 1.1 petrov 1096 1.1 petrov void 1097 1.25 cdi sabtty_start(struct tty *tp) 1098 1.1 petrov { 1099 1.42 cegger struct sabtty_softc *sc = device_lookup_private(&sabtty_cd, SABUNIT(tp->t_dev)); 1100 1.1 petrov int s; 1101 1.1 petrov 1102 1.1 petrov s = spltty(); 1103 1.1 petrov if ((tp->t_state & (TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) == 0) { 1104 1.39 ad if (ttypull(tp)) { 1105 1.1 petrov sc->sc_txc = ndqb(&tp->t_outq, 0); 1106 1.1 petrov sc->sc_txp = tp->t_outq.c_cf; 1107 1.1 petrov tp->t_state |= TS_BUSY; 1108 1.11 petrov sc->sc_imr1 &= ~(SAB_ISR1_XPR | SAB_ISR1_ALLS); 1109 1.1 petrov SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 1110 1.1 petrov } 1111 1.1 petrov } 1112 1.1 petrov splx(s); 1113 1.1 petrov } 1114 1.1 petrov 1115 1.1 petrov void 1116 1.25 cdi sabtty_cec_wait(struct sabtty_softc *sc) 1117 1.1 petrov { 1118 1.1 petrov int i = 50000; 1119 1.1 petrov 1120 1.1 petrov for (;;) { 1121 1.1 petrov if ((SAB_READ(sc, SAB_STAR) & SAB_STAR_CEC) == 0) 1122 1.1 petrov return; 1123 1.1 petrov if (--i == 0) 1124 1.1 petrov break; 1125 1.1 petrov DELAY(1); 1126 1.1 petrov } 1127 1.1 petrov } 1128 1.1 petrov 1129 1.1 petrov void 1130 1.25 cdi sabtty_tec_wait(struct sabtty_softc *sc) 1131 1.1 petrov { 1132 1.1 petrov int i = 200000; 1133 1.1 petrov 1134 1.1 petrov for (;;) { 1135 1.1 petrov if ((SAB_READ(sc, SAB_STAR) & SAB_STAR_TEC) == 0) 1136 1.1 petrov return; 1137 1.1 petrov if (--i == 0) 1138 1.1 petrov break; 1139 1.1 petrov DELAY(1); 1140 1.1 petrov } 1141 1.1 petrov } 1142 1.1 petrov 1143 1.1 petrov void 1144 1.25 cdi sabtty_reset(struct sabtty_softc *sc) 1145 1.1 petrov { 1146 1.1 petrov /* power down */ 1147 1.1 petrov SAB_WRITE(sc, SAB_CCR0, 0); 1148 1.1 petrov 1149 1.1 petrov /* set basic configuration */ 1150 1.1 petrov SAB_WRITE(sc, SAB_CCR0, 1151 1.1 petrov SAB_CCR0_MCE | SAB_CCR0_SC_NRZ | SAB_CCR0_SM_ASYNC); 1152 1.1 petrov SAB_WRITE(sc, SAB_CCR1, SAB_CCR1_ODS | SAB_CCR1_BCR | SAB_CCR1_CM_7); 1153 1.1 petrov SAB_WRITE(sc, SAB_CCR2, SAB_CCR2_BDF | SAB_CCR2_SSEL | SAB_CCR2_TOE); 1154 1.1 petrov SAB_WRITE(sc, SAB_CCR3, 0); 1155 1.27 martin SAB_WRITE(sc, SAB_CCR4, SAB_CCR4_MCK4 | SAB_CCR4_EBRG | SAB_CCR4_ICD); 1156 1.1 petrov SAB_WRITE(sc, SAB_MODE, SAB_MODE_RTS | SAB_MODE_FCTS | SAB_MODE_RAC); 1157 1.1 petrov SAB_WRITE(sc, SAB_RFC, 1158 1.1 petrov SAB_RFC_DPS | SAB_RFC_RFDF | SAB_RFC_RFTH_32CHAR); 1159 1.1 petrov 1160 1.1 petrov /* clear interrupts */ 1161 1.1 petrov sc->sc_imr0 = sc->sc_imr1 = 0xff; 1162 1.1 petrov SAB_WRITE(sc, SAB_IMR0, sc->sc_imr0); 1163 1.1 petrov SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 1164 1.29 christos (void)SAB_READ(sc, SAB_ISR0); 1165 1.29 christos (void)SAB_READ(sc, SAB_ISR1); 1166 1.1 petrov } 1167 1.1 petrov 1168 1.1 petrov void 1169 1.25 cdi sabtty_flush(struct sabtty_softc *sc) 1170 1.1 petrov { 1171 1.1 petrov /* clear rx fifo */ 1172 1.1 petrov sabtty_cec_wait(sc); 1173 1.1 petrov SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES); 1174 1.1 petrov 1175 1.1 petrov /* clear tx fifo */ 1176 1.1 petrov sabtty_cec_wait(sc); 1177 1.1 petrov SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_XRES); 1178 1.1 petrov } 1179 1.1 petrov 1180 1.1 petrov int 1181 1.25 cdi sabtty_speed(int rate) 1182 1.1 petrov { 1183 1.1 petrov int i, len, r; 1184 1.1 petrov 1185 1.1 petrov if (rate == 0) 1186 1.1 petrov return (0); 1187 1.1 petrov len = sizeof(sabtty_baudtable)/sizeof(sabtty_baudtable[0]); 1188 1.1 petrov for (i = 0; i < len; i++) { 1189 1.1 petrov if (rate == sabtty_baudtable[i].baud) { 1190 1.1 petrov r = sabtty_baudtable[i].n | 1191 1.1 petrov (sabtty_baudtable[i].m << 6); 1192 1.1 petrov return (r); 1193 1.1 petrov } 1194 1.1 petrov } 1195 1.1 petrov return (-1); 1196 1.1 petrov } 1197 1.1 petrov 1198 1.1 petrov void 1199 1.25 cdi sabtty_cnputc(struct sabtty_softc *sc, int c) 1200 1.1 petrov { 1201 1.1 petrov sabtty_tec_wait(sc); 1202 1.1 petrov SAB_WRITE(sc, SAB_TIC, c); 1203 1.1 petrov sabtty_tec_wait(sc); 1204 1.1 petrov } 1205 1.1 petrov 1206 1.1 petrov int 1207 1.25 cdi sabtty_cngetc(struct sabtty_softc *sc) 1208 1.1 petrov { 1209 1.25 cdi uint8_t r, len; 1210 1.1 petrov 1211 1.1 petrov again: 1212 1.1 petrov do { 1213 1.1 petrov r = SAB_READ(sc, SAB_STAR); 1214 1.1 petrov } while ((r & SAB_STAR_RFNE) == 0); 1215 1.1 petrov 1216 1.1 petrov /* 1217 1.1 petrov * Ok, at least one byte in RFIFO, ask for permission to access RFIFO 1218 1.1 petrov * (I hate this chip... hate hate hate). 1219 1.1 petrov */ 1220 1.1 petrov sabtty_cec_wait(sc); 1221 1.1 petrov SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RFRD); 1222 1.1 petrov 1223 1.1 petrov /* Wait for RFIFO to come ready */ 1224 1.1 petrov do { 1225 1.1 petrov r = SAB_READ(sc, SAB_ISR0); 1226 1.1 petrov } while ((r & SAB_ISR0_TCD) == 0); 1227 1.1 petrov 1228 1.1 petrov len = SAB_READ(sc, SAB_RBCL) & (32 - 1); 1229 1.1 petrov if (len == 0) 1230 1.1 petrov goto again; /* Shouldn't happen... */ 1231 1.1 petrov 1232 1.1 petrov r = SAB_READ(sc, SAB_RFIFO); 1233 1.1 petrov 1234 1.1 petrov /* 1235 1.1 petrov * Blow away everything left in the FIFO... 1236 1.1 petrov */ 1237 1.1 petrov sabtty_cec_wait(sc); 1238 1.1 petrov SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RMC); 1239 1.1 petrov return (r); 1240 1.1 petrov } 1241 1.1 petrov 1242 1.1 petrov void 1243 1.25 cdi sabtty_cnpollc(struct sabtty_softc *sc, int on) 1244 1.1 petrov { 1245 1.25 cdi uint8_t r; 1246 1.1 petrov 1247 1.1 petrov if (on) { 1248 1.1 petrov if (sc->sc_polling) 1249 1.1 petrov return; 1250 1.1 petrov SAB_WRITE(sc, SAB_IPC, SAB_READ(sc, SAB_IPC) | SAB_IPC_VIS); 1251 1.1 petrov r = sc->sc_pollrfc = SAB_READ(sc, SAB_RFC); 1252 1.1 petrov r &= ~(SAB_RFC_RFDF); 1253 1.1 petrov SAB_WRITE(sc, SAB_RFC, r); 1254 1.1 petrov sabtty_cec_wait(sc); 1255 1.1 petrov SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES); 1256 1.1 petrov sc->sc_polling = 1; 1257 1.1 petrov } else { 1258 1.1 petrov if (!sc->sc_polling) 1259 1.1 petrov return; 1260 1.1 petrov SAB_WRITE(sc, SAB_IPC, SAB_READ(sc, SAB_IPC) & ~SAB_IPC_VIS); 1261 1.1 petrov SAB_WRITE(sc, SAB_RFC, sc->sc_pollrfc); 1262 1.1 petrov sabtty_cec_wait(sc); 1263 1.1 petrov SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES); 1264 1.1 petrov sc->sc_polling = 0; 1265 1.1 petrov } 1266 1.1 petrov } 1267 1.1 petrov 1268 1.1 petrov void 1269 1.25 cdi sab_cnputc(dev_t dev, int c) 1270 1.1 petrov { 1271 1.1 petrov struct sabtty_softc *sc = sabtty_cons_output; 1272 1.1 petrov 1273 1.1 petrov if (sc == NULL) 1274 1.1 petrov return; 1275 1.1 petrov sabtty_cnputc(sc, c); 1276 1.1 petrov } 1277 1.1 petrov 1278 1.1 petrov void 1279 1.25 cdi sab_cnpollc(dev_t dev, int on) 1280 1.1 petrov { 1281 1.1 petrov struct sabtty_softc *sc = sabtty_cons_input; 1282 1.1 petrov 1283 1.1 petrov sabtty_cnpollc(sc, on); 1284 1.1 petrov } 1285 1.1 petrov 1286 1.1 petrov int 1287 1.25 cdi sab_cngetc(dev_t dev) 1288 1.1 petrov { 1289 1.1 petrov struct sabtty_softc *sc = sabtty_cons_input; 1290 1.1 petrov 1291 1.1 petrov if (sc == NULL) 1292 1.1 petrov return (-1); 1293 1.1 petrov return (sabtty_cngetc(sc)); 1294 1.1 petrov } 1295 1.1 petrov 1296 1.1 petrov void 1297 1.25 cdi sabtty_console_flags(struct sabtty_softc *sc) 1298 1.1 petrov { 1299 1.1 petrov int node, channel, cookie; 1300 1.1 petrov char buf[255]; 1301 1.1 petrov 1302 1.1 petrov node = sc->sc_parent->sc_node; 1303 1.1 petrov channel = sc->sc_portno; 1304 1.1 petrov 1305 1.1 petrov /* Default to channel 0 if there are no explicit prom args */ 1306 1.1 petrov cookie = 0; 1307 1.1 petrov 1308 1.16 pk if (node == prom_instance_to_package(prom_stdin())) { 1309 1.16 pk if (prom_getoption("input-device", buf, sizeof buf) == 0 && 1310 1.16 pk strcmp("ttyb", buf) == 0) 1311 1.1 petrov cookie = 1; 1312 1.1 petrov 1313 1.1 petrov if (channel == cookie) 1314 1.1 petrov sc->sc_flags |= SABTTYF_CONS_IN; 1315 1.1 petrov } 1316 1.1 petrov 1317 1.1 petrov /* Default to same channel if there are no explicit prom args */ 1318 1.1 petrov 1319 1.16 pk if (node == prom_instance_to_package(prom_stdout())) { 1320 1.16 pk if (prom_getoption("output-device", buf, sizeof buf) == 0 && 1321 1.16 pk strcmp("ttyb", buf) == 0) 1322 1.1 petrov cookie = 1; 1323 1.1 petrov 1324 1.1 petrov if (channel == cookie) 1325 1.1 petrov sc->sc_flags |= SABTTYF_CONS_OUT; 1326 1.1 petrov } 1327 1.44 jdc /* Are we connected to an E250 RSC? */ 1328 1.44 jdc if (channel == prom_getpropint(node, "ssp-console", -1) || 1329 1.44 jdc channel == prom_getpropint(node, "ssp-control", -1)) 1330 1.44 jdc sc->sc_flags |= SABTTYF_IS_RSC; 1331 1.1 petrov } 1332 1.1 petrov 1333 1.53 nakayama bool 1334 1.53 nakayama sabtty_shutdown(device_t dev, int how) 1335 1.1 petrov { 1336 1.53 nakayama struct sabtty_softc *sc = device_private(dev); 1337 1.1 petrov 1338 1.1 petrov /* Have to put the chip back into single char mode */ 1339 1.1 petrov sc->sc_flags |= SABTTYF_DONTDDB; 1340 1.1 petrov SAB_WRITE(sc, SAB_RFC, SAB_READ(sc, SAB_RFC) & ~SAB_RFC_RFDF); 1341 1.1 petrov sabtty_cec_wait(sc); 1342 1.1 petrov SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES); 1343 1.1 petrov sabtty_cec_wait(sc); 1344 1.53 nakayama return true; 1345 1.1 petrov } 1346 1.36 martin 1347 1.36 martin #ifdef KGDB 1348 1.36 martin static int 1349 1.36 martin sab_kgdb_getc(void *arg) 1350 1.36 martin { 1351 1.36 martin struct sabtty_softc *sc = arg; 1352 1.36 martin 1353 1.36 martin return sabtty_cngetc(sc); 1354 1.36 martin } 1355 1.36 martin 1356 1.36 martin static void 1357 1.36 martin sab_kgdb_putc(void *arg, int c) 1358 1.36 martin { 1359 1.36 martin struct sabtty_softc *sc = arg; 1360 1.36 martin 1361 1.36 martin return sabtty_cnputc(sc, c); 1362 1.36 martin } 1363 1.36 martin 1364 1.36 martin #ifndef KGDB_DEVRATE 1365 1.36 martin #define KGDB_DEVRATE 9600 1366 1.36 martin #endif 1367 1.36 martin 1368 1.36 martin int 1369 1.36 martin sab_kgdb_check(struct sabtty_softc *sc) 1370 1.36 martin { 1371 1.48 christos return strcmp(device_xname(sc->sc_dev), KGDB_DEVNAME) == 0; 1372 1.36 martin } 1373 1.36 martin 1374 1.36 martin void 1375 1.36 martin sab_kgdb_init(struct sabtty_softc *sc) 1376 1.36 martin { 1377 1.36 martin int sp; 1378 1.36 martin uint8_t dafo, r; 1379 1.36 martin extern int kgdb_break_at_attach; 1380 1.36 martin 1381 1.36 martin kgdb_attach(sab_kgdb_getc, sab_kgdb_putc, sc); 1382 1.36 martin kgdb_dev = 123; /* not used, but checked against NODEV */ 1383 1.36 martin 1384 1.36 martin /* 1385 1.36 martin * Configure the port to speed/8n1 1386 1.36 martin */ 1387 1.36 martin dafo = SAB_READ(sc, SAB_DAFO); 1388 1.36 martin dafo &= ~(SAB_DAFO_STOP|SAB_DAFO_CHL_CSIZE|SAB_DAFO_PARMASK); 1389 1.36 martin dafo |= SAB_DAFO_CHL_CS8|SAB_DAFO_PAR_NONE; 1390 1.36 martin SAB_WRITE(sc, SAB_DAFO, dafo); 1391 1.36 martin sp = sabtty_speed(KGDB_DEVRATE); 1392 1.36 martin SAB_WRITE(sc, SAB_BGR, sp & 0xff); 1393 1.36 martin r = SAB_READ(sc, SAB_CCR2); 1394 1.36 martin r &= ~(SAB_CCR2_BR9 | SAB_CCR2_BR8); 1395 1.36 martin r |= (sp >> 2) & (SAB_CCR2_BR9 | SAB_CCR2_BR8); 1396 1.36 martin SAB_WRITE(sc, SAB_CCR2, r); 1397 1.36 martin 1398 1.36 martin /* 1399 1.36 martin * If we are booting with -d, break into kgdb now 1400 1.36 martin */ 1401 1.36 martin if (kgdb_break_at_attach) 1402 1.36 martin kgdb_connect(1); 1403 1.36 martin } 1404 1.36 martin #endif 1405