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