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