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