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