45#include <sys/stdint.h>
46#include <sys/stddef.h>
51#include <sys/kernel.h>
53#include <sys/linker_set.h>
54#include <sys/module.h>
57#include <sys/condvar.h>
58#include <sys/sysctl.h>
60#include <sys/unistd.h>
61#include <sys/callout.h>
62#include <sys/malloc.h>
71#define USB_DEBUG_VAR umcs_debug
79#define UMCS7840_MODVER 1
82static int umcs_debug = 0;
84static SYSCTL_NODE(_hw_usb, OID_AUTO, umcs, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
85 "USB umcs quadport serial adapter");
86SYSCTL_INT(_hw_usb_umcs, OID_AUTO,
debug, CTLFLAG_RWTUN, &umcs_debug, 0,
"Debug level");
207 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
217 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
229 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
260 {
USB_VPI(USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7820, 0)},
261 {
USB_VPI(USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7840, 0)},
316 mtx_init(&sc->
sc_mtx,
"umcs7840", NULL, MTX_DEF);
350 device_printf(
dev,
"On-die confguration: RST: active %s, HRD: %s, PLL: %s, POR: %s, Ports: %s, EEPROM write %s, IrDA is %savailable\n",
360 for (subunit = 0; subunit < sc->
sc_numports; ++subunit) {
370 device_printf(
dev,
"allocating USB transfers failed for subunit %d of %d\n",
379 device_printf(
dev,
"allocating USB transfers failed for interrupt\n");
384 for (subunit = 0; subunit < sc->
sc_numports; ++subunit) {
412 for (subunit = 0; subunit < sc->
sc_numports; ++subunit)
416 device_claim_softc(
dev);
430 device_free_softc(sc);
466 data &= ~MCS7840_DEV_SPx_UART_RESET;
503 if (ucom->
sc_tty == NULL || (ucom->
sc_tty->t_termios.c_cflag & CNO_RTSDTR) == 0)
536 data &= ~MCS7840_DEV_CONTROLx_RX_DISABLE;
540 DPRINTF(
"Port %d has been opened\n", pn);
562 DPRINTF(
"Port %d has been closed\n", pn);
577 DPRINTF(
"Port %d DTR set to: %s\n", pn, onoff ?
"on" :
"off");
592 DPRINTF(
"Port %d RTS set to: %s\n", pn, onoff ?
"on" :
"off");
607 DPRINTF(
"Port %d BREAK set to: %s\n", pn, onoff ?
"on" :
"off");
618 DPRINTF(
"Port %d config:\n", pn);
619 if (t->c_cflag & CSTOPB) {
627 lcr &= ~MCS7840_UART_LCR_PARITYMASK;
628 if (t->c_cflag & PARENB) {
630 if (t->c_cflag & PARODD) {
635 DPRINTF(
" parity on - even\n");
638 lcr &= ~MCS7840_UART_LCR_PARITYON;
642 lcr &= ~MCS7840_UART_LCR_DATALENMASK;
643 switch (t->c_cflag & CSIZE) {
662 if (t->c_cflag & CRTSCTS) {
666 mcr &= ~MCS7840_UART_MCR_CTSRTS;
668 if (t->c_cflag & (CDTR_IFLOW | CDSR_OFLOW)) {
672 mcr &= ~MCS7840_UART_MCR_DTRDSR;
768 DPRINTF(
"Port %d status: LSR=%02x MSR=%02x\n", ucom->
sc_portno, *lsr, *msr);
784 if (actlen == 5 || actlen == 13) {
788 for (subunit = 0; subunit < sc->
sc_numports; ++subunit) {
807 device_printf(sc->
sc_dev,
"Invalid interrupt data length %d", actlen);
962 device_printf(sc->
sc_dev,
"Reading register %d failed: invalid length %d\n",
reg,
len);
997 wVal = ((uint16_t)(portno + 1)) << 8;
1007 device_printf(sc->
sc_dev,
"Reading UART%d register %d failed: invalid length %d\n", portno,
reg,
len);
1010 device_printf(sc->
sc_dev,
"Reading UART%d register %d failed: %s\n", portno,
reg,
usbd_errstr(err));
1022 wVal = ((uint16_t)(portno + 1)) << 8 |
data;
1032 device_printf(sc->
sc_dev,
"Writing UART%d register %d failed: %s\n", portno,
reg,
usbd_errstr(err));
1045 DPRINTF(
"Port %d bad speed: %d\n", portno, rate);
1049 DPRINTF(
"Port %d bad speed calculation: %d\n", portno, rate);
1052 DPRINTF(
"Port %d set speed: %d (%02x / %d)\n", portno, rate, clk, divisor);
static SYSCTL_NODE(_hw_usb, OID_AUTO, dwc_otg, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "USB DWC OTG")
SYSCTL_INT(_hw_usb_dwc_otg, OID_AUTO, phy_type, CTLFLAG_RDTUN, &dwc_otg_phy_type, 0, "DWC OTG PHY TYPE - 0/1/2/3 - ULPI/HSIC/INTERNAL/UTMI+")
void(* ucom_cfg_get_status)(struct ucom_softc *, uint8_t *plsr, uint8_t *pmsr)
struct usb_xfer * sc_xfer[UMCS7840_N_TRANSFERS]
struct ucom_super_softc sc_super_ucom
struct usb_device * sc_udev
struct umcs7840_softc_oneport sc_ports[UMCS7840_MAX_PORTS]
struct usb_xfer * sc_intr_xfer
struct ucom_softc sc_ucom[UMCS7840_MAX_PORTS]
enum usb_hc_mode usb_mode
struct usbd_lookup_info info
struct usb_device * device
usb_callback_t * callback
static usb_callback_t umcs7840_intr_callback
static void umcs7840_read_callbackN(struct usb_xfer *, usb_error_t, uint8_t)
static struct ucom_callback umcs7840_callback
static usb_error_t umcs7840_set_UART_reg_sync(struct umcs7840_softc *, uint8_t, uint8_t, uint8_t)
static const struct usb_config umcs7840_bulk_config_data[UMCS7840_N_TRANSFERS]
static device_detach_t umcs7840_detach
static usb_callback_t umcs7840_write_callback1
static void umcs7840_cfg_set_break(struct ucom_softc *, uint8_t)
static void umcs7840_stop_read(struct ucom_softc *)
DRIVER_MODULE(umcs7840, uhub, umcs7840_driver, umcs7840_devclass, 0, 0)
static usb_callback_t umcs7840_write_callback3
static void umcs7840_cfg_open(struct ucom_softc *)
static const uint32_t umcs7840_baudrate_divisors[]
static usb_error_t umcs7840_set_reg_sync(struct umcs7840_softc *, uint8_t, uint8_t)
static void umcs7840_cfg_set_dtr(struct ucom_softc *, uint8_t)
static const uint8_t umcs7840_baudrate_divisors_len
static usb_error_t umcs7840_get_reg_sync(struct umcs7840_softc *, uint8_t, uint8_t *)
static usb_error_t umcs7840_set_baudrate(struct umcs7840_softc *, uint8_t, uint32_t)
MODULE_VERSION(umcs7840, UMCS7840_MODVER)
MODULE_DEPEND(umcs7840, ucom, 1, 1, 1)
static const STRUCT_USB_HOST_ID umcs7840_devs[]
static void umcs7840_cfg_close(struct ucom_softc *)
static void umcs7840_free_softc(struct umcs7840_softc *)
static void umcs7840_cfg_param(struct ucom_softc *, struct termios *)
static usb_error_t umcs7840_calc_baudrate(uint32_t rate, uint16_t *, uint8_t *)
static usb_callback_t umcs7840_read_callback2
static devclass_t umcs7840_devclass
USB_PNP_HOST_INFO(umcs7840_devs)
static void umcs7840_start_write(struct ucom_softc *)
static usb_callback_t umcs7840_write_callback4
static usb_callback_t umcs7840_read_callback3
static int umcs7840_pre_param(struct ucom_softc *, struct termios *)
static device_method_t umcs7840_methods[]
static usb_callback_t * umcs7840_rw_callbacks[UMCS7840_MAX_PORTS][UMCS7840_N_TRANSFERS]
static void umcs7840_stop_write(struct ucom_softc *)
static void umcs7840_start_read(struct ucom_softc *)
static usb_callback_t umcs7840_write_callback2
static void umcs7840_write_callbackN(struct usb_xfer *, usb_error_t, uint8_t)
UCOM_UNLOAD_DRAIN(umcs7840)
static usb_callback_t umcs7840_read_callback1
static void umcs7840_cfg_get_status(struct ucom_softc *, uint8_t *, uint8_t *)
static usb_callback_t umcs7840_read_callback4
static usb_error_t umcs7840_get_UART_reg_sync(struct umcs7840_softc *, uint8_t, uint8_t, uint8_t *)
static device_probe_t umcs7840_probe
static void umcs7840_cfg_set_rts(struct ucom_softc *, uint8_t)
static const struct usb_config umcs7840_intr_config_data[1]
static device_attach_t umcs7840_attach
static driver_t umcs7840_driver
static void umcs7840_poll(struct ucom_softc *ucom)
static void umcs7840_free(struct ucom_softc *)
#define MCS7840_DEV_SPx_CLOCK_SHIFT
#define MCS7840_DEV_REG_SP2
#define MCS7840_UART_LCR_PARITYEVEN
#define UMCS7840_CTRL_TIMEOUT
#define MCS7840_DEV_SPx_RESET_IN_FIFO
#define UMCS7840_MAX_PORTS
#define MCS7840_UART_REG_FCR
#define MCS7840_DEV_REG_CONTROL2
#define MCS7840_DEV_SPx_UART_RESET
#define MCS7840_UART_FCR_RTL_1_14
#define MCS7840_UART_REG_DLL
#define MCS7840_DEV_REG_CONTROL1
#define MCS7840_UART_REG_IER
#define MCS7840_UART_FCR_ENABLE
#define MCS7840_IFACE_INDEX
#define MCS7840_UART_IER_RXSTAT
#define MCS7840_DEV_CONTROLx_RX_DISABLE
#define MCS7840_UART_LCR_PARITYODD
#define MCS7840_UART_MCR_IE
#define MCS7840_DEV_MODE_IRDA
#define MCS7840_DEV_REG_MODE
#define MCS7840_UART_REG_LSR
#define MCS7840_DEV_MODE_SER_PRSNT
#define MCS7840_DEV_MODE_EEPROMWR
#define MCS7840_UART_REG_MSR
#define MCS7840_UART_LCR_STOPB2
#define MCS7840_UART_MCR_DTR
#define MCS7840_UART_MSR_NEGDCD
#define MCS7840_UART_ISR_NOPENDING
#define MCS7840_UART_LCR_DATALEN6
#define MCS7840_DEV_MODE_RESET
#define MCS7840_UART_ISR_INTMASK
#define MCS7840_UART_MSR_NEGRI
#define MCS7840_UART_LCR_BREAK
#define MCS7840_UART_LCR_DATALEN8
#define MCS7840_DEV_REG_SP3
#define MCS7840_DEV_CONTROL1_DRIVER_DONE
#define MCS7840_DEV_REG_CONTROL4
#define MCS7840_UART_FCR_FLUSHTHR
#define MCS7840_UART_MSR_NEGCTS
#define MCS7840_DEV_REG_GPIO
#define MCS7840_UART_ISR_RXHASDATA
#define MCS7840_UART_MCR_RTS
#define MCS7840_UART_ISR_RXERR
#define MCS7840_UART_MCR_DTRDSR
#define MCS7840_UART_REG_LCR
#define MCS7840_UART_MCR_CTSRTS
#define MCS7840_UART_MSR_NEGDSR
#define MCS7840_UART_LCR_DIVISORS
#define MCS7840_DEV_REG_CONTROL3
#define MCS7840_UART_REG_MCR
#define MCS7840_UART_LCR_DATALEN5
#define MCS7840_UART_LCR_PARITYON
#define MCS7840_DEV_GPIO_4PORTS
#define MCS7840_UART_ISR_RXTIMEOUT
#define MCS7840_DEV_MODE_PLLBYPASS
#define MCS7840_DEV_REG_DCR0_4
#define MCS7840_UART_IER_MODEM
#define MCS7840_UART_LCR_DATALEN7
#define MCS7840_UART_LCR_STOPB1
#define MCS7840_DEV_MODE_SELECT24S
#define MCS7840_DEV_REG_DCR0_2
#define UMCS7840_READ_LENGTH
#define MCS7840_DEV_SPx_RESET_OUT_FIFO
#define MCS7840_DEV_REG_DCR0_1
#define MCS7840_DEV_REG_SP1
#define MCS7840_DEV_MODE_PORBYPASS
#define MCS7840_DEV_REG_SP4
#define MCS7840_DEV_SPx_CLOCK_MASK
#define MCS7840_UART_REG_SCRATCHPAD
#define MCS7840_UART_FCR_FLUSHRHR
#define MCS7840_UART_ISR_MSCHANGE
#define MCS7840_UART_REG_DLM
#define MCS7840_CONFIG_INDEX
#define MCS7840_DEV_REG_DCR0_3
#define MCS7840_UART_SCRATCHPAD_RS232
#define UT_WRITE_VENDOR_DEVICE
#define UT_READ_VENDOR_DEVICE
void usbd_copy_out(struct usb_page_cache *cache, usb_frlength_t offset, void *ptr, usb_frlength_t len)
const char * usbd_errstr(usb_error_t err)
int usbd_lookup_id_by_uaa(const struct usb_device_id *id, usb_size_t sizeof_id, struct usb_attach_arg *uaa)
usb_error_t usbd_do_request_proc(struct usb_device *udev, struct usb_process *pproc, struct usb_device_request *req, void *data, uint16_t flags, uint16_t *actlen, usb_timeout_t timeout)
uint8_t ucom_get_data(struct ucom_softc *sc, struct usb_page_cache *pc, uint32_t offset, uint32_t len, uint32_t *actlen)
void ucom_status_change(struct ucom_softc *sc)
int ucom_attach(struct ucom_super_softc *ssc, struct ucom_softc *sc, int subunits, void *parent, const struct ucom_callback *callback, struct mtx *mtx)
int ucom_unref(struct ucom_super_softc *ssc)
void ucom_ref(struct ucom_super_softc *ssc)
void ucom_set_pnpinfo_usb(struct ucom_super_softc *ssc, device_t dev)
void ucom_detach(struct ucom_super_softc *ssc, struct ucom_softc *sc)
void ucom_put_data(struct ucom_softc *sc, struct usb_page_cache *pc, uint32_t offset, uint32_t len)
void usbd_transfer_submit(struct usb_xfer *xfer)
void usbd_transfer_unsetup(struct usb_xfer **pxfer, uint16_t n_setup)
void usbd_xfer_set_frame_len(struct usb_xfer *xfer, usb_frcount_t frindex, usb_frlength_t len)
struct usb_page_cache * usbd_xfer_get_frame(struct usb_xfer *xfer, usb_frcount_t frindex)
usb_error_t usbd_transfer_setup(struct usb_device *udev, const uint8_t *ifaces, struct usb_xfer **ppxfer, const struct usb_config *setup_start, uint16_t n_setup, void *priv_sc, struct mtx *xfer_mtx)
void usbd_transfer_start(struct usb_xfer *xfer)
void usbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max)
void * usbd_xfer_softc(struct usb_xfer *xfer)
void usbd_xfer_set_stall(struct usb_xfer *xfer)
void usbd_transfer_stop(struct usb_xfer *xfer)
void usbd_xfer_status(struct usb_xfer *xfer, int *actlen, int *sumlen, int *aframes, int *nframes)
usb_frlength_t usbd_xfer_max_len(struct usb_xfer *xfer)
void device_set_usb_desc(device_t dev)
@ USB_ERR_NORMAL_COMPLETION
#define USB_ST_TRANSFERRED
void() usb_callback_t(struct usb_xfer *, usb_error_t)
#define USB_VPI(vend, prod, info)
#define STRUCT_USB_HOST_ID
#define USB_GET_STATE(xfer)