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