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