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