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