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