1 /* $OpenBSD: magma.c,v 1.13 2003/10/03 16:44:51 miod Exp $ */ 2 /* 3 * magma.c 4 * 5 * Copyright (c) 1998 Iain Hibbert 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Iain Hibbert 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 #define MAGMA_DEBUG 34 */ 35 36 /* 37 * Driver for Magma SBus Serial/Parallel cards using the Cirrus Logic 38 * CD1400 & CD1190 chips 39 */ 40 41 #include "magma.h" 42 #if NMAGMA > 0 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/proc.h> 47 #include <sys/device.h> 48 #include <sys/file.h> 49 #include <sys/ioctl.h> 50 #include <sys/malloc.h> 51 #include <sys/tty.h> 52 #include <sys/time.h> 53 #include <sys/kernel.h> 54 #include <sys/syslog.h> 55 #include <sys/conf.h> 56 #include <sys/errno.h> 57 58 #include <machine/autoconf.h> 59 #include <machine/conf.h> 60 #include <machine/bus.h> 61 #include <machine/bppioctl.h> 62 63 #include <dev/sbus/sbusvar.h> 64 #include <dev/ic/cd1400reg.h> 65 #include <dev/ic/cd1190reg.h> 66 67 #include <dev/sbus/magmareg.h> 68 69 /* supported cards 70 * 71 * The table below lists the cards that this driver is likely to 72 * be able to support. 73 * 74 * Cards with parallel ports: except for the LC2+1Sp, they all use 75 * the CD1190 chip which I know nothing about. I've tried to leave 76 * hooks for it so it shouldn't be too hard to add support later. 77 * (I think somebody is working on this separately) 78 * 79 * Thanks to Bruce at Magma for telling me the hardware offsets. 80 */ 81 static const struct magma_board_info supported_cards[] = { 82 { 83 "MAGMA_Sp", "MAGMA,4_Sp", "Magma 4 Sp", 4, 0, 84 1, 0xa000, 0xc000, 0xe000, { 0x8000, 0, 0, 0 }, 85 0, { 0, 0 } 86 }, 87 { 88 "MAGMA_Sp", "MAGMA,8_Sp", "Magma 8 Sp", 8, 0, 89 2, 0xa000, 0xc000, 0xe000, { 0x4000, 0x6000, 0, 0 }, 90 0, { 0, 0 } 91 }, 92 { 93 "MAGMA_Sp", "MAGMA,_8HS_Sp", "Magma Fast 8 Sp", 8, 0, 94 2, 0x2000, 0x4000, 0x6000, { 0x8000, 0xa000, 0, 0 }, 95 0, { 0, 0 } 96 }, 97 { 98 "MAGMA_Sp", "MAGMA,_8SP_422", "Magma 8 Sp - 422", 8, 0, 99 2, 0x2000, 0x4000, 0x6000, { 0x8000, 0xa000, 0, 0 }, 100 0, { 0, 0 } 101 }, 102 { 103 "MAGMA_Sp", "MAGMA,12_Sp", "Magma 12 Sp", 12, 0, 104 3, 0xa000, 0xc000, 0xe000, { 0x2000, 0x4000, 0x6000, 0 }, 105 0, { 0, 0 } 106 }, 107 { 108 "MAGMA_Sp", "MAGMA,16_Sp", "Magma 16 Sp", 16, 0, 109 4, 0xd000, 0xe000, 0xf000, { 0x8000, 0x9000, 0xa000, 0xb000 }, 110 0, { 0, 0 } 111 }, 112 { 113 "MAGMA_Sp", "MAGMA,16_Sp_2", "Magma 16 Sp", 16, 0, 114 4, 0x2000, 0x4000, 0x6000, { 0x8000, 0xa000, 0xc000, 0xe000 }, 115 0, { 0, 0 } 116 }, 117 { 118 "MAGMA_Sp", "MAGMA,16HS_Sp", "Magma Fast 16 Sp", 16, 0, 119 4, 0x2000, 0x4000, 0x6000, { 0x8000, 0xa000, 0xc000, 0xe000 }, 120 0, { 0, 0 } 121 }, 122 { 123 "MAGMA_Sp", "MAGMA,21_Sp", "Magma LC 2+1 Sp", 2, 1, 124 1, 0xa000, 0xc000, 0xe000, { 0x8000, 0, 0, 0 }, 125 0, { 0, 0 } 126 }, 127 { 128 "MAGMA_Sp", "MAGMA,21HS_Sp", "Magma 2+1 Sp", 2, 1, 129 1, 0xa000, 0xc000, 0xe000, { 0x4000, 0, 0, 0 }, 130 1, { 0x6000, 0 } 131 }, 132 { 133 "MAGMA_Sp", "MAGMA,41_Sp", "Magma 4+1 Sp", 4, 1, 134 1, 0xa000, 0xc000, 0xe000, { 0x4000, 0, 0, 0 }, 135 1, { 0x6000, 0 } 136 }, 137 { 138 "MAGMA_Sp", "MAGMA,82_Sp", "Magma 8+2 Sp", 8, 2, 139 2, 0xd000, 0xe000, 0xf000, { 0x8000, 0x9000, 0, 0 }, 140 2, { 0xa000, 0xb000 } 141 }, 142 { 143 "MAGMA_Sp", "MAGMA,P1_Sp", "Magma P1 Sp", 0, 1, 144 0, 0, 0, 0, { 0, 0, 0, 0 }, 145 1, { 0x8000, 0 } 146 }, 147 { 148 "MAGMA_Sp", "MAGMA,P2_Sp", "Magma P2 Sp", 0, 2, 149 0, 0, 0, 0, { 0, 0, 0, 0 }, 150 2, { 0x4000, 0x8000 } 151 }, 152 { 153 "MAGMA 2+1HS Sp", "", "Magma 2+1HS Sp", 2, 0, 154 1, 0xa000, 0xc000, 0xe000, { 0x4000, 0, 0, 0 }, 155 1, { 0x8000, 0 } 156 }, 157 { 158 NULL, NULL, NULL, 0, 0, 159 0, 0, 0, 0, { 0, 0, 0, 0 }, 160 0, { 0, 0 } 161 } 162 }; 163 164 /************************************************************************ 165 * 166 * Autoconfig Stuff 167 */ 168 169 struct cfattach magma_ca = { 170 sizeof(struct magma_softc), magma_match, magma_attach 171 }; 172 173 struct cfdriver magma_cd = { 174 NULL, "magma", DV_DULL 175 }; 176 177 struct cfattach mtty_ca = { 178 sizeof(struct mtty_softc), mtty_match, mtty_attach 179 }; 180 181 struct cfdriver mtty_cd = { 182 NULL, "mtty", DV_TTY 183 }; 184 185 struct cfattach mbpp_ca = { 186 sizeof(struct mbpp_softc), mbpp_match, mbpp_attach 187 }; 188 189 struct cfdriver mbpp_cd = { 190 NULL, "mbpp", DV_DULL 191 }; 192 193 /************************************************************************ 194 * 195 * CD1400 Routines 196 * 197 * cd1400_compute_baud calculate COR/BPR register values 198 * cd1400_write_ccr write a value to CD1400 ccr 199 * cd1400_read_reg read from a CD1400 register 200 * cd1400_write_reg write to a CD1400 register 201 * cd1400_enable_transmitter enable transmitting on CD1400 channel 202 */ 203 204 /* 205 * compute the bpr/cor pair for any baud rate 206 * returns 0 for success, 1 for failure 207 */ 208 int 209 cd1400_compute_baud(speed_t speed, int clock, int *cor, int *bpr) 210 { 211 int c, co, br; 212 213 if (speed < 50 || speed > 150000) 214 return (1); 215 216 for (c = 0, co = 8 ; co <= 2048 ; co <<= 2, c++) { 217 br = ((clock * 1000000) + (co * speed) / 2) / (co * speed); 218 if (br < 0x100) { 219 *bpr = br; 220 *cor = c; 221 return (0); 222 } 223 } 224 225 return (1); 226 } 227 228 #define CD1400_READ_REG(cd,reg) \ 229 bus_space_read_1((cd)->cd_regt, (cd)->cd_regh, (reg)) 230 #define CD1400_WRITE_REG(cd,reg,value) \ 231 bus_space_write_1((cd)->cd_regt, (cd)->cd_regh, (reg), (value)) 232 233 /* 234 * Write a CD1400 channel command, should have a timeout? 235 */ 236 __inline void 237 cd1400_write_ccr(struct cd1400 *cd, u_char cmd) 238 { 239 while (CD1400_READ_REG(cd, CD1400_CCR)) 240 /*EMPTY*/; 241 242 CD1400_WRITE_REG(cd, CD1400_CCR, cmd); 243 } 244 245 /* 246 * enable transmit service requests for cd1400 channel 247 */ 248 void 249 cd1400_enable_transmitter(struct cd1400 *cd, int channel) 250 { 251 int s, srer; 252 253 s = spltty(); 254 CD1400_WRITE_REG(cd, CD1400_CAR, channel); 255 srer = CD1400_READ_REG(cd, CD1400_SRER); 256 SET(srer, CD1400_SRER_TXRDY); 257 CD1400_WRITE_REG(cd, CD1400_SRER, srer); 258 splx(s); 259 } 260 261 /************************************************************************ 262 * 263 * CD1190 Routines 264 */ 265 266 /* well, there are none yet */ 267 268 /************************************************************************ 269 * 270 * Magma Routines 271 * 272 * magma_match reports if we have a magma board available 273 * magma_attach attaches magma boards to the sbus 274 * magma_hard hardware level interrupt routine 275 * magma_soft software level interrupt routine 276 */ 277 278 int 279 magma_match(struct device *parent, void *vcf, void *aux) 280 { 281 struct sbus_attach_args *sa = aux; 282 const struct magma_board_info *card; 283 284 /* See if we support this device */ 285 for (card = supported_cards; ; card++) { 286 if (card->mb_sbusname == NULL) 287 /* End of table: no match */ 288 return (0); 289 if (strcmp(sa->sa_name, card->mb_sbusname) == 0) 290 break; 291 } 292 return (1); 293 } 294 295 void 296 magma_attach(struct device *parent, struct device *dev, void *aux) 297 { 298 struct sbus_attach_args *sa = aux; 299 struct magma_softc *sc = (struct magma_softc *)dev; 300 const struct magma_board_info *card; 301 char magma_prom[40], *clockstr; 302 int chip, cd_clock; 303 304 getpropstringA(sa->sa_node, "magma_prom", magma_prom); 305 for (card = supported_cards; card->mb_name != NULL; card++) { 306 if (strcmp(sa->sa_name, card->mb_sbusname) != 0) 307 continue; 308 if (strcmp(magma_prom, card->mb_name) == 0) 309 break; 310 } 311 if (card->mb_name == NULL) { 312 printf(": %s (unsupported)\n", magma_prom); 313 return; 314 } 315 316 sc->sc_bustag = sa->sa_bustag; 317 318 clockstr = getpropstring(sa->sa_node, "clock"); 319 if (strlen(clockstr) == 0) 320 cd_clock = 25; 321 else { 322 cd_clock = 0; 323 while (*clockstr != '\0') 324 cd_clock = cd_clock * 10 + *clockstr++ - '0'; 325 } 326 327 if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, 328 sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size, 329 0, 0, &sc->sc_iohandle) != 0) { 330 printf(": can't map registers\n"); 331 return; 332 } 333 334 if (sa->sa_nintr < 1) { 335 printf(": can't find interrupt\n"); 336 return; 337 } 338 sc->sc_ih = bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_TTY, 0, 339 magma_hard, sc, dev->dv_xname); 340 if (sc->sc_ih == NULL) { 341 printf(": failed to establish interrupt\n"); 342 bus_space_unmap(sc->sc_bustag, sc->sc_iohandle, 343 sa->sa_reg[0].sbr_size); 344 return; 345 } 346 347 sc->sc_sih = softintr_establish(IPL_TTY, magma_soft, sc); 348 if (sc->sc_sih == NULL) { 349 printf(": can't get soft intr\n"); 350 bus_space_unmap(sc->sc_bustag, sc->sc_iohandle, 351 sa->sa_reg[0].sbr_size); 352 return; 353 } 354 355 printf(": %s\n", card->mb_realname); 356 357 sc->ms_board = card; 358 sc->ms_ncd1400 = card->mb_ncd1400; 359 sc->ms_ncd1190 = card->mb_ncd1190; 360 361 /* the SVCACK* lines are daisychained */ 362 if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle, 363 card->mb_svcackr, 1, &sc->sc_svcackrh)) { 364 printf(": failed to map svcackr\n"); 365 return; 366 } 367 if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle, 368 card->mb_svcackt, 1, &sc->sc_svcackth)) { 369 printf(": failed to map svcackt\n"); 370 return; 371 } 372 if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle, 373 card->mb_svcackm, 1, &sc->sc_svcackmh)) { 374 printf(": failed to map svcackm\n"); 375 return; 376 } 377 378 /* init the cd1400 chips */ 379 for (chip = 0 ; chip < card->mb_ncd1400 ; chip++) { 380 struct cd1400 *cd = &sc->ms_cd1400[chip]; 381 382 cd->cd_clock = cd_clock; 383 384 if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle, 385 card->mb_cd1400[chip], CD1400_REGMAPSIZE, &cd->cd_regh)) { 386 printf(": failed to map cd1400 regs\n"); 387 return; 388 } 389 cd->cd_regt = sc->sc_bustag; 390 391 /* getpropstring(sa->sa_node, "chiprev"); */ 392 /* seemingly the Magma drivers just ignore the propstring */ 393 cd->cd_chiprev = CD1400_READ_REG(cd, CD1400_GFRCR); 394 395 dprintf(("%s attach CD1400 %d addr 0x%x rev %x clock %dMHz\n", 396 sc->ms_dev.dv_xname, chip, cd->cd_reg, 397 cd->cd_chiprev, cd->cd_clock)); 398 399 /* clear GFRCR */ 400 CD1400_WRITE_REG(cd, CD1400_GFRCR, 0x00); 401 402 /* reset whole chip */ 403 cd1400_write_ccr(cd, 404 CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); 405 406 /* wait for revision code to be restored */ 407 while (CD1400_READ_REG(cd, CD1400_GFRCR) != cd->cd_chiprev) 408 ; 409 410 /* set the Prescaler Period Register to tick at 1ms */ 411 CD1400_WRITE_REG(cd, CD1400_PPR, 412 ((cd->cd_clock * 1000000 / CD1400_PPR_PRESCALER + 500) 413 / 1000)); 414 415 /* 416 * The LC2+1Sp card is the only card that doesn't have a 417 * CD1190 for the parallel port, but uses channel 0 of the 418 * CD1400, so we make a note of it for later and set up the 419 * CD1400 for parallel mode operation. 420 */ 421 if (card->mb_npar && card->mb_ncd1190 == 0) { 422 CD1400_WRITE_REG(cd, CD1400_GCR, CD1400_GCR_PARALLEL); 423 cd->cd_parmode = 1; 424 } 425 } 426 427 /* init the cd1190 chips */ 428 for (chip = 0 ; chip < card->mb_ncd1190 ; chip++) { 429 struct cd1190 *cd = &sc->ms_cd1190[chip]; 430 431 if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle, 432 card->mb_cd1190[chip], CD1190_REGMAPSIZE, &cd->cd_regh)) { 433 printf(": failed to map cd1190 regs\n"); 434 return; 435 } 436 cd->cd_regt = sc->sc_bustag; 437 dprintf(("%s attach CD1190 %d addr 0x%x (failed)\n", 438 sc->ms_dev.dv_xname, chip, cd->cd_reg)); 439 /* XXX don't know anything about these chips yet */ 440 } 441 442 /* configure the children */ 443 (void)config_found(dev, mtty_match, NULL); 444 (void)config_found(dev, mbpp_match, NULL); 445 } 446 447 /* 448 * hard interrupt routine 449 * 450 * returns 1 if it handled it, otherwise 0 451 * 452 * runs at interrupt priority 453 */ 454 int 455 magma_hard(void *arg) 456 { 457 struct magma_softc *sc = arg; 458 struct cd1400 *cd; 459 int chip, status = 0; 460 int serviced = 0; 461 int needsoftint = 0; 462 463 /* 464 * check status of all the CD1400 chips 465 */ 466 for (chip = 0 ; chip < sc->ms_ncd1400 ; chip++) 467 status |= CD1400_READ_REG(&sc->ms_cd1400[chip], CD1400_SVRR); 468 469 if (ISSET(status, CD1400_SVRR_RXRDY)) { 470 /* enter rx service context */ 471 u_int8_t rivr = bus_space_read_1(sc->sc_bustag, sc->sc_svcackrh, 0); 472 int port = rivr >> 4; 473 474 if (rivr & (1<<3)) { /* parallel port */ 475 struct mbpp_port *mbpp; 476 int n_chars; 477 478 mbpp = &sc->ms_mbpp->ms_port[port]; 479 cd = mbpp->mp_cd1400; 480 481 /* don't think we have to handle exceptions */ 482 n_chars = CD1400_READ_REG(cd, CD1400_RDCR); 483 while (n_chars--) { 484 if (mbpp->mp_cnt == 0) { 485 SET(mbpp->mp_flags, MBPPF_WAKEUP); 486 needsoftint = 1; 487 break; 488 } 489 *mbpp->mp_ptr = CD1400_READ_REG(cd, CD1400_RDSR); 490 mbpp->mp_ptr++; 491 mbpp->mp_cnt--; 492 } 493 } else { /* serial port */ 494 struct mtty_port *mtty; 495 u_char *ptr, n_chars, line_stat; 496 497 mtty = &sc->ms_mtty->ms_port[port]; 498 cd = mtty->mp_cd1400; 499 500 if (ISSET(rivr, CD1400_RIVR_EXCEPTION)) { 501 line_stat = CD1400_READ_REG(cd, CD1400_RDSR); 502 n_chars = 1; 503 } else { /* no exception, received data OK */ 504 line_stat = 0; 505 n_chars = CD1400_READ_REG(cd, CD1400_RDCR); 506 } 507 508 ptr = mtty->mp_rput; 509 while (n_chars--) { 510 *ptr++ = line_stat; 511 *ptr++ = CD1400_READ_REG(cd, CD1400_RDSR); 512 if (ptr == mtty->mp_rend) 513 ptr = mtty->mp_rbuf; 514 if (ptr == mtty->mp_rget) { 515 if (ptr == mtty->mp_rbuf) 516 ptr = mtty->mp_rend; 517 ptr -= 2; 518 SET(mtty->mp_flags, 519 MTTYF_RING_OVERFLOW); 520 break; 521 } 522 } 523 mtty->mp_rput = ptr; 524 525 needsoftint = 1; 526 } 527 528 CD1400_WRITE_REG(cd, CD1400_EOSRR, 0); /* end service context */ 529 serviced = 1; 530 } /* if(rx_service...) */ 531 532 if (ISSET(status, CD1400_SVRR_MDMCH)) { 533 u_int8_t mivr = bus_space_read_1(sc->sc_bustag, sc->sc_svcackmh, 0); 534 int port = mivr >> 4; 535 struct mtty_port *mtty; 536 int carrier; 537 u_char msvr; 538 539 /* 540 * Handle CD (LC2+1Sp = DSR) changes. 541 */ 542 mtty = &sc->ms_mtty->ms_port[port]; 543 cd = mtty->mp_cd1400; 544 msvr = CD1400_READ_REG(cd, CD1400_MSVR2); 545 carrier = ISSET(msvr, cd->cd_parmode ? CD1400_MSVR2_DSR : CD1400_MSVR2_CD); 546 547 if (mtty->mp_carrier != carrier) { 548 SET(mtty->mp_flags, MTTYF_CARRIER_CHANGED); 549 mtty->mp_carrier = carrier; 550 needsoftint = 1; 551 } 552 553 CD1400_WRITE_REG(cd, CD1400_EOSRR, 0); /* end service context */ 554 serviced = 1; 555 } /* if(mdm_service...) */ 556 557 if (ISSET(status, CD1400_SVRR_TXRDY)) { 558 /* enter tx service context */ 559 u_int8_t tivr = bus_space_read_1(sc->sc_bustag, sc->sc_svcackth, 0); 560 int port = tivr >> 4; 561 562 if (tivr & (1<<3)) { /* parallel port */ 563 struct mbpp_port *mbpp; 564 565 mbpp = &sc->ms_mbpp->ms_port[port]; 566 cd = mbpp->mp_cd1400; 567 568 if (mbpp->mp_cnt) { 569 int count = 0; 570 571 /* fill the fifo */ 572 while (mbpp->mp_cnt && count++ < CD1400_PAR_FIFO_SIZE) { 573 CD1400_WRITE_REG(cd, CD1400_TDR, *mbpp->mp_ptr); 574 mbpp->mp_ptr++; 575 mbpp->mp_cnt--; 576 } 577 } else { 578 /* fifo is empty and we got no more data to send, so shut 579 * off interrupts and signal for a wakeup, which can't be 580 * done here in case we beat mbpp_send to the tsleep call 581 * (we are running at >spltty) 582 */ 583 CD1400_WRITE_REG(cd, CD1400_SRER, 0); 584 SET(mbpp->mp_flags, MBPPF_WAKEUP); 585 needsoftint = 1; 586 } 587 } else { /* serial port */ 588 struct mtty_port *mtty; 589 struct tty *tp; 590 591 mtty = &sc->ms_mtty->ms_port[port]; 592 cd = mtty->mp_cd1400; 593 tp = mtty->mp_tty; 594 595 if (!ISSET(mtty->mp_flags, MTTYF_STOP)) { 596 int count = 0; 597 598 /* check if we should start/stop a break */ 599 if (ISSET(mtty->mp_flags, MTTYF_SET_BREAK)) { 600 CD1400_WRITE_REG(cd, CD1400_TDR, 0); 601 CD1400_WRITE_REG(cd, CD1400_TDR, 0x81); 602 /* should we delay too? */ 603 CLR(mtty->mp_flags, MTTYF_SET_BREAK); 604 count += 2; 605 } 606 607 if (ISSET(mtty->mp_flags, MTTYF_CLR_BREAK)) { 608 CD1400_WRITE_REG(cd, CD1400_TDR, 0); 609 CD1400_WRITE_REG(cd, CD1400_TDR, 0x83); 610 CLR(mtty->mp_flags, MTTYF_CLR_BREAK); 611 count += 2; 612 } 613 614 /* I don't quite fill the fifo in case the last one is a 615 * NULL which I have to double up because its the escape 616 * code for embedded transmit characters. 617 */ 618 while (mtty->mp_txc > 0 && count < CD1400_TX_FIFO_SIZE - 1) { 619 u_char ch; 620 621 ch = *mtty->mp_txp; 622 623 mtty->mp_txc--; 624 mtty->mp_txp++; 625 626 if (ch == 0) { 627 CD1400_WRITE_REG(cd, CD1400_TDR, ch); 628 count++; 629 } 630 631 CD1400_WRITE_REG(cd, CD1400_TDR, ch); 632 count++; 633 } 634 } 635 636 /* if we ran out of work or are requested to STOP then 637 * shut off the txrdy interrupts and signal DONE to flush 638 * out the chars we have sent. 639 */ 640 if (mtty->mp_txc == 0 || ISSET(mtty->mp_flags, MTTYF_STOP)) { 641 int srer; 642 643 srer = CD1400_READ_REG(cd, CD1400_SRER); 644 CLR(srer, CD1400_SRER_TXRDY); 645 CD1400_WRITE_REG(cd, CD1400_SRER, srer); 646 CLR(mtty->mp_flags, MTTYF_STOP); 647 648 SET(mtty->mp_flags, MTTYF_DONE); 649 needsoftint = 1; 650 } 651 } 652 653 CD1400_WRITE_REG(cd, CD1400_EOSRR, 0); /* end service context */ 654 serviced = 1; 655 } /* if(tx_service...) */ 656 657 /* XXX service CD1190 interrupts too 658 for (chip = 0 ; chip < sc->ms_ncd1190 ; chip++) { 659 } 660 */ 661 662 if (needsoftint) 663 softintr_schedule(sc->sc_sih); 664 665 return (serviced); 666 } 667 668 /* 669 * magma soft interrupt handler 670 * 671 * returns 1 if it handled it, 0 otherwise 672 * 673 * runs at spltty() 674 */ 675 void 676 magma_soft(void *arg) 677 { 678 struct magma_softc *sc = arg; 679 struct mtty_softc *mtty = sc->ms_mtty; 680 struct mbpp_softc *mbpp = sc->ms_mbpp; 681 int port; 682 int serviced = 0; 683 int s, flags; 684 685 /* 686 * check the tty ports (if any) to see what needs doing 687 */ 688 if (mtty) { 689 for (port = 0 ; port < mtty->ms_nports ; port++) { 690 struct mtty_port *mp = &mtty->ms_port[port]; 691 struct tty *tp = mp->mp_tty; 692 693 if (!ISSET(tp->t_state, TS_ISOPEN)) 694 continue; 695 696 /* 697 * handle any received data 698 */ 699 while (mp->mp_rget != mp->mp_rput) { 700 u_char stat; 701 int data; 702 703 stat = mp->mp_rget[0]; 704 data = mp->mp_rget[1]; 705 mp->mp_rget = ((mp->mp_rget + 2) == mp->mp_rend) ? mp->mp_rbuf : (mp->mp_rget + 2); 706 707 if (stat & (CD1400_RDSR_BREAK | CD1400_RDSR_FE)) 708 data |= TTY_FE; 709 if (stat & CD1400_RDSR_PE) 710 data |= TTY_PE; 711 712 if (stat & CD1400_RDSR_OE) 713 log(LOG_WARNING, "%s%x: fifo overflow\n", mtty->ms_dev.dv_xname, port); 714 715 (*linesw[tp->t_line].l_rint)(data, tp); 716 serviced = 1; 717 } 718 719 s = splhigh(); /* block out hard interrupt routine */ 720 flags = mp->mp_flags; 721 CLR(mp->mp_flags, MTTYF_DONE | MTTYF_CARRIER_CHANGED | MTTYF_RING_OVERFLOW); 722 splx(s); /* ok */ 723 724 if (ISSET(flags, MTTYF_CARRIER_CHANGED)) { 725 dprintf(("%s%x: cd %s\n", mtty->ms_dev.dv_xname, port, mp->mp_carrier ? "on" : "off")); 726 (*linesw[tp->t_line].l_modem)(tp, mp->mp_carrier); 727 serviced = 1; 728 } 729 730 if (ISSET(flags, MTTYF_RING_OVERFLOW)) { 731 log(LOG_WARNING, "%s%x: ring buffer overflow\n", mtty->ms_dev.dv_xname, port); 732 serviced = 1; 733 } 734 735 if (ISSET(flags, MTTYF_DONE)) { 736 ndflush(&tp->t_outq, mp->mp_txp - tp->t_outq.c_cf); 737 CLR(tp->t_state, TS_BUSY); 738 (*linesw[tp->t_line].l_start)(tp); /* might be some more */ 739 serviced = 1; 740 } 741 } /* for (each mtty...) */ 742 } 743 744 /* 745 * check the bpp ports (if any) to see what needs doing 746 */ 747 if (mbpp) { 748 for (port = 0 ; port < mbpp->ms_nports ; port++) { 749 struct mbpp_port *mp = &mbpp->ms_port[port]; 750 751 if (!ISSET(mp->mp_flags, MBPPF_OPEN)) 752 continue; 753 754 s = splhigh(); /* block out hard intr routine */ 755 flags = mp->mp_flags; 756 CLR(mp->mp_flags, MBPPF_WAKEUP); 757 splx(s); 758 759 if (ISSET(flags, MBPPF_WAKEUP)) { 760 wakeup(mp); 761 serviced = 1; 762 } 763 } /* for (each mbpp...) */ 764 } 765 } 766 767 /************************************************************************ 768 * 769 * MTTY Routines 770 * 771 * mtty_match match one mtty device 772 * mtty_attach attach mtty devices 773 * mttyopen open mtty device 774 * mttyclose close mtty device 775 * mttyread read from mtty 776 * mttywrite write to mtty 777 * mttyioctl do ioctl on mtty 778 * mttytty return tty pointer for mtty 779 * mttystop stop mtty device 780 * mtty_start start mtty device 781 * mtty_param set mtty parameters 782 * mtty_modem_control set modem control lines 783 */ 784 785 int 786 mtty_match(struct device *parent, void *vcf, void *args) 787 { 788 struct magma_softc *sc = (struct magma_softc *)parent; 789 790 return (args == mtty_match && sc->ms_board->mb_nser && 791 sc->ms_mtty == NULL); 792 } 793 794 void 795 mtty_attach(struct device *parent, struct device *dev, void *args) 796 { 797 struct magma_softc *sc = (struct magma_softc *)parent; 798 struct mtty_softc *ms = (struct mtty_softc *)dev; 799 int port, chip, chan; 800 801 sc->ms_mtty = ms; 802 dprintf((" addr 0x%x", ms)); 803 804 for (port = 0, chip = 0, chan = 0; 805 port < sc->ms_board->mb_nser; port++) { 806 struct mtty_port *mp = &ms->ms_port[port]; 807 struct tty *tp; 808 809 mp->mp_cd1400 = &sc->ms_cd1400[chip]; 810 if (mp->mp_cd1400->cd_parmode && chan == 0) { 811 /* skip channel 0 if parmode */ 812 chan = 1; 813 } 814 mp->mp_channel = chan; 815 816 tp = ttymalloc(); 817 tp->t_oproc = mtty_start; 818 tp->t_param = mtty_param; 819 820 mp->mp_tty = tp; 821 822 mp->mp_rbuf = malloc(MTTY_RBUF_SIZE, M_DEVBUF, M_NOWAIT); 823 if (mp->mp_rbuf == NULL) 824 break; 825 826 mp->mp_rend = mp->mp_rbuf + MTTY_RBUF_SIZE; 827 828 chan = (chan + 1) % CD1400_NO_OF_CHANNELS; 829 if (chan == 0) 830 chip++; 831 } 832 833 ms->ms_nports = port; 834 printf(": %d tty%s\n", port, port == 1 ? "" : "s"); 835 } 836 837 /* 838 * open routine. returns zero if successful, else error code 839 */ 840 int 841 mttyopen(dev_t dev, int flags, int mode, struct proc *p) 842 { 843 int card = MAGMA_CARD(dev); 844 int port = MAGMA_PORT(dev); 845 struct mtty_softc *ms; 846 struct mtty_port *mp; 847 struct tty *tp; 848 struct cd1400 *cd; 849 int s; 850 851 if (card >= mtty_cd.cd_ndevs || (ms = mtty_cd.cd_devs[card]) == NULL 852 || port >= ms->ms_nports) 853 return (ENXIO); /* device not configured */ 854 855 mp = &ms->ms_port[port]; 856 tp = mp->mp_tty; 857 tp->t_dev = dev; 858 859 if (!ISSET(tp->t_state, TS_ISOPEN)) { 860 SET(tp->t_state, TS_WOPEN); 861 862 /* set defaults */ 863 ttychars(tp); 864 tp->t_iflag = TTYDEF_IFLAG; 865 tp->t_oflag = TTYDEF_OFLAG; 866 tp->t_cflag = TTYDEF_CFLAG; 867 if (ISSET(mp->mp_openflags, TIOCFLAG_CLOCAL)) 868 SET(tp->t_cflag, CLOCAL); 869 if (ISSET(mp->mp_openflags, TIOCFLAG_CRTSCTS)) 870 SET(tp->t_cflag, CRTSCTS); 871 if (ISSET(mp->mp_openflags, TIOCFLAG_MDMBUF)) 872 SET(tp->t_cflag, MDMBUF); 873 tp->t_lflag = TTYDEF_LFLAG; 874 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 875 876 /* init ring buffer */ 877 mp->mp_rput = mp->mp_rget = mp->mp_rbuf; 878 879 s = spltty(); 880 881 /* reset CD1400 channel */ 882 cd = mp->mp_cd1400; 883 CD1400_WRITE_REG(cd, CD1400_CAR, mp->mp_channel); 884 cd1400_write_ccr(cd, CD1400_CCR_CMDRESET); 885 886 /* encode the port number in top half of LIVR */ 887 CD1400_WRITE_REG(cd, CD1400_LIVR, port << 4); 888 889 /* sets parameters and raises DTR */ 890 (void)mtty_param(tp, &tp->t_termios); 891 892 /* set tty watermarks */ 893 ttsetwater(tp); 894 895 /* enable service requests */ 896 CD1400_WRITE_REG(cd, CD1400_SRER, CD1400_SRER_RXDATA | CD1400_SRER_MDMCH); 897 898 /* tell the tty about the carrier status */ 899 if (ISSET(mp->mp_openflags, TIOCFLAG_SOFTCAR) || mp->mp_carrier) 900 SET(tp->t_state, TS_CARR_ON); 901 else 902 CLR(tp->t_state, TS_CARR_ON); 903 } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) { 904 return (EBUSY); /* superuser can break exclusive access */ 905 } else { 906 s = spltty(); 907 } 908 909 /* wait for carrier if necessary */ 910 if (!ISSET(flags, O_NONBLOCK)) { 911 while (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON)) { 912 int error; 913 914 SET(tp->t_state, TS_WOPEN); 915 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, "mttydcd", 0); 916 if (error != 0) { 917 splx(s); 918 CLR(tp->t_state, TS_WOPEN); 919 return (error); 920 } 921 } 922 } 923 924 splx(s); 925 926 return ((*linesw[tp->t_line].l_open)(dev, tp)); 927 } 928 929 /* 930 * close routine. returns zero if successful, else error code 931 */ 932 int 933 mttyclose(dev_t dev, int flag, int mode, struct proc *p) 934 { 935 struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(dev)]; 936 struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(dev)]; 937 struct tty *tp = mp->mp_tty; 938 int s; 939 940 (*linesw[tp->t_line].l_close)(tp, flag); 941 s = spltty(); 942 943 /* if HUPCL is set, and the tty is no longer open 944 * shut down the port 945 */ 946 if (ISSET(tp->t_cflag, HUPCL) || !ISSET(tp->t_state, TS_ISOPEN)) { 947 /* XXX wait until FIFO is empty before turning off the channel 948 struct cd1400 *cd = mp->mp_cd1400; 949 */ 950 951 /* drop DTR and RTS */ 952 (void)mtty_modem_control(mp, 0, DMSET); 953 954 /* turn off the channel 955 CD1400_WRITE_REG(cd, CD1400_CAR, mp->mp_channel); 956 cd1400_write_ccr(cd, CD1400_CCR_CMDRESET); 957 */ 958 } 959 960 splx(s); 961 ttyclose(tp); 962 963 return (0); 964 } 965 966 /* 967 * Read routine 968 */ 969 int 970 mttyread(dev_t dev, struct uio *uio, int flags) 971 { 972 struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(dev)]; 973 struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(dev)]; 974 struct tty *tp = mp->mp_tty; 975 976 return ((*linesw[tp->t_line].l_read)(tp, uio, flags)); 977 } 978 979 /* 980 * Write routine 981 */ 982 int 983 mttywrite(dev_t dev, struct uio *uio, int flags) 984 { 985 struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(dev)]; 986 struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(dev)]; 987 struct tty *tp = mp->mp_tty; 988 989 return ((*linesw[tp->t_line].l_write)(tp, uio, flags)); 990 } 991 992 /* 993 * return tty pointer 994 */ 995 struct tty * 996 mttytty(dev_t dev) 997 { 998 struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(dev)]; 999 struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(dev)]; 1000 1001 return (mp->mp_tty); 1002 } 1003 1004 /* 1005 * ioctl routine 1006 */ 1007 int 1008 mttyioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 1009 { 1010 struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(dev)]; 1011 struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(dev)]; 1012 struct tty *tp = mp->mp_tty; 1013 int error; 1014 1015 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flags, p); 1016 if (error >= 0) 1017 return (error); 1018 1019 error = ttioctl(tp, cmd, data, flags, p); 1020 if (error >= 0) 1021 return (error); 1022 1023 error = 0; 1024 1025 switch(cmd) { 1026 case TIOCSBRK: /* set break */ 1027 SET(mp->mp_flags, MTTYF_SET_BREAK); 1028 cd1400_enable_transmitter(mp->mp_cd1400, mp->mp_channel); 1029 break; 1030 1031 case TIOCCBRK: /* clear break */ 1032 SET(mp->mp_flags, MTTYF_CLR_BREAK); 1033 cd1400_enable_transmitter(mp->mp_cd1400, mp->mp_channel); 1034 break; 1035 1036 case TIOCSDTR: /* set DTR */ 1037 mtty_modem_control(mp, TIOCM_DTR, DMBIS); 1038 break; 1039 1040 case TIOCCDTR: /* clear DTR */ 1041 mtty_modem_control(mp, TIOCM_DTR, DMBIC); 1042 break; 1043 1044 case TIOCMSET: /* set modem lines */ 1045 mtty_modem_control(mp, *((int *)data), DMSET); 1046 break; 1047 1048 case TIOCMBIS: /* bit set modem lines */ 1049 mtty_modem_control(mp, *((int *)data), DMBIS); 1050 break; 1051 1052 case TIOCMBIC: /* bit clear modem lines */ 1053 mtty_modem_control(mp, *((int *)data), DMBIC); 1054 break; 1055 1056 case TIOCMGET: /* get modem lines */ 1057 *((int *)data) = mtty_modem_control(mp, 0, DMGET); 1058 break; 1059 1060 case TIOCGFLAGS: 1061 *((int *)data) = mp->mp_openflags; 1062 break; 1063 1064 case TIOCSFLAGS: 1065 if (suser(p, 0)) 1066 error = EPERM; 1067 else 1068 mp->mp_openflags = *((int *)data) & 1069 (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | 1070 TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF); 1071 break; 1072 1073 default: 1074 error = ENOTTY; 1075 } 1076 1077 return (error); 1078 } 1079 1080 /* 1081 * Stop output, e.g., for ^S or output flush. 1082 */ 1083 int 1084 mttystop(struct tty *tp, int flags) 1085 { 1086 struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(tp->t_dev)]; 1087 struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(tp->t_dev)]; 1088 int s; 1089 1090 s = spltty(); 1091 1092 if (ISSET(tp->t_state, TS_BUSY)) { 1093 if (!ISSET(tp->t_state, TS_TTSTOP)) 1094 SET(tp->t_state, TS_FLUSH); 1095 1096 /* 1097 * the transmit interrupt routine will disable transmit when it 1098 * notices that MTTYF_STOP has been set. 1099 */ 1100 SET(mp->mp_flags, MTTYF_STOP); 1101 } 1102 1103 splx(s); 1104 return (0); 1105 } 1106 1107 /* 1108 * Start output, after a stop. 1109 */ 1110 void 1111 mtty_start(struct tty *tp) 1112 { 1113 struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(tp->t_dev)]; 1114 struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(tp->t_dev)]; 1115 int s; 1116 1117 s = spltty(); 1118 1119 /* we only need to do something if we are not already busy 1120 * or delaying or stopped 1121 */ 1122 if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) { 1123 1124 /* if we are sleeping and output has drained below 1125 * low water mark, awaken 1126 */ 1127 if (tp->t_outq.c_cc <= tp->t_lowat) { 1128 if (ISSET(tp->t_state, TS_ASLEEP)) { 1129 CLR(tp->t_state, TS_ASLEEP); 1130 wakeup(&tp->t_outq); 1131 } 1132 1133 selwakeup(&tp->t_wsel); 1134 } 1135 1136 /* if something to send, start transmitting 1137 */ 1138 if (tp->t_outq.c_cc) { 1139 mp->mp_txc = ndqb(&tp->t_outq, 0); 1140 mp->mp_txp = tp->t_outq.c_cf; 1141 SET(tp->t_state, TS_BUSY); 1142 cd1400_enable_transmitter(mp->mp_cd1400, mp->mp_channel); 1143 } 1144 } 1145 1146 splx(s); 1147 } 1148 1149 /* 1150 * set/get modem line status 1151 * 1152 * bits can be: TIOCM_DTR, TIOCM_RTS, TIOCM_CTS, TIOCM_CD, TIOCM_RI, TIOCM_DSR 1153 * 1154 * note that DTR and RTS lines are exchanged, and that DSR is 1155 * not available on the LC2+1Sp card (used as CD) 1156 * 1157 * only let them fiddle with RTS if CRTSCTS is not enabled 1158 */ 1159 int 1160 mtty_modem_control(struct mtty_port *mp, int bits, int howto) 1161 { 1162 struct cd1400 *cd = mp->mp_cd1400; 1163 struct tty *tp = mp->mp_tty; 1164 int s, msvr; 1165 1166 s = spltty(); 1167 1168 CD1400_WRITE_REG(cd, CD1400_CAR, mp->mp_channel); 1169 1170 switch(howto) { 1171 case DMGET: /* get bits */ 1172 bits = 0; 1173 1174 bits |= TIOCM_LE; 1175 1176 msvr = CD1400_READ_REG(cd, CD1400_MSVR1); 1177 if (msvr & CD1400_MSVR1_RTS) 1178 bits |= TIOCM_DTR; 1179 1180 msvr = CD1400_READ_REG(cd, CD1400_MSVR2); 1181 if (msvr & CD1400_MSVR2_DTR) 1182 bits |= TIOCM_RTS; 1183 if (msvr & CD1400_MSVR2_CTS) 1184 bits |= TIOCM_CTS; 1185 if (msvr & CD1400_MSVR2_RI) 1186 bits |= TIOCM_RI; 1187 if (msvr & CD1400_MSVR2_DSR) 1188 bits |= (cd->cd_parmode ? TIOCM_CD : TIOCM_DSR); 1189 if (msvr & CD1400_MSVR2_CD) 1190 bits |= (cd->cd_parmode ? 0 : TIOCM_CD); 1191 1192 break; 1193 1194 case DMSET: /* reset bits */ 1195 if (!ISSET(tp->t_cflag, CRTSCTS)) 1196 CD1400_WRITE_REG(cd, CD1400_MSVR2, 1197 ((bits & TIOCM_RTS) ? CD1400_MSVR2_DTR : 0)); 1198 1199 CD1400_WRITE_REG(cd, CD1400_MSVR1, 1200 ((bits & TIOCM_DTR) ? CD1400_MSVR1_RTS : 0)); 1201 1202 break; 1203 1204 case DMBIS: /* set bits */ 1205 if ((bits & TIOCM_RTS) && !ISSET(tp->t_cflag, CRTSCTS)) 1206 CD1400_WRITE_REG(cd, CD1400_MSVR2, CD1400_MSVR2_DTR); 1207 1208 if (bits & TIOCM_DTR) 1209 CD1400_WRITE_REG(cd, CD1400_MSVR1, CD1400_MSVR1_RTS); 1210 1211 break; 1212 1213 case DMBIC: /* clear bits */ 1214 if ((bits & TIOCM_RTS) && !ISSET(tp->t_cflag, CRTSCTS)) 1215 CD1400_WRITE_REG(cd, CD1400_MSVR2, 0); 1216 1217 if (bits & TIOCM_DTR) 1218 CD1400_WRITE_REG(cd, CD1400_MSVR1, 0); 1219 1220 break; 1221 } 1222 1223 splx(s); 1224 return (bits); 1225 } 1226 1227 /* 1228 * Set tty parameters, returns error or 0 on success 1229 */ 1230 int 1231 mtty_param(struct tty *tp, struct termios *t) 1232 { 1233 struct mtty_softc *ms = mtty_cd.cd_devs[MAGMA_CARD(tp->t_dev)]; 1234 struct mtty_port *mp = &ms->ms_port[MAGMA_PORT(tp->t_dev)]; 1235 struct cd1400 *cd = mp->mp_cd1400; 1236 int rbpr, tbpr, rcor, tcor; 1237 u_char mcor1 = 0, mcor2 = 0; 1238 int s, opt; 1239 1240 if (t->c_ospeed && 1241 cd1400_compute_baud(t->c_ospeed, cd->cd_clock, &tcor, &tbpr)) 1242 return (EINVAL); 1243 1244 if (t->c_ispeed && 1245 cd1400_compute_baud(t->c_ispeed, cd->cd_clock, &rcor, &rbpr)) 1246 return (EINVAL); 1247 1248 s = spltty(); 1249 1250 /* hang up the line if ospeed is zero, else raise DTR */ 1251 (void)mtty_modem_control(mp, TIOCM_DTR, 1252 (t->c_ospeed == 0 ? DMBIC : DMBIS)); 1253 1254 /* select channel, done in mtty_modem_control() */ 1255 /* CD1400_WRITE_REG(cd, CD1400_CAR, mp->mp_channel); */ 1256 1257 /* set transmit speed */ 1258 if (t->c_ospeed) { 1259 CD1400_WRITE_REG(cd, CD1400_TCOR, tcor); 1260 CD1400_WRITE_REG(cd, CD1400_TBPR, tbpr); 1261 } 1262 1263 /* set receive speed */ 1264 if (t->c_ispeed) { 1265 CD1400_WRITE_REG(cd, CD1400_RCOR, rcor); 1266 CD1400_WRITE_REG(cd, CD1400_RBPR, rbpr); 1267 } 1268 1269 /* enable transmitting and receiving on this channel */ 1270 opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN | CD1400_CCR_RCVEN; 1271 cd1400_write_ccr(cd, opt); 1272 1273 /* set parity, data and stop bits */ 1274 opt = 0; 1275 if (ISSET(t->c_cflag, PARENB)) 1276 opt |= (ISSET(t->c_cflag, PARODD) ? CD1400_COR1_PARODD : CD1400_COR1_PARNORMAL); 1277 1278 if (!ISSET(t->c_iflag, INPCK)) 1279 opt |= CD1400_COR1_NOINPCK; /* no parity checking */ 1280 1281 if (ISSET(t->c_cflag, CSTOPB)) 1282 opt |= CD1400_COR1_STOP2; 1283 1284 switch( t->c_cflag & CSIZE) { 1285 case CS5: 1286 opt |= CD1400_COR1_CS5; 1287 break; 1288 1289 case CS6: 1290 opt |= CD1400_COR1_CS6; 1291 break; 1292 1293 case CS7: 1294 opt |= CD1400_COR1_CS7; 1295 break; 1296 1297 default: 1298 opt |= CD1400_COR1_CS8; 1299 break; 1300 } 1301 1302 CD1400_WRITE_REG(cd, CD1400_COR1, opt); 1303 1304 /* 1305 * enable Embedded Transmit Commands (for breaks) 1306 * use the CD1400 automatic CTS flow control if CRTSCTS is set 1307 */ 1308 opt = CD1400_COR2_ETC; 1309 if (ISSET(t->c_cflag, CRTSCTS)) 1310 opt |= CD1400_COR2_CCTS_OFLOW; 1311 CD1400_WRITE_REG(cd, CD1400_COR2, opt); 1312 1313 CD1400_WRITE_REG(cd, CD1400_COR3, MTTY_RX_FIFO_THRESHOLD); 1314 1315 cd1400_write_ccr(cd, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR1 | CD1400_CCR_COR2 | CD1400_CCR_COR3); 1316 1317 CD1400_WRITE_REG(cd, CD1400_COR4, CD1400_COR4_PFO_EXCEPTION); 1318 CD1400_WRITE_REG(cd, CD1400_COR5, 0); 1319 1320 /* 1321 * if automatic RTS handshaking enabled, set DTR threshold 1322 * (RTS and DTR lines are switched, CD1400 thinks its DTR) 1323 */ 1324 if (ISSET(t->c_cflag, CRTSCTS)) 1325 mcor1 = MTTY_RX_DTR_THRESHOLD; 1326 1327 /* set up `carrier detect' interrupts */ 1328 if (cd->cd_parmode) { 1329 SET(mcor1, CD1400_MCOR1_DSRzd); 1330 SET(mcor2, CD1400_MCOR2_DSRod); 1331 } else { 1332 SET(mcor1, CD1400_MCOR1_CDzd); 1333 SET(mcor2, CD1400_MCOR2_CDod); 1334 } 1335 1336 CD1400_WRITE_REG(cd, CD1400_MCOR1, mcor1); 1337 CD1400_WRITE_REG(cd, CD1400_MCOR2, mcor2); 1338 1339 /* receive timeout 2ms */ 1340 CD1400_WRITE_REG(cd, CD1400_RTPR, 2); 1341 1342 splx(s); 1343 return (0); 1344 } 1345 1346 /************************************************************************ 1347 * 1348 * MBPP Routines 1349 * 1350 * mbpp_match match one mbpp device 1351 * mbpp_attach attach mbpp devices 1352 * mbppopen open mbpp device 1353 * mbppclose close mbpp device 1354 * mbppread read from mbpp 1355 * mbppwrite write to mbpp 1356 * mbppioctl do ioctl on mbpp 1357 * mbpppoll do poll on mbpp 1358 * mbpp_rw general rw routine 1359 * mbpp_timeout rw timeout 1360 * mbpp_start rw start after delay 1361 * mbpp_send send data 1362 * mbpp_recv recv data 1363 */ 1364 1365 int 1366 mbpp_match(struct device *parent, void *vcf, void *args) 1367 { 1368 struct magma_softc *sc = (struct magma_softc *)parent; 1369 1370 return (args == mbpp_match && sc->ms_board->mb_npar && 1371 sc->ms_mbpp == NULL); 1372 } 1373 1374 void 1375 mbpp_attach(struct device *parent, struct device *dev, void *args) 1376 { 1377 struct magma_softc *sc = (struct magma_softc *)parent; 1378 struct mbpp_softc *ms = (struct mbpp_softc *)dev; 1379 struct mbpp_port *mp; 1380 int port; 1381 1382 sc->ms_mbpp = ms; 1383 dprintf((" addr 0x%x", ms)); 1384 1385 for (port = 0 ; port < sc->ms_board->mb_npar ; port++) { 1386 mp = &ms->ms_port[port]; 1387 1388 if (sc->ms_ncd1190) 1389 mp->mp_cd1190 = &sc->ms_cd1190[port]; 1390 else 1391 mp->mp_cd1400 = &sc->ms_cd1400[0]; 1392 1393 timeout_set(&mp->mp_timeout_tmo, mbpp_timeout, mp); 1394 timeout_set(&mp->mp_start_tmo, mbpp_start, mp); 1395 } 1396 1397 ms->ms_nports = port; 1398 printf(": %d port%s\n", port, port == 1 ? "" : "s"); 1399 } 1400 1401 /* 1402 * open routine. returns zero if successful, else error code 1403 */ 1404 int 1405 mbppopen(dev_t dev, int flags, int mode, struct proc *p) 1406 { 1407 int card = MAGMA_CARD(dev); 1408 int port = MAGMA_PORT(dev); 1409 struct mbpp_softc *ms; 1410 struct mbpp_port *mp; 1411 int s; 1412 1413 if (card >= mbpp_cd.cd_ndevs || (ms = mbpp_cd.cd_devs[card]) == NULL || port >= ms->ms_nports) 1414 return (ENXIO); 1415 1416 mp = &ms->ms_port[port]; 1417 1418 s = spltty(); 1419 if (ISSET(mp->mp_flags, MBPPF_OPEN)) { 1420 splx(s); 1421 return (EBUSY); 1422 } 1423 SET(mp->mp_flags, MBPPF_OPEN); 1424 splx(s); 1425 1426 /* set defaults */ 1427 mp->mp_burst = BPP_BURST; 1428 mp->mp_timeout = mbpp_mstohz(BPP_TIMEOUT); 1429 mp->mp_delay = mbpp_mstohz(BPP_DELAY); 1430 1431 /* init chips */ 1432 if (mp->mp_cd1400) { /* CD1400 */ 1433 struct cd1400 *cd = mp->mp_cd1400; 1434 1435 /* set up CD1400 channel */ 1436 s = spltty(); 1437 CD1400_WRITE_REG(cd, CD1400_CAR, 0); 1438 cd1400_write_ccr(cd, CD1400_CCR_CMDRESET); 1439 CD1400_WRITE_REG(cd, CD1400_LIVR, (1<<3)); 1440 splx(s); 1441 } else { /* CD1190 */ 1442 mp->mp_flags = 0; 1443 return (ENXIO); 1444 } 1445 1446 return (0); 1447 } 1448 1449 /* 1450 * close routine. returns zero if successful, else error code 1451 */ 1452 int 1453 mbppclose(dev_t dev, int flag, int mode, struct proc *p) 1454 { 1455 struct mbpp_softc *ms = mbpp_cd.cd_devs[MAGMA_CARD(dev)]; 1456 struct mbpp_port *mp = &ms->ms_port[MAGMA_PORT(dev)]; 1457 1458 mp->mp_flags = 0; 1459 return (0); 1460 } 1461 1462 /* 1463 * Read routine 1464 */ 1465 int 1466 mbppread(dev_t dev, struct uio *uio, int flags) 1467 { 1468 return (mbpp_rw(dev, uio)); 1469 } 1470 1471 /* 1472 * Write routine 1473 */ 1474 int 1475 mbppwrite(dev_t dev, struct uio *uio, int flags) 1476 { 1477 return (mbpp_rw(dev, uio)); 1478 } 1479 1480 /* 1481 * ioctl routine 1482 */ 1483 int 1484 mbppioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 1485 { 1486 struct mbpp_softc *ms = mbpp_cd.cd_devs[MAGMA_CARD(dev)]; 1487 struct mbpp_port *mp = &ms->ms_port[MAGMA_PORT(dev)]; 1488 struct bpp_param *bp; 1489 int error = 0; 1490 int s; 1491 1492 switch(cmd) { 1493 case BPPIOCSPARAM: 1494 bp = (struct bpp_param *)data; 1495 if (bp->bp_burst < BPP_BURST_MIN || bp->bp_burst > BPP_BURST_MAX || 1496 bp->bp_delay < BPP_DELAY_MIN || bp->bp_delay > BPP_DELAY_MIN) { 1497 error = EINVAL; 1498 } else { 1499 mp->mp_burst = bp->bp_burst; 1500 mp->mp_timeout = mbpp_mstohz(bp->bp_timeout); 1501 mp->mp_delay = mbpp_mstohz(bp->bp_delay); 1502 } 1503 break; 1504 case BPPIOCGPARAM: 1505 bp = (struct bpp_param *)data; 1506 bp->bp_burst = mp->mp_burst; 1507 bp->bp_timeout = mbpp_hztoms(mp->mp_timeout); 1508 bp->bp_delay = mbpp_hztoms(mp->mp_delay); 1509 break; 1510 case BPPIOCGSTAT: 1511 /* XXX make this more generic */ 1512 s = spltty(); 1513 CD1400_WRITE_REG(mp->mp_cd1400, CD1400_CAR, 0); 1514 *(int *)data = CD1400_READ_REG(mp->mp_cd1400, CD1400_PSVR); 1515 splx(s); 1516 break; 1517 default: 1518 error = ENOTTY; 1519 } 1520 1521 return (error); 1522 } 1523 1524 /* 1525 * poll routine 1526 */ 1527 int 1528 mbpppoll(dev_t dev, int events, struct proc *p) 1529 { 1530 return (seltrue(dev, events, p)); 1531 } 1532 1533 int 1534 mbpp_rw(dev_t dev, struct uio *uio) 1535 { 1536 int card = MAGMA_CARD(dev); 1537 int port = MAGMA_PORT(dev); 1538 struct mbpp_softc *ms = mbpp_cd.cd_devs[card]; 1539 struct mbpp_port *mp = &ms->ms_port[port]; 1540 caddr_t buffer, ptr; 1541 int buflen, cnt, len; 1542 int s, error = 0; 1543 int gotdata = 0; 1544 1545 if (uio->uio_resid == 0) 1546 return (0); 1547 1548 buflen = min(uio->uio_resid, mp->mp_burst); 1549 buffer = malloc(buflen, M_DEVBUF, M_WAITOK); 1550 1551 SET(mp->mp_flags, MBPPF_UIO); 1552 1553 /* 1554 * start timeout, if needed 1555 */ 1556 if (mp->mp_timeout > 0) { 1557 SET(mp->mp_flags, MBPPF_TIMEOUT); 1558 timeout_add(&mp->mp_timeout_tmo, mp->mp_timeout); 1559 } 1560 1561 len = cnt = 0; 1562 while (uio->uio_resid > 0) { 1563 len = min(buflen, uio->uio_resid); 1564 ptr = buffer; 1565 1566 if (uio->uio_rw == UIO_WRITE) { 1567 error = uiomove(ptr, len, uio); 1568 if (error) 1569 break; 1570 } 1571 again: /* goto bad */ 1572 /* timed out? */ 1573 if (!ISSET(mp->mp_flags, MBPPF_UIO)) 1574 break; 1575 1576 /* 1577 * perform the operation 1578 */ 1579 if (uio->uio_rw == UIO_WRITE) { 1580 cnt = mbpp_send(mp, ptr, len); 1581 } else { 1582 cnt = mbpp_recv(mp, ptr, len); 1583 } 1584 1585 if (uio->uio_rw == UIO_READ) { 1586 if (cnt) { 1587 error = uiomove(ptr, cnt, uio); 1588 if (error) 1589 break; 1590 gotdata++; 1591 } 1592 else if (gotdata) /* consider us done */ 1593 break; 1594 } 1595 1596 /* timed out? */ 1597 if (!ISSET(mp->mp_flags, MBPPF_UIO)) 1598 break; 1599 1600 /* 1601 * poll delay? 1602 */ 1603 if (mp->mp_delay > 0) { 1604 s = spltty(); /* XXX */ 1605 SET(mp->mp_flags, MBPPF_DELAY); 1606 timeout_add(&mp->mp_start_tmo, mp->mp_delay); 1607 error = tsleep(mp, PCATCH | PZERO, "mbppdelay", 0); 1608 splx(s); 1609 if (error) 1610 break; 1611 } 1612 1613 /* 1614 * don't call uiomove again until we used all the data we grabbed 1615 */ 1616 if (uio->uio_rw == UIO_WRITE && cnt != len) { 1617 ptr += cnt; 1618 len -= cnt; 1619 cnt = 0; 1620 goto again; 1621 } 1622 } 1623 1624 /* 1625 * clear timeouts 1626 */ 1627 s = spltty(); /* XXX */ 1628 if (ISSET(mp->mp_flags, MBPPF_TIMEOUT)) { 1629 timeout_del(&mp->mp_timeout_tmo); 1630 CLR(mp->mp_flags, MBPPF_TIMEOUT); 1631 } 1632 if (ISSET(mp->mp_flags, MBPPF_DELAY)) { 1633 timeout_del(&mp->mp_start_tmo); 1634 CLR(mp->mp_flags, MBPPF_DELAY); 1635 } 1636 splx(s); 1637 1638 /* 1639 * adjust for those chars that we uiomoved but never actually wrote 1640 */ 1641 if (uio->uio_rw == UIO_WRITE && cnt != len) { 1642 uio->uio_resid += (len - cnt); 1643 } 1644 1645 free(buffer, M_DEVBUF); 1646 return (error); 1647 } 1648 1649 void 1650 mbpp_timeout(void *arg) 1651 { 1652 struct mbpp_port *mp = arg; 1653 1654 CLR(mp->mp_flags, MBPPF_UIO | MBPPF_TIMEOUT); 1655 wakeup(mp); 1656 } 1657 1658 void 1659 mbpp_start(void *arg) 1660 { 1661 struct mbpp_port *mp = arg; 1662 1663 CLR(mp->mp_flags, MBPPF_DELAY); 1664 wakeup(mp); 1665 } 1666 1667 int 1668 mbpp_send(struct mbpp_port *mp, caddr_t ptr, int len) 1669 { 1670 int s; 1671 struct cd1400 *cd = mp->mp_cd1400; 1672 1673 /* set up io information */ 1674 mp->mp_ptr = ptr; 1675 mp->mp_cnt = len; 1676 1677 /* start transmitting */ 1678 s = spltty(); 1679 if (cd) { 1680 CD1400_WRITE_REG(cd, CD1400_CAR, 0); 1681 1682 /* output strobe width ~1microsecond */ 1683 CD1400_WRITE_REG(cd, CD1400_TBPR, 10); 1684 1685 /* enable channel */ 1686 cd1400_write_ccr(cd, CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN); 1687 CD1400_WRITE_REG(cd, CD1400_SRER, CD1400_SRER_TXRDY); 1688 } 1689 1690 /* ZZzzz... */ 1691 tsleep(mp, PCATCH | PZERO, "mbpp_send", 0); 1692 1693 /* stop transmitting */ 1694 if (cd) { 1695 CD1400_WRITE_REG(cd, CD1400_CAR, 0); 1696 1697 /* disable transmitter */ 1698 CD1400_WRITE_REG(cd, CD1400_SRER, 0); 1699 cd1400_write_ccr(cd, CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTDIS); 1700 1701 /* flush fifo */ 1702 cd1400_write_ccr(cd, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); 1703 } 1704 splx(s); 1705 1706 /* return number of chars sent */ 1707 return (len - mp->mp_cnt); 1708 } 1709 1710 int 1711 mbpp_recv(struct mbpp_port *mp, caddr_t ptr, int len) 1712 { 1713 int s; 1714 struct cd1400 *cd = mp->mp_cd1400; 1715 1716 /* set up io information */ 1717 mp->mp_ptr = ptr; 1718 mp->mp_cnt = len; 1719 1720 /* start receiving */ 1721 s = spltty(); 1722 if (cd) { 1723 int rcor, rbpr; 1724 1725 CD1400_WRITE_REG(cd, CD1400_CAR, 0); 1726 1727 /* input strobe at 100kbaud (10microseconds) */ 1728 cd1400_compute_baud(100000, cd->cd_clock, &rcor, &rbpr); 1729 CD1400_WRITE_REG(cd, CD1400_RCOR, rcor); 1730 CD1400_WRITE_REG(cd, CD1400_RBPR, rbpr); 1731 1732 /* rx threshold */ 1733 CD1400_WRITE_REG(cd, CD1400_COR3, MBPP_RX_FIFO_THRESHOLD); 1734 cd1400_write_ccr(cd, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); 1735 1736 /* enable channel */ 1737 cd1400_write_ccr(cd, CD1400_CCR_CMDCHANCTL | CD1400_CCR_RCVEN); 1738 CD1400_WRITE_REG(cd, CD1400_SRER, CD1400_SRER_RXDATA); 1739 } 1740 1741 /* ZZzzz... */ 1742 tsleep(mp, PCATCH | PZERO, "mbpp_recv", 0); 1743 1744 /* stop receiving */ 1745 if (cd) { 1746 CD1400_WRITE_REG(cd, CD1400_CAR, 0); 1747 1748 /* disable receiving */ 1749 CD1400_WRITE_REG(cd, CD1400_SRER, 0); 1750 cd1400_write_ccr(cd, CD1400_CCR_CMDCHANCTL | CD1400_CCR_RCVDIS); 1751 } 1752 splx(s); 1753 1754 /* return number of chars received */ 1755 return (len - mp->mp_cnt); 1756 } 1757 1758 int 1759 mbpp_hztoms(int h) 1760 { 1761 int m = h; 1762 1763 if (m > 0) 1764 m = m * 1000 / hz; 1765 return (m); 1766 } 1767 1768 int 1769 mbpp_mstohz(int m) 1770 { 1771 int h = m; 1772 1773 if (h > 0) { 1774 h = h * hz / 1000; 1775 if (h == 0) 1776 h = 1000 / hz; 1777 } 1778 return (h); 1779 } 1780 1781 #endif /* NMAGMA */ 1782