Commit | Line | Data |
---|---|---|
af5295ff | 1 | /* |
9c147255 KB |
2 | * Copyright (c) 1992, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
af5295ff KM |
4 | * |
5 | * This code is derived from software contributed to Berkeley by | |
6 | * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc. | |
7 | * | |
8 | * %sccs.include.redist.c% | |
9 | * | |
10 | * from: $Hdr: scc.c,v 4.300 91/06/09 06:44:53 root Rel41 $ SONY | |
11 | * | |
9c147255 | 12 | * @(#)scc.c 8.1 (Berkeley) %G% |
af5295ff KM |
13 | */ |
14 | ||
15 | /* | |
16 | * LH8530 SCC (serial communication controller) driver | |
17 | * | |
18 | * NOTE: This driver is available only for news700/1200/1700/3400. | |
19 | * | |
20 | * Any code and mechanism in this module may not be used | |
21 | * in any form without permissions. COPYRIGHT (C) 1989- | |
22 | * SONY Corporation, Super Microsystems Group (SMSG), | |
23 | * Work Station Division, all rights RESERVED. | |
24 | */ | |
25 | ||
5b7c2955 | 26 | #include <machine/adrsmap.h> |
af5295ff | 27 | |
af5295ff | 28 | #include "rs.h" |
af5295ff | 29 | |
5b7c2955 KU |
30 | #include <sys/param.h> |
31 | #include <sys/ioctl.h> | |
32 | #include <sys/tty.h> | |
33 | #include <sys/malloc.h> | |
af5295ff | 34 | |
5b7c2955 KU |
35 | #include <news3400/sio/sccparam.h> |
36 | #include <news3400/sio/sccreg.h> | |
37 | #include <news3400/sio/scc.h> | |
38 | #include <news3400/sio/scc.conf> | |
af5295ff KM |
39 | |
40 | #define PROBE_DATA 0x55 | |
41 | ||
42 | #ifdef mips | |
43 | #define VOLATILE volatile | |
44 | #else | |
45 | #define VOLATILE | |
46 | #endif | |
47 | ||
48 | int tty00_is_console = 0; | |
49 | ||
50 | #define SCC_BUFSIZE 256 | |
51 | ||
52 | char scc_buf[2][SCC_BUFSIZE]; | |
53 | ||
54 | scc_open(chan) | |
55 | int chan; | |
56 | { | |
57 | register Scc_channel *scc = &sccsw[chan]; | |
58 | register int s; | |
59 | ||
60 | s = splscc(); | |
61 | if ((scc->scc_status & CHAN_ACTIVE) == 0) { | |
62 | scc_init(chan); | |
63 | if (chan <= SCC_REMOTE1) | |
64 | scc->r_dma.dma_addr = scc_buf[chan]; | |
65 | else | |
66 | scc->r_dma.dma_addr = | |
67 | malloc(SCC_BUFSIZE, M_DEVBUF, M_WAITOK); | |
68 | scc->r_dma.dma_count = 0; | |
69 | scc->scc_status |= CHAN_ACTIVE; | |
70 | } | |
71 | (void) splx(s); | |
72 | return (0); | |
73 | } | |
74 | ||
75 | scc_probe(chan) | |
76 | register int chan; | |
77 | { | |
78 | VOLATILE struct scc_reg *port = sccsw[chan].scc_port; | |
79 | int s, temp, probe; | |
80 | ||
81 | if (badaddr(port, 1)) | |
82 | return (0); | |
83 | s = splscc(); | |
84 | temp = scc_read_reg(chan, RR12); | |
85 | scc_write_reg(chan, WR12, PROBE_DATA); | |
86 | probe = scc_read_reg(chan, RR12); | |
87 | scc_write_reg(chan, WR12, temp); | |
88 | (void) splx(s); | |
89 | return (probe == PROBE_DATA); | |
90 | } | |
91 | ||
92 | scc_getc(chan) | |
93 | int chan; | |
94 | { | |
95 | VOLATILE struct scc_reg *port = sccsw[chan].scc_port; | |
96 | int c; | |
97 | ||
98 | if (port->ctrl & R0_RxCA) { | |
99 | SCCWAIT; | |
100 | c = port->data; | |
101 | SCCWAIT; | |
102 | return (c); | |
103 | } | |
104 | SCCWAIT; | |
105 | return (-1); | |
106 | } | |
107 | ||
108 | #ifndef notdef | |
109 | scc_putc(chan, c) | |
110 | int chan, c; | |
111 | { | |
112 | register VOLATILE struct scc_reg *port = sccsw[chan].scc_port; | |
113 | ||
114 | while ((port->ctrl & R0_TxBE) == 0) | |
115 | SCCWAIT; | |
116 | SCCWAIT; | |
117 | port->data = c; | |
118 | SCCWAIT; | |
119 | } | |
120 | #else | |
121 | scc_putc(chan, c) | |
122 | int chan, c; | |
123 | { | |
124 | register VOLATILE struct scc_reg *port = sccsw[chan].scc_port; | |
125 | register VOLATILE u_char *ctrl = &sccsw[chan].scc_port->ctrl; | |
126 | register VOLATILE u_char *data = &sccsw[chan].scc_port->data; | |
127 | ||
128 | SCCWAIT; | |
129 | while ((*ctrl & R0_TxBE) == 0) { | |
130 | SCCWAIT; | |
131 | } | |
132 | SCCWAIT; | |
133 | ||
134 | *ctrl = W0_RES_TxINT; | |
135 | SCCWAIT; | |
136 | *data = (char)(c & 0xff); | |
137 | SCCWAIT; | |
138 | scc_write_reg(chan, WR1, W1_RxINT_ALL|W1_TxINTE|W1_EXTINTE|W1_PARITY); | |
139 | SCCWAIT; | |
140 | } | |
141 | #endif | |
142 | ||
143 | scc_init(chan) | |
144 | int chan; | |
145 | { | |
146 | register VOLATILE struct scc_reg *port; | |
147 | register char *data; | |
148 | register int i; | |
149 | register Scc_channel *scc = &sccsw[chan]; | |
150 | int s; | |
151 | ||
152 | s = splscc(); | |
153 | data = scc->scc_init; | |
154 | port = scc->scc_port; | |
155 | for (i = 0; i < N_INITDATA; i++) { | |
156 | port->ctrl = *data++; | |
157 | SCCWAIT; | |
158 | } | |
159 | scc_write_reg(chan, WR2, scc->scc_vec & ~0x0f); | |
160 | /* KU:XXX | |
161 | This must be bug because scc->scc_param is not initialized yet. | |
162 | scc_set_param(chan, scc->scc_param); | |
163 | */ | |
164 | (void) splx(s); | |
165 | } | |
166 | ||
167 | #define vec_to_scc(vec) ((((vec) - SCCVEC0) >> 3) & 0x000f) | |
168 | #define vec_to_chan(vec) scc2chan[vec_to_scc(vec)] | |
169 | ||
170 | int scc2chan[] = { | |
af5295ff | 171 | 1, 0, |
af5295ff KM |
172 | 3, 2, |
173 | 5, 4, | |
174 | 7, 6, | |
175 | 9, 8 | |
176 | }; | |
177 | ||
af5295ff KM |
178 | scc_rint(vec) |
179 | int vec; | |
180 | { | |
181 | int chan = vec_to_chan(vec); | |
182 | register Scc_channel *scc = &sccsw[chan]; | |
183 | register VOLATILE struct scc_reg *port = scc->scc_port; | |
184 | register int c; | |
185 | ||
186 | if ((scc->scc_status & CHAN_ACTIVE) == 0) { | |
187 | scc_reset(chan); | |
188 | goto out; | |
189 | } | |
190 | if (scc->scc_status & LINE_BREAK){ | |
191 | scc->scc_status &= ~LINE_BREAK; | |
192 | c = port->data; | |
193 | SCCWAIT; | |
194 | } | |
195 | while (port->ctrl & R0_RxCA) { | |
196 | SCCWAIT; | |
197 | c = port->data; | |
198 | SCCWAIT; | |
199 | #if NRS > 0 | |
200 | scc_pdma(chan, c); | |
201 | #endif | |
202 | } | |
203 | SCCWAIT; | |
204 | out: | |
205 | port->ctrl = W0_RES_IUS; | |
206 | SCCWAIT; | |
207 | } | |
af5295ff KM |
208 | |
209 | #if NRS > 0 | |
210 | scc_enable(chan) | |
211 | int chan; | |
212 | { | |
213 | register Scc_channel *scc = &sccsw[chan]; | |
214 | int n; | |
215 | int s; | |
216 | ||
217 | s = splscc(); | |
218 | if ((n = scc->r_dma.dma_count) > 0) { | |
219 | scc->r_dma.dma_count = 0; | |
220 | rsrint(chan, scc->r_dma.dma_addr, n); | |
221 | } else | |
222 | scc->scc_status |= ENABLE; | |
223 | (void) splx(s); | |
224 | } | |
225 | ||
226 | scc_pdma(chan, c) | |
227 | int chan; | |
228 | int c; | |
229 | { | |
230 | register Scc_channel *scc = &sccsw[chan]; | |
231 | int n; | |
232 | ||
233 | if (scc->r_dma.dma_count >= SCC_BUFSIZE) | |
234 | printf("rs%d soft fifo overflow\n", chan); | |
235 | else | |
236 | scc->r_dma.dma_addr[scc->r_dma.dma_count++] = c; | |
237 | if (scc->scc_status & ENABLE || scc->r_dma.dma_count >= SCC_BUFSIZE) { | |
238 | scc->scc_status &= ~ENABLE; | |
239 | n = scc->r_dma.dma_count; | |
240 | scc->r_dma.dma_count = 0; | |
241 | rsrint(chan, scc->r_dma.dma_addr, n); | |
242 | } | |
243 | } | |
244 | #endif /* NRS > 0 */ | |
245 | ||
246 | scc_xint(vec) | |
247 | int vec; | |
248 | { | |
249 | int chan = vec_to_chan(vec); | |
250 | register Scc_channel *scc = &sccsw[chan]; | |
251 | register VOLATILE struct scc_reg *port = scc->scc_port; | |
252 | ||
253 | if (scc->scc_status & OSTOP) | |
254 | scc->scc_status &= ~(OACTIVE|OSTOP); | |
255 | if (scc->scc_status & OFLUSH) { | |
256 | scc->x_dma.dma_count = 0; | |
257 | scc->scc_status &= ~(OACTIVE|OFLUSH); | |
258 | } | |
259 | if ((scc->scc_status & OACTIVE) && (scc->x_dma.dma_count > 0)) { | |
260 | port->data = *(scc->x_dma.dma_addr)++; | |
261 | SCCWAIT; | |
262 | scc->x_dma.dma_count--; | |
263 | } else { | |
264 | port->ctrl = W0_RES_TxINT; | |
265 | SCCWAIT; | |
266 | scc->scc_status &= ~OACTIVE; | |
267 | #if NRS > 0 | |
268 | if (scc->x_dma.dma_count == 0) | |
269 | rsxint(chan); | |
270 | #endif | |
271 | } | |
272 | port->ctrl = W0_RES_IUS; | |
273 | SCCWAIT; | |
274 | } | |
275 | ||
276 | scc_sint(vec) | |
277 | int vec; | |
278 | { | |
279 | int chan = vec_to_chan(vec); | |
280 | register Scc_channel *scc = &sccsw[chan]; | |
281 | register VOLATILE struct scc_reg *port = scc->scc_port; | |
282 | register int status; | |
283 | register int param = 0; | |
284 | ||
285 | port->ctrl = W0_RES_EXT; | |
286 | SCCWAIT; | |
287 | if ((scc->scc_status & CHAN_ACTIVE) == 0) { | |
288 | scc_reset(chan); | |
289 | goto out; | |
290 | } | |
291 | status = port->ctrl; | |
292 | SCCWAIT; | |
293 | if (status & R0_DCD) | |
294 | param |= DCD; | |
295 | if (status & R0_CTS) | |
296 | param |= CTS; | |
297 | if (status & R0_BREAK){ | |
298 | param |= RBREAK; | |
299 | scc->scc_status |= LINE_BREAK; | |
300 | } | |
301 | if ((scc->scc_param & (DCD|CTS|RBREAK)) != param) { | |
302 | scc->scc_param = (scc->scc_param & ~(DCD|CTS|RBREAK)) | param; | |
303 | #if NRS > 0 | |
304 | rssint(chan, scc->scc_param); | |
305 | #endif | |
306 | } | |
307 | out: | |
308 | port->ctrl = W0_RES_IUS; | |
309 | SCCWAIT; | |
310 | } | |
311 | ||
312 | scc_cint(vec) | |
313 | int vec; | |
314 | { | |
315 | int chan = vec_to_chan(vec); | |
316 | register Scc_channel *scc = &sccsw[chan]; | |
317 | register VOLATILE struct scc_reg *port = scc->scc_port; | |
318 | register int status; | |
319 | int c; | |
320 | ||
321 | if ((scc->scc_status & CHAN_ACTIVE) == 0) { | |
322 | scc_reset(chan); | |
323 | goto out; | |
324 | } | |
325 | status = scc_read_reg(chan, RR1); | |
326 | if (status & R1_CRC) | |
327 | scc->scc_param |= FRAMING_ERROR; | |
328 | if (status & R1_OVRUN) { | |
329 | if ((scc->scc_param & OVERRUN_ERROR) == 0) { | |
330 | scc->scc_param |= OVERRUN_ERROR; | |
331 | #if NRS > 0 | |
332 | rssint(chan, scc->scc_param); | |
746c97ef | 333 | #endif |
af5295ff KM |
334 | } |
335 | } | |
336 | if (status & R1_PARITY) { | |
337 | scc->scc_param |= SCC_PARITY_ERROR; | |
338 | while (port->ctrl & R0_RxCA) { | |
339 | SCCWAIT; | |
340 | c = port->data; | |
341 | SCCWAIT; | |
342 | #if NRS > 0 | |
343 | if (scc->scc_param & NOCHECK) | |
344 | scc_pdma(chan, c); | |
345 | #endif | |
346 | } | |
347 | SCCWAIT; | |
348 | } | |
349 | out: | |
350 | port->ctrl = W0_RES_ERROR; | |
351 | SCCWAIT; | |
352 | port->ctrl = W0_RES_IUS; | |
353 | SCCWAIT; | |
354 | } | |
355 | ||
356 | scc_write_reg(chan, reg, data) | |
357 | int chan, reg, data; | |
358 | { | |
359 | register VOLATILE struct scc_reg *port = sccsw[chan].scc_port; | |
360 | ||
361 | port->ctrl = reg; | |
362 | SCCWAIT; | |
363 | port->ctrl = data; | |
364 | SCCWAIT; | |
365 | } | |
366 | ||
367 | scc_read_reg(chan, reg) | |
368 | int chan, reg; | |
369 | { | |
370 | register VOLATILE struct scc_reg *port = sccsw[chan].scc_port; | |
371 | int result; | |
372 | ||
373 | port->ctrl = reg; | |
374 | SCCWAIT; | |
375 | result = port->ctrl; | |
376 | SCCWAIT; | |
377 | return (result); | |
378 | } | |
379 | ||
af5295ff KM |
380 | #ifdef news3400 |
381 | #define DSRA 0x01 | |
382 | #define RIA 0x02 | |
383 | #define DSRB 0x04 | |
384 | #define RIB 0x08 | |
385 | ||
386 | #define DSRC 0x01 | |
387 | #define RIC 0x02 | |
388 | #define DSRD 0x04 | |
389 | #define RID 0x08 | |
390 | #define DSRE 0x10 | |
391 | #define RIE 0x20 | |
392 | #define DSRF 0x40 | |
393 | #define RIF 0x80 | |
394 | #endif /* news3400 */ | |
395 | ||
396 | struct ri_dsr { | |
397 | char *status; | |
398 | int ri; | |
399 | int dsr; | |
400 | } ri_dsr[] = { | |
af5295ff KM |
401 | { (char *)SCC_STATUS0, RIA, DSRA }, |
402 | { (char *)SCC_STATUS0, RIB, DSRB }, | |
746c97ef | 403 | #if !defined(news3200) |
af5295ff KM |
404 | { (char *)SCC_STATUS1, RIC, DSRC }, |
405 | { (char *)SCC_STATUS1, RID, DSRD }, | |
406 | { (char *)SCC_STATUS1, RIE, DSRE }, | |
407 | { (char *)SCC_STATUS1, RIF, DSRF }, | |
408 | { (char *)SCC_STATUS2, RIC, DSRC }, | |
409 | { (char *)SCC_STATUS2, RID, DSRD }, | |
410 | { (char *)SCC_STATUS2, RIE, DSRE }, | |
411 | { (char *)SCC_STATUS2, RIF, DSRF } | |
746c97ef | 412 | #endif /* !news3200 */ |
af5295ff KM |
413 | }; |
414 | ||
415 | get_ri_dsr(chan) | |
416 | int chan; | |
417 | { | |
418 | register struct ri_dsr *p; | |
419 | register int status, param; | |
420 | ||
421 | param = 0; | |
af5295ff KM |
422 | p = &ri_dsr[chan]; |
423 | status = *p->status; | |
424 | if ((status & p->ri) == 0) | |
425 | param |= RI; | |
426 | if ((status & p->dsr) == 0) | |
427 | param |= DSR; | |
af5295ff KM |
428 | return (param); |
429 | } | |
430 | ||
746c97ef | 431 | #if defined(news3400) |
af5295ff KM |
432 | /* |
433 | * tc0 = floor(4915200 / 32 / baudrate - 2 + 0.5); | |
434 | */ | |
435 | static int tc0[] = { | |
436 | 0, /* B0 */ | |
437 | 3070, /* B50 */ | |
438 | 2046, /* B75 */ | |
439 | 1394, /* B110 */ | |
440 | 1144, /* B134 */ | |
441 | 1022, /* B150 */ | |
442 | 766, /* B200 */ | |
443 | 510, /* B300 */ | |
444 | 254, /* B600 */ | |
445 | 126, /* B1200 */ | |
446 | 83, /* B1800 */ | |
447 | 62, /* B2400 */ | |
448 | 30, /* B4800 */ | |
449 | 14, /* B9600 */ | |
450 | 6, /* EXTA (B19200) */ | |
451 | 2 /* EXTB (B38400) */ | |
452 | }; | |
746c97ef | 453 | #endif /* news3400 */ |
af5295ff | 454 | |
af5295ff KM |
455 | static int tc1[] = { |
456 | /* | |
457 | * tc1 = floor(3686400 / 32 / baudrate - 2 + 0.5); | |
458 | */ | |
459 | 0, /* B0 */ | |
460 | 2302, /* B50 */ | |
461 | 1534, /* B75 */ | |
462 | 1045, /* B110 */ | |
463 | 858, /* B134 */ | |
464 | 766, /* B150 */ | |
465 | 574, /* B200 */ | |
466 | 382, /* B300 */ | |
467 | 190, /* B600 */ | |
468 | 94, /* B1200 */ | |
469 | 62, /* B1800 */ | |
470 | 46, /* B2400 */ | |
471 | 22, /* B4800 */ | |
472 | 10, /* B9600 */ | |
473 | 4, /* B19200 */ | |
474 | 1, /* B38400 */ | |
475 | }; | |
af5295ff KM |
476 | |
477 | scc_set_param(chan, param) | |
478 | int chan; | |
479 | register int param; | |
480 | { | |
481 | register Scc_channel *scc = &sccsw[chan]; | |
482 | register int bit, baud, *tc; | |
483 | int s; | |
484 | ||
485 | s = splscc(); | |
486 | ||
487 | /* | |
488 | * Baud rate / external clock | |
489 | */ | |
490 | if ((baud = param & BAUD_RATE) == EXTB && chan <= SCC_REMOTE1 && | |
491 | param & EXTCLK_ENABLE) { | |
492 | scc_write_reg(chan, WR11, W11_RxC_RTxC|W11_TxC_TRxC); | |
493 | bit = W4_X1; | |
494 | } else { | |
af5295ff | 495 | tc = (chan <= SCC_REMOTE1) ? tc0 : tc1; |
af5295ff KM |
496 | scc_write_reg(chan, WR11, W11_RxC_BRG|W11_TxC_BRG); |
497 | scc_write_reg(chan, WR12, tc[baud] & 0xff); | |
498 | scc_write_reg(chan, WR13, tc[baud] >> 8); | |
499 | bit = W4_X16; | |
500 | } | |
501 | ||
502 | /* | |
503 | * Clock mode / parity / stop bit | |
504 | */ | |
505 | if (param & PARITY) { | |
506 | bit |= W4_PARITY; | |
507 | if (param & EVEN) | |
508 | bit |= W4_EVEN; | |
509 | } | |
510 | switch (param & STOPBIT) { | |
511 | ||
512 | case STOP1: | |
513 | bit |= W4_STOP1; | |
514 | break; | |
515 | ||
516 | case STOP1_5: | |
517 | bit |= W4_STOP1_5; | |
518 | break; | |
519 | ||
520 | case STOP2: | |
521 | bit |= W4_STOP2; | |
522 | break; | |
523 | ||
524 | } | |
525 | scc_write_reg(chan, WR4, bit); | |
526 | ||
527 | /* | |
528 | * Receiver enable / receive character size / auto enable | |
529 | */ | |
530 | bit = (param & RXE ? W3_RxE : 0); | |
531 | switch (param & CHAR_SIZE) { | |
532 | ||
533 | case C5BIT: | |
534 | break; | |
535 | ||
536 | case C6BIT: | |
537 | bit |= W3_Rx6BIT; | |
538 | break; | |
539 | ||
540 | case C7BIT: | |
541 | bit |= W3_Rx7BIT; | |
542 | break; | |
543 | ||
544 | case C8BIT: | |
545 | bit |= W3_Rx8BIT; | |
546 | break; | |
547 | } | |
548 | #ifdef AUTO_ENABLE | |
549 | if (param & AUTO_ENABLE) | |
550 | bit |= W3_AUTO; | |
551 | #endif /* AUTO_ENABLE */ | |
552 | scc_write_reg(chan, WR3, bit); | |
553 | ||
554 | /* | |
555 | * Transmitter enable / transmit character size / RTS / DTR / BREAK | |
556 | */ | |
557 | bit = (param & TXE ? W5_TxE : 0); | |
558 | switch (param & CHAR_SIZE) { | |
559 | ||
560 | case C5BIT: | |
561 | break; | |
562 | ||
563 | case C6BIT: | |
564 | bit |= W5_Tx6BIT; | |
565 | break; | |
566 | ||
567 | case C7BIT: | |
568 | bit |= W5_Tx7BIT; | |
569 | break; | |
570 | ||
571 | case C8BIT: | |
572 | bit |= W5_Tx8BIT; | |
573 | break; | |
574 | } | |
575 | if (param & RTS) | |
576 | bit |= W5_RTS; | |
577 | if (param & DTR) | |
578 | bit |= W5_DTR; | |
579 | if (param & XBREAK) | |
580 | bit |= W5_BREAK; | |
581 | scc_write_reg(chan, WR5, bit); | |
582 | scc->scc_param = param; | |
583 | (void) splx(s); | |
584 | return (0); | |
585 | } | |
586 | ||
587 | scc_get_param(chan) | |
588 | int chan; | |
589 | { | |
590 | register Scc_channel *scc = &sccsw[chan]; | |
591 | ||
592 | scc->scc_param = (scc->scc_param & ~(RI|DSR)) | get_ri_dsr(chan); | |
593 | return (scc->scc_param); | |
594 | } | |
595 | ||
596 | scc_get_status(chan) | |
597 | int chan; | |
598 | { | |
599 | ||
600 | return (sccsw[chan].scc_status); | |
601 | } | |
602 | ||
603 | scc_set_status(chan, stat) | |
604 | int chan, stat; | |
605 | { | |
606 | ||
607 | sccsw[chan].scc_status = stat; | |
608 | ||
609 | return (0); | |
610 | } | |
611 | ||
612 | scc_flush(chan) | |
613 | int chan; | |
614 | { | |
615 | register Scc_channel *scc = &sccsw[chan]; | |
616 | ||
617 | if (scc->scc_status & OACTIVE) | |
618 | scc->scc_status |= OFLUSH; | |
619 | else if (scc->x_dma.dma_count > 0) { | |
620 | scc->x_dma.dma_count = 0; | |
621 | #if NRS > 0 | |
622 | rsxint(chan); | |
623 | #endif | |
624 | } | |
625 | return (0); | |
626 | } | |
627 | ||
628 | scc_start(chan) | |
629 | int chan; | |
630 | { | |
631 | register Scc_channel *scc = &sccsw[chan]; | |
632 | ||
633 | if ((scc->scc_status & OACTIVE) == 0 && scc->x_dma.dma_count > 0) { | |
634 | scc->scc_port->data = *(scc->x_dma.dma_addr)++; | |
635 | SCCWAIT; | |
636 | scc->x_dma.dma_count--; | |
637 | scc->scc_status |= OACTIVE; | |
638 | } | |
639 | return (0); | |
640 | } | |
641 | ||
642 | scc_stop(chan) | |
643 | int chan; | |
644 | { | |
645 | register Scc_channel *scc = &sccsw[chan]; | |
646 | ||
647 | if (scc->scc_status & OACTIVE) | |
648 | scc->scc_status |= OSTOP; | |
649 | return (0); | |
650 | } | |
651 | ||
652 | scc_write(chan, buf, count) | |
653 | int chan; | |
654 | caddr_t buf; | |
655 | int count; | |
656 | { | |
657 | register Scc_channel *scc = &sccsw[chan]; | |
658 | ||
659 | if (count <= 0) | |
660 | return (0); | |
661 | scc->x_dma.dma_addr = buf; | |
662 | scc->x_dma.dma_count = count; | |
663 | scc_start(chan); | |
664 | return (count); | |
665 | } | |
666 | ||
667 | scc_error_write(chan, buf, count) | |
668 | int chan; | |
669 | register char *buf; | |
670 | register int count; | |
671 | { | |
672 | register int i; | |
673 | ||
674 | for (i = 0; i < count; i++) | |
675 | scc_putc(chan, *buf++); | |
676 | return (i); | |
677 | } | |
678 | ||
679 | scc_reset(chan) | |
680 | int chan; | |
681 | { | |
682 | register Scc_channel *scc = &sccsw[chan]; | |
683 | ||
684 | while (scc_getc(chan) != -1) | |
685 | ; | |
686 | scc->scc_status &= ~CHAN_ACTIVE; | |
687 | } |