1 1.63 riastrad /* $NetBSD: cy.c,v 1.63 2022/10/26 23:42:04 riastradh Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * cy.c 5 1.1 christos * 6 1.1 christos * Driver for Cyclades Cyclom-8/16/32 multiport serial cards 7 1.1 christos * (currently not tested with Cyclom-32 cards) 8 1.1 christos * 9 1.1 christos * Timo Rossi, 1996 10 1.1 christos * 11 1.1 christos * Supports both ISA and PCI Cyclom cards 12 1.1 christos * 13 1.1 christos * Lots of debug output can be enabled by defining CY_DEBUG 14 1.1 christos * Some debugging counters (number of receive/transmit interrupts etc.) 15 1.1 christos * can be enabled by defining CY_DEBUG1 16 1.1 christos */ 17 1.24 lukem 18 1.24 lukem #include <sys/cdefs.h> 19 1.63 riastrad __KERNEL_RCSID(0, "$NetBSD: cy.c,v 1.63 2022/10/26 23:42:04 riastradh Exp $"); 20 1.1 christos 21 1.1 christos #include <sys/param.h> 22 1.1 christos #include <sys/ioctl.h> 23 1.1 christos #include <sys/syslog.h> 24 1.1 christos #include <sys/fcntl.h> 25 1.1 christos #include <sys/tty.h> 26 1.1 christos #include <sys/proc.h> 27 1.1 christos #include <sys/conf.h> 28 1.1 christos #include <sys/select.h> 29 1.1 christos #include <sys/device.h> 30 1.1 christos #include <sys/malloc.h> 31 1.1 christos #include <sys/systm.h> 32 1.12 thorpej #include <sys/callout.h> 33 1.42 elad #include <sys/kauth.h> 34 1.5 thorpej 35 1.52 ad #include <sys/bus.h> 36 1.1 christos 37 1.1 christos #include <dev/ic/cd1400reg.h> 38 1.1 christos #include <dev/ic/cyreg.h> 39 1.1 christos #include <dev/ic/cyvar.h> 40 1.1 christos 41 1.61 riastrad #include "ioconf.h" 42 1.61 riastrad 43 1.55 matt static int cyparam(struct tty *, struct termios *); 44 1.55 matt static void cystart(struct tty *); 45 1.55 matt static void cy_poll(void *); 46 1.55 matt static int cy_modem_control(struct cy_softc *, struct cy_port *, int, int); 47 1.55 matt static void cy_enable_transmitter(struct cy_softc *, struct cy_port *); 48 1.55 matt static void cd1400_channel_cmd(struct cy_softc *, struct cy_port *, int); 49 1.55 matt static int cy_speed(speed_t, int *, int *, int); 50 1.1 christos 51 1.55 matt static dev_type_open(cyopen); 52 1.55 matt static dev_type_close(cyclose); 53 1.55 matt static dev_type_read(cyread); 54 1.55 matt static dev_type_write(cywrite); 55 1.55 matt static dev_type_ioctl(cyioctl); 56 1.55 matt static dev_type_stop(cystop); 57 1.55 matt static dev_type_tty(cytty); 58 1.55 matt static dev_type_poll(cypoll); 59 1.27 gehenna 60 1.27 gehenna const struct cdevsw cy_cdevsw = { 61 1.55 matt .d_open = cyopen, 62 1.55 matt .d_close = cyclose, 63 1.55 matt .d_read = cyread, 64 1.55 matt .d_write = cywrite, 65 1.55 matt .d_ioctl = cyioctl, 66 1.55 matt .d_stop = cystop, 67 1.55 matt .d_tty = cytty, 68 1.55 matt .d_poll = cypoll, 69 1.55 matt .d_mmap = nommap, 70 1.55 matt .d_kqfilter = ttykqfilter, 71 1.59 dholland .d_discard = nodiscard, 72 1.55 matt .d_flag = D_TTY 73 1.27 gehenna }; 74 1.27 gehenna 75 1.1 christos static int cy_open = 0; 76 1.1 christos static int cy_events = 0; 77 1.1 christos 78 1.20 thorpej int cy_attached_ttys; 79 1.51 ad bool cy_callout_init; 80 1.51 ad callout_t cy_poll_callout; 81 1.12 thorpej 82 1.1 christos /* 83 1.1 christos * Common probe routine 84 1.1 christos */ 85 1.1 christos int 86 1.18 thorpej cy_find(struct cy_softc *sc) 87 1.1 christos { 88 1.1 christos int cy_chip, chip; 89 1.36 reinoud u_char firmware_ver; 90 1.5 thorpej bus_space_tag_t tag = sc->sc_memt; 91 1.5 thorpej bus_space_handle_t bsh = sc->sc_bsh; 92 1.1 christos int bustype = sc->sc_bustype; 93 1.1 christos 94 1.1 christos /* Cyclom card hardware reset */ 95 1.5 thorpej bus_space_write_1(tag, bsh, CY16_RESET << bustype, 0); 96 1.1 christos DELAY(500); /* wait for reset to complete */ 97 1.5 thorpej bus_space_write_1(tag, bsh, CY_CLEAR_INTR << bustype, 0); 98 1.1 christos 99 1.1 christos #ifdef CY_DEBUG 100 1.4 christos printf("cy: card reset done\n"); 101 1.1 christos #endif 102 1.1 christos sc->sc_nchips = 0; 103 1.1 christos 104 1.1 christos for (cy_chip = 0, chip = 0; cy_chip < CY_MAX_CD1400s; 105 1.1 christos cy_chip++, chip += (CY_CD1400_MEMSPACING << bustype)) { 106 1.1 christos int i; 107 1.1 christos 108 1.1 christos /* 109 1.1 christos * the last 4 nchips are 'interleaved' with the first 4 on 110 1.1 christos * 32-port boards 111 1.1 christos */ 112 1.1 christos if (cy_chip == 4) 113 1.1 christos chip -= (CY32_ADDR_FIX << bustype); 114 1.1 christos 115 1.1 christos #ifdef CY_DEBUG 116 1.55 matt printf("sy: probe chip %d offset 0x%x ... ", cy_chip, chip); 117 1.1 christos #endif 118 1.1 christos 119 1.1 christos /* wait until the chip is ready for command */ 120 1.1 christos DELAY(1000); 121 1.37 perry if (bus_space_read_1(tag, bsh, chip + 122 1.1 christos ((CD1400_CCR << 1) << bustype)) != 0) { 123 1.1 christos #ifdef CY_DEBUG 124 1.4 christos printf("not ready for command\n"); 125 1.1 christos #endif 126 1.1 christos break; 127 1.1 christos } 128 1.1 christos /* clear the firmware version reg. */ 129 1.5 thorpej bus_space_write_1(tag, bsh, chip + 130 1.1 christos ((CD1400_GFRCR << 1) << bustype), 0); 131 1.1 christos 132 1.1 christos /* 133 1.1 christos * On Cyclom-16 references to non-existent chip 4 134 1.1 christos * actually access chip 0 (address line 9 not decoded). 135 1.1 christos * Here we check if the clearing of chip 4 GFRCR actually 136 1.1 christos * cleared chip 0 GFRCR. In that case we have a 16 port card. 137 1.1 christos */ 138 1.1 christos if (cy_chip == 4 && 139 1.7 cgd bus_space_read_1(tag, bsh, /* off for chip 0 (0) + */ 140 1.1 christos ((CD1400_GFRCR << 1) << bustype)) == 0) 141 1.1 christos break; 142 1.1 christos 143 1.1 christos /* reset the chip */ 144 1.5 thorpej bus_space_write_1(tag, bsh, chip + 145 1.1 christos ((CD1400_CCR << 1) << bustype), 146 1.1 christos CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); 147 1.1 christos 148 1.1 christos /* wait for the chip to initialize itself */ 149 1.1 christos for (i = 0; i < 200; i++) { 150 1.1 christos DELAY(50); 151 1.5 thorpej firmware_ver = bus_space_read_1(tag, bsh, chip + 152 1.1 christos ((CD1400_GFRCR << 1) << bustype)); 153 1.1 christos if ((firmware_ver & 0xf0) == 0x40) /* found a CD1400 */ 154 1.1 christos break; 155 1.1 christos } 156 1.1 christos #ifdef CY_DEBUG 157 1.4 christos printf("firmware version 0x%x\n", firmware_ver); 158 1.1 christos #endif 159 1.1 christos 160 1.1 christos if ((firmware_ver & 0xf0) != 0x40) 161 1.1 christos break; 162 1.1 christos 163 1.1 christos /* firmware version OK, CD1400 found */ 164 1.1 christos sc->sc_nchips++; 165 1.1 christos } 166 1.1 christos 167 1.1 christos if (sc->sc_nchips == 0) { 168 1.1 christos #ifdef CY_DEBUG 169 1.4 christos printf("no CD1400s found\n"); 170 1.1 christos #endif 171 1.1 christos return 0; 172 1.1 christos } 173 1.1 christos #ifdef CY_DEBUG 174 1.4 christos printf("found %d CD1400s\n", sc->sc_nchips); 175 1.1 christos #endif 176 1.1 christos 177 1.1 christos return 1; 178 1.1 christos } 179 1.1 christos 180 1.1 christos void 181 1.19 thorpej cy_attach(struct cy_softc *sc) 182 1.1 christos { 183 1.19 thorpej int port, cy_chip, num_chips, cdu, chip; 184 1.11 tron int cy_clock; 185 1.1 christos 186 1.51 ad if (!cy_callout_init) { 187 1.51 ad cy_callout_init = true; 188 1.51 ad callout_init(&cy_poll_callout, 0); 189 1.51 ad } 190 1.51 ad 191 1.1 christos num_chips = sc->sc_nchips; 192 1.1 christos if (num_chips == 0) 193 1.1 christos return; 194 1.1 christos 195 1.23 thorpej memset(sc->sc_ports, 0, sizeof(sc->sc_ports)); 196 1.1 christos 197 1.1 christos port = 0; 198 1.1 christos for (cy_chip = 0, chip = 0; cy_chip < num_chips; cy_chip++, 199 1.1 christos chip += (CY_CD1400_MEMSPACING << sc->sc_bustype)) { 200 1.1 christos 201 1.1 christos if (cy_chip == 4) 202 1.1 christos chip -= (CY32_ADDR_FIX << sc->sc_bustype); 203 1.1 christos 204 1.1 christos #ifdef CY_DEBUG 205 1.30 thorpej aprint_debug("attach CD1400 #%d offset 0x%x\n", cy_chip, chip); 206 1.1 christos #endif 207 1.1 christos sc->sc_cd1400_offs[cy_chip] = chip; 208 1.1 christos 209 1.1 christos /* 210 1.1 christos * configure port 0 as serial port (should already be after 211 1.1 christos * reset) 212 1.1 christos */ 213 1.1 christos cd_write_reg(sc, cy_chip, CD1400_GCR, 0); 214 1.1 christos 215 1.11 tron if (cd_read_reg(sc, cy_chip, CD1400_GFRCR) <= 0x46) 216 1.11 tron cy_clock = CY_CLOCK; 217 1.11 tron else 218 1.11 tron cy_clock = CY_CLOCK_60; 219 1.11 tron 220 1.1 christos /* set up a receive timeout period (1ms) */ 221 1.1 christos cd_write_reg(sc, cy_chip, CD1400_PPR, 222 1.11 tron (cy_clock / CD1400_PPR_PRESCALER / 1000) + 1); 223 1.1 christos 224 1.1 christos for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; cdu++) { 225 1.20 thorpej sc->sc_ports[port].cy_softc = sc; 226 1.3 christos sc->sc_ports[port].cy_port_num = port; 227 1.7 cgd sc->sc_ports[port].cy_chip = cy_chip; 228 1.11 tron sc->sc_ports[port].cy_clock = cy_clock; 229 1.1 christos 230 1.1 christos /* should we initialize anything else here? */ 231 1.1 christos port++; 232 1.1 christos } /* for(each port on one CD1400...) */ 233 1.1 christos 234 1.1 christos } /* for(each CD1400 on a card... ) */ 235 1.1 christos 236 1.20 thorpej sc->sc_nchannels = port; 237 1.20 thorpej 238 1.55 matt aprint_normal_dev(sc->sc_dev, "%d channels (ttyCY%03d..ttyCY%03d)\n", 239 1.55 matt sc->sc_nchannels, cy_attached_ttys, 240 1.20 thorpej cy_attached_ttys + (sc->sc_nchannels - 1)); 241 1.20 thorpej 242 1.20 thorpej cy_attached_ttys += sc->sc_nchannels; 243 1.1 christos 244 1.1 christos /* ensure an edge for the next interrupt */ 245 1.5 thorpej bus_space_write_1(sc->sc_memt, sc->sc_bsh, 246 1.1 christos CY_CLEAR_INTR << sc->sc_bustype, 0); 247 1.1 christos } 248 1.1 christos 249 1.60 christos #define CY_UNIT(dev) TTUNIT(dev) 250 1.60 christos #define CY_DIALOUT(dev) TTDIALOUT(dev) 251 1.20 thorpej 252 1.20 thorpej #define CY_PORT(dev) cy_getport((dev)) 253 1.20 thorpej #define CY_BOARD(cy) ((cy)->cy_softc) 254 1.20 thorpej 255 1.20 thorpej static struct cy_port * 256 1.20 thorpej cy_getport(dev_t dev) 257 1.20 thorpej { 258 1.60 christos int i, j, k, u = CY_UNIT(dev); 259 1.34 mycroft struct cy_softc *sc; 260 1.20 thorpej 261 1.20 thorpej for (i = 0, j = 0; i < cy_cd.cd_ndevs; i++) { 262 1.20 thorpej k = j; 263 1.55 matt sc = device_lookup_private(&cy_cd, i); 264 1.20 thorpej if (sc == NULL) 265 1.20 thorpej continue; 266 1.20 thorpej if (sc->sc_nchannels == 0) 267 1.20 thorpej continue; 268 1.20 thorpej j += sc->sc_nchannels; 269 1.20 thorpej if (j > u) 270 1.34 mycroft return (&sc->sc_ports[u - k]); 271 1.20 thorpej } 272 1.20 thorpej 273 1.34 mycroft return (NULL); 274 1.20 thorpej } 275 1.20 thorpej 276 1.1 christos /* 277 1.29 wiz * open routine. returns zero if successful, else error code 278 1.1 christos */ 279 1.1 christos int 280 1.48 christos cyopen(dev_t dev, int flag, int mode, struct lwp *l) 281 1.1 christos { 282 1.1 christos struct cy_softc *sc; 283 1.1 christos struct cy_port *cy; 284 1.1 christos struct tty *tp; 285 1.1 christos int s, error; 286 1.1 christos 287 1.20 thorpej cy = CY_PORT(dev); 288 1.20 thorpej if (cy == NULL) 289 1.14 thorpej return (ENXIO); 290 1.20 thorpej sc = CY_BOARD(cy); 291 1.1 christos 292 1.1 christos s = spltty(); 293 1.1 christos if (cy->cy_tty == NULL) { 294 1.58 rmind if ((cy->cy_tty = tty_alloc()) == NULL) { 295 1.1 christos splx(s); 296 1.55 matt aprint_error_dev(sc->sc_dev, 297 1.55 matt "port %d: can't allocate tty\n", 298 1.55 matt cy->cy_port_num); 299 1.20 thorpej return (ENOMEM); 300 1.1 christos } 301 1.3 christos tty_attach(cy->cy_tty); 302 1.1 christos } 303 1.1 christos splx(s); 304 1.1 christos 305 1.1 christos tp = cy->cy_tty; 306 1.1 christos tp->t_oproc = cystart; 307 1.1 christos tp->t_param = cyparam; 308 1.1 christos tp->t_dev = dev; 309 1.1 christos 310 1.45 elad if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 311 1.45 elad return (EBUSY); 312 1.45 elad 313 1.9 mjacob if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 314 1.1 christos ttychars(tp); 315 1.1 christos tp->t_iflag = TTYDEF_IFLAG; 316 1.1 christos tp->t_oflag = TTYDEF_OFLAG; 317 1.1 christos tp->t_cflag = TTYDEF_CFLAG; 318 1.1 christos if (ISSET(cy->cy_openflags, TIOCFLAG_CLOCAL)) 319 1.1 christos SET(tp->t_cflag, CLOCAL); 320 1.1 christos if (ISSET(cy->cy_openflags, TIOCFLAG_CRTSCTS)) 321 1.1 christos SET(tp->t_cflag, CRTSCTS); 322 1.1 christos if (ISSET(cy->cy_openflags, TIOCFLAG_MDMBUF)) 323 1.1 christos SET(tp->t_cflag, MDMBUF); 324 1.1 christos tp->t_lflag = TTYDEF_LFLAG; 325 1.1 christos tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 326 1.1 christos 327 1.1 christos s = spltty(); 328 1.1 christos 329 1.1 christos /* 330 1.1 christos * Allocate input ring buffer if we don't already have one 331 1.1 christos */ 332 1.1 christos if (cy->cy_ibuf == NULL) { 333 1.62 chs cy->cy_ibuf = malloc(CY_IBUF_SIZE, M_DEVBUF, M_WAITOK); 334 1.1 christos cy->cy_ibuf_end = cy->cy_ibuf + CY_IBUF_SIZE; 335 1.1 christos } 336 1.1 christos /* mark the ring buffer as empty */ 337 1.1 christos cy->cy_ibuf_rd_ptr = cy->cy_ibuf_wr_ptr = cy->cy_ibuf; 338 1.1 christos 339 1.1 christos /* select CD1400 channel */ 340 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_CAR, 341 1.20 thorpej cy->cy_port_num & CD1400_CAR_CHAN); 342 1.1 christos /* reset the channel */ 343 1.1 christos cd1400_channel_cmd(sc, cy, CD1400_CCR_CMDRESET); 344 1.1 christos /* encode unit (port) number in LIVR */ 345 1.1 christos /* there is just enough space for 5 bits (32 ports) */ 346 1.20 thorpej cd_write_reg(sc, cy->cy_chip, CD1400_LIVR, 347 1.20 thorpej cy->cy_port_num << 3); 348 1.1 christos 349 1.1 christos cy->cy_channel_control = 0; 350 1.1 christos 351 1.1 christos /* hmm... need spltty() here? */ 352 1.1 christos if (cy_open == 0) { 353 1.1 christos cy_open = 1; 354 1.12 thorpej callout_reset(&cy_poll_callout, 1, cy_poll, NULL); 355 1.1 christos } 356 1.1 christos /* this sets parameters and raises DTR */ 357 1.1 christos cyparam(tp, &tp->t_termios); 358 1.1 christos 359 1.1 christos ttsetwater(tp); 360 1.1 christos 361 1.1 christos /* raise RTS too */ 362 1.1 christos cy_modem_control(sc, cy, TIOCM_RTS, DMBIS); 363 1.1 christos 364 1.1 christos cy->cy_carrier_stat = 365 1.1 christos cd_read_reg(sc, cy->cy_chip, CD1400_MSVR2); 366 1.1 christos 367 1.1 christos /* enable receiver and modem change interrupts */ 368 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_SRER, 369 1.1 christos CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); 370 1.1 christos 371 1.1 christos if (CY_DIALOUT(dev) || 372 1.1 christos ISSET(cy->cy_openflags, TIOCFLAG_SOFTCAR) || 373 1.1 christos ISSET(tp->t_cflag, MDMBUF) || 374 1.1 christos ISSET(cy->cy_carrier_stat, CD1400_MSVR2_CD)) 375 1.1 christos SET(tp->t_state, TS_CARR_ON); 376 1.1 christos else 377 1.1 christos CLR(tp->t_state, TS_CARR_ON); 378 1.53 ad splx(s); 379 1.1 christos } 380 1.1 christos 381 1.1 christos /* wait for carrier if necessary */ 382 1.1 christos if (!ISSET(flag, O_NONBLOCK)) { 383 1.63 riastrad ttylock(tp); 384 1.1 christos while (!ISSET(tp->t_cflag, CLOCAL) && 385 1.1 christos !ISSET(tp->t_state, TS_CARR_ON)) { 386 1.9 mjacob tp->t_wopen++; 387 1.56 ad error = ttysleep(tp, &tp->t_rawcv, true, 0); 388 1.9 mjacob tp->t_wopen--; 389 1.1 christos if (error != 0) { 390 1.63 riastrad ttyunlock(tp); 391 1.1 christos return error; 392 1.1 christos } 393 1.1 christos } 394 1.63 riastrad ttyunlock(tp); 395 1.1 christos } 396 1.1 christos 397 1.16 eeh return (*tp->t_linesw->l_open) (dev, tp); 398 1.1 christos } 399 1.1 christos 400 1.1 christos /* 401 1.29 wiz * close routine. returns zero if successful, else error code 402 1.1 christos */ 403 1.1 christos int 404 1.48 christos cyclose(dev_t dev, int flag, int mode, struct lwp *l) 405 1.1 christos { 406 1.20 thorpej struct cy_softc *sc; 407 1.20 thorpej struct cy_port *cy; 408 1.20 thorpej struct tty *tp; 409 1.1 christos int s; 410 1.1 christos 411 1.20 thorpej cy = CY_PORT(dev); 412 1.20 thorpej sc = CY_BOARD(cy); 413 1.20 thorpej tp = cy->cy_tty; 414 1.1 christos 415 1.16 eeh (*tp->t_linesw->l_close) (tp, flag); 416 1.1 christos s = spltty(); 417 1.1 christos 418 1.1 christos if (ISSET(tp->t_cflag, HUPCL) && 419 1.1 christos !ISSET(cy->cy_openflags, TIOCFLAG_SOFTCAR)) { 420 1.1 christos /* 421 1.1 christos * drop DTR and RTS (should we wait for output buffer to 422 1.1 christos * become empty first?) 423 1.1 christos */ 424 1.1 christos cy_modem_control(sc, cy, 0, DMSET); 425 1.1 christos } 426 1.1 christos /* 427 1.1 christos * XXX should we disable modem change and 428 1.1 christos * receive interrupts here or somewhere ? 429 1.1 christos */ 430 1.1 christos CLR(tp->t_state, TS_BUSY | TS_FLUSH); 431 1.1 christos 432 1.1 christos splx(s); 433 1.1 christos ttyclose(tp); 434 1.1 christos 435 1.1 christos return 0; 436 1.1 christos } 437 1.1 christos 438 1.1 christos /* 439 1.1 christos * Read routine 440 1.1 christos */ 441 1.1 christos int 442 1.18 thorpej cyread(dev_t dev, struct uio *uio, int flag) 443 1.1 christos { 444 1.20 thorpej struct cy_port *cy; 445 1.20 thorpej struct tty *tp; 446 1.1 christos 447 1.20 thorpej cy = CY_PORT(dev); 448 1.20 thorpej tp = cy->cy_tty; 449 1.1 christos 450 1.20 thorpej return ((*tp->t_linesw->l_read)(tp, uio, flag)); 451 1.1 christos } 452 1.1 christos 453 1.1 christos /* 454 1.1 christos * Write routine 455 1.1 christos */ 456 1.1 christos int 457 1.18 thorpej cywrite(dev_t dev, struct uio *uio, int flag) 458 1.1 christos { 459 1.20 thorpej struct cy_port *cy; 460 1.20 thorpej struct tty *tp; 461 1.1 christos 462 1.20 thorpej cy = CY_PORT(dev); 463 1.20 thorpej tp = cy->cy_tty; 464 1.1 christos 465 1.20 thorpej return ((*tp->t_linesw->l_write)(tp, uio, flag)); 466 1.22 scw } 467 1.22 scw 468 1.22 scw /* 469 1.22 scw * Poll routine 470 1.22 scw */ 471 1.22 scw int 472 1.39 christos cypoll(dev_t dev, int events, struct lwp *l) 473 1.22 scw { 474 1.22 scw struct cy_port *cy; 475 1.22 scw struct tty *tp; 476 1.22 scw 477 1.22 scw cy = CY_PORT(dev); 478 1.22 scw tp = cy->cy_tty; 479 1.37 perry 480 1.39 christos return ((*tp->t_linesw->l_poll)(tp, events, l)); 481 1.1 christos } 482 1.1 christos 483 1.1 christos /* 484 1.1 christos * return tty pointer 485 1.1 christos */ 486 1.1 christos struct tty * 487 1.18 thorpej cytty(dev_t dev) 488 1.1 christos { 489 1.20 thorpej struct cy_port *cy; 490 1.20 thorpej 491 1.20 thorpej cy = CY_PORT(dev); 492 1.1 christos 493 1.20 thorpej return (cy->cy_tty); 494 1.1 christos } 495 1.1 christos 496 1.1 christos /* 497 1.1 christos * ioctl routine 498 1.1 christos */ 499 1.1 christos int 500 1.50 christos cyioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 501 1.1 christos { 502 1.20 thorpej struct cy_softc *sc; 503 1.20 thorpej struct cy_port *cy; 504 1.20 thorpej struct tty *tp; 505 1.1 christos int error; 506 1.1 christos 507 1.20 thorpej cy = CY_PORT(dev); 508 1.20 thorpej sc = CY_BOARD(cy); 509 1.20 thorpej tp = cy->cy_tty; 510 1.1 christos 511 1.39 christos error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 512 1.26 atatat if (error != EPASSTHROUGH) 513 1.1 christos return error; 514 1.1 christos 515 1.39 christos error = ttioctl(tp, cmd, data, flag, l); 516 1.26 atatat if (error != EPASSTHROUGH) 517 1.1 christos return error; 518 1.1 christos 519 1.1 christos /* XXX should not allow dropping DTR when dialin? */ 520 1.1 christos 521 1.1 christos switch (cmd) { 522 1.1 christos case TIOCSBRK: /* start break */ 523 1.1 christos SET(cy->cy_flags, CY_F_START_BREAK); 524 1.1 christos cy_enable_transmitter(sc, cy); 525 1.1 christos break; 526 1.1 christos 527 1.1 christos case TIOCCBRK: /* stop break */ 528 1.1 christos SET(cy->cy_flags, CY_F_END_BREAK); 529 1.1 christos cy_enable_transmitter(sc, cy); 530 1.1 christos break; 531 1.1 christos 532 1.1 christos case TIOCSDTR: /* DTR on */ 533 1.1 christos cy_modem_control(sc, cy, TIOCM_DTR, DMBIS); 534 1.1 christos break; 535 1.1 christos 536 1.1 christos case TIOCCDTR: /* DTR off */ 537 1.1 christos cy_modem_control(sc, cy, TIOCM_DTR, DMBIC); 538 1.1 christos break; 539 1.1 christos 540 1.1 christos case TIOCMSET: /* set new modem control line values */ 541 1.1 christos cy_modem_control(sc, cy, *((int *) data), DMSET); 542 1.1 christos break; 543 1.1 christos 544 1.1 christos case TIOCMBIS: /* turn modem control bits on */ 545 1.1 christos cy_modem_control(sc, cy, *((int *) data), DMBIS); 546 1.1 christos break; 547 1.1 christos 548 1.1 christos case TIOCMBIC: /* turn modem control bits off */ 549 1.1 christos cy_modem_control(sc, cy, *((int *) data), DMBIC); 550 1.1 christos break; 551 1.1 christos 552 1.1 christos case TIOCMGET: /* get modem control/status line state */ 553 1.1 christos *((int *) data) = cy_modem_control(sc, cy, 0, DMGET); 554 1.1 christos break; 555 1.1 christos 556 1.1 christos case TIOCGFLAGS: 557 1.1 christos *((int *) data) = cy->cy_openflags | 558 1.1 christos (CY_DIALOUT(dev) ? TIOCFLAG_SOFTCAR : 0); 559 1.1 christos break; 560 1.1 christos 561 1.1 christos case TIOCSFLAGS: 562 1.46 elad error = kauth_authorize_device_tty(l->l_cred, 563 1.46 elad KAUTH_DEVICE_TTY_PRIVSET, tp); 564 1.1 christos if (error != 0) 565 1.1 christos return EPERM; 566 1.1 christos 567 1.1 christos cy->cy_openflags = *((int *) data) & 568 1.1 christos (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | 569 1.1 christos TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF); 570 1.1 christos break; 571 1.1 christos 572 1.1 christos default: 573 1.26 atatat return EPASSTHROUGH; 574 1.1 christos } 575 1.1 christos 576 1.1 christos return 0; 577 1.1 christos } 578 1.1 christos 579 1.1 christos /* 580 1.1 christos * start output 581 1.1 christos */ 582 1.1 christos void 583 1.18 thorpej cystart(struct tty *tp) 584 1.1 christos { 585 1.20 thorpej struct cy_softc *sc; 586 1.20 thorpej struct cy_port *cy; 587 1.1 christos int s; 588 1.1 christos 589 1.20 thorpej cy = CY_PORT(tp->t_dev); 590 1.20 thorpej sc = cy->cy_softc; 591 1.1 christos 592 1.1 christos s = spltty(); 593 1.1 christos 594 1.1 christos #ifdef CY_DEBUG1 595 1.1 christos cy->cy_start_count++; 596 1.1 christos #endif 597 1.1 christos 598 1.1 christos if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) { 599 1.54 ad if (!ttypull(tp)) 600 1.54 ad goto out; 601 1.1 christos SET(tp->t_state, TS_BUSY); 602 1.1 christos cy_enable_transmitter(sc, cy); 603 1.1 christos } 604 1.1 christos out: 605 1.1 christos 606 1.1 christos splx(s); 607 1.1 christos } 608 1.1 christos 609 1.1 christos /* 610 1.1 christos * stop output 611 1.1 christos */ 612 1.1 christos void 613 1.48 christos cystop(struct tty *tp, int flag) 614 1.1 christos { 615 1.20 thorpej struct cy_port *cy; 616 1.1 christos int s; 617 1.1 christos 618 1.20 thorpej cy = CY_PORT(tp->t_dev); 619 1.1 christos 620 1.1 christos s = spltty(); 621 1.1 christos if (ISSET(tp->t_state, TS_BUSY)) { 622 1.1 christos if (!ISSET(tp->t_state, TS_TTSTOP)) 623 1.1 christos SET(tp->t_state, TS_FLUSH); 624 1.1 christos 625 1.1 christos /* 626 1.1 christos * the transmit interrupt routine will disable transmit when it 627 1.1 christos * notices that CY_F_STOP has been set. 628 1.1 christos */ 629 1.1 christos SET(cy->cy_flags, CY_F_STOP); 630 1.1 christos } 631 1.1 christos splx(s); 632 1.1 christos } 633 1.1 christos 634 1.1 christos /* 635 1.1 christos * parameter setting routine. 636 1.29 wiz * returns 0 if successful, else returns error code 637 1.1 christos */ 638 1.18 thorpej int 639 1.18 thorpej cyparam(struct tty *tp, struct termios *t) 640 1.1 christos { 641 1.20 thorpej struct cy_softc *sc; 642 1.20 thorpej struct cy_port *cy; 643 1.41 christos int ibpr = 0, obpr = 0, i_clk_opt = 0, o_clk_opt = 0; /* XXX: GCC */ 644 1.41 christos int s, opt; 645 1.1 christos 646 1.20 thorpej cy = CY_PORT(tp->t_dev); 647 1.20 thorpej sc = CY_BOARD(cy); 648 1.1 christos 649 1.11 tron if (t->c_ospeed != 0 && cy_speed(t->c_ospeed, &o_clk_opt, &obpr, cy->cy_clock) < 0) 650 1.1 christos return EINVAL; 651 1.1 christos 652 1.11 tron if (t->c_ispeed != 0 && cy_speed(t->c_ispeed, &i_clk_opt, &ibpr, cy->cy_clock) < 0) 653 1.1 christos return EINVAL; 654 1.1 christos 655 1.1 christos s = spltty(); 656 1.1 christos 657 1.1 christos /* hang up the line is ospeed is zero, else turn DTR on */ 658 1.1 christos cy_modem_control(sc, cy, TIOCM_DTR, (t->c_ospeed == 0 ? DMBIC : DMBIS)); 659 1.1 christos 660 1.1 christos /* channel was selected by the above call to cy_modem_control() */ 661 1.1 christos #if 0 662 1.37 perry cd_write_reg(sc, cy->cy_chip, CD1400_CAR, port & CD1400_CAR_CHAN); 663 1.1 christos #endif 664 1.1 christos 665 1.1 christos /* set transmit speed */ 666 1.1 christos if (t->c_ospeed != 0) { 667 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_TCOR, o_clk_opt); 668 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_TBPR, obpr); 669 1.1 christos } 670 1.1 christos /* set receive speed */ 671 1.1 christos if (t->c_ispeed != 0) { 672 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_RCOR, i_clk_opt); 673 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_RBPR, ibpr); 674 1.1 christos } 675 1.1 christos opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN 676 1.1 christos | (ISSET(t->c_cflag, CREAD) ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); 677 1.1 christos 678 1.1 christos if (opt != cy->cy_channel_control) { 679 1.1 christos cy->cy_channel_control = opt; 680 1.1 christos cd1400_channel_cmd(sc, cy, opt); 681 1.1 christos } 682 1.1 christos /* compute COR1 contents */ 683 1.1 christos opt = 0; 684 1.1 christos if (ISSET(t->c_cflag, PARENB)) { 685 1.1 christos if (ISSET(t->c_cflag, PARODD)) 686 1.1 christos opt |= CD1400_COR1_PARODD; 687 1.1 christos opt |= CD1400_COR1_PARNORMAL; 688 1.1 christos } 689 1.1 christos if (!ISSET(t->c_iflag, INPCK)) 690 1.1 christos opt |= CD1400_COR1_NOINPCK; /* no parity checking */ 691 1.1 christos 692 1.1 christos if (ISSET(t->c_cflag, CSTOPB)) 693 1.1 christos opt |= CD1400_COR1_STOP2; 694 1.1 christos 695 1.1 christos switch (t->c_cflag & CSIZE) { 696 1.1 christos case CS5: 697 1.1 christos opt |= CD1400_COR1_CS5; 698 1.1 christos break; 699 1.1 christos 700 1.1 christos case CS6: 701 1.1 christos opt |= CD1400_COR1_CS6; 702 1.1 christos break; 703 1.1 christos 704 1.1 christos case CS7: 705 1.1 christos opt |= CD1400_COR1_CS7; 706 1.1 christos break; 707 1.1 christos 708 1.1 christos default: 709 1.1 christos opt |= CD1400_COR1_CS8; 710 1.1 christos break; 711 1.1 christos } 712 1.1 christos 713 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_COR1, opt); 714 1.1 christos 715 1.1 christos #ifdef CY_DEBUG 716 1.4 christos printf("cor1 = 0x%x...", opt); 717 1.1 christos #endif 718 1.1 christos 719 1.1 christos /* 720 1.1 christos * use the CD1400 automatic CTS flow control if CRTSCTS is set 721 1.1 christos * 722 1.1 christos * CD1400_COR2_ETC is used because breaks are generated with 723 1.1 christos * embedded transmit commands 724 1.1 christos */ 725 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_COR2, 726 1.1 christos CD1400_COR2_ETC | 727 1.1 christos (ISSET(t->c_cflag, CRTSCTS) ? CD1400_COR2_CCTS_OFLOW : 0)); 728 1.1 christos 729 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_COR3, CY_RX_FIFO_THRESHOLD); 730 1.1 christos 731 1.1 christos cd1400_channel_cmd(sc, cy, CD1400_CCR_CMDCORCHG | 732 1.1 christos CD1400_CCR_COR1 | CD1400_CCR_COR2 | CD1400_CCR_COR3); 733 1.1 christos 734 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_COR4, CD1400_COR4_PFO_EXCEPTION); 735 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_COR5, 0); 736 1.1 christos 737 1.1 christos /* 738 1.1 christos * set modem change option registers to generate interrupts 739 1.1 christos * on carrier detect changes. 740 1.1 christos * 741 1.11 tron * if hardware RTS handshaking is used 742 1.11 tron * also set the handshaking threshold. 743 1.1 christos */ 744 1.11 tron if (cy->cy_clock == CY_CLOCK_60) { 745 1.11 tron cd_write_reg(sc, cy->cy_chip, CD1400_MCOR1, CD1400_MCOR1_CDzd | 746 1.11 tron (ISSET(t->c_cflag, CRTSCTS) ? CY_RX_DTR_THRESHOLD : 0)); 747 1.11 tron } else { 748 1.11 tron cd_write_reg(sc, cy->cy_chip, CD1400_MCOR1, CD1400_MCOR1_CDzd); 749 1.11 tron } 750 1.1 christos 751 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_MCOR2, CD1400_MCOR2_CDod); 752 1.1 christos 753 1.1 christos /* 754 1.1 christos * set receive timeout to approx. 2ms 755 1.1 christos * could use more complex logic here... 756 1.1 christos * (but is it actually needed or even useful?) 757 1.1 christos */ 758 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_RTPR, 2); 759 1.1 christos 760 1.1 christos /* 761 1.1 christos * should do anything else here? 762 1.1 christos * XXX check MDMBUF handshaking like in com.c? 763 1.1 christos */ 764 1.1 christos 765 1.1 christos splx(s); 766 1.1 christos return 0; 767 1.1 christos } 768 1.1 christos 769 1.1 christos /* 770 1.1 christos * set/get modem line status 771 1.1 christos * 772 1.1 christos * bits can be: TIOCM_DTR, TIOCM_RTS, TIOCM_CTS, TIOCM_CD, TIOCM_RI, TIOCM_DSR 773 1.1 christos */ 774 1.18 thorpej int 775 1.18 thorpej cy_modem_control(struct cy_softc *sc, struct cy_port *cy, int bits, int howto) 776 1.1 christos { 777 1.21 thorpej struct tty *tp = cy->cy_tty; 778 1.1 christos int s, msvr; 779 1.1 christos 780 1.1 christos s = spltty(); 781 1.1 christos 782 1.1 christos /* select channel */ 783 1.2 thorpej cd_write_reg(sc, cy->cy_chip, CD1400_CAR, 784 1.2 thorpej cy->cy_port_num & CD1400_CAR_CHAN); 785 1.1 christos 786 1.21 thorpej /* Does not manipulate RTS if it is used for flow control. */ 787 1.1 christos switch (howto) { 788 1.1 christos case DMGET: 789 1.1 christos bits = 0; 790 1.1 christos if (cy->cy_channel_control & CD1400_CCR_RCVEN) 791 1.1 christos bits |= TIOCM_LE; 792 1.1 christos msvr = cd_read_reg(sc, cy->cy_chip, CD1400_MSVR2); 793 1.11 tron if (cy->cy_clock == CY_CLOCK_60) { 794 1.11 tron if (cd_read_reg(sc, cy->cy_chip, CD1400_MSVR1) & 795 1.11 tron CD1400_MSVR1_RTS) 796 1.11 tron bits |= TIOCM_DTR; 797 1.11 tron if (msvr & CD1400_MSVR2_DTR) 798 1.11 tron bits |= TIOCM_RTS; 799 1.11 tron } else { 800 1.11 tron if (cd_read_reg(sc, cy->cy_chip, CD1400_MSVR1) & 801 1.11 tron CD1400_MSVR1_RTS) 802 1.11 tron bits |= TIOCM_RTS; 803 1.11 tron if (msvr & CD1400_MSVR2_DTR) 804 1.11 tron bits |= TIOCM_DTR; 805 1.11 tron } 806 1.1 christos if (msvr & CD1400_MSVR2_CTS) 807 1.1 christos bits |= TIOCM_CTS; 808 1.1 christos if (msvr & CD1400_MSVR2_CD) 809 1.1 christos bits |= TIOCM_CD; 810 1.21 thorpej /* Not connected on some Cyclom-Y boards? */ 811 1.21 thorpej if (msvr & CD1400_MSVR2_DSR) 812 1.1 christos bits |= TIOCM_DSR; 813 1.21 thorpej /* Not connected on some Cyclom-8Y boards? */ 814 1.21 thorpej if (msvr & CD1400_MSVR2_RI) 815 1.1 christos bits |= TIOCM_RI; 816 1.21 thorpej break; 817 1.1 christos 818 1.1 christos case DMSET: /* replace old values with new ones */ 819 1.11 tron if (cy->cy_clock == CY_CLOCK_60) { 820 1.11 tron if (!ISSET(tp->t_cflag, CRTSCTS)) 821 1.11 tron cd_write_reg(sc, cy->cy_chip, CD1400_MSVR2, 822 1.11 tron ((bits & TIOCM_RTS) ? CD1400_MSVR2_DTR : 0)); 823 1.11 tron cd_write_reg(sc, cy->cy_chip, CD1400_MSVR1, 824 1.11 tron ((bits & TIOCM_DTR) ? CD1400_MSVR1_RTS : 0)); 825 1.11 tron } else { 826 1.11 tron if (!ISSET(tp->t_cflag, CRTSCTS)) 827 1.11 tron cd_write_reg(sc, cy->cy_chip, CD1400_MSVR1, 828 1.11 tron ((bits & TIOCM_RTS) ? CD1400_MSVR1_RTS : 0)); 829 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_MSVR2, 830 1.11 tron ((bits & TIOCM_DTR) ? CD1400_MSVR2_DTR : 0)); 831 1.11 tron } 832 1.1 christos break; 833 1.1 christos 834 1.1 christos case DMBIS: /* set bits */ 835 1.11 tron if (cy->cy_clock == CY_CLOCK_60) { 836 1.21 thorpej if (!ISSET(tp->t_cflag, CRTSCTS) && 837 1.21 thorpej (bits & TIOCM_RTS) != 0) 838 1.11 tron cd_write_reg(sc, cy->cy_chip, CD1400_MSVR2, 839 1.11 tron CD1400_MSVR2_DTR); 840 1.11 tron if (bits & TIOCM_DTR) 841 1.11 tron cd_write_reg(sc, cy->cy_chip, CD1400_MSVR1, 842 1.11 tron CD1400_MSVR1_RTS); 843 1.11 tron } else { 844 1.21 thorpej if (!ISSET(tp->t_cflag, CRTSCTS) && 845 1.21 thorpej (bits & TIOCM_RTS) != 0) 846 1.11 tron cd_write_reg(sc, cy->cy_chip, CD1400_MSVR1, 847 1.11 tron CD1400_MSVR1_RTS); 848 1.11 tron if (bits & TIOCM_DTR) 849 1.11 tron cd_write_reg(sc, cy->cy_chip, CD1400_MSVR2, 850 1.11 tron CD1400_MSVR2_DTR); 851 1.11 tron } 852 1.1 christos break; 853 1.1 christos 854 1.1 christos case DMBIC: /* clear bits */ 855 1.11 tron if (cy->cy_clock == CY_CLOCK_60) { 856 1.11 tron if (!ISSET(tp->t_cflag, CRTSCTS) && (bits & TIOCM_RTS)) 857 1.11 tron cd_write_reg(sc, cy->cy_chip, CD1400_MSVR2, 0); 858 1.11 tron if (bits & TIOCM_DTR) 859 1.11 tron cd_write_reg(sc, cy->cy_chip, CD1400_MSVR1, 0); 860 1.11 tron } else { 861 1.11 tron if (!ISSET(tp->t_cflag, CRTSCTS) && (bits & TIOCM_RTS)) 862 1.11 tron cd_write_reg(sc, cy->cy_chip, CD1400_MSVR1, 0); 863 1.11 tron if (bits & TIOCM_DTR) 864 1.11 tron cd_write_reg(sc, cy->cy_chip, CD1400_MSVR2, 0); 865 1.11 tron } 866 1.1 christos break; 867 1.1 christos } 868 1.1 christos splx(s); 869 1.21 thorpej return ((howto == DMGET) ? bits : 0); 870 1.1 christos } 871 1.1 christos 872 1.1 christos /* 873 1.1 christos * Upper-level handler loop (called from timer interrupt?) 874 1.1 christos * This routine is common for multiple cards 875 1.1 christos */ 876 1.18 thorpej void 877 1.48 christos cy_poll(void *arg) 878 1.1 christos { 879 1.1 christos int card, port; 880 1.1 christos struct cy_softc *sc; 881 1.1 christos struct cy_port *cy; 882 1.1 christos struct tty *tp; 883 1.1 christos static int counter = 0; 884 1.1 christos #ifdef CY_DEBUG1 885 1.1 christos int did_something; 886 1.1 christos #endif 887 1.1 christos int s = spltty(); 888 1.1 christos 889 1.1 christos if (cy_events == 0 && ++counter < 200) { 890 1.1 christos splx(s); 891 1.1 christos goto out; 892 1.1 christos } 893 1.1 christos cy_events = 0; 894 1.1 christos splx(s); 895 1.1 christos 896 1.1 christos for (card = 0; card < cy_cd.cd_ndevs; card++) { 897 1.55 matt sc = device_lookup_private(&cy_cd, card); 898 1.1 christos if (sc == NULL) 899 1.1 christos continue; 900 1.1 christos 901 1.1 christos #ifdef CY_DEBUG1 902 1.1 christos sc->sc_poll_count1++; 903 1.1 christos did_something = 0; 904 1.1 christos #endif 905 1.1 christos 906 1.20 thorpej for (port = 0; port < sc->sc_nchannels; port++) { 907 1.1 christos cy = &sc->sc_ports[port]; 908 1.1 christos if ((tp = cy->cy_tty) == NULL || cy->cy_ibuf == NULL || 909 1.10 mycroft (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0)) 910 1.1 christos continue; 911 1.1 christos 912 1.1 christos /* 913 1.1 christos * handle received data 914 1.1 christos */ 915 1.1 christos while (cy->cy_ibuf_rd_ptr != cy->cy_ibuf_wr_ptr) { 916 1.1 christos u_char line_stat; 917 1.1 christos int chr; 918 1.1 christos 919 1.1 christos line_stat = cy->cy_ibuf_rd_ptr[0]; 920 1.1 christos chr = cy->cy_ibuf_rd_ptr[1]; 921 1.1 christos 922 1.1 christos if (line_stat & 923 1.1 christos (CD1400_RDSR_BREAK | CD1400_RDSR_FE)) 924 1.1 christos chr |= TTY_FE; 925 1.1 christos if (line_stat & CD1400_RDSR_PE) 926 1.1 christos chr |= TTY_PE; 927 1.1 christos 928 1.1 christos /* 929 1.1 christos * on an overrun error the data is treated as 930 1.1 christos * good just as it should be. 931 1.1 christos */ 932 1.1 christos 933 1.1 christos #ifdef CY_DEBUG 934 1.55 matt aprint_debug_dev(sc->sc_dev, 935 1.55 matt "port %d ttyinput 0x%x\n", 936 1.55 matt port, chr); 937 1.1 christos #endif 938 1.1 christos 939 1.16 eeh (*tp->t_linesw->l_rint) (chr, tp); 940 1.1 christos 941 1.1 christos s = spltty(); /* really necessary? */ 942 1.1 christos if ((cy->cy_ibuf_rd_ptr += 2) == 943 1.1 christos cy->cy_ibuf_end) 944 1.1 christos cy->cy_ibuf_rd_ptr = cy->cy_ibuf; 945 1.1 christos splx(s); 946 1.1 christos 947 1.1 christos #ifdef CY_DEBUG1 948 1.1 christos did_something = 1; 949 1.1 christos #endif 950 1.1 christos } 951 1.1 christos 952 1.1 christos /* 953 1.1 christos * If we don't have any received data in ibuf and 954 1.1 christos * CRTSCTS is on and RTS is turned off, it is time to 955 1.1 christos * turn RTS back on 956 1.1 christos */ 957 1.1 christos if (ISSET(tp->t_cflag, CRTSCTS)) { 958 1.1 christos /* 959 1.1 christos * we can't use cy_modem_control() here as it 960 1.1 christos * doesn't change RTS if RTSCTS is on 961 1.1 christos */ 962 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_CAR, 963 1.1 christos port & CD1400_CAR_CHAN); 964 1.1 christos 965 1.11 tron if (cy->cy_clock == CY_CLOCK_60) { 966 1.11 tron if ((cd_read_reg(sc, cy->cy_chip, 967 1.11 tron CD1400_MSVR2) & CD1400_MSVR2_DTR) == 0) { 968 1.11 tron cd_write_reg(sc, cy->cy_chip, 969 1.11 tron CD1400_MSVR2,CD1400_MSVR2_DTR); 970 1.11 tron #ifdef CY_DEBUG1 971 1.11 tron did_something = 1; 972 1.11 tron #endif 973 1.11 tron } 974 1.11 tron } else { 975 1.11 tron if ((cd_read_reg(sc, cy->cy_chip, 976 1.1 christos CD1400_MSVR1) & CD1400_MSVR1_RTS) == 0) { 977 1.11 tron cd_write_reg(sc, cy->cy_chip, 978 1.11 tron CD1400_MSVR1,CD1400_MSVR1_RTS); 979 1.1 christos #ifdef CY_DEBUG1 980 1.1 christos did_something = 1; 981 1.1 christos #endif 982 1.11 tron } 983 1.1 christos } 984 1.1 christos } 985 1.1 christos 986 1.1 christos /* 987 1.1 christos * handle carrier changes 988 1.1 christos */ 989 1.1 christos s = spltty(); 990 1.1 christos if (ISSET(cy->cy_flags, CY_F_CARRIER_CHANGED)) { 991 1.1 christos int carrier; 992 1.1 christos 993 1.1 christos CLR(cy->cy_flags, CY_F_CARRIER_CHANGED); 994 1.1 christos splx(s); 995 1.1 christos 996 1.1 christos carrier = ((cy->cy_carrier_stat & 997 1.1 christos CD1400_MSVR2_CD) != 0); 998 1.1 christos 999 1.1 christos #ifdef CY_DEBUG 1000 1.4 christos printf("cy_poll: carrier change " 1001 1.1 christos "(card %d, port %d, carrier %d)\n", 1002 1.1 christos card, port, carrier); 1003 1.1 christos #endif 1004 1.20 thorpej if (CY_DIALOUT(tp->t_dev) == 0 && 1005 1.16 eeh !(*tp->t_linesw->l_modem)(tp, carrier)) 1006 1.1 christos cy_modem_control(sc, cy, 1007 1.1 christos TIOCM_DTR, DMBIC); 1008 1.1 christos 1009 1.1 christos #ifdef CY_DEBUG1 1010 1.1 christos did_something = 1; 1011 1.1 christos #endif 1012 1.37 perry } else 1013 1.1 christos splx(s); 1014 1.1 christos 1015 1.1 christos s = spltty(); 1016 1.1 christos if (ISSET(cy->cy_flags, CY_F_START)) { 1017 1.1 christos CLR(cy->cy_flags, CY_F_START); 1018 1.1 christos splx(s); 1019 1.1 christos 1020 1.16 eeh (*tp->t_linesw->l_start) (tp); 1021 1.1 christos 1022 1.1 christos #ifdef CY_DEBUG1 1023 1.1 christos did_something = 1; 1024 1.1 christos #endif 1025 1.1 christos } else 1026 1.1 christos splx(s); 1027 1.1 christos 1028 1.1 christos /* could move this to even upper level... */ 1029 1.1 christos if (cy->cy_fifo_overruns) { 1030 1.1 christos cy->cy_fifo_overruns = 0; 1031 1.1 christos /* 1032 1.1 christos * doesn't report overrun count, but 1033 1.1 christos * shouldn't really matter 1034 1.1 christos */ 1035 1.1 christos log(LOG_WARNING, "%s: port %d fifo overrun\n", 1036 1.55 matt device_xname(sc->sc_dev), port); 1037 1.1 christos } 1038 1.1 christos if (cy->cy_ibuf_overruns) { 1039 1.1 christos cy->cy_ibuf_overruns = 0; 1040 1.1 christos log(LOG_WARNING, "%s: port %d ibuf overrun\n", 1041 1.55 matt device_xname(sc->sc_dev), port); 1042 1.1 christos } 1043 1.1 christos } /* for(port...) */ 1044 1.1 christos #ifdef CY_DEBUG1 1045 1.1 christos if (did_something && counter >= 200) 1046 1.1 christos sc->sc_poll_count2++; 1047 1.1 christos #endif 1048 1.1 christos } /* for(card...) */ 1049 1.1 christos 1050 1.1 christos counter = 0; 1051 1.1 christos 1052 1.1 christos out: 1053 1.12 thorpej callout_reset(&cy_poll_callout, 1, cy_poll, NULL); 1054 1.1 christos } 1055 1.1 christos 1056 1.1 christos /* 1057 1.1 christos * hardware interrupt routine 1058 1.1 christos */ 1059 1.1 christos int 1060 1.18 thorpej cy_intr(void *arg) 1061 1.1 christos { 1062 1.1 christos struct cy_softc *sc = arg; 1063 1.1 christos struct cy_port *cy; 1064 1.1 christos int cy_chip, stat; 1065 1.1 christos int int_serviced = 0; 1066 1.1 christos 1067 1.1 christos /* 1068 1.1 christos * Check interrupt status of each CD1400 chip on this card 1069 1.1 christos * (multiple cards cannot share the same interrupt) 1070 1.1 christos */ 1071 1.1 christos for (cy_chip = 0; cy_chip < sc->sc_nchips; cy_chip++) { 1072 1.1 christos 1073 1.1 christos stat = cd_read_reg(sc, cy_chip, CD1400_SVRR); 1074 1.1 christos if (stat == 0) 1075 1.1 christos continue; 1076 1.1 christos 1077 1.1 christos if (ISSET(stat, CD1400_SVRR_RXRDY)) { 1078 1.1 christos u_char save_car, save_rir, serv_type; 1079 1.1 christos u_char line_stat, recv_data, n_chars; 1080 1.1 christos u_char *buf_p; 1081 1.1 christos 1082 1.1 christos save_rir = cd_read_reg(sc, cy_chip, CD1400_RIR); 1083 1.1 christos save_car = cd_read_reg(sc, cy_chip, CD1400_CAR); 1084 1.1 christos /* enter rx service */ 1085 1.1 christos cd_write_reg(sc, cy_chip, CD1400_CAR, save_rir); 1086 1.1 christos 1087 1.1 christos serv_type = cd_read_reg(sc, cy_chip, CD1400_RIVR); 1088 1.1 christos cy = &sc->sc_ports[serv_type >> 3]; 1089 1.1 christos 1090 1.1 christos #ifdef CY_DEBUG1 1091 1.1 christos cy->cy_rx_int_count++; 1092 1.1 christos #endif 1093 1.1 christos 1094 1.1 christos buf_p = cy->cy_ibuf_wr_ptr; 1095 1.1 christos 1096 1.1 christos if (ISSET(serv_type, CD1400_RIVR_EXCEPTION)) { 1097 1.1 christos line_stat = cd_read_reg(sc, cy->cy_chip, 1098 1.1 christos CD1400_RDSR); 1099 1.1 christos recv_data = cd_read_reg(sc, cy->cy_chip, 1100 1.1 christos CD1400_RDSR); 1101 1.1 christos 1102 1.15 sommerfe if (cy->cy_tty == NULL || 1103 1.15 sommerfe !ISSET(cy->cy_tty->t_state, TS_ISOPEN)) 1104 1.15 sommerfe goto end_rx_serv; 1105 1.15 sommerfe 1106 1.1 christos #ifdef CY_DEBUG 1107 1.55 matt aprint_debug_dev( 1108 1.55 matt sc->sc_dev, 1109 1.55 matt "port %d recv exception, " 1110 1.55 matt "line_stat 0x%x, char 0x%x\n", 1111 1.55 matt cy->cy_port_num, line_stat, recv_data); 1112 1.1 christos #endif 1113 1.1 christos if (ISSET(line_stat, CD1400_RDSR_OE)) 1114 1.1 christos cy->cy_fifo_overruns++; 1115 1.1 christos 1116 1.1 christos *buf_p++ = line_stat; 1117 1.1 christos *buf_p++ = recv_data; 1118 1.1 christos if (buf_p == cy->cy_ibuf_end) 1119 1.1 christos buf_p = cy->cy_ibuf; 1120 1.1 christos 1121 1.1 christos if (buf_p == cy->cy_ibuf_rd_ptr) { 1122 1.1 christos if (buf_p == cy->cy_ibuf) 1123 1.1 christos buf_p = cy->cy_ibuf_end; 1124 1.1 christos buf_p -= 2; 1125 1.1 christos cy->cy_ibuf_overruns++; 1126 1.1 christos } 1127 1.1 christos cy_events = 1; 1128 1.1 christos } else {/* no exception, received data OK */ 1129 1.1 christos n_chars = cd_read_reg(sc, cy->cy_chip, 1130 1.1 christos CD1400_RDCR); 1131 1.15 sommerfe 1132 1.15 sommerfe /* If no tty or not open, discard data */ 1133 1.15 sommerfe if (cy->cy_tty == NULL || 1134 1.15 sommerfe !ISSET(cy->cy_tty->t_state, TS_ISOPEN)) { 1135 1.15 sommerfe while (n_chars--) 1136 1.43 christos (void)cd_read_reg(sc, 1137 1.43 christos cy->cy_chip, CD1400_RDSR); 1138 1.15 sommerfe goto end_rx_serv; 1139 1.15 sommerfe } 1140 1.15 sommerfe 1141 1.1 christos #ifdef CY_DEBUG 1142 1.55 matt aprint_debug_dev(sc->sc_dev, 1143 1.55 matt "port %d receive ok %d chars\n", 1144 1.55 matt cy->cy_port_num, n_chars); 1145 1.1 christos #endif 1146 1.1 christos while (n_chars--) { 1147 1.1 christos *buf_p++ = 0; /* status: OK */ 1148 1.1 christos /* data byte */ 1149 1.1 christos *buf_p++ = cd_read_reg(sc, 1150 1.1 christos cy->cy_chip, CD1400_RDSR); 1151 1.1 christos if (buf_p == cy->cy_ibuf_end) 1152 1.1 christos buf_p = cy->cy_ibuf; 1153 1.1 christos if (buf_p == cy->cy_ibuf_rd_ptr) { 1154 1.1 christos if (buf_p == cy->cy_ibuf) 1155 1.1 christos buf_p = cy->cy_ibuf_end; 1156 1.1 christos buf_p -= 2; 1157 1.1 christos cy->cy_ibuf_overruns++; 1158 1.1 christos break; 1159 1.1 christos } 1160 1.1 christos } 1161 1.1 christos cy_events = 1; 1162 1.1 christos } 1163 1.1 christos 1164 1.1 christos cy->cy_ibuf_wr_ptr = buf_p; 1165 1.1 christos 1166 1.1 christos /* RTS handshaking for incoming data */ 1167 1.1 christos if (ISSET(cy->cy_tty->t_cflag, CRTSCTS)) { 1168 1.15 sommerfe int bf, msvr; 1169 1.1 christos 1170 1.1 christos bf = buf_p - cy->cy_ibuf_rd_ptr; 1171 1.1 christos if (bf < 0) 1172 1.1 christos bf += CY_IBUF_SIZE; 1173 1.1 christos 1174 1.37 perry if (bf > (CY_IBUF_SIZE / 2)) { 1175 1.15 sommerfe /* turn RTS off */ 1176 1.37 perry if (cy->cy_clock == CY_CLOCK_60) 1177 1.15 sommerfe msvr = CD1400_MSVR2; 1178 1.15 sommerfe else 1179 1.37 perry msvr = CD1400_MSVR1; 1180 1.15 sommerfe cd_write_reg(sc, cy->cy_chip, msvr, 0); 1181 1.11 tron } 1182 1.1 christos } 1183 1.1 christos 1184 1.1 christos end_rx_serv: 1185 1.1 christos /* terminate service context */ 1186 1.37 perry cd_write_reg(sc, cy->cy_chip, CD1400_RIR, 1187 1.15 sommerfe save_rir & 0x3f); 1188 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_CAR, save_car); 1189 1.1 christos int_serviced = 1; 1190 1.11 tron } /* if (rx_service...) */ 1191 1.1 christos if (ISSET(stat, CD1400_SVRR_MDMCH)) { 1192 1.1 christos u_char save_car, save_mir, serv_type, modem_stat; 1193 1.1 christos 1194 1.1 christos save_mir = cd_read_reg(sc, cy_chip, CD1400_MIR); 1195 1.1 christos save_car = cd_read_reg(sc, cy_chip, CD1400_CAR); 1196 1.1 christos /* enter modem service */ 1197 1.1 christos cd_write_reg(sc, cy_chip, CD1400_CAR, save_mir); 1198 1.1 christos 1199 1.1 christos serv_type = cd_read_reg(sc, cy_chip, CD1400_MIVR); 1200 1.1 christos cy = &sc->sc_ports[serv_type >> 3]; 1201 1.1 christos 1202 1.1 christos #ifdef CY_DEBUG1 1203 1.1 christos cy->cy_modem_int_count++; 1204 1.1 christos #endif 1205 1.1 christos 1206 1.1 christos modem_stat = cd_read_reg(sc, cy->cy_chip, CD1400_MSVR2); 1207 1.1 christos 1208 1.1 christos #ifdef CY_DEBUG 1209 1.55 matt aprint_debug_dev(sc->sc_dev, 1210 1.55 matt "port %d modem line change, new stat 0x%x\n", 1211 1.55 matt cy->cy_port_num, modem_stat); 1212 1.1 christos #endif 1213 1.1 christos if (ISSET((cy->cy_carrier_stat ^ modem_stat), CD1400_MSVR2_CD)) { 1214 1.1 christos SET(cy->cy_flags, CY_F_CARRIER_CHANGED); 1215 1.1 christos cy_events = 1; 1216 1.1 christos } 1217 1.1 christos cy->cy_carrier_stat = modem_stat; 1218 1.1 christos 1219 1.1 christos /* terminate service context */ 1220 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_MIR, save_mir & 0x3f); 1221 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_CAR, save_car); 1222 1.1 christos int_serviced = 1; 1223 1.11 tron } /* if (modem_service...) */ 1224 1.1 christos if (ISSET(stat, CD1400_SVRR_TXRDY)) { 1225 1.1 christos u_char save_car, save_tir, serv_type, 1226 1.1 christos count, ch; 1227 1.1 christos struct tty *tp; 1228 1.1 christos 1229 1.1 christos save_tir = cd_read_reg(sc, cy_chip, CD1400_TIR); 1230 1.1 christos save_car = cd_read_reg(sc, cy_chip, CD1400_CAR); 1231 1.1 christos /* enter tx service */ 1232 1.1 christos cd_write_reg(sc, cy_chip, CD1400_CAR, save_tir); 1233 1.1 christos 1234 1.1 christos serv_type = cd_read_reg(sc, cy_chip, CD1400_TIVR); 1235 1.1 christos cy = &sc->sc_ports[serv_type >> 3]; 1236 1.1 christos 1237 1.1 christos #ifdef CY_DEBUG1 1238 1.1 christos cy->cy_tx_int_count++; 1239 1.1 christos #endif 1240 1.1 christos #ifdef CY_DEBUG 1241 1.55 matt aprint_debug_dev(sc->sc_dev, "port %d tx service\n", 1242 1.2 thorpej cy->cy_port_num); 1243 1.1 christos #endif 1244 1.1 christos 1245 1.1 christos /* stop transmitting if no tty or CY_F_STOP set */ 1246 1.1 christos tp = cy->cy_tty; 1247 1.1 christos if (tp == NULL || ISSET(cy->cy_flags, CY_F_STOP)) 1248 1.1 christos goto txdone; 1249 1.1 christos 1250 1.1 christos count = 0; 1251 1.1 christos if (ISSET(cy->cy_flags, CY_F_SEND_NUL)) { 1252 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_TDR, 0); 1253 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_TDR, 0); 1254 1.1 christos count += 2; 1255 1.1 christos CLR(cy->cy_flags, CY_F_SEND_NUL); 1256 1.1 christos } 1257 1.1 christos if (tp->t_outq.c_cc > 0) { 1258 1.1 christos SET(tp->t_state, TS_BUSY); 1259 1.1 christos while (tp->t_outq.c_cc > 0 && 1260 1.1 christos count < CD1400_TX_FIFO_SIZE) { 1261 1.1 christos ch = getc(&tp->t_outq); 1262 1.1 christos /* 1263 1.1 christos * remember to double NUL characters 1264 1.1 christos * because embedded transmit commands 1265 1.1 christos * are enabled 1266 1.1 christos */ 1267 1.1 christos if (ch == 0) { 1268 1.1 christos if (count >= CD1400_TX_FIFO_SIZE - 2) { 1269 1.1 christos SET(cy->cy_flags, CY_F_SEND_NUL); 1270 1.1 christos break; 1271 1.1 christos } 1272 1.1 christos cd_write_reg(sc, cy->cy_chip, 1273 1.1 christos CD1400_TDR, ch); 1274 1.1 christos count++; 1275 1.1 christos } 1276 1.1 christos cd_write_reg(sc, cy->cy_chip, 1277 1.1 christos CD1400_TDR, ch); 1278 1.1 christos count++; 1279 1.1 christos } 1280 1.1 christos } else { 1281 1.1 christos /* 1282 1.1 christos * no data to send -- check if we should 1283 1.1 christos * start/stop a break 1284 1.1 christos */ 1285 1.1 christos /* 1286 1.1 christos * XXX does this cause too much delay before 1287 1.1 christos * breaks? 1288 1.1 christos */ 1289 1.1 christos if (ISSET(cy->cy_flags, CY_F_START_BREAK)) { 1290 1.1 christos cd_write_reg(sc, cy->cy_chip, 1291 1.1 christos CD1400_TDR, 0); 1292 1.1 christos cd_write_reg(sc, cy->cy_chip, 1293 1.1 christos CD1400_TDR, 0x81); 1294 1.1 christos CLR(cy->cy_flags, CY_F_START_BREAK); 1295 1.1 christos } 1296 1.1 christos if (ISSET(cy->cy_flags, CY_F_END_BREAK)) { 1297 1.1 christos cd_write_reg(sc, cy->cy_chip, 1298 1.1 christos CD1400_TDR, 0); 1299 1.1 christos cd_write_reg(sc, cy->cy_chip, 1300 1.1 christos CD1400_TDR, 0x83); 1301 1.1 christos CLR(cy->cy_flags, CY_F_END_BREAK); 1302 1.1 christos } 1303 1.1 christos } 1304 1.1 christos 1305 1.1 christos if (tp->t_outq.c_cc == 0) { 1306 1.1 christos txdone: 1307 1.1 christos /* 1308 1.1 christos * No data to send or requested to stop. 1309 1.1 christos * Disable transmit interrupt 1310 1.1 christos */ 1311 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_SRER, 1312 1.1 christos cd_read_reg(sc, cy->cy_chip, CD1400_SRER) 1313 1.1 christos & ~CD1400_SRER_TXRDY); 1314 1.1 christos CLR(cy->cy_flags, CY_F_STOP); 1315 1.1 christos CLR(tp->t_state, TS_BUSY); 1316 1.1 christos } 1317 1.1 christos if (tp->t_outq.c_cc <= tp->t_lowat) { 1318 1.1 christos SET(cy->cy_flags, CY_F_START); 1319 1.1 christos cy_events = 1; 1320 1.1 christos } 1321 1.1 christos /* terminate service context */ 1322 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_TIR, save_tir & 0x3f); 1323 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_CAR, save_car); 1324 1.1 christos int_serviced = 1; 1325 1.11 tron } /* if (tx_service...) */ 1326 1.1 christos } /* for(...all CD1400s on a card) */ 1327 1.1 christos 1328 1.1 christos /* ensure an edge for next interrupt */ 1329 1.5 thorpej bus_space_write_1(sc->sc_memt, sc->sc_bsh, 1330 1.1 christos CY_CLEAR_INTR << sc->sc_bustype, 0); 1331 1.1 christos return int_serviced; 1332 1.1 christos } 1333 1.1 christos 1334 1.1 christos /* 1335 1.1 christos * subroutine to enable CD1400 transmitter 1336 1.1 christos */ 1337 1.18 thorpej void 1338 1.18 thorpej cy_enable_transmitter(struct cy_softc *sc, struct cy_port *cy) 1339 1.1 christos { 1340 1.1 christos int s = spltty(); 1341 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_CAR, 1342 1.2 thorpej cy->cy_port_num & CD1400_CAR_CHAN); 1343 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_SRER, 1344 1.1 christos cd_read_reg(sc, cy->cy_chip, CD1400_SRER) | CD1400_SRER_TXRDY); 1345 1.1 christos splx(s); 1346 1.1 christos } 1347 1.1 christos 1348 1.1 christos /* 1349 1.1 christos * Execute a CD1400 channel command 1350 1.1 christos */ 1351 1.18 thorpej void 1352 1.18 thorpej cd1400_channel_cmd(struct cy_softc *sc, struct cy_port *cy, int cmd) 1353 1.1 christos { 1354 1.1 christos u_int waitcnt = 5 * 8 * 1024; /* approx 5 ms */ 1355 1.1 christos 1356 1.1 christos #ifdef CY_DEBUG 1357 1.13 tsubai printf("c1400_channel_cmd cy %p command 0x%x\n", cy, cmd); 1358 1.1 christos #endif 1359 1.1 christos 1360 1.1 christos /* wait until cd1400 is ready to process a new command */ 1361 1.1 christos while (cd_read_reg(sc, cy->cy_chip, CD1400_CCR) != 0 && waitcnt-- > 0); 1362 1.1 christos 1363 1.1 christos if (waitcnt == 0) 1364 1.1 christos log(LOG_ERR, "%s: channel command timeout\n", 1365 1.55 matt device_xname(sc->sc_dev)); 1366 1.1 christos 1367 1.1 christos cd_write_reg(sc, cy->cy_chip, CD1400_CCR, cmd); 1368 1.1 christos } 1369 1.1 christos 1370 1.1 christos /* 1371 1.1 christos * Compute clock option register and baud rate register values 1372 1.1 christos * for a given speed. Return 0 on success, -1 on failure. 1373 1.1 christos * 1374 1.1 christos * The error between requested and actual speed seems 1375 1.1 christos * to be well within allowed limits (less than 3%) 1376 1.1 christos * with every speed value between 50 and 150000 bps. 1377 1.1 christos */ 1378 1.18 thorpej int 1379 1.18 thorpej cy_speed(speed_t speed, int *cor, int *bpr, int cy_clock) 1380 1.1 christos { 1381 1.1 christos int c, co, br; 1382 1.1 christos 1383 1.1 christos if (speed < 50 || speed > 150000) 1384 1.1 christos return -1; 1385 1.1 christos 1386 1.1 christos for (c = 0, co = 8; co <= 2048; co <<= 2, c++) { 1387 1.11 tron br = (cy_clock + (co * speed) / 2) / (co * speed); 1388 1.1 christos if (br < 0x100) { 1389 1.1 christos *bpr = br; 1390 1.1 christos *cor = c; 1391 1.1 christos return 0; 1392 1.1 christos } 1393 1.1 christos } 1394 1.1 christos 1395 1.1 christos return -1; 1396 1.1 christos } 1397