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