FreeBSD/Linux Kernel Cross Reference
sys/sqtsec/co.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991 Carnegie Mellon University
4 * Copyright (c) 1991 Sequent Computer Systems
5 * All Rights Reserved.
6 *
7 * Permission to use, copy, modify and distribute this software and its
8 * documentation is hereby granted, provided that both the copyright
9 * notice and this permission notice appear in all copies of the
10 * software, derivative works or modified versions, and any portions
11 * thereof, and that both notices appear in supporting documentation.
12 *
13 * CARNEGIE MELLON AND SEQUENT COMPUTER SYSTEMS ALLOW FREE USE OF
14 * THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON AND
15 * SEQUENT COMPUTER SYSTEMS DISCLAIM ANY LIABILITY OF ANY KIND FOR
16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17 *
18 * Carnegie Mellon requests users of this software to return to
19 *
20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
24 *
25 * any improvements or extensions that they make and grant Carnegie Mellon
26 * the rights to redistribute these changes.
27 */
28
29 /*
30 * HISTORY
31 * $Log: co.c,v $
32 * Revision 2.3 91/07/31 18:06:19 dbg
33 * Changed copyright.
34 * [91/07/31 dbg]
35 *
36 * Revision 2.2 91/05/08 13:04:47 dbg
37 * Added cn routines for kernel debugger input.
38 * [90/11/16 dbg]
39 *
40 * Adapted for pure kernel.
41 * [90/09/24 dbg]
42 *
43 */
44
45 #ifndef lint
46 static char rcsid[]= "$Header: co.c,v 2.3 91/07/31 18:06:19 dbg Exp $";
47 #endif
48
49 /*
50 * SCSI/Ether console driver
51 *
52 * There are two consoles per SEC card. The SEC attached to the
53 * front panel is distinguished. The port selected as console on this
54 * sec can be accessed through minor device 64 (0x40). All ports can
55 * be accessed through minor device numbers 0 through 2*n, for n sec
56 * boards. The minor device number 64 is an alias for one of these
57 * devices.
58 */
59
60 /*
61 * Revision 1.3 89/08/03 12:30:02 kak
62 * balance -> sqt
63 *
64 * Revision 1.2 89/07/25 11:20:56 kak
65 * fixed p_sema_v_lock define
66 *
67 * Revision 1.1 89/07/05 13:20:12 kak
68 * Initial revision
69 *
70 */
71
72 #ifdef MACH_KERNEL
73 #include <mach_kdb.h>
74
75 #include <kern/time_out.h>
76
77 #include <device/conf.h>
78 #include <device/tty.h>
79 #include <device/errno.h>
80 #include <device/io_req.h>
81
82 #include <sqt/vm_defs.h>
83 #include <sqt/cfg.h>
84
85 #include <sqt/ioconf.h>
86 #include <sqt/intctl.h>
87 #include <sqt/mutex.h>
88
89 #include <sqtsec/sec.h>
90 #include <sqtsec/co.h>
91
92 #else /* MACH_KERNEL */
93 #include "sys/param.h"
94 #include "sys/user.h"
95 #include "sys/conf.h"
96 #include "sys/ioctl.h"
97 #include "sys/tty.h"
98 #include "sys/systm.h"
99 #include "sys/clist.h"
100 #include "sys/file.h"
101 #include "sys/uio.h"
102 #include "sys/proc.h"
103
104 #include "sqt/cfg.h"
105
106 #include "sqt/ioconf.h"
107 #include "sqt/intctl.h"
108 #include "sqt/mutex.h"
109
110 #include "sqtsec/sec.h"
111 #include "sqtsec/co.h"
112
113 #endif /* MACH_KERNEL */
114
115 #ifdef DEBUG
116 int co_debug = 0;
117 #endif DEBUG
118
119 #ifdef MACH_KERNEL
120 /*
121 * Pure kernel really does locks
122 */
123 #define CO_TTYLOCK(tp) p_lock(&(tp)->t_lock, SPLTTY)
124 #define CO_TTYUNLOCK(tp,spl) v_lock(&(tp)->t_lock, (spl))
125
126 /*
127 * But no gates on i386
128 */
129 #define ttyinit(tty_p, gate)
130
131 #else /* MACH_KERNEL */
132 #ifndef MACH
133
134 /*
135 * Dynix really does locks/etc.
136 */
137
138 #define CO_TTYLOCK(tp) p_lock(&(tp)->t_ttylock, SPLTTY)
139 #define CO_TTYUNLOCK(tp,spl) v_lock(&(tp)->t_ttylock, (spl))
140
141 #else MACH
142
143 /*
144 * For now, MACH calls all driver code on master_cpu. Also, no sema_t
145 * and lock_t with full semantics (eg, force_v_sema(), etc). Thus,
146 * define the primitives so the driver can work.
147 *
148 * Since all code runs on master_cpu, it is sufficient for the driver
149 * that all semaphore activity is treated as "sleep/wakeup",
150 * and "p_lock" is just an spl().
151 */
152
153 #define CO_TTYLOCK(tp) spltty()
154 #define CO_TTYUNLOCK(tp,spl) splx(spl)
155
156 #define t_rawqwait t_rawq
157 #define t_outqwait t_outq
158
159 #define ttyinit(tty_p, gate)
160
161 #define p_sema_v_lock(sema_p, pri, lock_p, spl) \
162 sleep((caddr_t) (sema_p), pri)
163
164 #define vall_sema(sema_p) wakeup((caddr_t) (sema_p))
165
166 #endif MACH
167 #endif /* MACH_KERNEL */
168
169 #define CO_FLAG 0x40
170
171 int coprobe(), coboot(), cointr();
172
173 struct sec_driver co_driver={
174 /* name base flags probe boot intr */
175 "co", 3, SED_TYPICAL, coprobe, coboot, cointr
176 };
177
178 int co_max_unit = -1;
179 u_char co_base_vec;
180 struct co_state *co_state;
181 struct co_state *co_costate;
182
183 extern int coflags;
184 extern char cospeed;
185 struct sec_dev_prog * CO_GET_Q_TAIL();
186 struct sec_dev_prog * CO_GET_Q_HEAD();
187
188
189 /*
190 * coprobe - probe a SCSI/Ether for a console device.
191 *
192 * Look at the flags returned by the powerup firmware.
193 */
194
195 coprobe(probe)
196 struct sec_probe *probe;
197 {
198 int failure_flag;
199
200 switch(probe->secp_chan) {
201 case SDEV_CONSOLE0IN:
202 case SDEV_CONSOLE0OUT:
203 failure_flag = CFG_PORT0;
204 break;
205 case SDEV_CONSOLE1IN:
206 case SDEV_CONSOLE1OUT:
207 failure_flag = CFG_PORT1;
208 break;
209 }
210
211 if(probe->secp_desc->sec_diag_flags & failure_flag) {
212 #ifdef DEBUG
213 if(co_debug) printf("P-");
214 #endif DEBUG
215 return(0);
216 }
217 #ifdef DEBUG
218 if(co_debug) printf("P+");
219 #endif DEBUG
220 return(1);
221 }
222
223 /*
224 * coboot - allocate data structures, etc at beginning of time.
225 *
226 * Called by autoconfig with an array of configured devices and their
227 * number. We allocate the necessary soft descriptions and fill them
228 * with the various fields from the devs[] array. Due to the dual
229 * device-channel nature of SEC devices, each devs[] entry describes
230 * input side or output side of a console device.
231 */
232
233 coboot(ndevs, devs)
234 struct sec_dev *devs;
235 {
236 register int i;
237
238 /*
239 * find out the maximum potential unit number, and
240 * allocate array of soft states.
241 */
242
243 for (i = 0; i < ndevs; ++i) {
244 if (co_max_unit < 2*devs[i].sd_sec_idx + 1)
245 co_max_unit = 2*devs[i].sd_sec_idx + 1;
246 }
247
248 co_state = (struct co_state *)calloc((co_max_unit + 1) *
249 sizeof(struct co_state));
250
251 co_base_vec = devs[0].sd_vector;
252
253
254 /*
255 * now boot each configured device.
256 */
257
258 for (i = 0; i < ndevs; ++i) {
259 register struct sec_dev *devp;
260 register int unit;
261
262 devp = &devs[i];
263 if (devp->sd_alive == 0)
264 continue;
265
266 unit = i/2;
267
268 if (unit >= co_bin_config_count) {
269 printf("%s%d: console device not binary configured.\n",
270 co_driver.sed_name, unit);
271 continue;
272 }
273
274 co_boot_one(&co_state[unit], devp, &co_bin_config[unit]);
275 }
276 #ifdef MACH_KERNEL
277 /*
278 * Fix the console indirection
279 */
280 if (co_costate) /* had better be non-zero */
281 dev_change_indirect("console", "co", co_costate - co_state);
282
283 #endif MACH_KERNEL
284 }
285
286 /*
287 * co_boot_one - combine binary config, autoconfig information into
288 * softstate, for convenient access.
289 *
290 * Allocate device program, etc. The device program queues were allocated
291 * by autoconfig.
292 *
293 * status pointers for cibs point to data in the soft state.
294 *
295 * No locking needs to be done here, as we are still running config
296 * code single processor.
297 */
298
299 co_boot_one(softp, sd, bc)
300 register struct co_state *softp;
301 register struct sec_dev *sd;
302 register struct co_bin_config *bc;
303 {
304 struct sec_cib *pu_cib;
305
306 #ifdef DEBUG
307 if (co_debug > 2)
308 printf("B%d.\n", sd->sd_unit);
309 #endif DEBUG
310
311 if (!softp->ss_initted) {
312
313 ttyinit(&softp->ss_tty, bc->cobc_gate);
314 softp->ss_alive = 1;
315 softp->ss_initted = 1;
316 if (sd->sd_desc->sec_is_cons) {
317 switch(sd->sd_desc->sec_is_cons) {
318
319 case CDSC_LOCAL:
320 #if DEBUG
321 printf("local console\n");
322 #endif DEBUG
323 if (sd->sd_chan == SDEV_CONSOLE0IN ||
324 sd->sd_chan == SDEV_CONSOLE0OUT)
325 co_costate = softp;
326 break;
327
328 case CDSC_REMOTE:
329 #if DEBUG
330 printf("remote console\n");
331 #endif DEBUG
332 if (sd->sd_chan == SDEV_CONSOLE1IN ||
333 sd->sd_chan == SDEV_CONSOLE1OUT)
334 co_costate = softp;
335 break;
336
337 default:
338 panic("console: invalid device as console \n");
339 break;
340 }
341 }
342
343 }
344
345 if (sd->sd_chan == SDEV_CONSOLE0IN || sd->sd_chan == SDEV_CONSOLE1IN) {
346 assert(!softp->is_initted);
347
348 softp->is_sd = sd;
349 softp->is_ovc = 0;
350 softp->is_parc = 0;
351
352 softp->is_reqq.sq_size = sd->sd_req_size;
353 softp->is_reqq.sq_progq = sd->sd_requestq;
354
355 softp->is_doneq.sq_size = sd->sd_doneq_size;
356 softp->is_doneq.sq_progq = sd->sd_doneq;
357
358 SEC_fill_progq(softp->is_reqq.sq_progq,
359 (int)softp->is_reqq.sq_size,
360 (int)sizeof(struct sec_dev_prog));
361
362 softp->is_initted = 1;
363
364 } else
365 if (sd->sd_chan==SDEV_CONSOLE0OUT || sd->sd_chan==SDEV_CONSOLE1OUT) {
366 assert(!softp->os_initted);
367 softp->os_sd = sd;
368
369 softp->os_reqq.sq_size = sd->sd_req_size;
370 softp->os_reqq.sq_progq = sd->sd_requestq;
371
372 softp->os_doneq.sq_size = sd->sd_doneq_size;
373 softp->os_doneq.sq_progq = sd->sd_doneq;
374
375 SEC_fill_progq(softp->os_reqq.sq_progq,
376 (int)softp->os_reqq.sq_size,
377 (int)sizeof(struct sec_dev_prog));
378
379 softp->os_busy_flag = 0;
380 init_sema(&softp->os_busy_wait, 0, 0, bc->cobc_gate);
381
382 pu_cib = &softp->os_sd->sd_desc->sec_powerup->pu_cib;
383 #ifdef DEBUG
384 if (co_debug > 1){
385 printf("coboot doing getmode\n");
386 }
387 #endif DEBUG
388 SEC_startio(SINST_GETMODE, &softp->os_smode.sm_status,
389 sd->sd_bin,
390 sd->sd_chan,
391 pu_cib,
392 sd->sd_desc->sec_slicaddr);
393 if (softp->os_smode.sm_status & (~SINST_INSDONE))
394 printf("co: bad get_mode: %x\n", softp->os_smode.sm_status);
395 #ifdef DEBUG
396 if (co_debug > 1)
397 printf("coboot getmode done flags %x, baud %x\n",
398 softp->os_smode.CM_FLAGS, softp->os_smode.CM_BAUD);
399 #endif DEBUG
400
401 softp->os_smode.CM_FLAGS &= ~(SCONS_DZMODE );
402
403 #ifdef DEBUG
404 if (co_debug > 1)
405 printf("coboot doing setmode\n");
406 #endif DEBUG
407 SEC_startio(SINST_SETMODE, &softp->os_smode.sm_status,
408 sd->sd_bin,
409 sd->sd_chan,
410 pu_cib,
411 sd->sd_desc->sec_slicaddr);
412 if (softp->os_smode.sm_status & (~SINST_INSDONE))
413 printf("co: bad set_mode: %x\n", softp->os_smode.sm_status);
414 #ifdef DEBUG
415 if (co_debug > 1)
416 printf("coboot setmode done flags %x, baud %x\n",
417 softp->os_smode.CM_FLAGS, softp->os_smode.CM_BAUD);
418 #endif DEBUG
419
420 softp->os_initted = 1;
421
422 } else {
423 printf("%s %d: invalid device chan %d(0x%x) in boot routine\n",
424 co_driver.sed_name, sd->sd_sec_idx,
425 sd->sd_chan, sd->sd_chan);
426 }
427 }
428
429 int costart();
430 #ifdef MACH_KERNEL
431 int costop();
432 int cogetstat();
433 int cosetstat();
434 #endif /* MACH_KERNEL */
435
436 /*ARGSUSED*/
437 #ifdef MACH_KERNEL
438 coopen(dev, flag, ior)
439 register dev_t dev;
440 int flag;
441 io_req_t ior;
442 #else /* MACH_KERNEL */
443 coopen(dev, flag)
444 register dev_t dev;
445 int flag;
446 #endif /* MACH_KERNEL */
447 {
448 register struct tty *tp;
449 register struct co_state *softp;
450 register unit;
451 spl_t tplock;
452 int retval;
453
454 #ifdef DEBUG
455 if(co_debug)
456 printf("O");
457 #endif DEBUG
458 /*
459 * Check for errors
460 */
461
462 unit = minor(dev);
463 if (unit & CO_FLAG)
464 softp = co_costate;
465 else {
466 softp = &co_state[unit];
467 if(unit > co_max_unit || softp->ss_alive == 0)
468 return(ENXIO);
469 }
470
471 /*
472 * Lock the device and initialize the channel
473 */
474
475 tp = &softp->ss_tty;
476 tplock = CO_TTYLOCK(tp);
477
478 #ifdef MACH_KERNEL
479 /* done at higher level */
480 #else /* MACH_KERNEL */
481 tp->t_nopen++;
482 while(tp->t_state&TS_LCLOSE) { /* In process close so hang! */
483 tp->t_state |= TS_WOPEN;
484 p_sema_v_lock(&tp->t_rawqwait, TTIPRI, &tp->t_ttylock, tplock);
485 tplock = CO_TTYLOCK(tp);
486 }
487 #endif /* MACH_KERNEL */
488
489 if((tp->t_state & TS_ISOPEN) == 0) {
490 tp->t_oproc = costart;
491 #ifdef MACH_KERNEL
492 tp->t_stop = costop;
493 tp->t_setstat = cosetstat;
494 tp->t_getstat = cogetstat;
495 #endif /* MACH_KERNEL */
496 tp->t_addr = (caddr_t)softp;
497 if(tp->t_ispeed == 0) {
498 if (softp == co_costate)
499 tp->t_ospeed = tp->t_ispeed =
500 softp->os_smode.CM_BAUD;
501 else
502 tp->t_ospeed = tp->t_ispeed = cospeed;
503 tp->t_flags = coflags;
504 }
505 ttychars(tp); /* setup default signal chars */
506 /*
507 * over ride some of those defaults with those from
508 * the cfg structure. Only for /dev/console
509 */
510 #ifdef MACH_KERNEL
511 #else /* MACH_KERNEL */
512 if (softp == co_costate) {
513 tp->t_erase = CD_LOC->c_erase;
514 tp->t_kill = CD_LOC->c_kill;
515 tp->t_intrc = CD_LOC->c_interrupt;
516 }
517 #endif /* MACH_KERNEL */
518
519 co_param(softp); /* setup default baud rate */
520
521 co_abort_read(softp);
522 softp->is_restart_read = 1;
523 co_start_read(softp);
524 }else{
525 #ifdef MACH_KERNEL
526 #else /* MACH_KERNEL */
527 /*
528 * Someone has an exclusive open on the device.
529 * Return error EBUSY
530 */
531 if((tp->t_state & TS_XCLUDE) && u.u_uid != 0) {
532 tp->t_nopen--;
533 CO_TTYUNLOCK(tp, tplock);
534 return(EBUSY);
535 }
536 #endif /* MACH_KERNEL */
537 }
538
539
540 /*
541 * Set up modem status.
542 */
543 softp->os_smode.CM_FLAGS &= ~( SCONS_CLEAR_RTS |
544 SCONS_CLEAR_DTR |
545 SCONS_IGN_CARRIER);
546 co_wset_modes(softp);
547
548 /*
549 * Block waiting for carrier.
550 */
551 co_get_modes(softp);
552 if ((softp->os_smode.CM_FLAGS & SCONS_CARRIER_CLEAR)==0)
553 tp->t_state |= TS_CARR_ON;
554 #ifdef MACH_KERNEL
555 CO_TTYUNLOCK(tp, tplock);
556 return (char_open(dev, tp, flag, ior));
557 #else /* MACH_KERNEL */
558 while((tp->t_state&TS_CARR_ON) == 0) {
559 tp->t_state |= TS_WOPEN;
560 #ifdef DEBUG
561 if (co_debug > 1)
562 printf("coopen: waiting for carrier\n");
563 #endif DEBUG
564 p_sema_v_lock(&tp->t_rawqwait, PZERO+1, &tp->t_ttylock, tplock);
565 tplock = CO_TTYLOCK(tp);
566 }
567 #ifdef DEBUG
568 if (co_debug > 1)
569 printf("coopen: got carrier\n");
570 #endif DEBUG
571
572 retval = (*(linesw[tp->t_line].l_open))(dev, tp);
573 #ifdef DEBUG
574 if (co_debug > 1)
575 printf("coopen: open finished\n");
576 #endif DEBUG
577 CO_TTYUNLOCK(tp, tplock);
578 return(retval);
579 #endif /* MACH_KERNEL */
580 }
581
582 /*
583 * To "close" an CO channel, we need to kill off the read that is
584 * pending all the time. If the TS_HUPCLS flag is set,
585 * the RTS and DTR lines are turned off after all of the output queues are
586 * flushed. Note: ttyclose makes tp->t_state = 0;
587 *
588 * NOTE: The driver will get called on every close and must keep track
589 * of when last close happens to know when to call linesw close.
590 */
591 /*ARGSUSED*/
592 coclose(dev, flag)
593 dev_t dev;
594 int flag;
595 {
596 register struct tty *tp;
597 register struct co_state *softp;
598 register unit;
599 spl_t tplock;
600
601 #ifdef DEBUG
602 if(co_debug>2)
603 printf("co_close dev=%x\n", dev);
604 else if(co_debug)
605 printf("C");
606 #endif DEBUG
607 unit = minor(dev);
608 if (unit & CO_FLAG)
609 softp = co_costate;
610 else {
611 softp = &co_state[unit];
612 assert(unit <= co_max_unit);
613 assert(softp->ss_alive == 1);
614 }
615
616 tp = &softp->ss_tty;
617 tplock = CO_TTYLOCK(tp);
618 #ifdef MACH_KERNEL
619 #else /* MACH_KERNEL */
620 if(--tp->t_nopen > 0 || (tp->t_state&TS_LCLOSE)) {
621 CO_TTYUNLOCK(tp, tplock);
622 return;
623 }
624 assert(tp->t_nopen>=0);
625 tp->t_state |= TS_LCLOSE;
626 (*linesw[tp->t_line].l_close)(tp);
627 #endif /* MACH_KERNEL */
628 if((tp->t_state & TS_ISOPEN) == 0 || (tp->t_state&TS_HUPCLS)) {
629 /*
630 * Turn h/w off on hupcls on last close (new line disc).
631 * Assumes all output flushed before here.
632 */
633 softp->os_smode.CM_FLAGS |= (SCONS_CLEAR_DTR |
634 SCONS_CLEAR_RTS );
635
636 softp->os_smode.CM_FLAGS &= ~(SCONS_SET_BREAK);
637 co_wset_modes(softp);
638 }
639 softp->is_restart_read = 0;
640 co_abort_read(softp);
641 ttyclose(tp);
642 CO_TTYUNLOCK(tp, tplock);
643 }
644
645 #ifdef MACH_KERNEL
646 coportdeath(dev, port)
647 dev_t dev;
648 mach_port_t port;
649 {
650 register struct co_state *softp;
651 register int unit;
652
653 unit = minor(dev);
654 if (unit & CO_FLAG)
655 softp = co_costate;
656 else {
657 softp = &co_state[unit];
658 assert(unit <= co_max_unit);
659 assert(softp->ss_alive==1);
660 }
661
662 return (tty_portdeath(&softp->ss_tty, port));
663 }
664
665 /*
666 * Standard read and write.
667 *
668 * Mutual exclusion: called procedures lock tp themselves.
669 */
670 coread(dev, ior)
671 dev_t dev;
672 io_req_t ior;
673 {
674 register struct co_state *softp;
675 register int unit;
676
677 unit = minor(dev);
678 if (unit & CO_FLAG)
679 softp = co_costate;
680 else {
681 softp = &co_state[unit];
682 assert(unit <= co_max_unit);
683 assert(softp->ss_alive==1);
684 }
685
686 return (char_read(&softp->ss_tty, ior));
687 }
688
689 cowrite(dev, ior)
690 dev_t dev;
691 io_req_t ior;
692 {
693 register struct co_state *softp;
694 register int unit;
695
696 unit = minor(dev);
697 if (unit & CO_FLAG)
698 softp = co_costate;
699 else {
700 softp = &co_state[unit];
701 assert(unit <= co_max_unit);
702 assert(softp->ss_alive==1);
703 }
704
705 return (char_write(&softp->ss_tty, ior));
706 }
707 #else /* MACH_KERNEL */
708 /*
709 * Standard read.
710 *
711 * Mutual exclusion: called procedures assume locked tp.
712 */
713 coread(dev, uio)
714 register dev_t dev;
715 register struct uio *uio;
716 {
717 register struct co_state *softp;
718 register struct tty *tp;
719 register int retval;
720 int unit;
721 spl_t tplock;
722
723 #ifdef DEBUG
724 if(co_debug)
725 printf("r");
726 #endif DEBUG
727 unit = minor(dev);
728 if (unit & CO_FLAG)
729 softp = co_costate;
730 else {
731 softp = &co_state[unit];
732 assert(unit <= co_max_unit);
733 assert(softp->ss_alive==1);
734 }
735
736
737
738 tp = &softp->ss_tty;
739 tplock = CO_TTYLOCK(tp);
740 retval = ((*(linesw[tp->t_line].l_read))(tp, uio));
741 CO_TTYUNLOCK(tp, tplock);
742 return(retval);
743 }
744
745 /*
746 * Standard write.
747 *
748 * Mutual exclusion: called procedures assume locked tp.
749 */
750 cowrite(dev, uio)
751 register dev_t dev;
752 register struct uio *uio;
753 {
754 register struct co_state *softp;
755 register struct tty *tp;
756 register int retval;
757 int unit;
758 spl_t tplock;
759
760 #ifdef DEBUG
761 if(co_debug)
762 printf("w");
763 #endif DEBUG
764
765 unit = minor(dev);
766 if (unit & CO_FLAG)
767 softp = co_costate;
768 else {
769 softp = &co_state[unit];
770 assert(unit <= co_max_unit);
771 assert(softp->ss_alive == 1);
772 }
773
774 tp = &softp->ss_tty;
775 if (!tp)
776 panic("null tp");
777 tplock = CO_TTYLOCK(tp);
778 retval = ((*(linesw[tp->t_line].l_write))(tp, uio));
779 CO_TTYUNLOCK(tp, tplock);
780 return(retval);
781 }
782 #endif /* MACH_KERNEL */
783
784 #if MACH_KDB
785 /*
786 * Console input for ddb.
787 */
788
789 #define CNDEBUG 0
790
791 char * cnbptr = 0; /* console buffer pointer - current character */
792 int cncount = 0; /* number of characters in buffer */
793 boolean_t
794 cnpolling = FALSE;
795 /* polling switch for interrupt handler */
796
797 /*
798 * Return character from console, or -1 if none available.
799 */
800 int
801 cnmaygetc()
802 {
803 register struct co_state *softp;
804 register struct sec_dev_prog *completion;
805 register int status;
806 int c;
807
808 softp = co_costate;
809
810 if (cncount == 0) {
811 /*
812 * No characters. Check for input.
813 */
814 if (CO_TEST_Q_EMPTY(&softp->is_doneq))
815 return -1; /* no input */
816
817 #if CNDEBUG
818 printf("*c");
819 #endif
820 completion = CO_GET_Q_TAIL(&softp->is_doneq);
821 status = (int)completion->dp_status1;
822 if (!(status & SCONS_FLUSHED)) {
823 /* Have more characters. */
824 cnbptr = softp->is_buffer;
825 cncount = completion->dp_count;
826 #if CNDEBUG
827 printf("%d",cncount);
828 #endif
829 }
830 else {
831 cncount = 0;
832 #if CNDEBUG
833 printf("%#x",status);
834 #endif
835 }
836 CO_INCR_Q_TAIL(&softp->is_doneq);
837 #if CNDEBUG
838 printf("*i");
839 #endif
840
841 if (cncount == 0) {
842 /* still do not have any characters */
843 #if CNDEBUG
844 printf("*s");
845 #endif
846 co_start_read(softp);
847 return;
848 }
849 }
850
851 c = *cnbptr++;
852 if (--cncount == 0) {
853 /*
854 * No more characters in buffer - restart read.
855 */
856 #if CNDEBUG
857 printf("*s");
858 #endif
859 co_start_read(softp);
860 }
861 return c;
862 }
863
864 /*
865 * Return character from console.
866 * Wait until one appears.
867 */
868 int
869 cngetc()
870 {
871 register int c;
872
873 while ((c = cnmaygetc()) == -1)
874 continue;
875 return c;
876 }
877
878 /*
879 * Turn console polling input on or off.
880 */
881 cnpollc(on)
882 boolean_t on;
883 {
884 register struct co_state *softp;
885
886 softp = co_costate;
887
888 #if CNDEBUG
889 printf("*a%d",on);
890 #endif
891 if (on) {
892 /* Disable console interrupts before aborting read. */
893
894 cnpolling = TRUE;
895
896 co_abort_read(softp);
897
898 /* no characters in buffer. Start read. */
899 cnbptr = 0;
900 cncount = 0;
901 #if CNDEBUG
902 printf("*s");
903 #endif
904 co_start_read(softp);
905 }
906 else {
907 co_abort_read(softp);
908
909 /* Restart read for user if TTY open. */
910 if (softp->is_restart_read)
911 co_start_read(softp);
912
913 /* Enable console interrupts after restarting read. */
914 cnpolling = FALSE;
915 }
916 }
917
918 int cnescape = 0; /* escape character was last */
919
920 #endif MACH_KDB
921
922 cointr(vector)
923 int vector;
924 {
925 register int count;
926 register caddr_t bptr;
927 register int status;
928 register struct tty *tp;
929 register struct co_state *softp;
930 int unit;
931 spl_t tplock;
932 int is_read;
933 struct sec_dev_prog *completion;
934
935 unit = (vector - co_base_vec)/2;
936 is_read = (((vector - co_base_vec) % 2) == 0);
937 softp = &co_state[unit];
938
939 if (unit < 0 || unit > co_max_unit) {
940 printf("co: stray interrupt, unit out of range %x\n",unit);
941 return;
942 }
943
944 if (softp->ss_alive == 0) {
945 printf("co: stray interrupt, dead unit %x\n", unit);
946 return;
947 }
948
949 #if MACH_KDB
950 /* Ignore interrupt if polling input from console. */
951 if (softp == co_costate && cnpolling)
952 return;
953 #endif MACH_KDB
954 #ifdef DEBUG
955 if (co_debug)
956 printf("C");
957 #endif DEBUG
958
959 tp = &softp->ss_tty;
960 tplock = CO_TTYLOCK(tp);
961
962 if (is_read) {
963 while (!CO_TEST_Q_EMPTY(&softp->is_doneq)) {
964 completion = CO_GET_Q_TAIL(&softp->is_doneq);
965 status = (int)completion->dp_status1;
966 #ifdef DEBUG
967 if (co_debug)
968 printf("I");
969 if (co_debug > 1)
970 printf("%x ", status);
971 #endif DEBUG
972
973 if(status & SCONS_CARR_DET) {
974 co_get_modes(softp);
975 if (softp->os_smode.CM_FLAGS & SCONS_CARRIER_CLEAR) {
976 #ifdef MACH_KERNEL
977 (void) ttymodem(tp, 0);
978 #else /* MACH_KERNEL */
979 if (tp->t_state & TS_CARR_ON) {
980 tp->t_state &= ~TS_CARR_ON;
981 if(((tp->t_state&TS_WOPEN) == 0)
982 &&(tp->t_state&TS_ISOPEN)
983 &&((tp->t_flags&NOHANG) == 0)) {
984 gsignal(tp->t_pgrp, SIGHUP);
985 gsignal(tp->t_pgrp, SIGCONT);
986 ttyflush(tp, FREAD|FWRITE);
987 }
988 }
989 #endif /* MACH_KERNEL */
990 } else {
991 #ifdef MACH_KERNEL
992 (void) ttymodem(tp, 1);
993 #else /* MACH_KERNEL */
994 if ((tp->t_state & TS_CARR_ON) == 0) {
995 tp->t_state |= TS_CARR_ON;
996 vall_sema(&tp->t_rawqwait);
997 }
998 #endif /* MACH_KERNEL */
999 }
1000 }
1001 if (!(status & SCONS_FLUSHED)) {
1002 if(status & SCONS_PARITY_ERR)
1003 softp->is_parc++;
1004 if(status & SCONS_OVRFLOW)
1005 softp->is_ovc++;
1006 if(status & SCONS_BREAK_DET)
1007 #ifdef MACH_KERNEL
1008 ttyinput(tp->t_breakc, tp);
1009 #else /* MACH_KERNEL */
1010 if(tp->t_flags&RAW)
1011 (*linesw[tp->t_line].l_rint)(0, tp);
1012 else
1013 (*linesw[tp->t_line].l_rint)(tp->t_intrc, tp);
1014 #endif /* MACH_KERNEL */
1015 count = completion->dp_count;
1016 #ifdef DEBUG
1017 if (co_debug > 1)
1018 printf("%x\n", count);
1019 #endif DEBUG
1020 bptr = softp->is_buffer;
1021 while(count-- > 0) {
1022 #if MACH_KDB
1023 #define CNESC ('_' & 077)
1024 {
1025 register int c;
1026
1027 c = *bptr++;
1028
1029 if (cnescape) {
1030 cnescape = 0;
1031 switch (c & 0177) {
1032 case CNESC:
1033 /* Escaped escape character. */
1034 /* Use it. */
1035 break;
1036
1037 case 'k':
1038 case 'K':
1039 /* Kernel debugger keyboard intr. */
1040 simple_unlock(&tp->t_lock);
1041 kdb_kintr();
1042 splx(tplock);
1043 return;
1044
1045 default:
1046 /* Any other character. Queue the */
1047 /* delayed escape character, then */
1048 /* the current character. */
1049 ttyinput(CNESC, tp);
1050 break;
1051 }
1052 }
1053 else if ((c & 0177) == CNESC) {
1054 cnescape = 1;
1055 continue;
1056 }
1057 ttyinput(c, tp);
1058 }
1059 #else MACH_KDB
1060
1061 #ifdef DEBUG
1062 /*
1063 * Handle debug stuff.
1064 */
1065
1066 if (gc_last == DBGCHAR) {
1067 gc_last = '\0';
1068 debugit(*bptr);
1069 } else {
1070 gc_last = *bptr;
1071 if (*bptr != DBGCHAR)
1072 (*linesw[tp->t_line].l_rint)(*bptr, tp);
1073 }
1074 bptr++;
1075 #else !DEBUG
1076
1077 #ifdef MACH_KERNEL
1078 ttyinput(*bptr, tp);
1079 #else /* MACH_KERNEL */
1080 (*linesw[tp->t_line].l_rint)(*bptr, tp);
1081 #endif /* MACH_KERNEL */
1082 bptr++;
1083 #endif DEBUG
1084 #endif MACH_KDB
1085 }
1086 }
1087 CO_INCR_Q_TAIL(&softp->is_doneq);
1088 }
1089 if(softp->is_restart_read)
1090 co_start_read(softp);
1091 } else {
1092 while (!CO_TEST_Q_EMPTY(&softp->os_doneq)) {
1093 completion = CO_GET_Q_TAIL(&softp->os_doneq);
1094 status = (int)completion->dp_status1;
1095 count = completion->dp_count;
1096 #ifdef DEBUG
1097 if (co_debug)
1098 printf("O");
1099 if (co_debug > 1)
1100 printf("%x %x\n", status, count);
1101 #endif DEBUG
1102
1103 tp->t_state &= ~TS_BUSY;
1104
1105 if(tp->t_state&TS_FLUSH)
1106 tp->t_state &= ~TS_FLUSH;
1107 else
1108 ndflush(&tp->t_outq, count);
1109
1110 CO_INCR_Q_TAIL(&softp->os_doneq);
1111
1112 #ifdef MACH_KERNEL
1113 #else /* MACH_KERNEL */
1114 if(tp->t_line)
1115 (*linesw[tp->t_line].l_start)(tp);
1116 else
1117 #endif /* MACH_KERNEL */
1118 costart(tp);
1119 }
1120 }
1121 CO_TTYUNLOCK(tp, tplock);
1122 }
1123
1124 #ifdef MACH_KERNEL
1125 cogetstat(dev, flavor, data, count)
1126 dev_t dev;
1127 int flavor;
1128 int * data; /* pointer to OUT array */
1129 unsigned int *count; /* out */
1130 {
1131 register int unit;
1132 register struct tty *tp;
1133 register struct co_state *softp;
1134
1135 unit = minor(dev);
1136 if (unit & CO_FLAG)
1137 softp = co_costate;
1138 else {
1139 softp = &co_state[unit];
1140 assert(unit <= co_max_unit);
1141 assert(softp->ss_alive == 1);
1142 }
1143
1144 return (tty_get_status(&softp->ss_tty, flavor, data, count));
1145 }
1146
1147 cosetstat(dev, flavor, data, count)
1148 dev_t dev;
1149 int flavor;
1150 int * data;
1151 unsigned int count;
1152 {
1153 register int unit;
1154 register struct tty *tp;
1155 register struct co_state *softp;
1156 spl_t tplock;
1157
1158 unit = minor(dev);
1159 if (unit & CO_FLAG)
1160 softp = co_costate;
1161 else {
1162 softp = &co_state[unit];
1163 assert(unit <= co_max_unit);
1164 assert(softp->ss_alive == 1);
1165 }
1166
1167 tp = &softp->ss_tty;
1168 tplock = CO_TTYLOCK(tp);
1169
1170 switch (flavor) {
1171 case TTY_MODEM:
1172 if ((*data & TM_DTR) != 0) {
1173 if (softp->os_smode.CM_FLAGS & (SCONS_CLEAR_DTR |
1174 SCONS_CLEAR_RTS)) {
1175 softp->os_smode.CM_FLAGS &= ~(SCONS_CLEAR_DTR |
1176 SCONS_CLEAR_RTS);
1177 co_wset_modes(softp);
1178 }
1179 }
1180 else if ((*data & TM_DTR) == 0) {
1181 if ((softp->os_smode.CM_FLAGS & (SCONS_CLEAR_DTR |
1182 SCONS_CLEAR_RTS)) == 0) {
1183 softp->os_smode.CM_FLAGS |= (SCONS_CLEAR_DTR |
1184 SCONS_CLEAR_RTS);
1185 co_wset_modes(softp);
1186 }
1187 }
1188 break;
1189 case TTY_SET_BREAK:
1190 softp->os_smode.CM_FLAGS |= SCONS_SET_BREAK;
1191 co_wset_modes(softp);
1192 break;
1193 case TTY_CLEAR_BREAK:
1194 softp->os_smode.CM_FLAGS &= ~SCONS_SET_BREAK;
1195 co_wset_modes(softp);
1196 break;
1197 default:
1198 CO_TTYUNLOCK(tp, tplock);
1199 return (tty_get_status(&softp->ss_tty, flavor, data, count));
1200 }
1201 CO_TTYUNLOCK(tp, tplock);
1202 return (D_SUCCESS);
1203 }
1204
1205 #else /* MACH_KERNEL */
1206 /*
1207 * stioctl - io controls
1208 *
1209 * Mutex: assumes called with a non-locked tp.
1210 */
1211 coioctl(dev, cmd, data, flag)
1212 dev_t dev;
1213 register cmd;
1214 int flag;
1215 caddr_t data;
1216 {
1217 register struct tty *tp;
1218 register error;
1219 register int unit;
1220 register struct co_state *softp;
1221 spl_t tplock;
1222
1223 #ifdef DEBUG
1224 if(co_debug)
1225 printf("coioctl: dev=0x%x, cmd=0x%x, flag=0x%x, data=0x%x\n",
1226 dev, cmd, flag, data);
1227 #endif DEBUG
1228
1229 unit = minor(dev);
1230 if (unit & CO_FLAG)
1231 softp = co_costate;
1232 else {
1233 softp = &co_state[unit];
1234 assert(unit <= co_max_unit);
1235 assert(softp->ss_alive == 1);
1236 }
1237
1238 tp = &softp->ss_tty;
1239
1240 tplock = CO_TTYLOCK(tp);
1241
1242 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
1243 if(error >= 0) {
1244 CO_TTYUNLOCK(tp, tplock);
1245 return(error);
1246 }
1247
1248 error = ttioctl(tp, cmd, data, flag);
1249 if(error >= 0) {
1250 if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
1251 cmd == TIOCLBIC || cmd == TIOCLSET)
1252 co_param(softp);
1253 CO_TTYUNLOCK(tp, tplock);
1254 return(error);
1255 }
1256
1257 /*
1258 * Process special stuff...
1259 */
1260 error = 0;
1261 switch(cmd) {
1262 case TIOCSBRK: /* set break on */
1263 softp->os_smode.CM_FLAGS |= SCONS_SET_BREAK;
1264 co_wset_modes(softp);
1265 break;
1266 case TIOCCBRK: /* clear break off */
1267 softp->os_smode.CM_FLAGS &= ~SCONS_SET_BREAK;
1268 co_wset_modes(softp);
1269 break;
1270 case TIOCSDTR: /* Turn on dtr rts */
1271 softp->os_smode.CM_FLAGS &= ~(SCONS_CLEAR_DTR | SCONS_CLEAR_RTS);
1272 co_wset_modes(softp);
1273 break;
1274 case TIOCCDTR: /* turn off dtr rts */
1275 softp->os_smode.CM_FLAGS |= (SCONS_CLEAR_DTR | SCONS_CLEAR_RTS);
1276 co_wset_modes(softp);
1277 break;
1278 default:
1279 error = ENOTTY;
1280 }
1281 CO_TTYUNLOCK(tp, tplock);
1282 return(error);
1283 }
1284
1285
1286
1287 /*
1288 * coselect
1289 *
1290 * Mutual exclusion: called procedures assume locked tp.
1291 */
1292 coselect(dev, rw)
1293 dev_t dev;
1294 int rw;
1295 {
1296 register struct tty *tp;
1297 int retval;
1298 spl_t tplock;
1299 int unit;
1300
1301 unit = minor(dev);
1302 if (unit & CO_FLAG)
1303 tp = &co_costate->ss_tty;
1304 else
1305 tp = &co_state[unit].ss_tty;
1306 tplock = CO_TTYLOCK(tp);
1307 #ifndef MACH
1308 retval = (*linesw[tp->t_line].l_select)(tp, rw);
1309 #else
1310 retval = tpselect(tp, rw);
1311 #endif MACH
1312 CO_TTYUNLOCK(tp, tplock);
1313 return(retval);
1314 }
1315 #endif /* MACH_KERNEL */
1316
1317 /*
1318 * This table defines the CO command bits for setting asynchronous
1319 * baud rates. '-1' is the signal to turn off the DTR and RTS signals.
1320 * '-2' indicates that a baud rate is not available on the CO. The
1321 * 'Mxxx' entries are for the 'rate' parameter in calls to co_setmodes();
1322 */
1323
1324
1325 /*
1326 * co_param - set line parameters on the hardware.
1327 *
1328 * Mutex: assumed called with locked tp to insure stable data
1329 * being read.
1330 */
1331 co_param(softp)
1332 register struct co_state *softp;
1333 {
1334 register struct tty *tp;
1335 u_char lpar, len, stop, parflag;
1336
1337 #ifdef DEBUG
1338 if(co_debug>1)
1339 printf(" co_param: enter ");
1340 else if(co_debug)
1341 printf("P");
1342 #endif DEBUG
1343
1344 tp = &softp->ss_tty;
1345
1346 if(tp->t_ispeed == 0) {
1347 tp->t_state |= TS_HUPCLS;
1348 softp->os_smode.CM_FLAGS |= (SCONS_CLEAR_DTR |
1349 SCONS_CLEAR_RTS);
1350 softp->os_smode.CM_FLAGS &= ~(SCONS_SET_BREAK);
1351 co_wset_modes(softp);
1352 return;
1353 }
1354
1355 if (tp->t_flags & (RAW|LITOUT|PASS8)) {
1356 len = SCONS_DATA8;
1357 parflag = 0;
1358 } else {
1359 len = SCONS_DATA7;
1360 parflag = 1;
1361 }
1362 lpar = 0;
1363 if (parflag)
1364 if ((tp->t_flags&EVENP) == 0)
1365 lpar = SCONS_ODD_PARITY;
1366 else
1367 lpar = SCONS_EVEN_PARITY;
1368 if ((tp->t_ospeed) == B110)
1369 stop = SCONS_STOP2;
1370 else
1371 stop = SCONS_STOP1;
1372
1373 softp->os_smode.CM_BAUD = tp->t_ospeed;
1374 softp->os_smode.CM_FLAGS &= ~(SCONS_STOP1P5 | SCONS_STOP2 |
1375 SCONS_DATA7 |
1376 SCONS_EVEN_PARITY |
1377 SCONS_ODD_PARITY);
1378 softp->os_smode.CM_FLAGS |= (stop | len | lpar);
1379 co_wset_modes(softp);
1380 }
1381 int ttrstrt();
1382
1383 /*
1384 * costart - start a character out on the interface.
1385 *
1386 * This procedure starts a character out by calculating the maximum
1387 * number of characters it can get from the clist and then programming
1388 * the scsi to send that many characters from the clist.
1389 * When the device program completes there will
1390 * be included in the completion a byte count which is what was transmitted.
1391 *
1392 * Assumes: caller locks the tp before calling costart().
1393 */
1394 costart(tp)
1395 register struct tty *tp;
1396 {
1397 register int nch;
1398 register struct co_state *softp;
1399 u_char *addr;
1400
1401 /*
1402 * If the channel is already working, or if it is waiting on
1403 * a delay, then nothing is done right now.
1404 */
1405 #ifdef DEBUG
1406 if(co_debug>1)
1407 printf("c\n");
1408 #endif DEBUG
1409
1410 if(tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) {
1411 return;
1412 }
1413
1414 /*
1415 * let those wanting to do setmodes get a chance first.
1416 */
1417
1418 softp = (struct co_state *)tp->t_addr;
1419 if(softp->os_busy_flag) {
1420 softp->os_busy_flag = 0;
1421 vall_sema(&softp->os_busy_wait);
1422 return;
1423 }
1424
1425 /*
1426 * If the output queue has emptied to the low threshold, and
1427 * if anyone is sleeping on this queue, wake them up.
1428 */
1429
1430 if(tp->t_outq.c_cc <= TTLOWAT(tp)) {
1431 #ifdef MACH_KERNEL
1432 tt_write_wakeup(tp);
1433 #else /* MACH_KERNEL */
1434 if(tp->t_state & TS_ASLEEP) {
1435 tp->t_state &= ~TS_ASLEEP;
1436 vall_sema(&tp->t_outqwait);
1437 }
1438 if(tp->t_wsel) {
1439 selwakeup(tp->t_wsel, tp->t_state&TS_WCOLL);
1440 tp->t_state &= ~TS_WCOLL;
1441 tp->t_wsel = (struct proc *)NULL;
1442 }
1443 #endif /* MACH_KERNEL */
1444 }
1445
1446 if(tp->t_outq.c_cc == 0) { /* Nothing to process */
1447 return;
1448 }
1449
1450
1451 /*
1452 * Dma from clist direct.
1453 *
1454 * Find where on clist and tell board to dma from there. When the interrupt
1455 * comes in that signals the block output done all we have to do
1456 * is ndflush the clist which is much less overhead then many getc's.
1457 */
1458 if(tp->t_flags & (RAW|LITOUT))
1459 nch = ndqb(&tp->t_outq, 0);
1460 else{
1461 /*
1462 * not raw so check for timeout chars and if we
1463 * have dma'd out to one then do the timeout.
1464 */
1465 nch = ndqb(&tp->t_outq, 0200);
1466 if(nch==0) {
1467 nch = getc(&tp->t_outq);
1468 timeout(ttrstrt, (caddr_t)tp, ((nch & 0x7f) + 6));
1469 tp->t_state |= TS_TIMEOUT;
1470 return;
1471 }
1472 }
1473
1474 addr = (u_char *)tp->t_outq.c_cf;
1475 #ifdef MACH_KERNEL
1476 /*
1477 * Copy characters from the circular buffer to the output
1478 * buffer. The circular buffer may not be within SCED space.
1479 */
1480 if (nch > CBSIZE)
1481 nch = CBSIZE;
1482 bcopy((char *)addr, softp->os_buffer, nch);
1483 addr = (u_char *)softp->os_buffer;
1484 #endif /* MACH_KERNEL */
1485 #ifdef DEBUG
1486 if(co_debug>2)
1487 printf("BO: %d\n", nch);
1488 else if(co_debug)
1489 printf("X");
1490 #endif DEBUG
1491 assert(((nch>0) && (nch<=CBSIZE)));
1492 co_start_write(softp, nch, addr);
1493 tp->t_state |= TS_BUSY;
1494 }
1495
1496 /*
1497 * costop - Abort an in progress dma on a channel.
1498 *
1499 * This procedure aborts output on a line.
1500 * Curious note: No driver seems to ever use the flag parameter.
1501 *
1502 * Mutex: Assumes caller has locked the tp prior to
1503 * calling this procedure.
1504 */
1505 /*ARGSUSED*/
1506 costop(tp, flag)
1507 register struct tty *tp;
1508 {
1509 register struct co_state *softp;
1510
1511 #ifdef DEBUG
1512 if(co_debug)
1513 printf("S");
1514 #endif DEBUG
1515
1516 if (tp->t_state & TS_BUSY) {
1517 /*
1518 * Device is transmitting; stop output.
1519 * We will clean up later
1520 * by examining the xfer count for a completion.
1521 *
1522 * The TS_FLUSH flag is used to tell us HOW to clean
1523 * up. If it is set, the characters have
1524 * aleady been cleaned off the t_outq by ttyflush().
1525 * Otherwise, we need to clean off the ones that have
1526 * been transmitted.
1527 */
1528 if ((tp->t_state&TS_TTSTOP)==0)
1529 tp->t_state |= TS_FLUSH;
1530
1531 softp = (struct co_state *)tp->t_addr;
1532 co_abort_write(softp);
1533 }
1534 }
1535
1536
1537
1538 /*
1539 * co_start_write -queue a write request to the output channel.
1540 *
1541 * assume request queue and status are locked prior to entry
1542 * also assumes that the request queue is not full.
1543 */
1544 co_start_write(softp, nch, addr)
1545 register struct co_state *softp;
1546 register int nch;
1547 register u_char *addr;
1548 {
1549 register struct sec_dev_prog *request;
1550
1551 request = CO_GET_Q_HEAD(&softp->os_reqq);
1552 request->dp_status1 = 0;
1553 request->dp_count = 0;
1554 request->dp_un.dp_data = KVTOPHYS(addr, u_char *);
1555 request->dp_data_len = nch;
1556 request->dp_next = (struct sec_dev_prog*)0;
1557 CO_INCR_Q_HEAD(&softp->os_reqq);
1558 sec_startio(SINST_STARTIO, &softp->os_status, softp->os_sd);
1559 if (softp->os_status & (~SINST_INSDONE))
1560 printf("co: bad start_write: %x\n", softp->os_status);
1561 }
1562
1563 /*
1564 * co_start_read -queue a read request to the output channel.
1565 *
1566 * assume request queue and status are locked prior to entry
1567 * also assumes that the request queue is not full.
1568 */
1569 co_start_read(softp)
1570 register struct co_state * softp;
1571 {
1572 register struct sec_dev_prog *request;
1573
1574 request = CO_GET_Q_HEAD(&softp->is_reqq);
1575 request->dp_status1 = 0;
1576 request->dp_count = 0;
1577 request->dp_un.dp_data = KVTOPHYS(softp->is_buffer, u_char *);
1578 request->dp_data_len = CBSIZE;
1579 request->dp_next = (struct sec_dev_prog*)0;
1580 CO_INCR_Q_HEAD(&softp->is_reqq);
1581 sec_startio(SINST_STARTIO, &softp->is_status, softp->is_sd);
1582 if (softp->is_status & (~SINST_INSDONE))
1583 printf("co: bad start_read: %x\n", softp->is_status);
1584 }
1585
1586 /*
1587 * co_wset_modes - set console modes.
1588 *
1589 * This procedure assumes that access to the os_smode structure and
1590 * to the cib are locked. It waits until the transmitting channel is
1591 * not busy, then does the set modes. This ensures that the last of
1592 * previous output has gone to the display before changing anything.
1593 */
1594 co_wset_modes(softp)
1595 register struct co_state *softp;
1596 {
1597 register struct tty *tp;
1598
1599 tp = &softp->ss_tty;
1600 while (tp->t_state & TS_BUSY) {
1601 softp->os_busy_flag = 1;
1602 #ifdef MACH_KERNEL
1603 p_sema_v_lock(&softp->os_busy_wait, 0, &tp->t_lock, SPLTTY);
1604 #else /* MACH_KERNEL */
1605 p_sema_v_lock(&softp->os_busy_wait, TTIPRI, &tp->t_ttylock, SPLTTY);
1606 #endif MACH_KERNEL
1607 (void) CO_TTYLOCK(tp);
1608 }
1609
1610 sec_startio(SINST_SETMODE, &softp->os_smode.sm_status, softp->os_sd);
1611 if (softp->os_smode.sm_status & (~SINST_INSDONE))
1612 printf("co: bad set_mode: %x\n", softp->os_smode.sm_status);
1613 #ifdef DEBUG
1614 if (co_debug > 1)
1615 printf("setmode done flags %x, baud %x\n",
1616 softp->os_smode.CM_FLAGS, softp->os_smode.CM_BAUD);
1617 #endif DEBUG
1618 costart(tp);
1619 }
1620
1621 /*
1622 * co_get_modes - get console modes.
1623 *
1624 * This procedure assumes that access to the os_smode structure and
1625 * to the cib are locked.
1626 */
1627 co_get_modes(softp)
1628 register struct co_state *softp;
1629 {
1630 sec_startio(SINST_GETMODE, &softp->os_smode.sm_status, softp->os_sd);
1631 if (softp->os_smode.sm_status & (~SINST_INSDONE))
1632 printf("co: bad get_mode: %x\n", softp->os_smode.sm_status);
1633 #ifdef DEBUG
1634 if (co_debug > 1)
1635 printf("getmode done flags %x, baud %x\n",
1636 softp->os_smode.CM_FLAGS, softp->os_smode.CM_BAUD);
1637 #endif DEBUG
1638 }
1639
1640
1641
1642 /*
1643 * co_abort_write - abort any pending or current write device programs
1644 *
1645 * This procedure assumes that access to the output structures are locked.
1646 */
1647 co_abort_write(softp)
1648 register struct co_state *softp;
1649 {
1650 sec_startio(SINST_FLUSHQUEUE, &softp->os_status, softp->os_sd);
1651 if (softp->os_status & (~SINST_INSDONE))
1652 printf("co: bad abort_write: %x\n", softp->os_status);
1653 }
1654
1655 /*
1656 * co_abort_read - abort any pending or current read device programs
1657 *
1658 * This procedure assumes that access to the output structures are locked.
1659 */
1660 co_abort_read(softp)
1661 register struct co_state *softp;
1662 {
1663 sec_startio(SINST_FLUSHQUEUE, &softp->is_status, softp->is_sd);
1664 if (softp->is_status & (~SINST_INSDONE))
1665 printf("co: bad abort_read: %x\n", softp->is_status);
1666 }
1667
1668 /*
1669 * Program queue management routines. These may be candidates for
1670 * implementation as macros. Or, they may be moved in line and
1671 * implemented more efficiently later.
1672 *
1673 * CO_TEST_Q_EMPTY - return true if program queue is empty
1674 */
1675
1676 CO_TEST_Q_EMPTY(sq)
1677 struct sec_pq *sq;
1678 {
1679 struct sec_progq *pq;
1680
1681 pq = sq->sq_progq;
1682 assert(pq->pq_tail < sq->sq_size);
1683 assert(pq->pq_head < sq->sq_size);
1684
1685 return(pq->pq_head == pq->pq_tail);
1686 }
1687
1688 /*
1689 * CO_GET_Q_HEAD - return pointer to first available "empty" device
1690 * program.
1691 */
1692
1693 struct sec_dev_prog *
1694 CO_GET_Q_HEAD(sq)
1695 struct sec_pq *sq;
1696 {
1697 struct sec_progq *pq;
1698
1699 pq = sq->sq_progq;
1700 assert(pq->pq_tail < sq->sq_size);
1701 assert(pq->pq_head < sq->sq_size);
1702
1703 return(PHYSTOKV(pq->pq_un.pq_progs[pq->pq_head],
1704 struct sec_dev_prog *));
1705 }
1706
1707 /*
1708 * CO_INCR_Q_HEAD - increment the head of the queue, thus adding a
1709 * device program to the request queue.
1710 */
1711
1712 CO_INCR_Q_HEAD(sq)
1713 struct sec_pq *sq;
1714 {
1715 struct sec_progq *pq;
1716
1717 pq = sq->sq_progq;
1718 assert(pq->pq_tail < sq->sq_size);
1719 assert(pq->pq_head < sq->sq_size);
1720
1721 pq->pq_head = (pq->pq_head + 1) % sq->sq_size;
1722 }
1723
1724 /*
1725 * CO_GET_Q_TAIL - return pointer to first completed device
1726 * program.
1727 */
1728
1729 struct sec_dev_prog *
1730 CO_GET_Q_TAIL(sq)
1731 struct sec_pq *sq;
1732 {
1733 struct sec_progq *pq;
1734
1735 pq = sq->sq_progq;
1736 assert(pq->pq_tail < sq->sq_size);
1737 assert(pq->pq_head < sq->sq_size);
1738
1739 return(PHYSTOKV(pq->pq_un.pq_progs[pq->pq_tail],
1740 struct sec_dev_prog *));
1741 }
1742
1743 /*
1744 * CO_INCR_Q_TAIL - increment the tail of the queue, thus deleting a
1745 * device program to the completion queue.
1746 */
1747
1748 CO_INCR_Q_TAIL(sq)
1749 struct sec_pq *sq;
1750 {
1751 struct sec_progq *pq;
1752
1753 pq = sq->sq_progq;
1754 assert(pq->pq_tail < sq->sq_size);
1755 assert(pq->pq_head < sq->sq_size);
1756
1757 pq->pq_tail = (pq->pq_tail + 1) % sq->sq_size;
1758 }
Cache object: d479a1055914e8e937ebc562b05f7615
|