Lines Matching +full:enable +full:- +full:modem +full:- +full:interrupt
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
30 * This driver supports several multiport USB-to-RS232 serial adapters driven
39 * quad-port mos7840.
88 * Two-port devices (both with 7820 chip and 7840 chip configured as two-port)
90 * So,PHYSICAL port numbers (indexes) on two-port device will be 0 and 2.
96 * Pack non-regular registers to array to easier if-less access.
123 uint8_t sc_mcr; /* local modem control register */
133 struct usb_xfer *sc_intr_xfer; /* Interrupt endpoint */
192 /* Indexed by LOGICAL port number (subunit), so two-port device uses 0 & 1 */
286 if (uaa->usb_mode != USB_MODE_HOST) in umcs7840_probe()
288 if (uaa->info.bConfigIndex != MCS7840_CONFIG_INDEX) in umcs7840_probe()
290 if (uaa->info.bIfaceIndex != MCS7840_IFACE_INDEX) in umcs7840_probe()
312 mtx_init(&sc->sc_mtx, "umcs7840", NULL, MTX_DEF); in umcs7840_attach()
313 ucom_ref(&sc->sc_super_ucom); in umcs7840_attach()
315 sc->sc_dev = dev; in umcs7840_attach()
316 sc->sc_udev = uaa->device; in umcs7840_attach()
326 * (4 ports) bit on 2-port device, so use vendor driver's way. in umcs7840_attach()
332 sc->sc_numports = 4; in umcs7840_attach()
334 sc->sc_ucom[0].sc_portno = 0; in umcs7840_attach()
335 sc->sc_ucom[1].sc_portno = 1; in umcs7840_attach()
336 sc->sc_ucom[2].sc_portno = 2; in umcs7840_attach()
337 sc->sc_ucom[3].sc_portno = 3; in umcs7840_attach()
339 sc->sc_numports = 2; in umcs7840_attach()
341 sc->sc_ucom[0].sc_portno = 0; in umcs7840_attach()
342 sc->sc_ucom[1].sc_portno = 2; /* '1' is skipped */ in umcs7840_attach()
344 device_printf(dev, "Chip mcs%04x, found %d active ports\n", uaa->info.idProduct, sc->sc_numports); in umcs7840_attach()
346 …device_printf(dev, "On-die configuration: RST: active %s, HRD: %s, PLL: %s, POR: %s, Ports: %s, EE… in umcs7840_attach()
356 for (subunit = 0; subunit < sc->sc_numports; ++subunit) { in umcs7840_attach()
359 …umcs7840_config_tmp[n].endpoint = umcs7840_bulk_config_data[n].endpoint + 2 * sc->sc_ucom[subunit]… in umcs7840_attach()
362 error = usbd_transfer_setup(uaa->device, in umcs7840_attach()
363 &iface_index, sc->sc_ports[sc->sc_ucom[subunit].sc_portno].sc_xfer, umcs7840_config_tmp, in umcs7840_attach()
364 UMCS7840_N_TRANSFERS, sc, &sc->sc_mtx); in umcs7840_attach()
367 subunit + 1, sc->sc_numports); in umcs7840_attach()
371 error = usbd_transfer_setup(uaa->device, in umcs7840_attach()
372 &iface_index, &sc->sc_intr_xfer, umcs7840_intr_config_data, in umcs7840_attach()
373 1, sc, &sc->sc_mtx); in umcs7840_attach()
375 device_printf(dev, "allocating USB transfers failed for interrupt\n"); in umcs7840_attach()
379 mtx_lock(&sc->sc_mtx); in umcs7840_attach()
380 for (subunit = 0; subunit < sc->sc_numports; ++subunit) { in umcs7840_attach()
381 usbd_xfer_set_stall(sc->sc_ports[sc->sc_ucom[subunit].sc_portno].sc_xfer[UMCS7840_BULK_RD_EP]); in umcs7840_attach()
382 usbd_xfer_set_stall(sc->sc_ports[sc->sc_ucom[subunit].sc_portno].sc_xfer[UMCS7840_BULK_WR_EP]); in umcs7840_attach()
384 mtx_unlock(&sc->sc_mtx); in umcs7840_attach()
386 error = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom, sc->sc_numports, sc, in umcs7840_attach()
387 &umcs7840_callback, &sc->sc_mtx); in umcs7840_attach()
391 ucom_set_pnpinfo_usb(&sc->sc_super_ucom, dev); in umcs7840_attach()
406 ucom_detach(&sc->sc_super_ucom, sc->sc_ucom); in umcs7840_detach()
408 for (subunit = 0; subunit < sc->sc_numports; ++subunit) in umcs7840_detach()
409 usbd_transfer_unsetup(sc->sc_ports[sc->sc_ucom[subunit].sc_portno].sc_xfer, UMCS7840_N_TRANSFERS); in umcs7840_detach()
410 usbd_transfer_unsetup(&sc->sc_intr_xfer, 1); in umcs7840_detach()
424 if (ucom_unref(&sc->sc_super_ucom)) { in umcs7840_free_softc()
425 mtx_destroy(&sc->sc_mtx); in umcs7840_free_softc()
433 umcs7840_free_softc(ucom->sc_parent); in umcs7840_free()
439 struct umcs7840_softc *sc = ucom->sc_parent; in umcs7840_cfg_open()
440 uint16_t pn = ucom->sc_portno; in umcs7840_cfg_open()
444 if (!sc->sc_driver_done) { in umcs7840_cfg_open()
454 sc->sc_driver_done = 1; in umcs7840_cfg_open()
456 /* Toggle reset bit on-off */ in umcs7840_cfg_open()
466 /* Set RS-232 mode */ in umcs7840_cfg_open()
481 /* Reset FIFO -- documented */ in umcs7840_cfg_open()
489 /* Set 8 bit, no parity, 1 stop bit -- documented */ in umcs7840_cfg_open()
490 sc->sc_ports[pn].sc_lcr = MCS7840_UART_LCR_DATALEN8 | MCS7840_UART_LCR_STOPB1; in umcs7840_cfg_open()
491 if (umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_LCR, sc->sc_ports[pn].sc_lcr)) in umcs7840_cfg_open()
495 * Enable DTR/RTS on modem control, enable modem interrupts -- in umcs7840_cfg_open()
498 sc->sc_ports[pn].sc_mcr = MCS7840_UART_MCR_IE; in umcs7840_cfg_open()
499 if (ucom->sc_tty == NULL || (ucom->sc_tty->t_termios.c_cflag & CNO_RTSDTR) == 0) in umcs7840_cfg_open()
500 sc->sc_ports[pn].sc_mcr |= MCS7840_UART_MCR_DTR | MCS7840_UART_MCR_RTS; in umcs7840_cfg_open()
501 if (umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_MCR, sc->sc_ports[pn].sc_mcr)) in umcs7840_cfg_open()
518 /* Finally enable all interrupts -- documented */ in umcs7840_cfg_open()
523 if (umcs7840_get_UART_reg_sync(sc, pn, MCS7840_UART_REG_LCR, &sc->sc_ports[pn].sc_lcr)) in umcs7840_cfg_open()
529 /* Enable RX */ in umcs7840_cfg_open()
542 struct umcs7840_softc *sc = ucom->sc_parent; in umcs7840_cfg_close()
543 uint16_t pn = ucom->sc_portno; in umcs7840_cfg_close()
564 struct umcs7840_softc *sc = ucom->sc_parent; in umcs7840_cfg_set_dtr()
565 uint8_t pn = ucom->sc_portno; in umcs7840_cfg_set_dtr()
568 sc->sc_ports[pn].sc_mcr |= MCS7840_UART_MCR_DTR; in umcs7840_cfg_set_dtr()
570 sc->sc_ports[pn].sc_mcr &= ~MCS7840_UART_MCR_DTR; in umcs7840_cfg_set_dtr()
572 umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_MCR, sc->sc_ports[pn].sc_mcr); in umcs7840_cfg_set_dtr()
579 struct umcs7840_softc *sc = ucom->sc_parent; in umcs7840_cfg_set_rts()
580 uint8_t pn = ucom->sc_portno; in umcs7840_cfg_set_rts()
583 sc->sc_ports[pn].sc_mcr |= MCS7840_UART_MCR_RTS; in umcs7840_cfg_set_rts()
585 sc->sc_ports[pn].sc_mcr &= ~MCS7840_UART_MCR_RTS; in umcs7840_cfg_set_rts()
587 umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_MCR, sc->sc_ports[pn].sc_mcr); in umcs7840_cfg_set_rts()
594 struct umcs7840_softc *sc = ucom->sc_parent; in umcs7840_cfg_set_break()
595 uint8_t pn = ucom->sc_portno; in umcs7840_cfg_set_break()
598 sc->sc_ports[pn].sc_lcr |= MCS7840_UART_LCR_BREAK; in umcs7840_cfg_set_break()
600 sc->sc_ports[pn].sc_lcr &= ~MCS7840_UART_LCR_BREAK; in umcs7840_cfg_set_break()
602 umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_LCR, sc->sc_ports[pn].sc_lcr); in umcs7840_cfg_set_break()
609 struct umcs7840_softc *sc = ucom->sc_parent; in umcs7840_cfg_param()
610 uint8_t pn = ucom->sc_portno; in umcs7840_cfg_param()
611 uint8_t lcr = sc->sc_ports[pn].sc_lcr; in umcs7840_cfg_param()
612 uint8_t mcr = sc->sc_ports[pn].sc_mcr; in umcs7840_cfg_param()
615 if (t->c_cflag & CSTOPB) { in umcs7840_cfg_param()
624 if (t->c_cflag & PARENB) { in umcs7840_cfg_param()
626 if (t->c_cflag & PARODD) { in umcs7840_cfg_param()
628 DPRINTF(" parity on - odd\n"); in umcs7840_cfg_param()
631 DPRINTF(" parity on - even\n"); in umcs7840_cfg_param()
639 switch (t->c_cflag & CSIZE) { in umcs7840_cfg_param()
658 if (t->c_cflag & CRTSCTS) { in umcs7840_cfg_param()
664 if (t->c_cflag & (CDTR_IFLOW | CDSR_OFLOW)) { in umcs7840_cfg_param()
670 sc->sc_ports[pn].sc_lcr = lcr; in umcs7840_cfg_param()
671 umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_LCR, sc->sc_ports[pn].sc_lcr); in umcs7840_cfg_param()
672 DPRINTF("Port %d LCR=%02x\n", pn, sc->sc_ports[pn].sc_lcr); in umcs7840_cfg_param()
674 sc->sc_ports[pn].sc_mcr = mcr; in umcs7840_cfg_param()
675 umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_MCR, sc->sc_ports[pn].sc_mcr); in umcs7840_cfg_param()
676 DPRINTF("Port %d MCR=%02x\n", pn, sc->sc_ports[pn].sc_mcr); in umcs7840_cfg_param()
678 umcs7840_set_baudrate(sc, pn, t->c_ospeed); in umcs7840_cfg_param()
687 if (umcs7840_calc_baudrate(t->c_ospeed, &divisor, &clk) || !divisor) in umcs7840_pre_param()
695 struct umcs7840_softc *sc = ucom->sc_parent; in umcs7840_start_read()
696 uint8_t pn = ucom->sc_portno; in umcs7840_start_read()
698 /* Start interrupt transfer */ in umcs7840_start_read()
699 usbd_transfer_start(sc->sc_intr_xfer); in umcs7840_start_read()
702 usbd_transfer_start(sc->sc_ports[pn].sc_xfer[UMCS7840_BULK_RD_EP]); in umcs7840_start_read()
708 struct umcs7840_softc *sc = ucom->sc_parent; in umcs7840_stop_read()
709 uint8_t pn = ucom->sc_portno; in umcs7840_stop_read()
712 usbd_transfer_stop(sc->sc_ports[pn].sc_xfer[UMCS7840_BULK_RD_EP]); in umcs7840_stop_read()
718 struct umcs7840_softc *sc = ucom->sc_parent; in umcs7840_start_write()
719 uint8_t pn = ucom->sc_portno; in umcs7840_start_write()
721 /* Start interrupt transfer */ in umcs7840_start_write()
722 usbd_transfer_start(sc->sc_intr_xfer); in umcs7840_start_write()
725 usbd_transfer_start(sc->sc_ports[pn].sc_xfer[UMCS7840_BULK_WR_EP]); in umcs7840_start_write()
731 struct umcs7840_softc *sc = ucom->sc_parent; in umcs7840_stop_write()
732 uint8_t pn = ucom->sc_portno; in umcs7840_stop_write()
735 usbd_transfer_stop(sc->sc_ports[pn].sc_xfer[UMCS7840_BULK_WR_EP]); in umcs7840_stop_write()
741 struct umcs7840_softc *sc = ucom->sc_parent; in umcs7840_cfg_get_status()
742 uint8_t pn = ucom->sc_portno; in umcs7840_cfg_get_status()
743 uint8_t hw_msr = 0; /* local modem status register */ in umcs7840_cfg_get_status()
764 DPRINTF("Port %d status: LSR=%02x MSR=%02x\n", ucom->sc_portno, *lsr, *msr); in umcs7840_cfg_get_status()
784 for (subunit = 0; subunit < sc->sc_numports; ++subunit) { in umcs7840_intr_callback()
785 uint8_t pn = sc->sc_ucom[subunit].sc_portno; in umcs7840_intr_callback()
789 …DPRINTF("Port %d has pending interrupt: %02x (FIFO: %02x)\n", pn, buf[pn] & MCS7840_UART_ISR_INTMA… in umcs7840_intr_callback()
795 ucom_status_change(&sc->sc_ucom[subunit]); in umcs7840_intr_callback()
803 device_printf(sc->sc_dev, "Invalid interrupt data length %d", actlen); in umcs7840_intr_callback()
848 struct ucom_softc *ucom = &sc->sc_ucom[subunit]; in umcs7840_read_callbackN()
854 …DPRINTF("Port %d read, state = %d, data length = %d\n", ucom->sc_portno, USB_GET_STATE(xfer), actl… in umcs7840_read_callbackN()
905 struct ucom_softc *ucom = &sc->sc_ucom[subunit]; in umcs7840_write_callbackN()
909 DPRINTF("Port %d write, state = %d\n", ucom->sc_portno, USB_GET_STATE(xfer)); in umcs7840_write_callbackN()
917 DPRINTF("Port %d write, has %d bytes\n", ucom->sc_portno, actlen); in umcs7840_write_callbackN()
936 struct umcs7840_softc *sc = ucom->sc_parent; in umcs7840_poll()
938 DPRINTF("Port %d poll\n", ucom->sc_portno); in umcs7840_poll()
939 usbd_transfer_poll(sc->sc_ports[ucom->sc_portno].sc_xfer, UMCS7840_N_TRANSFERS); in umcs7840_poll()
940 usbd_transfer_poll(&sc->sc_intr_xfer, 1); in umcs7840_poll()
956 …err = usbd_do_request_proc(sc->sc_udev, &sc->sc_super_ucom.sc_tq, &req, (void *)data, 0, &len, UMC… in umcs7840_get_reg_sync()
958 device_printf(sc->sc_dev, "Reading register %d failed: invalid length %d\n", reg, len); in umcs7840_get_reg_sync()
961 device_printf(sc->sc_dev, "Reading register %d failed: %s\n", reg, usbd_errstr(err)); in umcs7840_get_reg_sync()
977 …err = usbd_do_request_proc(sc->sc_udev, &sc->sc_super_ucom.sc_tq, &req, NULL, 0, NULL, UMCS7840_CT… in umcs7840_set_reg_sync()
979 device_printf(sc->sc_dev, "Writing register %d failed: %s\n", reg, usbd_errstr(err)); in umcs7840_set_reg_sync()
1001 …err = usbd_do_request_proc(sc->sc_udev, &sc->sc_super_ucom.sc_tq, &req, (void *)data, 0, &len, UMC… in umcs7840_get_UART_reg_sync()
1003 …device_printf(sc->sc_dev, "Reading UART%d register %d failed: invalid length %d\n", portno, reg, l… in umcs7840_get_UART_reg_sync()
1006 …device_printf(sc->sc_dev, "Reading UART%d register %d failed: %s\n", portno, reg, usbd_errstr(err)… in umcs7840_get_UART_reg_sync()
1026 …err = usbd_do_request_proc(sc->sc_udev, &sc->sc_super_ucom.sc_tq, &req, NULL, 0, NULL, UMCS7840_CT… in umcs7840_set_UART_reg_sync()
1028 …device_printf(sc->sc_dev, "Writing UART%d register %d failed: %s\n", portno, reg, usbd_errstr(err)… in umcs7840_set_UART_reg_sync()
1042 return (-1); in umcs7840_set_baudrate()
1046 return (-1); in umcs7840_set_baudrate()
1061 sc->sc_ports[portno].sc_lcr |= MCS7840_UART_LCR_DIVISORS; in umcs7840_set_baudrate()
1062 err = umcs7840_set_UART_reg_sync(sc, portno, MCS7840_UART_REG_LCR, sc->sc_ports[portno].sc_lcr); in umcs7840_set_baudrate()
1074 sc->sc_ports[portno].sc_lcr &= ~MCS7840_UART_LCR_DIVISORS; in umcs7840_set_baudrate()
1075 err = umcs7840_set_UART_reg_sync(sc, portno, MCS7840_UART_REG_LCR, sc->sc_ports[portno].sc_lcr); in umcs7840_set_baudrate()
1090 if (rate > umcs7840_baudrate_divisors[umcs7840_baudrate_divisors_len - 1]) in umcs7840_calc_baudrate()
1091 return (-1); in umcs7840_calc_baudrate()
1093 for (i = 0; i < umcs7840_baudrate_divisors_len - 1 && in umcs7840_calc_baudrate()