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