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