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