On Sun, Jul 01, 2018 at 04:38:35PM +0200, Mark Kettenis wrote: > Since the ARM SBSA Generic UART is effectively a PL011 UART, the > expectation is that most arm64 servers will actually have pluart(4) as > their serial console instead of com(4). So we need a glue for > acpi(4). This provides that glue and moves the shared code from > dev/fdt to dev/ic. > > ok? >
ok mlarkin. > P.S. This driver needs some cleanup. But that should be done separately. > Yeah, you're not kidding there... > > Index: conf/files > =================================================================== > RCS file: /cvs/src/sys/conf/files,v > retrieving revision 1.661 > diff -u -p -r1.661 files > --- conf/files 20 Apr 2018 04:37:21 -0000 1.661 > +++ conf/files 1 Jul 2018 14:29:40 -0000 > @@ -324,6 +324,10 @@ device com: tty > file dev/ic/com.c com & (com | com_cardbus | com_gsc | > com_isapnp) needs-flag > > +# ARM PrimeCell PL011 UART > +device pluart: tty > +file dev/ic/pluart.c pluart > + > # PC-like keyboard controller > define pckbcslot {[slot = -1]} > device pckbc: pckbcslot > Index: dev/acpi/files.acpi > =================================================================== > RCS file: /cvs/src/sys/dev/acpi/files.acpi,v > retrieving revision 1.45 > diff -u -p -r1.45 files.acpi > --- dev/acpi/files.acpi 1 Jul 2018 10:29:30 -0000 1.45 > +++ dev/acpi/files.acpi 1 Jul 2018 14:29:40 -0000 > @@ -137,9 +137,17 @@ device ccpmic > attach ccpmic at i2c > file dev/acpi/ccpmic.c ccpmic > > # NS16550 compatible UART > attach com at acpi with com_acpi > file dev/acpi/com_acpi.c com_acpi > + > +# PL011 UART > +attach pluart at acpi with pluart_acpi > +file dev/acpi/pluart_acpi.c pluart_acpi > > # SD Host Controller > attach sdhc at acpi with sdhc_acpi > Index: dev/acpi/pluart_acpi.c > =================================================================== > RCS file: dev/acpi/pluart_acpi.c > diff -N dev/acpi/pluart_acpi.c > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ dev/acpi/pluart_acpi.c 1 Jul 2018 14:29:40 -0000 > @@ -0,0 +1,153 @@ > +/* $OpenBSD$ */ > +/* > + * Copyright (c) 2018 Mark Kettenis > + * > + * Permission to use, copy, modify, and distribute this software for any > + * purpose with or without fee is hereby granted, provided that the above > + * copyright notice and this permission notice appear in all copies. > + * > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > + */ > + > +#include <sys/param.h> > +#include <sys/malloc.h> > +#include <sys/systm.h> > +#include <sys/tty.h> > + > +#include <dev/acpi/acpireg.h> > +#include <dev/acpi/acpivar.h> > +#include <dev/acpi/acpidev.h> > +#include <dev/acpi/amltypes.h> > +#include <dev/acpi/dsdt.h> > + > +#undef DEVNAME > +#include <dev/fdt/pluartvar.h> > +#include <dev/cons.h> > + > +struct pluart_acpi_softc { > + struct pluart_softc sc; > + struct acpi_softc *sc_acpi; > + struct aml_node *sc_node; > + > + bus_addr_t sc_addr; > + bus_size_t sc_size; > + > + int sc_irq; > + int sc_irq_flags; > + void *sc_ih; > +}; > + > +int pluart_acpi_match(struct device *, void *, void *); > +void pluart_acpi_attach(struct device *, struct device *, void *); > + > +struct cfattach pluart_acpi_ca = { > + sizeof(struct pluart_acpi_softc), pluart_acpi_match, pluart_acpi_attach > +}; > + > +const char *pluart_hids[] = { > + "AMDI0511", > + NULL > +}; > + > +int pluart_acpi_parse_resources(int, union acpi_resource *, void *); > +int pluart_acpi_is_console(struct pluart_acpi_softc *); > + > +int > +pluart_acpi_match(struct device *parent, void *match, void *aux) > +{ > + struct acpi_attach_args *aaa = aux; > + struct cfdata *cf = match; > + > + return acpi_matchhids(aaa, pluart_hids, cf->cf_driver->cd_name); > +} > + > +void > +pluart_acpi_attach(struct device *parent, struct device *self, void *aux) > +{ > + struct acpi_attach_args *aaa = aux; > + struct pluart_acpi_softc *sc = (struct pluart_acpi_softc *)self; > + struct aml_value res; > + > + sc->sc_acpi = (struct acpi_softc *)parent; > + sc->sc_node = aaa->aaa_node; > + printf(" %s", sc->sc_node->name); > + > + if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, &res)) { > + printf(": can't find registers\n"); > + return; > + } > + > + aml_parse_resource(&res, pluart_acpi_parse_resources, sc); > + printf(" addr 0x%lx/0x%lx", sc->sc_addr, sc->sc_size); > + if (sc->sc_addr == 0 || sc->sc_size == 0) { > + printf("\n"); > + return; > + } > + > + printf(" irq %d", sc->sc_irq); > + > + sc->sc.sc_iot = aaa->aaa_memt; > + if (bus_space_map(sc->sc.sc_iot, sc->sc_addr, sc->sc_size, 0, > + &sc->sc.sc_ioh)) { > + printf(": can't map registers\n"); > + return; > + } > + > + sc->sc_ih = acpi_intr_establish(sc->sc_irq, sc->sc_irq_flags, IPL_TTY, > + pluart_intr, sc, sc->sc.sc_dev.dv_xname); > + if (sc->sc_ih == NULL) { > + printf(": can't establish interrupt\n"); > + return; > + } > + > + pluart_attach_common(&sc->sc, pluart_acpi_is_console(sc)); > +} > + > +int > +pluart_acpi_parse_resources(int crsidx, union acpi_resource *crs, void *arg) > +{ > + struct pluart_acpi_softc *sc = arg; > + int type = AML_CRSTYPE(crs); > + > + switch (type) { > + case LR_MEM32FIXED: > + sc->sc_addr = crs->lr_m32fixed._bas; > + sc->sc_size = crs->lr_m32fixed._len; > + break; > + case LR_EXTIRQ: > + sc->sc_irq = crs->lr_extirq.irq[0]; > + sc->sc_irq_flags = crs->lr_extirq.flags; > + break; > + } > + > + return 0; > +} > + > +int > +pluart_acpi_is_console(struct pluart_acpi_softc *sc) > +{ > + struct acpi_table_header *hdr; > + struct acpi_spcr *spcr; > + struct acpi_gas *base; > + struct acpi_q *entry; > + > + SIMPLEQ_FOREACH(entry, &sc->sc_acpi->sc_tables, q_next) { > + hdr = entry->q_table; > + if (strncmp(hdr->signature, SPCR_SIG, > + sizeof(hdr->signature)) == 0) { > + spcr = entry->q_table; > + base = &spcr->base_address; > + if (base->address_space_id == GAS_SYSTEM_MEMORY && > + base->address == sc->sc_addr) > + return 1; > + } > + } > + > + return 0; > +} > Index: dev/fdt/files.fdt > =================================================================== > RCS file: /cvs/src/sys/dev/fdt/files.fdt,v > retrieving revision 1.64 > diff -u -p -r1.64 files.fdt > --- dev/fdt/files.fdt 16 Jun 2018 14:11:35 -0000 1.64 > +++ dev/fdt/files.fdt 1 Jul 2018 14:29:40 -0000 > @@ -79,9 +79,8 @@ attach plrtc at fdt > file dev/fdt/plrtc.c plrtc > > # ARM PrimeCell PL011 UART > -device pluart > -attach pluart at fdt > -file dev/fdt/pluart.c pluart > +attach pluart at fdt with pluart_fdt > +file dev/fdt/pluart_fdt.c pluart_fdt > > # ARM Power State Coordination Interface > device psci > Index: dev/fdt/pluart.c > =================================================================== > RCS file: dev/fdt/pluart.c > diff -N dev/fdt/pluart.c > --- dev/fdt/pluart.c 5 Jun 2018 20:41:19 -0000 1.1 > +++ /dev/null 1 Jan 1970 00:00:00 -0000 > @@ -1,912 +0,0 @@ > -/* $OpenBSD: pluart.c,v 1.1 2018/06/05 20:41:19 kettenis Exp $ */ > - > -/* > - * Copyright (c) 2014 Patrick Wildt <patr...@blueri.se> > - * Copyright (c) 2005 Dale Rahn <dr...@dalerahn.com> > - * > - * Permission to use, copy, modify, and distribute this software for any > - * purpose with or without fee is hereby granted, provided that the above > - * copyright notice and this permission notice appear in all copies. > - * > - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > - */ > - > -#include <sys/param.h> > -#include <sys/ioctl.h> > -#include <sys/proc.h> > -#include <sys/tty.h> > -#include <sys/uio.h> > -#include <sys/systm.h> > -#include <sys/time.h> > -#include <sys/device.h> > -#include <sys/syslog.h> > -#include <sys/conf.h> > -#include <sys/fcntl.h> > -#include <sys/select.h> > -#include <sys/kernel.h> > - > -#include <machine/bus.h> > -#include <machine/fdt.h> > - > -#include <dev/cons.h> > - > -#ifdef DDB > -#include <ddb/db_var.h> > -#endif > - > -#include <dev/ofw/fdt.h> > -#include <dev/ofw/openfirm.h> > - > -#define DEVUNIT(x) (minor(x) & 0x7f) > -#define DEVCUA(x) (minor(x) & 0x80) > - > -#define UART_DR 0x00 /* Data register */ > -#define UART_DR_DATA(x) ((x) & 0xf) > -#define UART_DR_FE (1 << 8) /* Framing error */ > -#define UART_DR_PE (1 << 9) /* Parity error */ > -#define UART_DR_BE (1 << 10) /* Break error */ > -#define UART_DR_OE (1 << 11) /* Overrun error */ > -#define UART_RSR 0x04 /* Receive status register */ > -#define UART_RSR_FE (1 << 0) /* Framing error */ > -#define UART_RSR_PE (1 << 1) /* Parity error */ > -#define UART_RSR_BE (1 << 2) /* Break error */ > -#define UART_RSR_OE (1 << 3) /* Overrun error */ > -#define UART_ECR 0x04 /* Error clear register */ > -#define UART_ECR_FE (1 << 0) /* Framing error */ > -#define UART_ECR_PE (1 << 1) /* Parity error */ > -#define UART_ECR_BE (1 << 2) /* Break error */ > -#define UART_ECR_OE (1 << 3) /* Overrun error */ > -#define UART_FR 0x18 /* Flag register */ > -#define UART_FR_CTS (1 << 0) /* Clear to send */ > -#define UART_FR_DSR (1 << 1) /* Data set ready */ > -#define UART_FR_DCD (1 << 2) /* Data carrier detect */ > -#define UART_FR_BUSY (1 << 3) /* UART busy */ > -#define UART_FR_RXFE (1 << 4) /* Receive FIFO empty */ > -#define UART_FR_TXFF (1 << 5) /* Transmit FIFO full */ > -#define UART_FR_RXFF (1 << 6) /* Receive FIFO full */ > -#define UART_FR_TXFE (1 << 7) /* Transmit FIFO empty */ > -#define UART_FR_RI (1 << 8) /* Ring indicator */ > -#define UART_ILPR 0x20 /* IrDA low-power counter > register */ > -#define UART_ILPR_ILPDVSR ((x) & 0xf) /* IrDA low-power divisor */ > -#define UART_IBRD 0x24 /* Integer baud rate register */ > -#define UART_IBRD_DIVINT ((x) & 0xff) /* Integer baud rate divisor */ > -#define UART_FBRD 0x28 /* Fractional baud rate > register */ > -#define UART_FBRD_DIVFRAC ((x) & 0x3f) /* Fractional baud rate divisor > */ > -#define UART_LCR_H 0x2c /* Line control register */ > -#define UART_LCR_H_BRK (1 << 0) /* Send break */ > -#define UART_LCR_H_PEN (1 << 1) /* Parity enable */ > -#define UART_LCR_H_EPS (1 << 2) /* Even parity select */ > -#define UART_LCR_H_STP2 (1 << 3) /* Two stop bits select > */ > -#define UART_LCR_H_FEN (1 << 4) /* Enable FIFOs */ > -#define UART_LCR_H_WLEN5 (0x0 << 5) /* Word length: 5 bits */ > -#define UART_LCR_H_WLEN6 (0x1 << 5) /* Word length: 6 bits */ > -#define UART_LCR_H_WLEN7 (0x2 << 5) /* Word length: 7 bits */ > -#define UART_LCR_H_WLEN8 (0x3 << 5) /* Word length: 8 bits */ > -#define UART_LCR_H_SPS (1 << 7) /* Stick parity select > */ > -#define UART_CR 0x30 /* Control register */ > -#define UART_CR_UARTEN (1 << 0) /* UART enable */ > -#define UART_CR_SIREN (1 << 1) /* SIR enable */ > -#define UART_CR_SIRLP (1 << 2) /* IrDA SIR low power > mode */ > -#define UART_CR_LBE (1 << 7) /* Loop back enable */ > -#define UART_CR_TXE (1 << 8) /* Transmit enable */ > -#define UART_CR_RXE (1 << 9) /* Receive enable */ > -#define UART_CR_DTR (1 << 10) /* Data transmit enable */ > -#define UART_CR_RTS (1 << 11) /* Request to send */ > -#define UART_CR_OUT1 (1 << 12) > -#define UART_CR_OUT2 (1 << 13) > -#define UART_CR_CTSE (1 << 14) /* CTS hardware flow control > enable */ > -#define UART_CR_RTSE (1 << 15) /* RTS hardware flow control > enable */ > -#define UART_IFLS 0x34 /* Interrupt FIFO level select > register */ > -#define UART_IMSC 0x38 /* Interrupt mask set/clear > register */ > -#define UART_IMSC_RIMIM (1 << 0) > -#define UART_IMSC_CTSMIM (1 << 1) > -#define UART_IMSC_DCDMIM (1 << 2) > -#define UART_IMSC_DSRMIM (1 << 3) > -#define UART_IMSC_RXIM (1 << 4) > -#define UART_IMSC_TXIM (1 << 5) > -#define UART_IMSC_RTIM (1 << 6) > -#define UART_IMSC_FEIM (1 << 7) > -#define UART_IMSC_PEIM (1 << 8) > -#define UART_IMSC_BEIM (1 << 9) > -#define UART_IMSC_OEIM (1 << 10) > -#define UART_RIS 0x3c /* Raw interrupt status > register */ > -#define UART_MIS 0x40 /* Masked interrupt status > register */ > -#define UART_ICR 0x44 /* Interrupt clear register */ > -#define UART_DMACR 0x48 /* DMA control register */ > -#define UART_SPACE 0x100 > - > -struct pluart_softc { > - struct device sc_dev; > - bus_space_tag_t sc_iot; > - bus_space_handle_t sc_ioh; > - struct soft_intrhand *sc_si; > - void *sc_irq; > - struct tty *sc_tty; > - struct timeout sc_diag_tmo; > - struct timeout sc_dtr_tmo; > - int sc_overflows; > - int sc_floods; > - int sc_errors; > - int sc_halt; > - u_int16_t sc_ucr1; > - u_int16_t sc_ucr2; > - u_int16_t sc_ucr3; > - u_int16_t sc_ucr4; > - u_int8_t sc_hwflags; > -#define COM_HW_NOIEN 0x01 > -#define COM_HW_FIFO 0x02 > -#define COM_HW_SIR 0x20 > -#define COM_HW_CONSOLE 0x40 > - u_int8_t sc_swflags; > -#define COM_SW_SOFTCAR 0x01 > -#define COM_SW_CLOCAL 0x02 > -#define COM_SW_CRTSCTS 0x04 > -#define COM_SW_MDMBUF 0x08 > -#define COM_SW_PPS 0x10 > - int sc_fifolen; > - > - u_int8_t sc_initialize; > - u_int8_t sc_cua; > - u_int16_t *sc_ibuf, *sc_ibufp, *sc_ibufhigh, *sc_ibufend; > -#define UART_IBUFSIZE 128 > -#define UART_IHIGHWATER 100 > - u_int16_t sc_ibufs[2][UART_IBUFSIZE]; > - > - struct clk *sc_clk; > -}; > - > -int pluartprobe(struct device *parent, void *self, void *aux); > -void pluartattach(struct device *parent, struct device *self, void *aux); > - > -void pluartcnprobe(struct consdev *cp); > -void pluartcninit(struct consdev *cp); > -int pluartcnattach(bus_space_tag_t iot, bus_addr_t iobase, int rate, > - tcflag_t cflag); > -int pluartcngetc(dev_t dev); > -void pluartcnputc(dev_t dev, int c); > -void pluartcnpollc(dev_t dev, int on); > -int pluart_param(struct tty *tp, struct termios *t); > -void pluart_start(struct tty *); > -void pluart_pwroff(struct pluart_softc *sc); > -void pluart_diag(void *arg); > -void pluart_raisedtr(void *arg); > -void pluart_softint(void *arg); > -struct pluart_softc *pluart_sc(dev_t dev); > - > -int pluart_intr(void *); > - > -/* XXX - we imitate 'com' serial ports and take over their entry points */ > -/* XXX: These belong elsewhere */ > -cdev_decl(com); > -cdev_decl(pluart); > - > -struct cfdriver pluart_cd = { > - NULL, "pluart", DV_TTY > -}; > - > -struct cfattach pluart_ca = { > - sizeof(struct pluart_softc), pluartprobe, pluartattach > -}; > - > -bus_space_tag_t pluartconsiot; > -bus_space_handle_t pluartconsioh; > -bus_addr_t pluartconsaddr; > -tcflag_t pluartconscflag = TTYDEF_CFLAG; > -int pluartdefaultrate = B38400; > - > -void > -pluart_init_cons(void) > -{ > - struct fdt_reg reg; > - void *node; > - > - if ((node = fdt_find_cons("arm,pl011")) == NULL) > - return; > - if (fdt_get_reg(node, 0, ®)) > - return; > - > - pluartcnattach(fdt_cons_bs_tag, reg.addr, B115200, TTYDEF_CFLAG); > -} > - > -int > -pluartprobe(struct device *parent, void *self, void *aux) > -{ > - struct fdt_attach_args *faa = aux; > - > - return OF_is_compatible(faa->fa_node, "arm,pl011"); > -} > - > -struct cdevsw pluartdev = > - cdev_tty_init(3/*XXX NUART */ ,pluart); /* 12: serial port */ > - > -void > -pluartattach(struct device *parent, struct device *self, void *aux) > -{ > - struct fdt_attach_args *faa = aux; > - struct pluart_softc *sc = (struct pluart_softc *) self; > - int maj; > - > - if (faa->fa_nreg < 1) { > - printf(": no register data\n"); > - return; > - } > - > - sc->sc_irq = arm_intr_establish_fdt(faa->fa_node, IPL_TTY, pluart_intr, > - sc, sc->sc_dev.dv_xname); > - > - sc->sc_iot = faa->fa_iot; > - if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, faa->fa_reg[0].size, > - 0, &sc->sc_ioh)) > - panic("pluartattach: bus_space_map failed!"); > - > - if (stdout_node == faa->fa_node) { > - /* Locate the major number. */ > - for (maj = 0; maj < nchrdev; maj++) > - if (cdevsw[maj].d_open == pluartopen) > - break; > - cn_tab->cn_dev = makedev(maj, sc->sc_dev.dv_unit); > - > - printf(": console"); > - SET(sc->sc_hwflags, COM_HW_CONSOLE); > - } > - > - timeout_set(&sc->sc_diag_tmo, pluart_diag, sc); > - timeout_set(&sc->sc_dtr_tmo, pluart_raisedtr, sc); > - sc->sc_si = softintr_establish(IPL_TTY, pluart_softint, sc); > - > - if(sc->sc_si == NULL) > - panic("%s: can't establish soft interrupt.", > - sc->sc_dev.dv_xname); > - > - bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_IMSC, (UART_IMSC_RXIM | > UART_IMSC_TXIM)); > - bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_ICR, 0x7ff); > - bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_LCR_H, > - bus_space_read_4(sc->sc_iot, sc->sc_ioh, UART_LCR_H) & > - ~UART_LCR_H_FEN); > - > - printf("\n"); > -} > - > -int > -pluart_intr(void *arg) > -{ > - struct pluart_softc *sc = arg; > - bus_space_tag_t iot = sc->sc_iot; > - bus_space_handle_t ioh = sc->sc_ioh; > - struct tty *tp = sc->sc_tty; > - u_int16_t fr; > - u_int16_t *p; > - u_int16_t c; > - > - bus_space_write_4(iot, ioh, UART_ICR, -1); > - > - if (sc->sc_tty == NULL) > - return(0); > - > - fr = bus_space_read_4(iot, ioh, UART_FR); > - if (ISSET(fr, UART_FR_TXFE) && ISSET(tp->t_state, TS_BUSY)) { > - CLR(tp->t_state, TS_BUSY | TS_FLUSH); > - if (sc->sc_halt > 0) > - wakeup(&tp->t_outq); > - (*linesw[tp->t_line].l_start)(tp); > - } > - > - if(!ISSET(bus_space_read_4(iot, ioh, UART_FR), UART_FR_RXFF)) > - return 0; > - > - p = sc->sc_ibufp; > - > - while (ISSET(bus_space_read_4(iot, ioh, UART_FR), UART_FR_RXFF)) { > - c = bus_space_read_2(iot, ioh, UART_DR); > - if (c & UART_DR_BE) { > -#ifdef DDB > - if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { > - if (db_console) > - db_enter(); > - continue; > - } > -#endif > - c = 0; > - } > - if (p >= sc->sc_ibufend) { > - sc->sc_floods++; > - if (sc->sc_errors++ == 0) > - timeout_add(&sc->sc_diag_tmo, 60 * hz); > - } else { > - *p++ = c; > - if (p == sc->sc_ibufhigh && ISSET(tp->t_cflag, > CRTSCTS)) { > - /* XXX */ > - //CLR(sc->sc_ucr3, IMXUART_CR3_DSR); > - //bus_space_write_4(iot, ioh, IMXUART_UCR3, > - // sc->sc_ucr3); > - } > - } > - /* XXX - msr stuff ? */ > - } > - sc->sc_ibufp = p; > - > - softintr_schedule(sc->sc_si); > - > - return 1; > -} > - > -int > -pluart_param(struct tty *tp, struct termios *t) > -{ > - struct pluart_softc *sc = pluart_cd.cd_devs[DEVUNIT(tp->t_dev)]; > - //bus_space_tag_t iot = sc->sc_iot; > - //bus_space_handle_t ioh = sc->sc_ioh; > - int ospeed = t->c_ospeed; > - int error; > - tcflag_t oldcflag; > - > - > - if (t->c_ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) > - return EINVAL; > - > - switch (ISSET(t->c_cflag, CSIZE)) { > - case CS5: > - return EINVAL; > - case CS6: > - return EINVAL; > - case CS7: > - //CLR(sc->sc_ucr2, IMXUART_CR2_WS); > - break; > - case CS8: > - //SET(sc->sc_ucr2, IMXUART_CR2_WS); > - break; > - } > -// bus_space_write_4(iot, ioh, IMXUART_UCR2, sc->sc_ucr2); > - > - /* > - if (ISSET(t->c_cflag, PARENB)) { > - SET(sc->sc_ucr2, IMXUART_CR2_PREN); > - bus_space_write_4(iot, ioh, IMXUART_UCR2, sc->sc_ucr2); > - } > - */ > - /* STOPB - XXX */ > - if (ospeed == 0) { > - /* lower dtr */ > - } > - > - if (ospeed != 0) { > - while (ISSET(tp->t_state, TS_BUSY)) { > - ++sc->sc_halt; > - error = ttysleep(tp, &tp->t_outq, > - TTOPRI | PCATCH, "pluartprm", 0); > - --sc->sc_halt; > - if (error) { > - pluart_start(tp); > - return (error); > - } > - } > - /* set speed */ > - } > - > - /* setup fifo */ > - > - /* When not using CRTSCTS, RTS follows DTR. */ > - /* sc->sc_dtr = MCR_DTR; */ > - > - > - /* and copy to tty */ > - tp->t_ispeed = t->c_ispeed; > - tp->t_ospeed = t->c_ospeed; > - oldcflag = tp->t_cflag; > - tp->t_cflag = t->c_cflag; > - > - /* > - * If DCD is off and MDMBUF is changed, ask the tty layer if we should > - * stop the device. > - */ > - /* XXX */ > - > - pluart_start(tp); > - > - return 0; > -} > - > -void > -pluart_start(struct tty *tp) > -{ > - struct pluart_softc *sc = pluart_cd.cd_devs[DEVUNIT(tp->t_dev)]; > - bus_space_tag_t iot = sc->sc_iot; > - bus_space_handle_t ioh = sc->sc_ioh; > - > - int s; > - s = spltty(); > - if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) > - goto out; > - if (tp->t_outq.c_cc <= tp->t_lowat) { > - if (ISSET(tp->t_state, TS_ASLEEP)) { > - CLR(tp->t_state, TS_ASLEEP); > - wakeup(&tp->t_outq); > - } > - if (tp->t_outq.c_cc == 0) > - goto out; > - selwakeup(&tp->t_wsel); > - } > - SET(tp->t_state, TS_BUSY); > - > - if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) { > - u_char buffer[64]; /* largest fifo */ > - int i, n; > - > - n = q_to_b(&tp->t_outq, buffer, > - min(sc->sc_fifolen, sizeof buffer)); > - for (i = 0; i < n; i++) { > - bus_space_write_4(iot, ioh, UART_DR, buffer[i]); > - } > - bzero(buffer, n); > - } else if (tp->t_outq.c_cc != 0) > - bus_space_write_4(iot, ioh, UART_DR, getc(&tp->t_outq)); > - > -out: > - splx(s); > -} > - > -void > -pluart_pwroff(struct pluart_softc *sc) > -{ > -} > - > -void > -pluart_diag(void *arg) > -{ > - struct pluart_softc *sc = arg; > - int overflows, floods; > - int s; > - > - s = spltty(); > - sc->sc_errors = 0; > - overflows = sc->sc_overflows; > - sc->sc_overflows = 0; > - floods = sc->sc_floods; > - sc->sc_floods = 0; > - splx(s); > - log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s\n", > - sc->sc_dev.dv_xname, > - overflows, overflows == 1 ? "" : "s", > - floods, floods == 1 ? "" : "s"); > -} > - > -void > -pluart_raisedtr(void *arg) > -{ > - //struct pluart_softc *sc = arg; > - > - //SET(sc->sc_ucr3, IMXUART_CR3_DSR); /* XXX */ > - //bus_space_write_4(sc->sc_iot, sc->sc_ioh, IMXUART_UCR3, sc->sc_ucr3); > -} > - > -void > -pluart_softint(void *arg) > -{ > - struct pluart_softc *sc = arg; > - struct tty *tp; > - u_int16_t *ibufp; > - u_int16_t *ibufend; > - int c; > - int err; > - int s; > - > - if (sc == NULL || sc->sc_ibufp == sc->sc_ibuf) > - return; > - > - tp = sc->sc_tty; > - s = spltty(); > - > - ibufp = sc->sc_ibuf; > - ibufend = sc->sc_ibufp; > - > - if (ibufp == ibufend || tp == NULL || !ISSET(tp->t_state, TS_ISOPEN)) { > - splx(s); > - return; > - } > - > - sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ? > - sc->sc_ibufs[1] : sc->sc_ibufs[0]; > - sc->sc_ibufhigh = sc->sc_ibuf + UART_IHIGHWATER; > - sc->sc_ibufend = sc->sc_ibuf + UART_IBUFSIZE; > - > -#if 0 > - if (ISSET(tp->t_cflag, CRTSCTS) && > - !ISSET(sc->sc_ucr3, IMXUART_CR3_DSR)) { > - /* XXX */ > - SET(sc->sc_ucr3, IMXUART_CR3_DSR); > - bus_space_write_4(sc->sc_iot, sc->sc_ioh, IMXUART_UCR3, > - sc->sc_ucr3); > - } > -#endif > - > - splx(s); > - > - while (ibufp < ibufend) { > - c = *ibufp++; > - /* > - if (ISSET(c, IMXUART_RX_OVERRUN)) { > - sc->sc_overflows++; > - if (sc->sc_errors++ == 0) > - timeout_add(&sc->sc_diag_tmo, 60 * hz); > - } > - */ > - /* This is ugly, but fast. */ > - > - err = 0; > - /* > - if (ISSET(c, IMXUART_RX_PRERR)) > - err |= TTY_PE; > - if (ISSET(c, IMXUART_RX_FRMERR)) > - err |= TTY_FE; > - */ > - c = (c & 0xff) | err; > - (*linesw[tp->t_line].l_rint)(c, tp); > - } > -} > - > -int > -pluartopen(dev_t dev, int flag, int mode, struct proc *p) > -{ > - int unit = DEVUNIT(dev); > - struct pluart_softc *sc; > - bus_space_tag_t iot; > - bus_space_handle_t ioh; > - struct tty *tp; > - int s; > - int error = 0; > - > - if (unit >= pluart_cd.cd_ndevs) > - return ENXIO; > - sc = pluart_cd.cd_devs[unit]; > - if (sc == NULL) > - return ENXIO; > - > - s = spltty(); > - if (sc->sc_tty == NULL) > - tp = sc->sc_tty = ttymalloc(0); > - else > - tp = sc->sc_tty; > - > - splx(s); > - > - tp->t_oproc = pluart_start; > - tp->t_param = pluart_param; > - tp->t_dev = dev; > - > - if (!ISSET(tp->t_state, TS_ISOPEN)) { > - SET(tp->t_state, TS_WOPEN); > - ttychars(tp); > - tp->t_iflag = TTYDEF_IFLAG; > - tp->t_oflag = TTYDEF_OFLAG; > - > - if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) > - tp->t_cflag = pluartconscflag; > - else > - tp->t_cflag = TTYDEF_CFLAG; > - if (ISSET(sc->sc_swflags, COM_SW_CLOCAL)) > - SET(tp->t_cflag, CLOCAL); > - if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS)) > - SET(tp->t_cflag, CRTSCTS); > - if (ISSET(sc->sc_swflags, COM_SW_MDMBUF)) > - SET(tp->t_cflag, MDMBUF); > - tp->t_lflag = TTYDEF_LFLAG; > - tp->t_ispeed = tp->t_ospeed = pluartdefaultrate; > - > - s = spltty(); > - > - sc->sc_initialize = 1; > - pluart_param(tp, &tp->t_termios); > - ttsetwater(tp); > - sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0]; > - sc->sc_ibufhigh = sc->sc_ibuf + UART_IHIGHWATER; > - sc->sc_ibufend = sc->sc_ibuf + UART_IBUFSIZE; > - > - iot = sc->sc_iot; > - ioh = sc->sc_ioh; > - > -#if 0 > - sc->sc_ucr1 = bus_space_read_4(iot, ioh, IMXUART_UCR1); > - sc->sc_ucr2 = bus_space_read_4(iot, ioh, IMXUART_UCR2); > - sc->sc_ucr3 = bus_space_read_4(iot, ioh, IMXUART_UCR3); > - sc->sc_ucr4 = bus_space_read_4(iot, ioh, IMXUART_UCR4); > - > - /* interrupt after one char on tx/rx */ > - /* reference frequency divider: 1 */ > - bus_space_write_4(iot, ioh, IMXUART_UFCR, > - 1 << IMXUART_FCR_TXTL_SH | > - 5 << IMXUART_FCR_RFDIV_SH | > - 1 << IMXUART_FCR_RXTL_SH); > - > - bus_space_write_4(iot, ioh, IMXUART_UBIR, > - (pluartdefaultrate / 100) - 1); > - > - /* formula: clk / (rfdiv * 1600) */ > - bus_space_write_4(iot, ioh, IMXUART_UBMR, > - (clk_get_rate(sc->sc_clk) * 1000) / 1600); > - > - SET(sc->sc_ucr1, IMXUART_CR1_EN|IMXUART_CR1_RRDYEN); > - SET(sc->sc_ucr2, IMXUART_CR2_TXEN|IMXUART_CR2_RXEN); > - bus_space_write_4(iot, ioh, IMXUART_UCR1, sc->sc_ucr1); > - bus_space_write_4(iot, ioh, IMXUART_UCR2, sc->sc_ucr2); > - > - /* sc->sc_mcr = MCR_DTR | MCR_RTS; XXX */ > - SET(sc->sc_ucr3, IMXUART_CR3_DSR); /* XXX */ > - bus_space_write_4(iot, ioh, IMXUART_UCR3, sc->sc_ucr3); > -#endif > - > - SET(tp->t_state, TS_CARR_ON); /* XXX */ > - > - > - } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) > - return EBUSY; > - else > - s = spltty(); > - > - if (DEVCUA(dev)) { > - if (ISSET(tp->t_state, TS_ISOPEN)) { > - splx(s); > - return EBUSY; > - } > - sc->sc_cua = 1; > - } else { > - /* tty (not cua) device; wait for carrier if necessary */ > - if (ISSET(flag, O_NONBLOCK)) { > - if (sc->sc_cua) { > - /* Opening TTY non-blocking... but the CUA is > busy */ > - splx(s); > - return EBUSY; > - } > - } else { > - while (sc->sc_cua || > - (!ISSET(tp->t_cflag, CLOCAL) && > - !ISSET(tp->t_state, TS_CARR_ON))) { > - SET(tp->t_state, TS_WOPEN); > - error = ttysleep(tp, &tp->t_rawq, > - TTIPRI | PCATCH, ttopen, 0); > - /* > - * If TS_WOPEN has been reset, that means the > - * cua device has been closed. We don't want > - * to fail in that case, > - * so just go around again. > - */ > - if (error && ISSET(tp->t_state, TS_WOPEN)) { > - CLR(tp->t_state, TS_WOPEN); > - if (!sc->sc_cua && !ISSET(tp->t_state, > - TS_ISOPEN)) > - pluart_pwroff(sc); > - splx(s); > - return error; > - } > - } > - } > - } > - splx(s); > - return (*linesw[tp->t_line].l_open)(dev,tp,p); > -} > - > -int > -pluartclose(dev_t dev, int flag, int mode, struct proc *p) > -{ > - int unit = DEVUNIT(dev); > - struct pluart_softc *sc = pluart_cd.cd_devs[unit]; > - //bus_space_tag_t iot = sc->sc_iot; > - //bus_space_handle_t ioh = sc->sc_ioh; > - struct tty *tp = sc->sc_tty; > - int s; > - > - /* XXX This is for cons.c. */ > - if (!ISSET(tp->t_state, TS_ISOPEN)) > - return 0; > - > - (*linesw[tp->t_line].l_close)(tp, flag, p); > - s = spltty(); > - if (ISSET(tp->t_state, TS_WOPEN)) { > - /* tty device is waiting for carrier; drop dtr then re-raise */ > - //CLR(sc->sc_ucr3, IMXUART_CR3_DSR); > - //bus_space_write_4(iot, ioh, IMXUART_UCR3, sc->sc_ucr3); > - timeout_add(&sc->sc_dtr_tmo, hz * 2); > - } else { > - /* no one else waiting; turn off the uart */ > - pluart_pwroff(sc); > - } > - CLR(tp->t_state, TS_BUSY | TS_FLUSH); > - > - sc->sc_cua = 0; > - splx(s); > - ttyclose(tp); > - > - return 0; > -} > - > -int > -pluartread(dev_t dev, struct uio *uio, int flag) > -{ > - struct tty *tty; > - > - tty = pluarttty(dev); > - if (tty == NULL) > - return ENODEV; > - > - return((*linesw[tty->t_line].l_read)(tty, uio, flag)); > -} > - > -int > -pluartwrite(dev_t dev, struct uio *uio, int flag) > -{ > - struct tty *tty; > - > - tty = pluarttty(dev); > - if (tty == NULL) > - return ENODEV; > - > - return((*linesw[tty->t_line].l_write)(tty, uio, flag)); > -} > - > -int > -pluartioctl( dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) > -{ > - struct pluart_softc *sc; > - struct tty *tp; > - int error; > - > - sc = pluart_sc(dev); > - if (sc == NULL) > - return (ENODEV); > - > - tp = sc->sc_tty; > - if (tp == NULL) > - return (ENXIO); > - > - error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); > - if (error >= 0) > - return (error); > - > - error = ttioctl(tp, cmd, data, flag, p); > - if (error >= 0) > - return (error); > - > - switch(cmd) { > - case TIOCSBRK: > - break; > - case TIOCCBRK: > - break; > - case TIOCSDTR: > - break; > - case TIOCCDTR: > - break; > - case TIOCMSET: > - break; > - case TIOCMBIS: > - break; > - case TIOCMBIC: > - break; > - case TIOCMGET: > - break; > - case TIOCGFLAGS: > - break; > - case TIOCSFLAGS: > - error = suser(p); > - if (error != 0) > - return(EPERM); > - break; > - default: > - return (ENOTTY); > - } > - > - return 0; > -} > - > -int > -pluartstop(struct tty *tp, int flag) > -{ > - return 0; > -} > - > -struct tty * > -pluarttty(dev_t dev) > -{ > - int unit; > - struct pluart_softc *sc; > - unit = DEVUNIT(dev); > - if (unit >= pluart_cd.cd_ndevs) > - return NULL; > - sc = (struct pluart_softc *)pluart_cd.cd_devs[unit]; > - if (sc == NULL) > - return NULL; > - return sc->sc_tty; > -} > - > -struct pluart_softc * > -pluart_sc(dev_t dev) > -{ > - int unit; > - struct pluart_softc *sc; > - unit = DEVUNIT(dev); > - if (unit >= pluart_cd.cd_ndevs) > - return NULL; > - sc = (struct pluart_softc *)pluart_cd.cd_devs[unit]; > - return sc; > -} > - > - > -/* serial console */ > -void > -pluartcnprobe(struct consdev *cp) > -{ > -} > - > -void > -pluartcninit(struct consdev *cp) > -{ > -} > - > -int > -pluartcnattach(bus_space_tag_t iot, bus_addr_t iobase, int rate, tcflag_t > cflag) > -{ > - static struct consdev pluartcons = { > - NULL, NULL, pluartcngetc, pluartcnputc, pluartcnpollc, NULL, > - NODEV, CN_MIDPRI > - }; > - int maj; > - > - if (bus_space_map(iot, iobase, UART_SPACE, 0, &pluartconsioh)) > - return ENOMEM; > - > - /* Disable FIFO. */ > - bus_space_write_4(iot, pluartconsioh, UART_LCR_H, > - bus_space_read_4(iot, pluartconsioh, UART_LCR_H) & ~UART_LCR_H_FEN); > - > - /* Look for major of com(4) to replace. */ > - for (maj = 0; maj < nchrdev; maj++) > - if (cdevsw[maj].d_open == comopen) > - break; > - if (maj == nchrdev) > - return ENXIO; > - > - cn_tab = &pluartcons; > - cn_tab->cn_dev = makedev(maj, 0); > - cdevsw[12] = pluartdev; /* KLUDGE */ > - > - pluartconsiot = iot; > - pluartconsaddr = iobase; > - pluartconscflag = cflag; > - > - return 0; > -} > - > -int > -pluartcngetc(dev_t dev) > -{ > - int c; > - int s; > - s = splhigh(); > - while((bus_space_read_4(pluartconsiot, pluartconsioh, UART_FR) & > - UART_FR_RXFF) == 0) > - ; > - c = bus_space_read_4(pluartconsiot, pluartconsioh, UART_DR); > - splx(s); > - return c; > -} > - > -void > -pluartcnputc(dev_t dev, int c) > -{ > - int s; > - s = splhigh(); > - while((bus_space_read_4(pluartconsiot, pluartconsioh, UART_FR) & > - UART_FR_TXFE) == 0) > - ; > - bus_space_write_4(pluartconsiot, pluartconsioh, UART_DR, (uint8_t)c); > - splx(s); > -} > - > -void > -pluartcnpollc(dev_t dev, int on) > -{ > -} > Index: dev/fdt/pluart_fdt.c > =================================================================== > RCS file: dev/fdt/pluart_fdt.c > diff -N dev/fdt/pluart_fdt.c > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ dev/fdt/pluart_fdt.c 1 Jul 2018 14:29:40 -0000 > @@ -0,0 +1,80 @@ > +/* $OpenBSD: pluart.c,v 1.1 2018/06/05 20:41:19 kettenis Exp $ */ > +/* > + * Copyright (c) 2014 Patrick Wildt <patr...@blueri.se> > + * Copyright (c) 2005 Dale Rahn <dr...@dalerahn.com> > + * > + * Permission to use, copy, modify, and distribute this software for any > + * purpose with or without fee is hereby granted, provided that the above > + * copyright notice and this permission notice appear in all copies. > + * > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > + */ > + > +#include <sys/param.h> > +#include <sys/systm.h> > +#include <sys/tty.h> > + > +#include <machine/bus.h> > +#include <machine/fdt.h> > + > +#include <dev/ic/pluartvar.h> > + > +#include <dev/ofw/fdt.h> > +#include <dev/ofw/openfirm.h> > + > +int pluart_fdt_match(struct device *, void *, void *); > +void pluart_fdt_attach(struct device *, struct device *, void *); > + > +struct cfattach pluart_fdt_ca = { > + sizeof(struct pluart_softc), pluart_fdt_match, pluart_fdt_attach > +}; > + > +void > +pluart_init_cons(void) > +{ > + struct fdt_reg reg; > + void *node; > + > + if ((node = fdt_find_cons("arm,pl011")) == NULL) > + return; > + if (fdt_get_reg(node, 0, ®)) > + return; > + > + pluartcnattach(fdt_cons_bs_tag, reg.addr, B115200, TTYDEF_CFLAG); > +} > + > +int > +pluart_fdt_match(struct device *parent, void *self, void *aux) > +{ > + struct fdt_attach_args *faa = aux; > + > + return OF_is_compatible(faa->fa_node, "arm,pl011"); > +} > + > +void > +pluart_fdt_attach(struct device *parent, struct device *self, void *aux) > +{ > + struct fdt_attach_args *faa = aux; > + struct pluart_softc *sc = (struct pluart_softc *) self; > + > + if (faa->fa_nreg < 1) { > + printf(": no registers\n"); > + return; > + } > + > + sc->sc_irq = arm_intr_establish_fdt(faa->fa_node, IPL_TTY, pluart_intr, > + sc, sc->sc_dev.dv_xname); > + > + sc->sc_iot = faa->fa_iot; > + if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, faa->fa_reg[0].size, > + 0, &sc->sc_ioh)) > + panic("pluartattach: bus_space_map failed!"); > + > + pluart_attach_common(sc, stdout_node == faa->fa_node); > +} > Index: dev/ic/pluart.c > =================================================================== > RCS file: dev/ic/pluart.c > diff -N dev/ic/pluart.c > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ dev/ic/pluart.c 1 Jul 2018 14:29:40 -0000 > @@ -0,0 +1,820 @@ > +/* $OpenBSD: pluart.c,v 1.1 2018/06/05 20:41:19 kettenis Exp $ */ > +/* > + * Copyright (c) 2014 Patrick Wildt <patr...@blueri.se> > + * Copyright (c) 2005 Dale Rahn <dr...@dalerahn.com> > + * > + * Permission to use, copy, modify, and distribute this software for any > + * purpose with or without fee is hereby granted, provided that the above > + * copyright notice and this permission notice appear in all copies. > + * > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > + */ > + > +#include <sys/param.h> > +#include <sys/ioctl.h> > +#include <sys/proc.h> > +#include <sys/tty.h> > +#include <sys/uio.h> > +#include <sys/systm.h> > +#include <sys/time.h> > +#include <sys/device.h> > +#include <sys/syslog.h> > +#include <sys/conf.h> > +#include <sys/fcntl.h> > +#include <sys/select.h> > +#include <sys/kernel.h> > + > +#include <machine/bus.h> > + > +#include <dev/ic/pluartvar.h> > +#include <dev/cons.h> > + > +#ifdef DDB > +#include <ddb/db_var.h> > +#endif > + > +#define DEVUNIT(x) (minor(x) & 0x7f) > +#define DEVCUA(x) (minor(x) & 0x80) > + > +#define UART_DR 0x00 /* Data register */ > +#define UART_DR_DATA(x) ((x) & 0xf) > +#define UART_DR_FE (1 << 8) /* Framing error */ > +#define UART_DR_PE (1 << 9) /* Parity error */ > +#define UART_DR_BE (1 << 10) /* Break error */ > +#define UART_DR_OE (1 << 11) /* Overrun error */ > +#define UART_RSR 0x04 /* Receive status register */ > +#define UART_RSR_FE (1 << 0) /* Framing error */ > +#define UART_RSR_PE (1 << 1) /* Parity error */ > +#define UART_RSR_BE (1 << 2) /* Break error */ > +#define UART_RSR_OE (1 << 3) /* Overrun error */ > +#define UART_ECR 0x04 /* Error clear register */ > +#define UART_ECR_FE (1 << 0) /* Framing error */ > +#define UART_ECR_PE (1 << 1) /* Parity error */ > +#define UART_ECR_BE (1 << 2) /* Break error */ > +#define UART_ECR_OE (1 << 3) /* Overrun error */ > +#define UART_FR 0x18 /* Flag register */ > +#define UART_FR_CTS (1 << 0) /* Clear to send */ > +#define UART_FR_DSR (1 << 1) /* Data set ready */ > +#define UART_FR_DCD (1 << 2) /* Data carrier detect */ > +#define UART_FR_BUSY (1 << 3) /* UART busy */ > +#define UART_FR_RXFE (1 << 4) /* Receive FIFO empty */ > +#define UART_FR_TXFF (1 << 5) /* Transmit FIFO full */ > +#define UART_FR_RXFF (1 << 6) /* Receive FIFO full */ > +#define UART_FR_TXFE (1 << 7) /* Transmit FIFO empty */ > +#define UART_FR_RI (1 << 8) /* Ring indicator */ > +#define UART_ILPR 0x20 /* IrDA low-power counter > register */ > +#define UART_ILPR_ILPDVSR ((x) & 0xf) /* IrDA low-power divisor */ > +#define UART_IBRD 0x24 /* Integer baud rate register */ > +#define UART_IBRD_DIVINT ((x) & 0xff) /* Integer baud rate divisor */ > +#define UART_FBRD 0x28 /* Fractional baud rate > register */ > +#define UART_FBRD_DIVFRAC ((x) & 0x3f) /* Fractional baud rate divisor > */ > +#define UART_LCR_H 0x2c /* Line control register */ > +#define UART_LCR_H_BRK (1 << 0) /* Send break */ > +#define UART_LCR_H_PEN (1 << 1) /* Parity enable */ > +#define UART_LCR_H_EPS (1 << 2) /* Even parity select */ > +#define UART_LCR_H_STP2 (1 << 3) /* Two stop bits select > */ > +#define UART_LCR_H_FEN (1 << 4) /* Enable FIFOs */ > +#define UART_LCR_H_WLEN5 (0x0 << 5) /* Word length: 5 bits */ > +#define UART_LCR_H_WLEN6 (0x1 << 5) /* Word length: 6 bits */ > +#define UART_LCR_H_WLEN7 (0x2 << 5) /* Word length: 7 bits */ > +#define UART_LCR_H_WLEN8 (0x3 << 5) /* Word length: 8 bits */ > +#define UART_LCR_H_SPS (1 << 7) /* Stick parity select > */ > +#define UART_CR 0x30 /* Control register */ > +#define UART_CR_UARTEN (1 << 0) /* UART enable */ > +#define UART_CR_SIREN (1 << 1) /* SIR enable */ > +#define UART_CR_SIRLP (1 << 2) /* IrDA SIR low power > mode */ > +#define UART_CR_LBE (1 << 7) /* Loop back enable */ > +#define UART_CR_TXE (1 << 8) /* Transmit enable */ > +#define UART_CR_RXE (1 << 9) /* Receive enable */ > +#define UART_CR_DTR (1 << 10) /* Data transmit enable */ > +#define UART_CR_RTS (1 << 11) /* Request to send */ > +#define UART_CR_OUT1 (1 << 12) > +#define UART_CR_OUT2 (1 << 13) > +#define UART_CR_CTSE (1 << 14) /* CTS hardware flow control > enable */ > +#define UART_CR_RTSE (1 << 15) /* RTS hardware flow control > enable */ > +#define UART_IFLS 0x34 /* Interrupt FIFO level select > register */ > +#define UART_IMSC 0x38 /* Interrupt mask set/clear > register */ > +#define UART_IMSC_RIMIM (1 << 0) > +#define UART_IMSC_CTSMIM (1 << 1) > +#define UART_IMSC_DCDMIM (1 << 2) > +#define UART_IMSC_DSRMIM (1 << 3) > +#define UART_IMSC_RXIM (1 << 4) > +#define UART_IMSC_TXIM (1 << 5) > +#define UART_IMSC_RTIM (1 << 6) > +#define UART_IMSC_FEIM (1 << 7) > +#define UART_IMSC_PEIM (1 << 8) > +#define UART_IMSC_BEIM (1 << 9) > +#define UART_IMSC_OEIM (1 << 10) > +#define UART_RIS 0x3c /* Raw interrupt status > register */ > +#define UART_MIS 0x40 /* Masked interrupt status > register */ > +#define UART_ICR 0x44 /* Interrupt clear register */ > +#define UART_DMACR 0x48 /* DMA control register */ > +#define UART_SPACE 0x100 > + > +void pluartcnprobe(struct consdev *cp); > +void pluartcninit(struct consdev *cp); > +int pluartcngetc(dev_t dev); > +void pluartcnputc(dev_t dev, int c); > +void pluartcnpollc(dev_t dev, int on); > +int pluart_param(struct tty *tp, struct termios *t); > +void pluart_start(struct tty *); > +void pluart_pwroff(struct pluart_softc *sc); > +void pluart_diag(void *arg); > +void pluart_raisedtr(void *arg); > +void pluart_softint(void *arg); > +struct pluart_softc *pluart_sc(dev_t dev); > + > +/* XXX - we imitate 'com' serial ports and take over their entry points */ > +/* XXX: These belong elsewhere */ > +cdev_decl(com); > +cdev_decl(pluart); > + > +struct cfdriver pluart_cd = { > + NULL, "pluart", DV_TTY > +}; > + > +bus_space_tag_t pluartconsiot; > +bus_space_handle_t pluartconsioh; > +bus_addr_t pluartconsaddr; > +tcflag_t pluartconscflag = TTYDEF_CFLAG; > +int pluartdefaultrate = B38400; > + > +struct cdevsw pluartdev = > + cdev_tty_init(3/*XXX NUART */ ,pluart); /* 12: serial port */ > + > +void > +pluart_attach_common(struct pluart_softc *sc, int console) > +{ > + int maj; > + > + if (console) { > + /* Locate the major number. */ > + for (maj = 0; maj < nchrdev; maj++) > + if (cdevsw[maj].d_open == pluartopen) > + break; > + cn_tab->cn_dev = makedev(maj, sc->sc_dev.dv_unit); > + > + printf(": console"); > + SET(sc->sc_hwflags, COM_HW_CONSOLE); > + } > + > + timeout_set(&sc->sc_diag_tmo, pluart_diag, sc); > + timeout_set(&sc->sc_dtr_tmo, pluart_raisedtr, sc); > + sc->sc_si = softintr_establish(IPL_TTY, pluart_softint, sc); > + > + if(sc->sc_si == NULL) > + panic("%s: can't establish soft interrupt.", > + sc->sc_dev.dv_xname); > + > + bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_IMSC, (UART_IMSC_RXIM | > UART_IMSC_TXIM)); > + bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_ICR, 0x7ff); > + bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_LCR_H, > + bus_space_read_4(sc->sc_iot, sc->sc_ioh, UART_LCR_H) & > + ~UART_LCR_H_FEN); > + > + printf("\n"); > +} > + > +int > +pluart_intr(void *arg) > +{ > + struct pluart_softc *sc = arg; > + bus_space_tag_t iot = sc->sc_iot; > + bus_space_handle_t ioh = sc->sc_ioh; > + struct tty *tp = sc->sc_tty; > + u_int16_t fr; > + u_int16_t *p; > + u_int16_t c; > + > + bus_space_write_4(iot, ioh, UART_ICR, -1); > + > + if (sc->sc_tty == NULL) > + return(0); > + > + fr = bus_space_read_4(iot, ioh, UART_FR); > + if (ISSET(fr, UART_FR_TXFE) && ISSET(tp->t_state, TS_BUSY)) { > + CLR(tp->t_state, TS_BUSY | TS_FLUSH); > + if (sc->sc_halt > 0) > + wakeup(&tp->t_outq); > + (*linesw[tp->t_line].l_start)(tp); > + } > + > + if(!ISSET(bus_space_read_4(iot, ioh, UART_FR), UART_FR_RXFF)) > + return 0; > + > + p = sc->sc_ibufp; > + > + while (ISSET(bus_space_read_4(iot, ioh, UART_FR), UART_FR_RXFF)) { > + c = bus_space_read_2(iot, ioh, UART_DR); > + if (c & UART_DR_BE) { > +#ifdef DDB > + if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { > + if (db_console) > + db_enter(); > + continue; > + } > +#endif > + c = 0; > + } > + if (p >= sc->sc_ibufend) { > + sc->sc_floods++; > + if (sc->sc_errors++ == 0) > + timeout_add(&sc->sc_diag_tmo, 60 * hz); > + } else { > + *p++ = c; > + if (p == sc->sc_ibufhigh && ISSET(tp->t_cflag, > CRTSCTS)) { > + /* XXX */ > + //CLR(sc->sc_ucr3, IMXUART_CR3_DSR); > + //bus_space_write_4(iot, ioh, IMXUART_UCR3, > + // sc->sc_ucr3); > + } > + } > + /* XXX - msr stuff ? */ > + } > + sc->sc_ibufp = p; > + > + softintr_schedule(sc->sc_si); > + > + return 1; > +} > + > +int > +pluart_param(struct tty *tp, struct termios *t) > +{ > + struct pluart_softc *sc = pluart_cd.cd_devs[DEVUNIT(tp->t_dev)]; > + //bus_space_tag_t iot = sc->sc_iot; > + //bus_space_handle_t ioh = sc->sc_ioh; > + int ospeed = t->c_ospeed; > + int error; > + tcflag_t oldcflag; > + > + > + if (t->c_ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) > + return EINVAL; > + > + switch (ISSET(t->c_cflag, CSIZE)) { > + case CS5: > + return EINVAL; > + case CS6: > + return EINVAL; > + case CS7: > + //CLR(sc->sc_ucr2, IMXUART_CR2_WS); > + break; > + case CS8: > + //SET(sc->sc_ucr2, IMXUART_CR2_WS); > + break; > + } > +// bus_space_write_4(iot, ioh, IMXUART_UCR2, sc->sc_ucr2); > + > + /* > + if (ISSET(t->c_cflag, PARENB)) { > + SET(sc->sc_ucr2, IMXUART_CR2_PREN); > + bus_space_write_4(iot, ioh, IMXUART_UCR2, sc->sc_ucr2); > + } > + */ > + /* STOPB - XXX */ > + if (ospeed == 0) { > + /* lower dtr */ > + } > + > + if (ospeed != 0) { > + while (ISSET(tp->t_state, TS_BUSY)) { > + ++sc->sc_halt; > + error = ttysleep(tp, &tp->t_outq, > + TTOPRI | PCATCH, "pluartprm", 0); > + --sc->sc_halt; > + if (error) { > + pluart_start(tp); > + return (error); > + } > + } > + /* set speed */ > + } > + > + /* setup fifo */ > + > + /* When not using CRTSCTS, RTS follows DTR. */ > + /* sc->sc_dtr = MCR_DTR; */ > + > + > + /* and copy to tty */ > + tp->t_ispeed = t->c_ispeed; > + tp->t_ospeed = t->c_ospeed; > + oldcflag = tp->t_cflag; > + tp->t_cflag = t->c_cflag; > + > + /* > + * If DCD is off and MDMBUF is changed, ask the tty layer if we should > + * stop the device. > + */ > + /* XXX */ > + > + pluart_start(tp); > + > + return 0; > +} > + > +void > +pluart_start(struct tty *tp) > +{ > + struct pluart_softc *sc = pluart_cd.cd_devs[DEVUNIT(tp->t_dev)]; > + bus_space_tag_t iot = sc->sc_iot; > + bus_space_handle_t ioh = sc->sc_ioh; > + > + int s; > + s = spltty(); > + if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) > + goto out; > + if (tp->t_outq.c_cc <= tp->t_lowat) { > + if (ISSET(tp->t_state, TS_ASLEEP)) { > + CLR(tp->t_state, TS_ASLEEP); > + wakeup(&tp->t_outq); > + } > + if (tp->t_outq.c_cc == 0) > + goto out; > + selwakeup(&tp->t_wsel); > + } > + SET(tp->t_state, TS_BUSY); > + > + if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) { > + u_char buffer[64]; /* largest fifo */ > + int i, n; > + > + n = q_to_b(&tp->t_outq, buffer, > + min(sc->sc_fifolen, sizeof buffer)); > + for (i = 0; i < n; i++) { > + bus_space_write_4(iot, ioh, UART_DR, buffer[i]); > + } > + bzero(buffer, n); > + } else if (tp->t_outq.c_cc != 0) > + bus_space_write_4(iot, ioh, UART_DR, getc(&tp->t_outq)); > + > +out: > + splx(s); > +} > + > +void > +pluart_pwroff(struct pluart_softc *sc) > +{ > +} > + > +void > +pluart_diag(void *arg) > +{ > + struct pluart_softc *sc = arg; > + int overflows, floods; > + int s; > + > + s = spltty(); > + sc->sc_errors = 0; > + overflows = sc->sc_overflows; > + sc->sc_overflows = 0; > + floods = sc->sc_floods; > + sc->sc_floods = 0; > + splx(s); > + log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s\n", > + sc->sc_dev.dv_xname, > + overflows, overflows == 1 ? "" : "s", > + floods, floods == 1 ? "" : "s"); > +} > + > +void > +pluart_raisedtr(void *arg) > +{ > + //struct pluart_softc *sc = arg; > + > + //SET(sc->sc_ucr3, IMXUART_CR3_DSR); /* XXX */ > + //bus_space_write_4(sc->sc_iot, sc->sc_ioh, IMXUART_UCR3, sc->sc_ucr3); > +} > + > +void > +pluart_softint(void *arg) > +{ > + struct pluart_softc *sc = arg; > + struct tty *tp; > + u_int16_t *ibufp; > + u_int16_t *ibufend; > + int c; > + int err; > + int s; > + > + if (sc == NULL || sc->sc_ibufp == sc->sc_ibuf) > + return; > + > + tp = sc->sc_tty; > + s = spltty(); > + > + ibufp = sc->sc_ibuf; > + ibufend = sc->sc_ibufp; > + > + if (ibufp == ibufend || tp == NULL || !ISSET(tp->t_state, TS_ISOPEN)) { > + splx(s); > + return; > + } > + > + sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ? > + sc->sc_ibufs[1] : sc->sc_ibufs[0]; > + sc->sc_ibufhigh = sc->sc_ibuf + UART_IHIGHWATER; > + sc->sc_ibufend = sc->sc_ibuf + UART_IBUFSIZE; > + > +#if 0 > + if (ISSET(tp->t_cflag, CRTSCTS) && > + !ISSET(sc->sc_ucr3, IMXUART_CR3_DSR)) { > + /* XXX */ > + SET(sc->sc_ucr3, IMXUART_CR3_DSR); > + bus_space_write_4(sc->sc_iot, sc->sc_ioh, IMXUART_UCR3, > + sc->sc_ucr3); > + } > +#endif > + > + splx(s); > + > + while (ibufp < ibufend) { > + c = *ibufp++; > + /* > + if (ISSET(c, IMXUART_RX_OVERRUN)) { > + sc->sc_overflows++; > + if (sc->sc_errors++ == 0) > + timeout_add(&sc->sc_diag_tmo, 60 * hz); > + } > + */ > + /* This is ugly, but fast. */ > + > + err = 0; > + /* > + if (ISSET(c, IMXUART_RX_PRERR)) > + err |= TTY_PE; > + if (ISSET(c, IMXUART_RX_FRMERR)) > + err |= TTY_FE; > + */ > + c = (c & 0xff) | err; > + (*linesw[tp->t_line].l_rint)(c, tp); > + } > +} > + > +int > +pluartopen(dev_t dev, int flag, int mode, struct proc *p) > +{ > + int unit = DEVUNIT(dev); > + struct pluart_softc *sc; > + bus_space_tag_t iot; > + bus_space_handle_t ioh; > + struct tty *tp; > + int s; > + int error = 0; > + > + if (unit >= pluart_cd.cd_ndevs) > + return ENXIO; > + sc = pluart_cd.cd_devs[unit]; > + if (sc == NULL) > + return ENXIO; > + > + s = spltty(); > + if (sc->sc_tty == NULL) > + tp = sc->sc_tty = ttymalloc(0); > + else > + tp = sc->sc_tty; > + > + splx(s); > + > + tp->t_oproc = pluart_start; > + tp->t_param = pluart_param; > + tp->t_dev = dev; > + > + if (!ISSET(tp->t_state, TS_ISOPEN)) { > + SET(tp->t_state, TS_WOPEN); > + ttychars(tp); > + tp->t_iflag = TTYDEF_IFLAG; > + tp->t_oflag = TTYDEF_OFLAG; > + > + if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) > + tp->t_cflag = pluartconscflag; > + else > + tp->t_cflag = TTYDEF_CFLAG; > + if (ISSET(sc->sc_swflags, COM_SW_CLOCAL)) > + SET(tp->t_cflag, CLOCAL); > + if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS)) > + SET(tp->t_cflag, CRTSCTS); > + if (ISSET(sc->sc_swflags, COM_SW_MDMBUF)) > + SET(tp->t_cflag, MDMBUF); > + tp->t_lflag = TTYDEF_LFLAG; > + tp->t_ispeed = tp->t_ospeed = pluartdefaultrate; > + > + s = spltty(); > + > + sc->sc_initialize = 1; > + pluart_param(tp, &tp->t_termios); > + ttsetwater(tp); > + sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0]; > + sc->sc_ibufhigh = sc->sc_ibuf + UART_IHIGHWATER; > + sc->sc_ibufend = sc->sc_ibuf + UART_IBUFSIZE; > + > + iot = sc->sc_iot; > + ioh = sc->sc_ioh; > + > +#if 0 > + sc->sc_ucr1 = bus_space_read_4(iot, ioh, IMXUART_UCR1); > + sc->sc_ucr2 = bus_space_read_4(iot, ioh, IMXUART_UCR2); > + sc->sc_ucr3 = bus_space_read_4(iot, ioh, IMXUART_UCR3); > + sc->sc_ucr4 = bus_space_read_4(iot, ioh, IMXUART_UCR4); > + > + /* interrupt after one char on tx/rx */ > + /* reference frequency divider: 1 */ > + bus_space_write_4(iot, ioh, IMXUART_UFCR, > + 1 << IMXUART_FCR_TXTL_SH | > + 5 << IMXUART_FCR_RFDIV_SH | > + 1 << IMXUART_FCR_RXTL_SH); > + > + bus_space_write_4(iot, ioh, IMXUART_UBIR, > + (pluartdefaultrate / 100) - 1); > + > + /* formula: clk / (rfdiv * 1600) */ > + bus_space_write_4(iot, ioh, IMXUART_UBMR, > + (clk_get_rate(sc->sc_clk) * 1000) / 1600); > + > + SET(sc->sc_ucr1, IMXUART_CR1_EN|IMXUART_CR1_RRDYEN); > + SET(sc->sc_ucr2, IMXUART_CR2_TXEN|IMXUART_CR2_RXEN); > + bus_space_write_4(iot, ioh, IMXUART_UCR1, sc->sc_ucr1); > + bus_space_write_4(iot, ioh, IMXUART_UCR2, sc->sc_ucr2); > + > + /* sc->sc_mcr = MCR_DTR | MCR_RTS; XXX */ > + SET(sc->sc_ucr3, IMXUART_CR3_DSR); /* XXX */ > + bus_space_write_4(iot, ioh, IMXUART_UCR3, sc->sc_ucr3); > +#endif > + > + SET(tp->t_state, TS_CARR_ON); /* XXX */ > + > + > + } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) > + return EBUSY; > + else > + s = spltty(); > + > + if (DEVCUA(dev)) { > + if (ISSET(tp->t_state, TS_ISOPEN)) { > + splx(s); > + return EBUSY; > + } > + sc->sc_cua = 1; > + } else { > + /* tty (not cua) device; wait for carrier if necessary */ > + if (ISSET(flag, O_NONBLOCK)) { > + if (sc->sc_cua) { > + /* Opening TTY non-blocking... but the CUA is > busy */ > + splx(s); > + return EBUSY; > + } > + } else { > + while (sc->sc_cua || > + (!ISSET(tp->t_cflag, CLOCAL) && > + !ISSET(tp->t_state, TS_CARR_ON))) { > + SET(tp->t_state, TS_WOPEN); > + error = ttysleep(tp, &tp->t_rawq, > + TTIPRI | PCATCH, ttopen, 0); > + /* > + * If TS_WOPEN has been reset, that means the > + * cua device has been closed. We don't want > + * to fail in that case, > + * so just go around again. > + */ > + if (error && ISSET(tp->t_state, TS_WOPEN)) { > + CLR(tp->t_state, TS_WOPEN); > + if (!sc->sc_cua && !ISSET(tp->t_state, > + TS_ISOPEN)) > + pluart_pwroff(sc); > + splx(s); > + return error; > + } > + } > + } > + } > + splx(s); > + return (*linesw[tp->t_line].l_open)(dev,tp,p); > +} > + > +int > +pluartclose(dev_t dev, int flag, int mode, struct proc *p) > +{ > + int unit = DEVUNIT(dev); > + struct pluart_softc *sc = pluart_cd.cd_devs[unit]; > + //bus_space_tag_t iot = sc->sc_iot; > + //bus_space_handle_t ioh = sc->sc_ioh; > + struct tty *tp = sc->sc_tty; > + int s; > + > + /* XXX This is for cons.c. */ > + if (!ISSET(tp->t_state, TS_ISOPEN)) > + return 0; > + > + (*linesw[tp->t_line].l_close)(tp, flag, p); > + s = spltty(); > + if (ISSET(tp->t_state, TS_WOPEN)) { > + /* tty device is waiting for carrier; drop dtr then re-raise */ > + //CLR(sc->sc_ucr3, IMXUART_CR3_DSR); > + //bus_space_write_4(iot, ioh, IMXUART_UCR3, sc->sc_ucr3); > + timeout_add(&sc->sc_dtr_tmo, hz * 2); > + } else { > + /* no one else waiting; turn off the uart */ > + pluart_pwroff(sc); > + } > + CLR(tp->t_state, TS_BUSY | TS_FLUSH); > + > + sc->sc_cua = 0; > + splx(s); > + ttyclose(tp); > + > + return 0; > +} > + > +int > +pluartread(dev_t dev, struct uio *uio, int flag) > +{ > + struct tty *tty; > + > + tty = pluarttty(dev); > + if (tty == NULL) > + return ENODEV; > + > + return((*linesw[tty->t_line].l_read)(tty, uio, flag)); > +} > + > +int > +pluartwrite(dev_t dev, struct uio *uio, int flag) > +{ > + struct tty *tty; > + > + tty = pluarttty(dev); > + if (tty == NULL) > + return ENODEV; > + > + return((*linesw[tty->t_line].l_write)(tty, uio, flag)); > +} > + > +int > +pluartioctl( dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) > +{ > + struct pluart_softc *sc; > + struct tty *tp; > + int error; > + > + sc = pluart_sc(dev); > + if (sc == NULL) > + return (ENODEV); > + > + tp = sc->sc_tty; > + if (tp == NULL) > + return (ENXIO); > + > + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); > + if (error >= 0) > + return (error); > + > + error = ttioctl(tp, cmd, data, flag, p); > + if (error >= 0) > + return (error); > + > + switch(cmd) { > + case TIOCSBRK: > + break; > + case TIOCCBRK: > + break; > + case TIOCSDTR: > + break; > + case TIOCCDTR: > + break; > + case TIOCMSET: > + break; > + case TIOCMBIS: > + break; > + case TIOCMBIC: > + break; > + case TIOCMGET: > + break; > + case TIOCGFLAGS: > + break; > + case TIOCSFLAGS: > + error = suser(p); > + if (error != 0) > + return(EPERM); > + break; > + default: > + return (ENOTTY); > + } > + > + return 0; > +} > + > +int > +pluartstop(struct tty *tp, int flag) > +{ > + return 0; > +} > + > +struct tty * > +pluarttty(dev_t dev) > +{ > + int unit; > + struct pluart_softc *sc; > + unit = DEVUNIT(dev); > + if (unit >= pluart_cd.cd_ndevs) > + return NULL; > + sc = (struct pluart_softc *)pluart_cd.cd_devs[unit]; > + if (sc == NULL) > + return NULL; > + return sc->sc_tty; > +} > + > +struct pluart_softc * > +pluart_sc(dev_t dev) > +{ > + int unit; > + struct pluart_softc *sc; > + unit = DEVUNIT(dev); > + if (unit >= pluart_cd.cd_ndevs) > + return NULL; > + sc = (struct pluart_softc *)pluart_cd.cd_devs[unit]; > + return sc; > +} > + > + > +/* serial console */ > +void > +pluartcnprobe(struct consdev *cp) > +{ > +} > + > +void > +pluartcninit(struct consdev *cp) > +{ > +} > + > +int > +pluartcnattach(bus_space_tag_t iot, bus_addr_t iobase, int rate, tcflag_t > cflag) > +{ > + static struct consdev pluartcons = { > + NULL, NULL, pluartcngetc, pluartcnputc, pluartcnpollc, NULL, > + NODEV, CN_MIDPRI > + }; > + int maj; > + > + if (bus_space_map(iot, iobase, UART_SPACE, 0, &pluartconsioh)) > + return ENOMEM; > + > + /* Disable FIFO. */ > + bus_space_write_4(iot, pluartconsioh, UART_LCR_H, > + bus_space_read_4(iot, pluartconsioh, UART_LCR_H) & ~UART_LCR_H_FEN); > + > + /* Look for major of com(4) to replace. */ > + for (maj = 0; maj < nchrdev; maj++) > + if (cdevsw[maj].d_open == comopen) > + break; > + if (maj == nchrdev) > + return ENXIO; > + > + cn_tab = &pluartcons; > + cn_tab->cn_dev = makedev(maj, 0); > + cdevsw[12] = pluartdev; /* KLUDGE */ > + > + pluartconsiot = iot; > + pluartconsaddr = iobase; > + pluartconscflag = cflag; > + > + return 0; > +} > + > +int > +pluartcngetc(dev_t dev) > +{ > + int c; > + int s; > + s = splhigh(); > + while((bus_space_read_4(pluartconsiot, pluartconsioh, UART_FR) & > + UART_FR_RXFF) == 0) > + ; > + c = bus_space_read_4(pluartconsiot, pluartconsioh, UART_DR); > + splx(s); > + return c; > +} > + > +void > +pluartcnputc(dev_t dev, int c) > +{ > + int s; > + s = splhigh(); > + while((bus_space_read_4(pluartconsiot, pluartconsioh, UART_FR) & > + UART_FR_TXFE) == 0) > + ; > + bus_space_write_4(pluartconsiot, pluartconsioh, UART_DR, (uint8_t)c); > + splx(s); > +} > + > +void > +pluartcnpollc(dev_t dev, int on) > +{ > +} > Index: dev/ic/pluartvar.h > =================================================================== > RCS file: dev/ic/pluartvar.h > diff -N dev/ic/pluartvar.h > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ dev/ic/pluartvar.h 1 Jul 2018 14:29:40 -0000 > @@ -0,0 +1,63 @@ > +/* $OpenBSD$ */ > +/* > + * Copyright (c) 2014 Patrick Wildt <patr...@blueri.se> > + * Copyright (c) 2005 Dale Rahn <dr...@dalerahn.com> > + * > + * Permission to use, copy, modify, and distribute this software for any > + * purpose with or without fee is hereby granted, provided that the above > + * copyright notice and this permission notice appear in all copies. > + * > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > + */ > + > +struct pluart_softc { > + struct device sc_dev; > + bus_space_tag_t sc_iot; > + bus_space_handle_t sc_ioh; > + struct soft_intrhand *sc_si; > + void *sc_irq; > + struct tty *sc_tty; > + struct timeout sc_diag_tmo; > + struct timeout sc_dtr_tmo; > + int sc_overflows; > + int sc_floods; > + int sc_errors; > + int sc_halt; > + u_int16_t sc_ucr1; > + u_int16_t sc_ucr2; > + u_int16_t sc_ucr3; > + u_int16_t sc_ucr4; > + u_int8_t sc_hwflags; > +#define COM_HW_NOIEN 0x01 > +#define COM_HW_FIFO 0x02 > +#define COM_HW_SIR 0x20 > +#define COM_HW_CONSOLE 0x40 > + u_int8_t sc_swflags; > +#define COM_SW_SOFTCAR 0x01 > +#define COM_SW_CLOCAL 0x02 > +#define COM_SW_CRTSCTS 0x04 > +#define COM_SW_MDMBUF 0x08 > +#define COM_SW_PPS 0x10 > + int sc_fifolen; > + > + u_int8_t sc_initialize; > + u_int8_t sc_cua; > + u_int16_t *sc_ibuf, *sc_ibufp, *sc_ibufhigh, *sc_ibufend; > +#define UART_IBUFSIZE 128 > +#define UART_IHIGHWATER 100 > + u_int16_t sc_ibufs[2][UART_IBUFSIZE]; > + > + struct clk *sc_clk; > +}; > + > +void pluart_attach_common(struct pluart_softc *, int); > +int pluart_intr(void *); > + > +int pluartcnattach(bus_space_tag_t iot, bus_addr_t iobase, int rate, > + tcflag_t cflag); >