1 /* $OpenBSD: umcs.c,v 1.8 2020/07/31 10:49:33 mglocker Exp $ */ 2 /* $NetBSD: umcs.c,v 1.8 2014/08/23 21:37:56 martin Exp $ */ 3 /* $FreeBSD: head/sys/dev/usb/serial/umcs.c 260559 2014-01-12 11:44:28Z hselasky $ */ 4 5 /*- 6 * Copyright (c) 2010 Lev Serebryakov <lev@FreeBSD.org>. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 /* 32 * This driver supports several multiport USB-to-RS232 serial adapters driven 33 * by MosChip mos7820 and mos7840, bridge chips. The adapters are sold under 34 * many different brand names. 35 * 36 * Datasheets are available at MosChip www site at http://www.moschip.com. 37 * The datasheets don't contain full programming information for the chip. 38 * 39 * It is nornal to have only two enabled ports in devices, based on quad-port 40 * mos7840. 41 */ 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/kernel.h> 46 #include <sys/malloc.h> 47 #include <sys/tty.h> 48 #include <sys/device.h> 49 #include <sys/task.h> 50 51 #include <dev/usb/usb.h> 52 #include <dev/usb/usbdi.h> 53 #include <dev/usb/usbdi_util.h> 54 #include <dev/usb/usbdevs.h> 55 56 #include <dev/usb/ucomvar.h> 57 58 #include "umcs.h" 59 60 #ifdef UMCS_DEBUG 61 #define DPRINTF(x...) printf(x) 62 #else 63 #define DPRINTF(x...) 64 #endif 65 66 #define DEVNAME(_sc) ((_sc)->sc_dev.dv_xname) 67 68 /* 69 * Two-port devices (both with 7820 chip and 7840 chip configured as two-port) 70 * have ports 0 and 2, with ports 1 and 3 omitted. 71 * So, PHYSICAL port numbers on two-port device will be 0 and 2. 72 * 73 * We use an array of the following struct, indexed by ucom port index, 74 * and include the physical port number in it. 75 */ 76 struct umcs_port { 77 struct ucom_softc *ucom; /* ucom subdevice */ 78 unsigned int pn; /* physical port number */ 79 int flags; 80 #define UMCS_STATCHG 0x01 81 82 uint8_t lcr; /* local line control reg. */ 83 uint8_t mcr; /* local modem control reg. */ 84 }; 85 86 struct umcs_softc { 87 struct device sc_dev; 88 struct usbd_device *sc_udev; /* the usb device */ 89 struct usbd_pipe *sc_ipipe; /* interrupt pipe */ 90 uint8_t *sc_ibuf; /* buffer for interrupt xfer */ 91 unsigned int sc_isize; /* size of buffer */ 92 93 struct umcs_port sc_subdevs[UMCS_MAX_PORTS]; 94 uint8_t sc_numports; /* number of ports */ 95 96 int sc_init_done; 97 struct task sc_status_task; 98 }; 99 100 int umcs_get_reg(struct umcs_softc *, uint8_t, uint8_t *); 101 int umcs_set_reg(struct umcs_softc *, uint8_t, uint8_t); 102 int umcs_get_uart_reg(struct umcs_softc *, uint8_t, uint8_t, uint8_t *); 103 int umcs_set_uart_reg(struct umcs_softc *, uint8_t, uint8_t, uint8_t); 104 int umcs_calc_baudrate(uint32_t, uint16_t *, uint8_t *); 105 int umcs_set_baudrate(struct umcs_softc *, uint8_t, uint32_t); 106 void umcs_dtr(struct umcs_softc *, int, int); 107 void umcs_rts(struct umcs_softc *, int, int); 108 void umcs_break(struct umcs_softc *, int, int); 109 110 int umcs_match(struct device *, void *, void *); 111 void umcs_attach(struct device *, struct device *, void *); 112 int umcs_detach(struct device *, int); 113 void umcs_intr(struct usbd_xfer *, void *, usbd_status); 114 void umcs_status_task(void *); 115 116 void umcs_get_status(void *, int, uint8_t *, uint8_t *); 117 void umcs_set(void *, int, int, int); 118 int umcs_param(void *, int, struct termios *); 119 int umcs_open(void *, int); 120 void umcs_close(void *, int); 121 122 struct ucom_methods umcs_methods = { 123 umcs_get_status, 124 umcs_set, 125 umcs_param, 126 NULL, 127 umcs_open, 128 umcs_close, 129 NULL, 130 NULL, 131 }; 132 133 const struct usb_devno umcs_devs[] = { 134 { USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7810 }, 135 { USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7820 }, 136 { USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7840 }, 137 { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC2324 } 138 }; 139 140 struct cfdriver umcs_cd = { 141 NULL, "umcs", DV_DULL 142 }; 143 144 const struct cfattach umcs_ca = { 145 sizeof(struct umcs_softc), umcs_match, umcs_attach, umcs_detach 146 }; 147 148 149 static inline int 150 umcs_reg_sp(int pn) 151 { 152 KASSERT(pn >= 0 && pn < 4); 153 switch (pn) { 154 default: 155 case 0: return UMCS_SP1; 156 case 1: return UMCS_SP2; 157 case 2: return UMCS_SP3; 158 case 3: return UMCS_SP4; 159 } 160 } 161 162 static inline int 163 umcs_reg_ctrl(int pn) 164 { 165 KASSERT(pn >= 0 && pn < 4); 166 switch (pn) { 167 default: 168 case 0: return UMCS_CTRL1; 169 case 1: return UMCS_CTRL2; 170 case 2: return UMCS_CTRL3; 171 case 3: return UMCS_CTRL4; 172 } 173 } 174 175 int 176 umcs_match(struct device *dev, void *match, void *aux) 177 { 178 struct usb_attach_arg *uaa = aux; 179 180 if (uaa->iface == NULL || uaa->ifaceno != UMCS_IFACE_NO) 181 return (UMATCH_NONE); 182 183 return (usb_lookup(umcs_devs, uaa->vendor, uaa->product) != NULL) ? 184 UMATCH_VENDOR_PRODUCT : UMATCH_NONE; 185 } 186 187 void 188 umcs_attach(struct device *parent, struct device *self, void *aux) 189 { 190 struct umcs_softc *sc = (struct umcs_softc *)self; 191 struct usb_attach_arg *uaa = aux; 192 usb_interface_descriptor_t *id; 193 usb_endpoint_descriptor_t *ed; 194 struct ucom_attach_args uca; 195 int error, i, intr_addr; 196 uint8_t data; 197 198 sc->sc_udev = uaa->device; 199 200 /* 201 * Get number of ports 202 * Documentation (full datasheet) says, that number of ports is 203 * set as UMCS_MODE_SELECT24S bit in MODE R/Only 204 * register. But vendor driver uses these undocumented 205 * register & bit. 206 * 207 * Experiments show, that MODE register can have `0' 208 * (4 ports) bit on 2-port device, so use vendor driver's way. 209 * 210 * Also, see notes in header file for these constants. 211 */ 212 if (umcs_get_reg(sc, UMCS_GPIO, &data)) { 213 printf("%s: unable to get number of ports\n", DEVNAME(sc)); 214 usbd_deactivate(sc->sc_udev); 215 return; 216 } 217 if (data & UMCS_GPIO_4PORTS) 218 sc->sc_numports = 4; /* physical port no are : 0, 1, 2, 3 */ 219 else if (uaa->product == USB_PRODUCT_MOSCHIP_MCS7810) 220 sc->sc_numports = 1; 221 else 222 sc->sc_numports = 2; /* physical port no are: 0 and 2 */ 223 224 #ifdef UMCS_DEBUG 225 if (!umcs_get_reg(sc, UMCS_MODE, &data)) { 226 printf("%s: On-die confguration: RST: active %s, " 227 "HRD: %s, PLL: %s, POR: %s, Ports: %s, EEPROM write %s, " 228 "IrDA is %savailable\n", DEVNAME(sc), 229 (data & UMCS_MODE_RESET) ? "low" : "high", 230 (data & UMCS_MODE_SER_PRSNT) ? "yes" : "no", 231 (data & UMCS_MODE_PLLBYPASS) ? "bypassed" : "avail", 232 (data & UMCS_MODE_PORBYPASS) ? "bypassed" : "avail", 233 (data & UMCS_MODE_SELECT24S) ? "2" : "4", 234 (data & UMCS_MODE_EEPROMWR) ? "enabled" : "disabled", 235 (data & UMCS_MODE_IRDA) ? "" : "not "); 236 } 237 #endif 238 239 /* Set up the interrupt pipe */ 240 id = usbd_get_interface_descriptor(uaa->iface); 241 intr_addr = -1; 242 for (i = 0 ; i < id->bNumEndpoints ; i++) { 243 ed = usbd_interface2endpoint_descriptor(uaa->iface, i); 244 if (ed == NULL) { 245 printf("%s: no endpoint descriptor found for %d\n", 246 DEVNAME(sc), i); 247 usbd_deactivate(sc->sc_udev); 248 return; 249 } 250 251 if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN || 252 UE_GET_XFERTYPE(ed->bmAttributes) != UE_INTERRUPT) 253 continue; 254 sc->sc_isize = UGETW(ed->wMaxPacketSize); 255 intr_addr = ed->bEndpointAddress; 256 break; 257 } 258 if (intr_addr < 0) { 259 printf("%s: missing endpoint\n", DEVNAME(sc)); 260 usbd_deactivate(sc->sc_udev); 261 return; 262 } 263 sc->sc_ibuf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK); 264 265 error = usbd_open_pipe_intr(uaa->iface, intr_addr, 266 USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_ibuf, 267 sc->sc_isize, umcs_intr, 100 /* XXX */); 268 if (error) { 269 printf("%s: cannot open interrupt pipe (addr %d)\n", 270 DEVNAME(sc), intr_addr); 271 usbd_deactivate(sc->sc_udev); 272 return; 273 } 274 275 memset(&uca, 0, sizeof uca); 276 uca.ibufsize = 256; 277 uca.obufsize = 256; 278 uca.ibufsizepad = 256; 279 uca.opkthdrlen = 0; 280 uca.device = sc->sc_udev; 281 uca.iface = uaa->iface; 282 uca.methods = &umcs_methods; 283 uca.arg = sc; 284 285 for (i = 0; i < sc->sc_numports; i++) { 286 uca.bulkin = uca.bulkout = -1; 287 288 /* 289 * On 4 port cards, endpoints are 0/1, 2/3, 4/5, and 6/7. 290 * On 2 port cards, they are 0/1 and 4/5. 291 * On single port, just 0/1 will be used. 292 */ 293 int pn = i * (sc->sc_numports == 2 ? 2 : 1); 294 295 ed = usbd_interface2endpoint_descriptor(uaa->iface, pn*2); 296 if (ed == NULL) { 297 printf("%s: no bulk in endpoint found for %d\n", 298 DEVNAME(sc), i); 299 usbd_deactivate(sc->sc_udev); 300 return; 301 } 302 uca.bulkin = ed->bEndpointAddress; 303 304 ed = usbd_interface2endpoint_descriptor(uaa->iface, pn*2+1); 305 if (ed == NULL) { 306 printf("%s: no bulk out endpoint found for %d\n", 307 DEVNAME(sc), i); 308 usbd_deactivate(sc->sc_udev); 309 return; 310 } 311 uca.bulkout = ed->bEndpointAddress; 312 uca.portno = i; 313 314 sc->sc_subdevs[i].pn = pn; 315 sc->sc_subdevs[i].ucom = (struct ucom_softc *) 316 config_found_sm(self, &uca, ucomprint, ucomsubmatch); 317 } 318 319 task_set(&sc->sc_status_task, umcs_status_task, sc); 320 } 321 322 int 323 umcs_get_reg(struct umcs_softc *sc, uint8_t reg, uint8_t *data) 324 { 325 usb_device_request_t req; 326 327 req.bmRequestType = UT_READ_VENDOR_DEVICE; 328 req.bRequest = UMCS_READ; 329 USETW(req.wValue, 0); 330 USETW(req.wIndex, reg); 331 USETW(req.wLength, UMCS_READ_LENGTH); 332 333 if (usbd_do_request(sc->sc_udev, &req, data)) 334 return (EIO); 335 336 return (0); 337 } 338 339 int 340 umcs_set_reg(struct umcs_softc *sc, uint8_t reg, uint8_t data) 341 { 342 usb_device_request_t req; 343 344 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 345 req.bRequest = UMCS_WRITE; 346 USETW(req.wValue, data); 347 USETW(req.wIndex, reg); 348 USETW(req.wLength, 0); 349 350 if (usbd_do_request(sc->sc_udev, &req, NULL)) 351 return (EIO); 352 353 return (0); 354 } 355 356 int 357 umcs_get_uart_reg(struct umcs_softc *sc, uint8_t portno, uint8_t reg, 358 uint8_t *data) 359 { 360 usb_device_request_t req; 361 uint16_t wVal; 362 363 wVal = ((uint16_t)(sc->sc_subdevs[portno].pn + 1)) << 8; 364 365 req.bmRequestType = UT_READ_VENDOR_DEVICE; 366 req.bRequest = UMCS_READ; 367 USETW(req.wValue, wVal); 368 USETW(req.wIndex, reg); 369 USETW(req.wLength, UMCS_READ_LENGTH); 370 371 if (usbd_do_request(sc->sc_udev, &req, data)) 372 return (EIO); 373 374 return (0); 375 } 376 377 int 378 umcs_set_uart_reg(struct umcs_softc *sc, uint8_t portno, uint8_t reg, 379 uint8_t data) 380 { 381 usb_device_request_t req; 382 uint16_t wVal; 383 384 wVal = ((uint16_t)(sc->sc_subdevs[portno].pn + 1)) << 8 | data; 385 386 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 387 req.bRequest = UMCS_WRITE; 388 USETW(req.wValue, wVal); 389 USETW(req.wIndex, reg); 390 USETW(req.wLength, 0); 391 392 if (usbd_do_request(sc->sc_udev, &req, NULL)) 393 return (EIO); 394 395 return (0); 396 } 397 398 int 399 umcs_set_baudrate(struct umcs_softc *sc, uint8_t portno, uint32_t rate) 400 { 401 int pn = sc->sc_subdevs[portno].pn; 402 int spreg = umcs_reg_sp(pn); 403 uint8_t lcr = sc->sc_subdevs[portno].lcr; 404 uint8_t clk, data; 405 uint16_t div; 406 407 if (umcs_calc_baudrate(rate, &div, &clk)) 408 return (EINVAL); 409 410 DPRINTF("%s: portno %d set speed: %d (%02x/%d)\n", DEVNAME(sc), portno, 411 rate, clk, div); 412 413 /* Set clock source for standard BAUD frequences */ 414 if (umcs_get_reg(sc, spreg, &data)) 415 return (EIO); 416 data &= UMCS_SPx_CLK_MASK; 417 if (umcs_set_reg(sc, spreg, data | clk)) 418 return (EIO); 419 420 /* Set divider */ 421 lcr |= UMCS_LCR_DIVISORS; 422 if (umcs_set_uart_reg(sc, portno, UMCS_REG_LCR, lcr)) 423 return (EIO); 424 sc->sc_subdevs[portno].lcr = lcr; 425 426 if (umcs_set_uart_reg(sc, portno, UMCS_REG_DLL, div & 0xff) || 427 umcs_set_uart_reg(sc, portno, UMCS_REG_DLM, (div >> 8) & 0xff)) 428 return (EIO); 429 430 /* Turn off access to DLL/DLM registers of UART */ 431 lcr &= ~UMCS_LCR_DIVISORS; 432 if (umcs_set_uart_reg(sc, portno, UMCS_REG_LCR, lcr)) 433 return (EIO); 434 sc->sc_subdevs[portno].lcr = lcr; 435 436 return (0); 437 } 438 439 /* Maximum speeds for standard frequences, when PLL is not used */ 440 static const uint32_t umcs_baudrate_divisors[] = { 441 0, 115200, 230400, 403200, 460800, 806400, 921600, 1572864, 3145728, 442 }; 443 444 int 445 umcs_calc_baudrate(uint32_t rate, uint16_t *divisor, uint8_t *clk) 446 { 447 const uint8_t divisors_len = nitems(umcs_baudrate_divisors); 448 uint8_t i = 0; 449 450 if (rate > umcs_baudrate_divisors[divisors_len - 1]) 451 return (-1); 452 453 for (i = 0; i < divisors_len - 1; i++) { 454 if (rate > umcs_baudrate_divisors[i] && 455 rate <= umcs_baudrate_divisors[i + 1]) { 456 *divisor = umcs_baudrate_divisors[i + 1] / rate; 457 /* 0x00 .. 0x70 */ 458 *clk = i << UMCS_SPx_CLK_SHIFT; 459 return (0); 460 } 461 } 462 463 return (-1); 464 } 465 466 int 467 umcs_detach(struct device *self, int flags) 468 { 469 struct umcs_softc *sc = (struct umcs_softc *)self; 470 471 task_del(systq, &sc->sc_status_task); 472 473 if (sc->sc_ipipe != NULL) { 474 usbd_close_pipe(sc->sc_ipipe); 475 sc->sc_ipipe = NULL; 476 } 477 478 if (sc->sc_ibuf != NULL) { 479 free(sc->sc_ibuf, M_USBDEV, sc->sc_isize); 480 sc->sc_ibuf = NULL; 481 } 482 483 return (config_detach_children(self, flags)); 484 } 485 486 void 487 umcs_get_status(void *self, int portno, uint8_t *lsr, uint8_t *msr) 488 { 489 struct umcs_softc *sc = self; 490 uint8_t hw_lsr = 0; /* local line status register */ 491 uint8_t hw_msr = 0; /* local modem status register */ 492 493 if (usbd_is_dying(sc->sc_udev)) 494 return; 495 496 /* Read LSR & MSR */ 497 if (umcs_get_uart_reg(sc, portno, UMCS_REG_LSR, &hw_lsr) || 498 umcs_get_uart_reg(sc, portno, UMCS_REG_MSR, &hw_msr)) 499 return; 500 501 *lsr = hw_lsr; 502 *msr = hw_msr; 503 } 504 505 void 506 umcs_set(void *self, int portno, int reg, int onoff) 507 { 508 struct umcs_softc *sc = self; 509 510 if (usbd_is_dying(sc->sc_udev)) 511 return; 512 513 switch (reg) { 514 case UCOM_SET_DTR: 515 umcs_dtr(sc, portno, onoff); 516 break; 517 case UCOM_SET_RTS: 518 umcs_rts(sc, portno, onoff); 519 break; 520 case UCOM_SET_BREAK: 521 umcs_break(sc, portno, onoff); 522 break; 523 default: 524 break; 525 } 526 } 527 528 int 529 umcs_param(void *self, int portno, struct termios *t) 530 { 531 struct umcs_softc *sc = self; 532 uint8_t lcr = sc->sc_subdevs[portno].lcr; 533 uint8_t mcr = sc->sc_subdevs[portno].mcr; 534 int error = 0; 535 536 if (t->c_cflag & CSTOPB) 537 lcr |= UMCS_LCR_STOPB2; 538 else 539 lcr |= UMCS_LCR_STOPB1; 540 541 lcr &= ~UMCS_LCR_PARITYMASK; 542 if (t->c_cflag & PARENB) { 543 lcr |= UMCS_LCR_PARITYON; 544 if (t->c_cflag & PARODD) { 545 lcr = UMCS_LCR_PARITYODD; 546 } else { 547 lcr = UMCS_LCR_PARITYEVEN; 548 } 549 } else { 550 lcr &= ~UMCS_LCR_PARITYON; 551 } 552 553 lcr &= ~UMCS_LCR_DATALENMASK; 554 switch (t->c_cflag & CSIZE) { 555 case CS5: 556 lcr |= UMCS_LCR_DATALEN5; 557 break; 558 case CS6: 559 lcr |= UMCS_LCR_DATALEN6; 560 break; 561 case CS7: 562 lcr |= UMCS_LCR_DATALEN7; 563 break; 564 case CS8: 565 lcr |= UMCS_LCR_DATALEN8; 566 break; 567 } 568 569 if (t->c_cflag & CRTSCTS) 570 mcr |= UMCS_MCR_CTSRTS; 571 else 572 mcr &= ~UMCS_MCR_CTSRTS; 573 574 if (t->c_cflag & CLOCAL) 575 mcr &= ~UMCS_MCR_DTRDSR; 576 else 577 mcr |= UMCS_MCR_DTRDSR; 578 579 if (umcs_set_uart_reg(sc, portno, UMCS_REG_LCR, lcr)) 580 return (EIO); 581 sc->sc_subdevs[portno].lcr = lcr; 582 583 if (umcs_set_uart_reg(sc, portno, UMCS_REG_MCR, mcr)) 584 return (EIO); 585 sc->sc_subdevs[portno].mcr = mcr; 586 587 error = umcs_set_baudrate(sc, portno, t->c_ospeed); 588 589 return (error); 590 } 591 592 void 593 umcs_dtr(struct umcs_softc *sc, int portno, int onoff) 594 { 595 uint8_t mcr = sc->sc_subdevs[portno].mcr; 596 597 if (onoff) 598 mcr |= UMCS_MCR_DTR; 599 else 600 mcr &= ~UMCS_MCR_DTR; 601 602 if (umcs_set_uart_reg(sc, portno, UMCS_REG_MCR, mcr)) 603 return; 604 sc->sc_subdevs[portno].mcr = mcr; 605 } 606 607 void 608 umcs_rts(struct umcs_softc *sc, int portno, int onoff) 609 { 610 uint8_t mcr = sc->sc_subdevs[portno].mcr; 611 612 if (onoff) 613 mcr |= UMCS_MCR_RTS; 614 else 615 mcr &= ~UMCS_MCR_RTS; 616 617 if (umcs_set_uart_reg(sc, portno, UMCS_REG_MCR, mcr)) 618 return; 619 sc->sc_subdevs[portno].mcr = mcr; 620 } 621 622 void 623 umcs_break(struct umcs_softc *sc, int portno, int onoff) 624 { 625 uint8_t lcr = sc->sc_subdevs[portno].lcr; 626 627 if (onoff) 628 lcr |= UMCS_LCR_BREAK; 629 else 630 lcr &= ~UMCS_LCR_BREAK; 631 632 if (umcs_set_uart_reg(sc, portno, UMCS_REG_LCR, lcr)) 633 return; 634 sc->sc_subdevs[portno].lcr = lcr; 635 } 636 637 int 638 umcs_open(void *self, int portno) 639 { 640 struct umcs_softc *sc = self; 641 int pn = sc->sc_subdevs[portno].pn; 642 int spreg = umcs_reg_sp(pn); 643 int ctrlreg = umcs_reg_ctrl(pn); 644 uint8_t mcr = sc->sc_subdevs[portno].mcr; 645 uint8_t lcr = sc->sc_subdevs[portno].lcr; 646 uint8_t data; 647 int error; 648 649 if (usbd_is_dying(sc->sc_udev)) 650 return (EIO); 651 652 /* If it very first open, finish global configuration */ 653 if (!sc->sc_init_done) { 654 if (umcs_get_reg(sc, UMCS_CTRL1, &data) || 655 umcs_set_reg(sc, UMCS_CTRL1, data | UMCS_CTRL1_DRIVER_DONE)) 656 return (EIO); 657 sc->sc_init_done = 1; 658 } 659 660 /* Toggle reset bit on-off */ 661 if (umcs_get_reg(sc, spreg, &data) || 662 umcs_set_reg(sc, spreg, data | UMCS_SPx_UART_RESET) || 663 umcs_set_reg(sc, spreg, data & ~UMCS_SPx_UART_RESET)) 664 return (EIO); 665 666 /* Set RS-232 mode */ 667 if (umcs_set_uart_reg(sc, portno, UMCS_REG_SCRATCHPAD, 668 UMCS_SCRATCHPAD_RS232)) 669 return (EIO); 670 671 /* Disable RX on time of initialization */ 672 if (umcs_get_reg(sc, ctrlreg, &data) || 673 umcs_set_reg(sc, ctrlreg, data | UMCS_CTRL_RX_DISABLE)) 674 return (EIO); 675 676 /* Disable all interrupts */ 677 if (umcs_set_uart_reg(sc, portno, UMCS_REG_IER, 0)) 678 return (EIO); 679 680 /* Reset FIFO -- documented */ 681 if (umcs_set_uart_reg(sc, portno, UMCS_REG_FCR, 0) || 682 umcs_set_uart_reg(sc, portno, UMCS_REG_FCR, 683 UMCS_FCR_ENABLE | UMCS_FCR_FLUSHRHR | 684 UMCS_FCR_FLUSHTHR | UMCS_FCR_RTL_1_14)) 685 return (EIO); 686 687 /* Set 8 bit, no parity, 1 stop bit -- documented */ 688 lcr = UMCS_LCR_DATALEN8 | UMCS_LCR_STOPB1; 689 if (umcs_set_uart_reg(sc, portno, UMCS_REG_LCR, lcr)) 690 return (EIO); 691 sc->sc_subdevs[portno].lcr = lcr; 692 693 /* 694 * Enable DTR/RTS on modem control, enable modem interrupts -- 695 * documented 696 */ 697 mcr = UMCS_MCR_DTR | UMCS_MCR_RTS | UMCS_MCR_IE; 698 if (umcs_set_uart_reg(sc, portno, UMCS_REG_MCR, mcr)) 699 return (EIO); 700 sc->sc_subdevs[portno].mcr = mcr; 701 702 /* Clearing Bulkin and Bulkout FIFO */ 703 if (umcs_get_reg(sc, spreg, &data)) 704 return (EIO); 705 data |= UMCS_SPx_RESET_OUT_FIFO|UMCS_SPx_RESET_IN_FIFO; 706 if (umcs_set_reg(sc, spreg, data)) 707 return (EIO); 708 data &= ~(UMCS_SPx_RESET_OUT_FIFO|UMCS_SPx_RESET_IN_FIFO); 709 if (umcs_set_reg(sc, spreg, data)) 710 return (EIO); 711 712 /* Set speed 9600 */ 713 if ((error = umcs_set_baudrate(sc, portno, 9600)) != 0) 714 return (error); 715 716 /* Finally enable all interrupts -- documented */ 717 /* 718 * Copied from vendor driver, I don't know why we should read LCR 719 * here 720 */ 721 if (umcs_get_uart_reg(sc, portno, UMCS_REG_LCR, 722 &sc->sc_subdevs[portno].lcr)) 723 return (EIO); 724 if (umcs_set_uart_reg(sc, portno, UMCS_REG_IER, 725 UMCS_IER_RXSTAT | UMCS_IER_MODEM)) 726 return (EIO); 727 728 /* Enable RX */ 729 if (umcs_get_reg(sc, ctrlreg, &data) || 730 umcs_set_reg(sc, ctrlreg, data & ~UMCS_CTRL_RX_DISABLE)) 731 return (EIO); 732 733 return (0); 734 } 735 736 void 737 umcs_close(void *self, int portno) 738 { 739 struct umcs_softc *sc = self; 740 int pn = sc->sc_subdevs[portno].pn; 741 int ctrlreg = umcs_reg_ctrl(pn); 742 uint8_t data; 743 744 if (usbd_is_dying(sc->sc_udev)) 745 return; 746 747 umcs_set_uart_reg(sc, portno, UMCS_REG_MCR, 0); 748 umcs_set_uart_reg(sc, portno, UMCS_REG_IER, 0); 749 750 /* Disable RX */ 751 if (umcs_get_reg(sc, ctrlreg, &data) || 752 umcs_set_reg(sc, ctrlreg, data | UMCS_CTRL_RX_DISABLE)) 753 return; 754 } 755 756 void 757 umcs_intr(struct usbd_xfer *xfer, void *priv, usbd_status status) 758 { 759 struct umcs_softc *sc = priv; 760 uint8_t *buf = sc->sc_ibuf; 761 int actlen, i; 762 763 if (usbd_is_dying(sc->sc_udev)) 764 return; 765 766 if (status == USBD_CANCELLED || status == USBD_IOERROR) 767 return; 768 769 if (status != USBD_NORMAL_COMPLETION) { 770 DPRINTF("%s: interrupt status=%d\n", DEVNAME(sc), status); 771 usbd_clear_endpoint_stall_async(sc->sc_ipipe); 772 return; 773 } 774 775 usbd_get_xfer_status(xfer, NULL, NULL, &actlen, NULL); 776 if (actlen != 5 && actlen != 13) { 777 printf("%s: invalid interrupt data length %d\n", DEVNAME(sc), 778 actlen); 779 return; 780 } 781 782 /* Check status of all ports */ 783 for (i = 0; i < sc->sc_numports; i++) { 784 uint8_t pn = sc->sc_subdevs[i].pn; 785 786 if (buf[pn] & UMCS_ISR_NOPENDING) 787 continue; 788 789 DPRINTF("%s: port %d has pending interrupt: %02x, FIFO=%02x\n", 790 DEVNAME(sc), i, buf[pn] & UMCS_ISR_INTMASK, 791 buf[pn] & (~UMCS_ISR_INTMASK)); 792 793 switch (buf[pn] & UMCS_ISR_INTMASK) { 794 case UMCS_ISR_RXERR: 795 case UMCS_ISR_RXHASDATA: 796 case UMCS_ISR_RXTIMEOUT: 797 case UMCS_ISR_MSCHANGE: 798 sc->sc_subdevs[i].flags |= UMCS_STATCHG; 799 task_add(systq, &sc->sc_status_task); 800 break; 801 default: 802 /* Do nothing */ 803 break; 804 } 805 } 806 } 807 808 void 809 umcs_status_task(void *arg) 810 { 811 struct umcs_softc *sc = arg; 812 int i; 813 814 for (i = 0; i < sc->sc_numports; i++) { 815 if ((sc->sc_subdevs[i].flags & UMCS_STATCHG) == 0) 816 continue; 817 818 sc->sc_subdevs[i].flags &= ~UMCS_STATCHG; 819 ucom_status_change(sc->sc_subdevs[i].ucom); 820 } 821 } 822