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