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