jcs's openbsd hax
openbsd
at jcs 902 lines 23 kB view raw
1/* $OpenBSD: pluart.c,v 1.14 2022/07/02 08:50:42 visa Exp $ */ 2/* 3 * Copyright (c) 2014 Patrick Wildt <patrick@blueri.se> 4 * Copyright (c) 2005 Dale Rahn <drahn@dalerahn.com> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#include <sys/param.h> 20#include <sys/ioctl.h> 21#include <sys/proc.h> 22#include <sys/tty.h> 23#include <sys/uio.h> 24#include <sys/systm.h> 25#include <sys/time.h> 26#include <sys/device.h> 27#include <sys/syslog.h> 28#include <sys/conf.h> 29#include <sys/fcntl.h> 30#include <sys/kernel.h> 31 32#include <machine/bus.h> 33 34#include <dev/ic/pluartvar.h> 35#include <dev/cons.h> 36 37#ifdef DDB 38#include <ddb/db_var.h> 39#endif 40 41#define DEVUNIT(x) (minor(x) & 0x7f) 42#define DEVCUA(x) (minor(x) & 0x80) 43 44#define UART_DR 0x00 /* Data register */ 45#define UART_DR_DATA(x) ((x) & 0xf) 46#define UART_DR_FE (1 << 8) /* Framing error */ 47#define UART_DR_PE (1 << 9) /* Parity error */ 48#define UART_DR_BE (1 << 10) /* Break error */ 49#define UART_DR_OE (1 << 11) /* Overrun error */ 50#define UART_RSR 0x04 /* Receive status register */ 51#define UART_RSR_FE (1 << 0) /* Framing error */ 52#define UART_RSR_PE (1 << 1) /* Parity error */ 53#define UART_RSR_BE (1 << 2) /* Break error */ 54#define UART_RSR_OE (1 << 3) /* Overrun error */ 55#define UART_ECR 0x04 /* Error clear register */ 56#define UART_ECR_FE (1 << 0) /* Framing error */ 57#define UART_ECR_PE (1 << 1) /* Parity error */ 58#define UART_ECR_BE (1 << 2) /* Break error */ 59#define UART_ECR_OE (1 << 3) /* Overrun error */ 60#define UART_FR 0x18 /* Flag register */ 61#define UART_FR_CTS (1 << 0) /* Clear to send */ 62#define UART_FR_DSR (1 << 1) /* Data set ready */ 63#define UART_FR_DCD (1 << 2) /* Data carrier detect */ 64#define UART_FR_BUSY (1 << 3) /* UART busy */ 65#define UART_FR_RXFE (1 << 4) /* Receive FIFO empty */ 66#define UART_FR_TXFF (1 << 5) /* Transmit FIFO full */ 67#define UART_FR_RXFF (1 << 6) /* Receive FIFO full */ 68#define UART_FR_TXFE (1 << 7) /* Transmit FIFO empty */ 69#define UART_FR_RI (1 << 8) /* Ring indicator */ 70#define UART_ILPR 0x20 /* IrDA low-power counter register */ 71#define UART_ILPR_ILPDVSR ((x) & 0xf) /* IrDA low-power divisor */ 72#define UART_IBRD 0x24 /* Integer baud rate register */ 73#define UART_IBRD_DIVINT(x) ((x) & 0xffff) /* Integer baud rate divisor */ 74#define UART_FBRD 0x28 /* Fractional baud rate register */ 75#define UART_FBRD_DIVFRAC(x) ((x) & 0x3f) /* Fractional baud rate divisor */ 76#define UART_LCR_H 0x2c /* Line control register */ 77#define UART_LCR_H_BRK (1 << 0) /* Send break */ 78#define UART_LCR_H_PEN (1 << 1) /* Parity enable */ 79#define UART_LCR_H_EPS (1 << 2) /* Even parity select */ 80#define UART_LCR_H_STP2 (1 << 3) /* Two stop bits select */ 81#define UART_LCR_H_FEN (1 << 4) /* Enable FIFOs */ 82#define UART_LCR_H_WLEN5 (0x0 << 5) /* Word length: 5 bits */ 83#define UART_LCR_H_WLEN6 (0x1 << 5) /* Word length: 6 bits */ 84#define UART_LCR_H_WLEN7 (0x2 << 5) /* Word length: 7 bits */ 85#define UART_LCR_H_WLEN8 (0x3 << 5) /* Word length: 8 bits */ 86#define UART_LCR_H_SPS (1 << 7) /* Stick parity select */ 87#define UART_CR 0x30 /* Control register */ 88#define UART_CR_UARTEN (1 << 0) /* UART enable */ 89#define UART_CR_SIREN (1 << 1) /* SIR enable */ 90#define UART_CR_SIRLP (1 << 2) /* IrDA SIR low power mode */ 91#define UART_CR_LBE (1 << 7) /* Loop back enable */ 92#define UART_CR_TXE (1 << 8) /* Transmit enable */ 93#define UART_CR_RXE (1 << 9) /* Receive enable */ 94#define UART_CR_DTR (1 << 10) /* Data transmit enable */ 95#define UART_CR_RTS (1 << 11) /* Request to send */ 96#define UART_CR_OUT1 (1 << 12) 97#define UART_CR_OUT2 (1 << 13) 98#define UART_CR_CTSE (1 << 14) /* CTS hardware flow control enable */ 99#define UART_CR_RTSE (1 << 15) /* RTS hardware flow control enable */ 100#define UART_IFLS 0x34 /* Interrupt FIFO level select register */ 101#define UART_IFLS_RX_SHIFT 3 /* RX level in bits [5:3] */ 102#define UART_IFLS_TX_SHIFT 0 /* TX level in bits [2:0] */ 103#define UART_IFLS_1_8 0 /* FIFO 1/8 full */ 104#define UART_IFLS_1_4 1 /* FIFO 1/4 full */ 105#define UART_IFLS_1_2 2 /* FIFO 1/2 full */ 106#define UART_IFLS_3_4 3 /* FIFO 3/4 full */ 107#define UART_IFLS_7_8 4 /* FIFO 7/8 full */ 108#define UART_IMSC 0x38 /* Interrupt mask set/clear register */ 109#define UART_IMSC_RIMIM (1 << 0) 110#define UART_IMSC_CTSMIM (1 << 1) 111#define UART_IMSC_DCDMIM (1 << 2) 112#define UART_IMSC_DSRMIM (1 << 3) 113#define UART_IMSC_RXIM (1 << 4) 114#define UART_IMSC_TXIM (1 << 5) 115#define UART_IMSC_RTIM (1 << 6) 116#define UART_IMSC_FEIM (1 << 7) 117#define UART_IMSC_PEIM (1 << 8) 118#define UART_IMSC_BEIM (1 << 9) 119#define UART_IMSC_OEIM (1 << 10) 120#define UART_RIS 0x3c /* Raw interrupt status register */ 121#define UART_MIS 0x40 /* Masked interrupt status register */ 122#define UART_ICR 0x44 /* Interrupt clear register */ 123#define UART_DMACR 0x48 /* DMA control register */ 124#define UART_PID0 0xfe0 /* Peripheral identification register 0 */ 125#define UART_PID1 0xfe4 /* Peripheral identification register 1 */ 126#define UART_PID2 0xfe8 /* Peripheral identification register 2 */ 127#define UART_PID2_REV(x) (((x) & 0xf0) >> 4) 128#define UART_PID3 0xfec /* Peripheral identification register 3 */ 129#define UART_SPACE 0x100 130 131#define UART_FIFO_SIZE 16 132#define UART_FIFO_SIZE_R3 32 133 134void pluartcnprobe(struct consdev *cp); 135void pluartcninit(struct consdev *cp); 136int pluartcngetc(dev_t dev); 137void pluartcnputc(dev_t dev, int c); 138void pluartcnpollc(dev_t dev, int on); 139int pluart_param(struct tty *tp, struct termios *t); 140void pluart_start(struct tty *); 141void pluart_diag(void *arg); 142void pluart_raisedtr(void *arg); 143void pluart_softint(void *arg); 144struct pluart_softc *pluart_sc(dev_t dev); 145 146/* XXX - we imitate 'com' serial ports and take over their entry points */ 147/* XXX: These belong elsewhere */ 148cdev_decl(com); 149cdev_decl(pluart); 150 151struct cfdriver pluart_cd = { 152 NULL, "pluart", DV_TTY 153}; 154 155int pluartdefaultrate = B38400; 156int pluartconsrate = B38400; 157bus_space_tag_t pluartconsiot; 158bus_space_handle_t pluartconsioh; 159bus_addr_t pluartconsaddr; 160tcflag_t pluartconscflag = TTYDEF_CFLAG; 161 162struct cdevsw pluartdev = 163 cdev_tty_init(3/*XXX NUART */ ,pluart); /* 12: serial port */ 164 165void 166pluart_attach_common(struct pluart_softc *sc, int console) 167{ 168 int fifolen, fr, lcr, maj; 169 170 if ((sc->sc_hwflags & COM_HW_SBSA) == 0) { 171 if (sc->sc_hwrev == 0) 172 sc->sc_hwrev = UART_PID2_REV(bus_space_read_4(sc->sc_iot, 173 sc->sc_ioh, UART_PID2)); 174 if (sc->sc_hwrev < 3) 175 fifolen = UART_FIFO_SIZE; 176 else 177 fifolen = UART_FIFO_SIZE_R3; 178 printf(": rev %d, %d byte fifo\n", sc->sc_hwrev, fifolen); 179 } else { 180 /* 181 * The SBSA UART is PL011 r1p5 compliant which implies revision 182 * 3 with a 32 byte FIFO. However, we cannot expect to configure 183 * RX/TX interrupt levels using the UARTIFLS register making it 184 * impossible to make assumptions about the number of available 185 * bytes in the FIFO. Therefore disable FIFO support for such 186 * devices. 187 */ 188 fifolen = 0; 189 printf("\n"); 190 } 191 192 if (console) { 193 /* Locate the major number. */ 194 for (maj = 0; maj < nchrdev; maj++) 195 if (cdevsw[maj].d_open == pluartopen) 196 break; 197 cn_tab->cn_dev = makedev(maj, sc->sc_dev.dv_unit); 198 199 printf("%s: console\n", sc->sc_dev.dv_xname); 200 SET(sc->sc_hwflags, COM_HW_CONSOLE); 201 } 202 203 timeout_set(&sc->sc_diag_tmo, pluart_diag, sc); 204 timeout_set(&sc->sc_dtr_tmo, pluart_raisedtr, sc); 205 sc->sc_si = softintr_establish(IPL_TTY, pluart_softint, sc); 206 207 if(sc->sc_si == NULL) 208 panic("%s: can't establish soft interrupt.", 209 sc->sc_dev.dv_xname); 210 211 /* Flush transmit before enabling FIFO. */ 212 for (;;) { 213 fr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, UART_FR); 214 if (fr & UART_FR_TXFE) 215 break; 216 delay(100); 217 } 218 219 if (fifolen > 0) { 220 bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_IFLS, 221 (UART_IFLS_3_4 << UART_IFLS_RX_SHIFT) | 222 (UART_IFLS_1_4 << UART_IFLS_TX_SHIFT)); 223 } 224 sc->sc_imsc = UART_IMSC_RXIM | UART_IMSC_RTIM; 225 bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_IMSC, sc->sc_imsc); 226 bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_ICR, 0x7ff); 227 228 229 lcr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, UART_LCR_H); 230 if (fifolen > 0) 231 lcr |= UART_LCR_H_FEN; 232 else 233 lcr &= ~UART_LCR_H_FEN; 234 bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_LCR_H, lcr); 235} 236 237int 238pluart_intr(void *arg) 239{ 240 struct pluart_softc *sc = arg; 241 bus_space_tag_t iot = sc->sc_iot; 242 bus_space_handle_t ioh = sc->sc_ioh; 243 struct tty *tp = sc->sc_tty; 244 u_int16_t is; 245 u_int16_t *p; 246 u_int16_t c; 247 248 is = bus_space_read_4(iot, ioh, UART_MIS); 249 bus_space_write_4(iot, ioh, UART_ICR, is & ~UART_IMSC_TXIM); 250 251 if (sc->sc_tty == NULL) 252 return 0; 253 254 if (!ISSET(is, UART_IMSC_RXIM) && !ISSET(is, UART_IMSC_RTIM) && 255 !ISSET(is, UART_IMSC_TXIM)) 256 return 0; 257 258 if (ISSET(is, UART_IMSC_TXIM) && ISSET(tp->t_state, TS_BUSY)) { 259 CLR(tp->t_state, TS_BUSY | TS_FLUSH); 260 if (sc->sc_halt > 0) 261 wakeup(&tp->t_outq); 262 (*linesw[tp->t_line].l_start)(tp); 263 } 264 265 p = sc->sc_ibufp; 266 267 while (!ISSET(bus_space_read_4(iot, ioh, UART_FR), UART_FR_RXFE)) { 268 c = bus_space_read_2(iot, ioh, UART_DR); 269 if (c & UART_DR_BE) { 270#ifdef DDB 271 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { 272 if (db_console) 273 db_enter(); 274 continue; 275 } 276#endif 277 c = 0; 278 } 279 if (p >= sc->sc_ibufend) { 280 sc->sc_floods++; 281 if (sc->sc_errors++ == 0) 282 timeout_add_sec(&sc->sc_diag_tmo, 60); 283 } else { 284 *p++ = c; 285 if (p == sc->sc_ibufhigh && ISSET(tp->t_cflag, CRTSCTS)) { 286 /* XXX */ 287 //CLR(sc->sc_ucr3, IMXUART_CR3_DSR); 288 //bus_space_write_4(iot, ioh, IMXUART_UCR3, 289 // sc->sc_ucr3); 290 } 291 } 292 /* XXX - msr stuff ? */ 293 } 294 sc->sc_ibufp = p; 295 296 softintr_schedule(sc->sc_si); 297 298 return 1; 299} 300 301int 302pluart_param(struct tty *tp, struct termios *t) 303{ 304 struct pluart_softc *sc = pluart_cd.cd_devs[DEVUNIT(tp->t_dev)]; 305 int ospeed = t->c_ospeed; 306 int error; 307 tcflag_t oldcflag; 308 309 if (t->c_ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 310 return EINVAL; 311 312 switch (ISSET(t->c_cflag, CSIZE)) { 313 case CS5: 314 return EINVAL; 315 case CS6: 316 return EINVAL; 317 case CS7: 318 //CLR(sc->sc_ucr2, IMXUART_CR2_WS); 319 break; 320 case CS8: 321 //SET(sc->sc_ucr2, IMXUART_CR2_WS); 322 break; 323 } 324// bus_space_write_4(iot, ioh, IMXUART_UCR2, sc->sc_ucr2); 325 326 /* 327 if (ISSET(t->c_cflag, PARENB)) { 328 SET(sc->sc_ucr2, IMXUART_CR2_PREN); 329 bus_space_write_4(iot, ioh, IMXUART_UCR2, sc->sc_ucr2); 330 } 331 */ 332 /* STOPB - XXX */ 333 if (ospeed == 0) { 334 /* lower dtr */ 335 } 336 337 if (sc->sc_clkfreq != 0 && ospeed != 0 && ospeed != tp->t_ospeed) { 338 int cr, div, lcr; 339 340 while (ISSET(tp->t_state, TS_BUSY)) { 341 ++sc->sc_halt; 342 error = ttysleep(tp, &tp->t_outq, 343 TTOPRI | PCATCH, "pluartprm"); 344 --sc->sc_halt; 345 if (error) { 346 pluart_start(tp); 347 return (error); 348 } 349 } 350 351 /* 352 * Writes to IBRD and FBRD are made effective first when LCR_H 353 * is written. 354 */ 355 lcr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, UART_LCR_H); 356 357 /* The UART must be disabled while changing the baud rate. */ 358 cr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, UART_CR); 359 bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_CR, 360 cr & ~UART_CR_UARTEN); 361 362 /* 363 * The baud rate divisor is expressed relative to the UART clock 364 * frequency where IBRD represents the quotient using 16 bits 365 * and FBRD the remainder using 6 bits. The PL011 specification 366 * provides the following formula: 367 * 368 * uartclk/(16 * baudrate) 369 * 370 * The formula can be estimated by scaling it with the 371 * precision 64 (2^6) and letting the resulting upper 16 bits 372 * represents the quotient and the lower 6 bits the remainder: 373 * 374 * 64 * uartclk/(16 * baudrate) = 4 * uartclk/baudrate 375 */ 376 div = 4 * sc->sc_clkfreq / ospeed; 377 bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_IBRD, 378 UART_IBRD_DIVINT(div >> 6)); 379 bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_FBRD, 380 UART_FBRD_DIVFRAC(div)); 381 /* Commit baud rate change. */ 382 bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_LCR_H, lcr); 383 /* Enable UART. */ 384 bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_CR, cr); 385 } 386 387 /* setup fifo */ 388 389 /* When not using CRTSCTS, RTS follows DTR. */ 390 /* sc->sc_dtr = MCR_DTR; */ 391 392 /* and copy to tty */ 393 tp->t_ispeed = t->c_ispeed; 394 tp->t_ospeed = t->c_ospeed; 395 oldcflag = tp->t_cflag; 396 tp->t_cflag = t->c_cflag; 397 398 /* 399 * If DCD is off and MDMBUF is changed, ask the tty layer if we should 400 * stop the device. 401 */ 402 /* XXX */ 403 404 pluart_start(tp); 405 406 return 0; 407} 408 409void 410pluart_start(struct tty *tp) 411{ 412 struct pluart_softc *sc = pluart_cd.cd_devs[DEVUNIT(tp->t_dev)]; 413 bus_space_tag_t iot = sc->sc_iot; 414 bus_space_handle_t ioh = sc->sc_ioh; 415 int s; 416 417 s = spltty(); 418 if (ISSET(tp->t_state, TS_BUSY)) 419 goto out; 420 if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP)) 421 goto stopped; 422 ttwakeupwr(tp); 423 if (tp->t_outq.c_cc == 0) 424 goto stopped; 425 SET(tp->t_state, TS_BUSY); 426 427 /* Enable transmit interrupt. */ 428 if (!ISSET(sc->sc_imsc, UART_IMSC_TXIM)) { 429 sc->sc_imsc |= UART_IMSC_TXIM; 430 bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_IMSC, 431 sc->sc_imsc); 432 } 433 434 while (tp->t_outq.c_cc > 0) { 435 uint16_t fr; 436 437 fr = bus_space_read_4(iot, ioh, UART_FR); 438 if (ISSET(fr, UART_FR_TXFF)) 439 break; 440 441 bus_space_write_4(iot, ioh, UART_DR, getc(&tp->t_outq)); 442 } 443 444out: 445 splx(s); 446 return; 447 448stopped: 449 /* Disable transmit interrupt. */ 450 if (ISSET(sc->sc_imsc, UART_IMSC_TXIM)) { 451 sc->sc_imsc &= ~UART_IMSC_TXIM; 452 bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_IMSC, 453 sc->sc_imsc); 454 } 455 splx(s); 456} 457 458void 459pluart_diag(void *arg) 460{ 461 struct pluart_softc *sc = arg; 462 int overflows, floods; 463 int s; 464 465 s = spltty(); 466 sc->sc_errors = 0; 467 overflows = sc->sc_overflows; 468 sc->sc_overflows = 0; 469 floods = sc->sc_floods; 470 sc->sc_floods = 0; 471 splx(s); 472 log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s\n", 473 sc->sc_dev.dv_xname, 474 overflows, overflows == 1 ? "" : "s", 475 floods, floods == 1 ? "" : "s"); 476} 477 478void 479pluart_raisedtr(void *arg) 480{ 481 //struct pluart_softc *sc = arg; 482 483 //SET(sc->sc_ucr3, IMXUART_CR3_DSR); /* XXX */ 484 //bus_space_write_4(sc->sc_iot, sc->sc_ioh, IMXUART_UCR3, sc->sc_ucr3); 485} 486 487void 488pluart_softint(void *arg) 489{ 490 struct pluart_softc *sc = arg; 491 struct tty *tp; 492 u_int16_t *ibufp; 493 u_int16_t *ibufend; 494 int c; 495 int err; 496 int s; 497 498 if (sc == NULL || sc->sc_ibufp == sc->sc_ibuf) 499 return; 500 501 tp = sc->sc_tty; 502 s = spltty(); 503 504 ibufp = sc->sc_ibuf; 505 ibufend = sc->sc_ibufp; 506 507 if (ibufp == ibufend || tp == NULL || !ISSET(tp->t_state, TS_ISOPEN)) { 508 splx(s); 509 return; 510 } 511 512 sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ? 513 sc->sc_ibufs[1] : sc->sc_ibufs[0]; 514 sc->sc_ibufhigh = sc->sc_ibuf + UART_IHIGHWATER; 515 sc->sc_ibufend = sc->sc_ibuf + UART_IBUFSIZE; 516 517#if 0 518 if (ISSET(tp->t_cflag, CRTSCTS) && 519 !ISSET(sc->sc_ucr3, IMXUART_CR3_DSR)) { 520 /* XXX */ 521 SET(sc->sc_ucr3, IMXUART_CR3_DSR); 522 bus_space_write_4(sc->sc_iot, sc->sc_ioh, IMXUART_UCR3, 523 sc->sc_ucr3); 524 } 525#endif 526 527 splx(s); 528 529 while (ibufp < ibufend) { 530 c = *ibufp++; 531 /* 532 if (ISSET(c, IMXUART_RX_OVERRUN)) { 533 sc->sc_overflows++; 534 if (sc->sc_errors++ == 0) 535 timeout_add_sec(&sc->sc_diag_tmo, 60); 536 } 537 */ 538 /* This is ugly, but fast. */ 539 540 err = 0; 541 /* 542 if (ISSET(c, IMXUART_RX_PRERR)) 543 err |= TTY_PE; 544 if (ISSET(c, IMXUART_RX_FRMERR)) 545 err |= TTY_FE; 546 */ 547 c = (c & 0xff) | err; 548 (*linesw[tp->t_line].l_rint)(c, tp); 549 } 550} 551 552int 553pluartopen(dev_t dev, int flag, int mode, struct proc *p) 554{ 555 int unit = DEVUNIT(dev); 556 struct pluart_softc *sc; 557 bus_space_tag_t iot; 558 bus_space_handle_t ioh; 559 struct tty *tp; 560 int s; 561 int error = 0; 562 563 if (unit >= pluart_cd.cd_ndevs) 564 return ENXIO; 565 sc = pluart_cd.cd_devs[unit]; 566 if (sc == NULL) 567 return ENXIO; 568 569 s = spltty(); 570 if (sc->sc_tty == NULL) 571 tp = sc->sc_tty = ttymalloc(0); 572 else 573 tp = sc->sc_tty; 574 575 splx(s); 576 577 tp->t_oproc = pluart_start; 578 tp->t_param = pluart_param; 579 tp->t_dev = dev; 580 581 if (!ISSET(tp->t_state, TS_ISOPEN)) { 582 SET(tp->t_state, TS_WOPEN); 583 ttychars(tp); 584 tp->t_iflag = TTYDEF_IFLAG; 585 tp->t_oflag = TTYDEF_OFLAG; 586 587 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) 588 tp->t_cflag = pluartconscflag; 589 else 590 tp->t_cflag = TTYDEF_CFLAG; 591 if (ISSET(sc->sc_swflags, COM_SW_CLOCAL)) 592 SET(tp->t_cflag, CLOCAL); 593 if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS)) 594 SET(tp->t_cflag, CRTSCTS); 595 if (ISSET(sc->sc_swflags, COM_SW_MDMBUF)) 596 SET(tp->t_cflag, MDMBUF); 597 tp->t_lflag = TTYDEF_LFLAG; 598 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) 599 tp->t_ispeed = tp->t_ospeed = pluartconsrate; 600 else 601 tp->t_ispeed = tp->t_ospeed = pluartdefaultrate; 602 603 s = spltty(); 604 605 sc->sc_initialize = 1; 606 pluart_param(tp, &tp->t_termios); 607 ttsetwater(tp); 608 sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0]; 609 sc->sc_ibufhigh = sc->sc_ibuf + UART_IHIGHWATER; 610 sc->sc_ibufend = sc->sc_ibuf + UART_IBUFSIZE; 611 612 iot = sc->sc_iot; 613 ioh = sc->sc_ioh; 614 615#if 0 616 sc->sc_ucr1 = bus_space_read_4(iot, ioh, IMXUART_UCR1); 617 sc->sc_ucr2 = bus_space_read_4(iot, ioh, IMXUART_UCR2); 618 sc->sc_ucr3 = bus_space_read_4(iot, ioh, IMXUART_UCR3); 619 sc->sc_ucr4 = bus_space_read_4(iot, ioh, IMXUART_UCR4); 620 621 /* interrupt after one char on tx/rx */ 622 /* reference frequency divider: 1 */ 623 bus_space_write_4(iot, ioh, IMXUART_UFCR, 624 1 << IMXUART_FCR_TXTL_SH | 625 5 << IMXUART_FCR_RFDIV_SH | 626 1 << IMXUART_FCR_RXTL_SH); 627 628 SET(sc->sc_ucr1, IMXUART_CR1_EN|IMXUART_CR1_RRDYEN); 629 SET(sc->sc_ucr2, IMXUART_CR2_TXEN|IMXUART_CR2_RXEN); 630 bus_space_write_4(iot, ioh, IMXUART_UCR1, sc->sc_ucr1); 631 bus_space_write_4(iot, ioh, IMXUART_UCR2, sc->sc_ucr2); 632 633 /* sc->sc_mcr = MCR_DTR | MCR_RTS; XXX */ 634 SET(sc->sc_ucr3, IMXUART_CR3_DSR); /* XXX */ 635 bus_space_write_4(iot, ioh, IMXUART_UCR3, sc->sc_ucr3); 636#endif 637 638 SET(tp->t_state, TS_CARR_ON); /* XXX */ 639 640 641 } else if (ISSET(tp->t_state, TS_XCLUDE) && suser(p) != 0) 642 return EBUSY; 643 else 644 s = spltty(); 645 646 if (DEVCUA(dev)) { 647 if (ISSET(tp->t_state, TS_ISOPEN)) { 648 splx(s); 649 return EBUSY; 650 } 651 sc->sc_cua = 1; 652 } else { 653 /* tty (not cua) device; wait for carrier if necessary */ 654 if (ISSET(flag, O_NONBLOCK)) { 655 if (sc->sc_cua) { 656 /* Opening TTY non-blocking... but the CUA is busy */ 657 splx(s); 658 return EBUSY; 659 } 660 } else { 661 while (sc->sc_cua || 662 (!ISSET(tp->t_cflag, CLOCAL) && 663 !ISSET(tp->t_state, TS_CARR_ON))) { 664 SET(tp->t_state, TS_WOPEN); 665 error = ttysleep(tp, &tp->t_rawq, 666 TTIPRI | PCATCH, ttopen); 667 /* 668 * If TS_WOPEN has been reset, that means the 669 * cua device has been closed. We don't want 670 * to fail in that case, 671 * so just go around again. 672 */ 673 if (error && ISSET(tp->t_state, TS_WOPEN)) { 674 CLR(tp->t_state, TS_WOPEN); 675 splx(s); 676 return error; 677 } 678 } 679 } 680 } 681 splx(s); 682 return (*linesw[tp->t_line].l_open)(dev,tp,p); 683} 684 685int 686pluartclose(dev_t dev, int flag, int mode, struct proc *p) 687{ 688 int unit = DEVUNIT(dev); 689 struct pluart_softc *sc = pluart_cd.cd_devs[unit]; 690 //bus_space_tag_t iot = sc->sc_iot; 691 //bus_space_handle_t ioh = sc->sc_ioh; 692 struct tty *tp = sc->sc_tty; 693 int s; 694 695 /* XXX This is for cons.c. */ 696 if (!ISSET(tp->t_state, TS_ISOPEN)) 697 return 0; 698 699 (*linesw[tp->t_line].l_close)(tp, flag, p); 700 s = spltty(); 701 if (ISSET(tp->t_state, TS_WOPEN)) { 702 /* tty device is waiting for carrier; drop dtr then re-raise */ 703 //CLR(sc->sc_ucr3, IMXUART_CR3_DSR); 704 //bus_space_write_4(iot, ioh, IMXUART_UCR3, sc->sc_ucr3); 705 timeout_add_sec(&sc->sc_dtr_tmo, 2); 706 } 707 CLR(tp->t_state, TS_BUSY | TS_FLUSH); 708 709 sc->sc_cua = 0; 710 splx(s); 711 ttyclose(tp); 712 713 return 0; 714} 715 716int 717pluartread(dev_t dev, struct uio *uio, int flag) 718{ 719 struct tty *tty; 720 721 tty = pluarttty(dev); 722 if (tty == NULL) 723 return ENODEV; 724 725 return((*linesw[tty->t_line].l_read)(tty, uio, flag)); 726} 727 728int 729pluartwrite(dev_t dev, struct uio *uio, int flag) 730{ 731 struct tty *tty; 732 733 tty = pluarttty(dev); 734 if (tty == NULL) 735 return ENODEV; 736 737 return((*linesw[tty->t_line].l_write)(tty, uio, flag)); 738} 739 740int 741pluartioctl( dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 742{ 743 struct pluart_softc *sc; 744 struct tty *tp; 745 int error; 746 747 sc = pluart_sc(dev); 748 if (sc == NULL) 749 return (ENODEV); 750 751 tp = sc->sc_tty; 752 if (tp == NULL) 753 return (ENXIO); 754 755 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 756 if (error >= 0) 757 return (error); 758 759 error = ttioctl(tp, cmd, data, flag, p); 760 if (error >= 0) 761 return (error); 762 763 switch(cmd) { 764 case TIOCSBRK: 765 break; 766 case TIOCCBRK: 767 break; 768 case TIOCSDTR: 769 break; 770 case TIOCCDTR: 771 break; 772 case TIOCMSET: 773 break; 774 case TIOCMBIS: 775 break; 776 case TIOCMBIC: 777 break; 778 case TIOCMGET: 779 break; 780 case TIOCGFLAGS: 781 break; 782 case TIOCSFLAGS: 783 error = suser(p); 784 if (error != 0) 785 return(EPERM); 786 break; 787 default: 788 return (ENOTTY); 789 } 790 791 return 0; 792} 793 794int 795pluartstop(struct tty *tp, int flag) 796{ 797 return 0; 798} 799 800struct tty * 801pluarttty(dev_t dev) 802{ 803 int unit; 804 struct pluart_softc *sc; 805 unit = DEVUNIT(dev); 806 if (unit >= pluart_cd.cd_ndevs) 807 return NULL; 808 sc = (struct pluart_softc *)pluart_cd.cd_devs[unit]; 809 if (sc == NULL) 810 return NULL; 811 return sc->sc_tty; 812} 813 814struct pluart_softc * 815pluart_sc(dev_t dev) 816{ 817 int unit; 818 struct pluart_softc *sc; 819 unit = DEVUNIT(dev); 820 if (unit >= pluart_cd.cd_ndevs) 821 return NULL; 822 sc = (struct pluart_softc *)pluart_cd.cd_devs[unit]; 823 return sc; 824} 825 826 827/* serial console */ 828void 829pluartcnprobe(struct consdev *cp) 830{ 831} 832 833void 834pluartcninit(struct consdev *cp) 835{ 836} 837 838int 839pluartcnattach(bus_space_tag_t iot, bus_addr_t iobase, int rate, tcflag_t cflag) 840{ 841 static struct consdev pluartcons = { 842 NULL, NULL, pluartcngetc, pluartcnputc, pluartcnpollc, NULL, 843 NODEV, CN_MIDPRI 844 }; 845 int maj; 846 847 if (bus_space_map(iot, iobase, UART_SPACE, 0, &pluartconsioh)) 848 return ENOMEM; 849 850 /* Disable FIFO. */ 851 bus_space_write_4(iot, pluartconsioh, UART_LCR_H, 852 bus_space_read_4(iot, pluartconsioh, UART_LCR_H) & ~UART_LCR_H_FEN); 853 854 /* Look for major of com(4) to replace. */ 855 for (maj = 0; maj < nchrdev; maj++) 856 if (cdevsw[maj].d_open == comopen) 857 break; 858 if (maj == nchrdev) 859 return ENXIO; 860 861 cn_tab = &pluartcons; 862 cn_tab->cn_dev = makedev(maj, 0); 863 cdevsw[maj] = pluartdev; /* KLUDGE */ 864 865 pluartconsiot = iot; 866 pluartconsaddr = iobase; 867 pluartconscflag = cflag; 868 pluartconsrate = rate; 869 870 return 0; 871} 872 873int 874pluartcngetc(dev_t dev) 875{ 876 int c; 877 int s; 878 s = splhigh(); 879 while ((bus_space_read_4(pluartconsiot, pluartconsioh, UART_FR) & 880 UART_FR_RXFE)) 881 ; 882 c = bus_space_read_4(pluartconsiot, pluartconsioh, UART_DR); 883 splx(s); 884 return c; 885} 886 887void 888pluartcnputc(dev_t dev, int c) 889{ 890 int s; 891 s = splhigh(); 892 while ((bus_space_read_4(pluartconsiot, pluartconsioh, UART_FR) & 893 UART_FR_TXFF)) 894 ; 895 bus_space_write_4(pluartconsiot, pluartconsioh, UART_DR, (uint8_t)c); 896 splx(s); 897} 898 899void 900pluartcnpollc(dev_t dev, int on) 901{ 902}