1 /*
2  * Copyright (c) 1992 The Regents of the University of California.
3  * All rights reserved.
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  *	@(#)kbms_if.c	7.1 (Berkeley) 06/04/92
11  */
12 
13 /* Keyboard Mouse Gate-array control routine */
14 
15 #include "../include/fix_machine_type.h"
16 #include "../include/adrsmap.h"
17 
18 #include "ms.h"
19 #include "bm.h"
20 
21 #include "param.h"
22 #include "../sio/scc.h"
23 
24 #if defined(news1200) || defined(news3200)
25 #include "time.h"
26 #include "../iop/mouse.h"
27 #endif
28 
29 typedef struct kbm_sw {
30 	u_char *stat_port;	/* Status port */
31 	u_char *data_port;	/* Data port */
32 	u_char *intr_port;	/* Interrupt port */
33 	u_char *reset_port;	/* Reset port */
34 	u_char *init1_port;	/* Initialize port 1 */
35 	u_char *init2_port;	/* Initialize port 2 */
36 	u_char *buzz_port;	/* Buzzer port */
37 	u_char *buzzf_port;	/* Buzzer frequency port */
38 	u_char intr_en;		/* Data for Interrupt Enable */
39 	u_char intr_in;		/* Interrupt Occur flag */
40 	u_char data_rdy;	/* Data Ready flag */
41 	u_char init1;		/* Speed */
42 	u_char init2;		/* Clock */
43 	u_char buzzf;		/* Buzzer frequency */
44 } Kbm_sw;
45 
46 #define OFF 0x80
47 struct kbm_sw Kbm_port[] = {
48 	{
49 #ifdef news3400
50 		(u_char *) MOUSE_STAT,
51 #else
52 		(u_char *) KEYB_STAT,
53 #endif
54 		(u_char *) MOUSE_DATA,
55 		(u_char *) MOUSE_INTE,
56 		(u_char *) MOUSE_RESET,
57 		(u_char *) MOUSE_INIT1,
58 		(u_char *) MOUSE_INIT2,
59 		(u_char *) KEYB_BUZZ,
60 		(u_char *) KEYB_BUZZF,
61 		RX_MSINTE,
62 		RX_MSINT,
63 		RX_MSRDY,
64 #ifdef news3400
65 		0x80,	/* 1200 bps */
66 		0,
67 		0
68 #else
69 		1,
70 		0xe0,
71 		0x0a
72 #endif
73 	},
74 	{
75 		(u_char *) KEYB_STAT,
76 		(u_char *) KEYB_DATA,
77 		(u_char *) KEYB_INTE,
78 		(u_char *) KEYB_RESET,
79 		(u_char *) KEYB_INIT1,
80 		(u_char *) KEYB_INIT2,
81 		(u_char *) KEYB_BUZZ,
82 		(u_char *) KEYB_BUZZF,
83 		RX_KBINTE,
84 		RX_KBINT,
85 		RX_KBRDY,
86 #ifdef news3400
87 		0xf0,	/* 9600 bps */
88 		0,
89 		0
90 #else
91 		0,
92 		0xc0,
93 		0x0a
94 #endif
95 	}
96 };
97 
98 kbm_open(chan)
99 	int chan;
100 {
101 	register Kbm_sw *kbm = &Kbm_port[chan];
102 
103 #ifdef news3400
104 	/*
105 	 * Reset KB I/F.
106 	 * Disable KB interrupt.
107 	 * Clear KB overrun flag.
108 	 */
109 	*(volatile u_char *)kbm->reset_port = (u_char)0x01;
110 	*(volatile u_char *)kbm->init1_port = kbm->init1;
111 	if (chan == SCC_MOUSE)
112 		*(volatile u_char *)kbm->intr_port |= kbm->intr_en;
113 #else
114 	*kbm->reset_port = (u_char)0;
115 	*kbm->intr_port = (u_char)1;
116 #endif
117 #ifdef news1200
118 	*kbm->init1_port = kbm->init1;
119 	*kbm->init2_port = kbm->init2;
120 	*kbm->buzzf_port = kbm->buzzf;
121 #endif
122 	kbd_flush();
123 }
124 
125 kbm_close(chan)
126 	int chan;
127 {
128 	register Kbm_sw *kbm = &Kbm_port[chan];
129 
130 #ifdef news3400
131 	*(volatile u_char *)kbm->reset_port = (u_char)0x01;
132 #else
133 	*kbm->reset_port = (u_char)0;
134 	*kbm->intr_port = (u_char)0;
135 #endif
136 }
137 
138 kbm_rint(chan)
139 	int chan;
140 {
141 #ifdef news3400
142 	volatile u_char *port = (volatile u_char *)Kbm_port[chan].data_port;
143 	volatile u_char *stat = (volatile u_char *)Kbm_port[chan].stat_port;
144 	volatile u_char *inte = (volatile u_char *)Kbm_port[chan].intr_port;
145 #else
146 	register u_char *port = Kbm_port[chan].data_port;
147 	register u_char *stat = Kbm_port[chan].stat_port;
148 	register u_char *inte = Kbm_port[chan].intr_port;
149 #endif
150 	int rdy = Kbm_port[chan].data_rdy;
151 	u_char code;
152 
153 #ifdef news3400
154 	*inte &= ~Kbm_port[chan].intr_en;
155 #endif
156 
157 	while (*stat & rdy) {
158 		code = *port;
159 		switch (chan) {
160 		    case SCC_MOUSE: {
161 #if NMS > 0
162 			extern int _ms_helper();
163 
164 			if (xputc(code, SCC_MOUSE) < 0)
165 				printf("mouse queue overflow\n");
166 			/* KU:XXX softcall? */
167 			timeout(_ms_helper, (caddr_t)0, 0);
168 #endif
169 			break;
170 		    }
171 		    case SCC_KEYBOARD: {
172 #if NBM > 0
173 			extern int kb_softint();
174 
175 			if (xputc(code, SCC_KEYBOARD) < 0)
176 				printf("keyboard queue overflow\n");
177 			/* KU:XXX softcall? */
178 			timeout(kb_softint, (caddr_t)0, 0);
179 #endif
180 			break;
181 		    }
182 		    default:
183 			printf("kb or ms stray intr\n");
184 			break;
185 		}
186 	}
187 
188 #ifdef news3400
189 	*inte |= Kbm_port[chan].intr_en;
190 #else
191 	*inte = 1;
192 #endif
193 }
194 
195 
196 kbm_write(chan, buf, count)
197 	int chan;
198 	char *buf;
199 	register int count;
200 {
201 	register u_char *port = Kbm_port[chan].buzz_port;
202 	int c_save = count;
203 
204 #ifdef news1200
205 	*port = count;
206 #endif
207 
208 #ifdef news1700
209 	if (buf == NULL)
210 		while (--count >= 0)
211 			*port = 0xff;
212 	else
213 		while (--count >= 0)
214 			*port = *buf++;
215 #endif
216 
217 #ifdef news3400
218 	*port = count / 3;
219 #endif
220 
221 	return (c_save);
222 }
223 
224 int
225 kbm_getc(chan)
226 	int chan;
227 {
228 #ifdef news3400
229 	volatile u_char *port = (volatile u_char *)Kbm_port[chan].data_port;
230 	volatile u_char *stat = (volatile u_char *)Kbm_port[chan].stat_port;
231 #else
232 	register u_char *port = Kbm_port[chan].data_port;
233 	register u_char *stat = Kbm_port[chan].stat_port;
234 #endif
235 	int rdy = Kbm_port[chan].data_rdy;
236 
237 	if (*stat & rdy)
238 		return (*port & 0xff);
239 	else
240 		return (-1);
241 }
242