zs_ap.c revision 1.30 1 1.30 tsutsui /* $NetBSD: zs_ap.c,v 1.30 2018/10/19 13:40:33 tsutsui Exp $ */
2 1.1 tsubai
3 1.1 tsubai /*-
4 1.1 tsubai * Copyright (c) 1996 The NetBSD Foundation, Inc.
5 1.1 tsubai * All rights reserved.
6 1.1 tsubai *
7 1.1 tsubai * This code is derived from software contributed to The NetBSD Foundation
8 1.1 tsubai * by Gordon W. Ross.
9 1.1 tsubai *
10 1.1 tsubai * Redistribution and use in source and binary forms, with or without
11 1.1 tsubai * modification, are permitted provided that the following conditions
12 1.1 tsubai * are met:
13 1.1 tsubai * 1. Redistributions of source code must retain the above copyright
14 1.1 tsubai * notice, this list of conditions and the following disclaimer.
15 1.1 tsubai * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 tsubai * notice, this list of conditions and the following disclaimer in the
17 1.1 tsubai * documentation and/or other materials provided with the distribution.
18 1.1 tsubai *
19 1.1 tsubai * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 tsubai * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 tsubai * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 tsubai * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 tsubai * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 tsubai * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 tsubai * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 tsubai * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 tsubai * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 tsubai * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 tsubai * POSSIBILITY OF SUCH DAMAGE.
30 1.1 tsubai */
31 1.1 tsubai
32 1.1 tsubai /*
33 1.1 tsubai * Zilog Z8530 Dual UART driver (machine-dependent part)
34 1.1 tsubai *
35 1.1 tsubai * Runs two serial lines per chip using slave drivers.
36 1.1 tsubai * Plain tty/async lines use the zs_async slave.
37 1.1 tsubai * Sun keyboard/mouse uses the zs_kbd/zs_ms slaves.
38 1.1 tsubai */
39 1.16 lukem
40 1.16 lukem #include <sys/cdefs.h>
41 1.30 tsutsui __KERNEL_RCSID(0, "$NetBSD: zs_ap.c,v 1.30 2018/10/19 13:40:33 tsutsui Exp $");
42 1.1 tsubai
43 1.1 tsubai #include <sys/param.h>
44 1.1 tsubai #include <sys/systm.h>
45 1.1 tsubai #include <sys/device.h>
46 1.1 tsubai #include <sys/tty.h>
47 1.6 gehenna #include <sys/conf.h>
48 1.23 ad #include <sys/cpu.h>
49 1.23 ad #include <sys/intr.h>
50 1.29 tsutsui #ifdef NEWS4000_ZS_AP_POLLING
51 1.29 tsutsui #include <sys/callout.h>
52 1.29 tsutsui #endif
53 1.1 tsubai
54 1.1 tsubai #include <machine/adrsmap.h>
55 1.1 tsubai #include <machine/z8530var.h>
56 1.1 tsubai
57 1.1 tsubai #include <dev/cons.h>
58 1.1 tsubai #include <dev/ic/z8530reg.h>
59 1.1 tsubai
60 1.1 tsubai #include <newsmips/apbus/apbusvar.h>
61 1.1 tsubai
62 1.1 tsubai #include "zsc.h" /* NZSC */
63 1.1 tsubai #define NZS NZSC
64 1.1 tsubai
65 1.1 tsubai /* Make life easier for the initialized arrays here. */
66 1.1 tsubai #if NZS < 2
67 1.1 tsubai #undef NZS
68 1.1 tsubai #define NZS 2
69 1.1 tsubai #endif
70 1.1 tsubai
71 1.29 tsutsui #define NEWS5000_PORTB_TXPORT 0x00000000
72 1.29 tsutsui #define NEWS5000_PORTB_RXPORT 0x00010000
73 1.29 tsutsui #define NEWS5000_PORTA_TXPORT 0x00020000
74 1.29 tsutsui #define NEWS5000_PORTA_RXPORT 0x00030000
75 1.29 tsutsui #define NEWS5000_DMA_MODE_REG 3
76 1.29 tsutsui #define NEWS5000_DMA_ENABLE 0x01 /* DMA enable */
77 1.29 tsutsui #define NEWS5000_DMA_DIR_DM 0x00 /* device to memory */
78 1.29 tsutsui #define NEWS5000_DMA_DIR_MD 0x02 /* memory to device */
79 1.29 tsutsui #define NEWS5000_DMA_EXTRDY 0x08 /* DMA external ready */
80 1.29 tsutsui #define NEWS5000_PORTB_OFFSET 0x00040000
81 1.29 tsutsui #define NEWS5000_PORTA_OFFSET 0x00050000
82 1.29 tsutsui #define NEWS5000_PORT_CTL 2
83 1.29 tsutsui #define NEWS5000_PORTCTL_RI 0x01
84 1.29 tsutsui #define NEWS5000_PORTCTL_DSR 0x02
85 1.29 tsutsui #define NEWS5000_PORTCTL_DTR 0x04
86 1.29 tsutsui #define NEWS5000_PORT_SEL 3
87 1.29 tsutsui #define NEWS5000_PORTSEL_LOCALTALK 0x01
88 1.29 tsutsui #define NEWS5000_PORTSEL_RS232C 0x02
89 1.29 tsutsui #define NEWS5000_ESCC_REG 0x00060000
90 1.29 tsutsui #define NEWS5000_ESCCREG_INTSTAT 0
91 1.29 tsutsui #define NEWS5000_INTSTAT_SCC 0x01
92 1.29 tsutsui #define NEWS5000_ESCCREG_INTMASK 1
93 1.29 tsutsui #define NEWS5000_INTMASK_SCC 0x01
94 1.29 tsutsui
95 1.29 tsutsui #define NEWS4000_PORTB_TXPORT 0x00000000 /* XXX: not confirmed */
96 1.29 tsutsui #define NEWS4000_PORTB_RXPORT 0x00010000 /* XXX: not confirmed */
97 1.29 tsutsui #define NEWS4000_PORTA_TXPORT 0x00040000 /* XXX: not confirmed */
98 1.29 tsutsui #define NEWS4000_PORTA_RXPORT 0x00050000 /* XXX: not confirmed */
99 1.29 tsutsui #define NEWS4000_DMA_MODE_REG 3
100 1.29 tsutsui #define NEWS4000_DMA_ENABLE 0x01 /* DMA enable */
101 1.29 tsutsui #define NEWS4000_DMA_DIR_DM 0x00 /* device to memory */
102 1.29 tsutsui #define NEWS4000_DMA_DIR_MD 0x02 /* memory to device */
103 1.29 tsutsui #define NEWS4000_DMA_EXTRDY 0x08 /* DMA external ready */
104 1.29 tsutsui #define NEWS4000_PORTB_CTL 0x00020000 /* XXX: not confirmed */
105 1.29 tsutsui #define NEWS4000_PORTA_CTL 0x00060000 /* XXX: not confirmed */
106 1.29 tsutsui #define NEWS4000_PORT_CTL 4
107 1.29 tsutsui #define NEWS4000_PORTCTL_RI 0x01
108 1.29 tsutsui #define NEWS4000_PORTCTL_DSR 0x02
109 1.29 tsutsui #define NEWS4000_PORTCTL_DTR 0x04
110 1.29 tsutsui #define NEWS4000_PORT_SEL 5
111 1.29 tsutsui #define NEWS4000_PORTSEL_LOCALTALK 0x01
112 1.29 tsutsui #define NEWS4000_PORTSEL_RS232C 0x02
113 1.29 tsutsui #define NEWS4000_ESCC_REG 0x00060000 /* XXX: not confirmed */
114 1.29 tsutsui #define NEWS4000_ESCCREG_INTSTAT 0
115 1.29 tsutsui #define NEWS4000_INTSTAT_SCC 0x01
116 1.29 tsutsui #define NEWS4000_ESCCREG_INTMASK 1
117 1.29 tsutsui #define NEWS4000_INTMASK_SCC 0x01
118 1.29 tsutsui #define NEWS4000_PORTB_OFFSET 0x00080000
119 1.29 tsutsui #define NEWS4000_PORTA_OFFSET 0x00080008
120 1.1 tsubai
121 1.1 tsubai extern int zs_def_cflag;
122 1.17 tsutsui extern void (*zs_delay)(void);
123 1.1 tsubai
124 1.1 tsubai /*
125 1.1 tsubai * The news5000 provides a 9.8304 MHz clock to the ZS chips.
126 1.1 tsubai */
127 1.1 tsubai #define PCLK (9600 * 1024) /* PCLK pin input clock rate */
128 1.1 tsubai
129 1.1 tsubai #define ZS_DELAY() DELAY(2)
130 1.1 tsubai
131 1.1 tsubai /* The layout of this is hardware-dependent (padding, order). */
132 1.1 tsubai struct zschan {
133 1.24 tsutsui volatile uint8_t pad1[3];
134 1.24 tsutsui volatile uint8_t zc_csr; /* ctrl,status, and indirect access */
135 1.24 tsutsui volatile uint8_t pad2[3];
136 1.24 tsutsui volatile uint8_t zc_data; /* data */
137 1.1 tsubai };
138 1.1 tsubai
139 1.20 christos static void *zsaddr[NZS];
140 1.1 tsubai
141 1.1 tsubai /* Default speed for all channels */
142 1.1 tsubai static int zs_defspeed = 9600;
143 1.1 tsubai
144 1.30 tsutsui /* console status from cninit */
145 1.30 tsutsui static struct zs_chanstate zs_ap_conschan_store;
146 1.30 tsutsui static struct zs_chanstate *zs_ap_conschan;
147 1.30 tsutsui static struct zschan *zc_ap_cons;
148 1.30 tsutsui
149 1.24 tsutsui static uint8_t zs_init_reg[16] = {
150 1.1 tsubai 0, /* 0: CMD (reset, etc.) */
151 1.1 tsubai 0, /* 1: No interrupts yet. */
152 1.1 tsubai 0, /* IVECT */
153 1.1 tsubai ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
154 1.1 tsubai ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
155 1.1 tsubai ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
156 1.1 tsubai 0, /* 6: TXSYNC/SYNCLO */
157 1.1 tsubai 0, /* 7: RXSYNC/SYNCHI */
158 1.1 tsubai 0, /* 8: alias for data port */
159 1.1 tsubai ZSWR9_MASTER_IE,
160 1.1 tsubai 0, /*10: Misc. TX/RX control bits */
161 1.1 tsubai ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
162 1.30 tsutsui BPS_TO_TCONST(PCLK/16,9600), /*12: BAUDLO (default=9600) */
163 1.1 tsubai 0, /*13: BAUDHI (default=9600) */
164 1.1 tsubai ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK,
165 1.1 tsubai ZSWR15_BREAK_IE,
166 1.1 tsubai };
167 1.1 tsubai
168 1.29 tsutsui #ifdef NEWS4000_ZS_AP_POLLING
169 1.29 tsutsui static struct callout zscallout;
170 1.29 tsutsui #endif
171 1.29 tsutsui
172 1.17 tsutsui static struct zschan * zs_get_chan_addr(int, int);
173 1.17 tsutsui static void zs_ap_delay(void);
174 1.17 tsutsui static int zshard_ap(void *);
175 1.17 tsutsui static int zs_getc(void *);
176 1.17 tsutsui static void zs_putc(void *, int);
177 1.1 tsubai
178 1.1 tsubai struct zschan *
179 1.17 tsutsui zs_get_chan_addr(int zs_unit, int channel)
180 1.1 tsubai {
181 1.20 christos void *addr;
182 1.29 tsutsui struct zschan *zc = NULL;
183 1.1 tsubai
184 1.1 tsubai if (zs_unit >= NZS)
185 1.1 tsubai return NULL;
186 1.1 tsubai addr = zsaddr[zs_unit];
187 1.1 tsubai if (addr == NULL)
188 1.1 tsubai return NULL;
189 1.29 tsutsui if (systype == NEWS5000) {
190 1.29 tsutsui if (channel == 0) {
191 1.29 tsutsui zc = (void *)((uint8_t *)addr + NEWS5000_PORTA_OFFSET);
192 1.29 tsutsui } else {
193 1.29 tsutsui zc = (void *)((uint8_t *)addr + NEWS5000_PORTB_OFFSET);
194 1.29 tsutsui }
195 1.29 tsutsui }
196 1.29 tsutsui if (systype == NEWS4000) {
197 1.29 tsutsui if (channel == 0) {
198 1.29 tsutsui zc = (void *)((uint8_t *)addr + NEWS4000_PORTA_OFFSET);
199 1.29 tsutsui } else {
200 1.29 tsutsui zc = (void *)((uint8_t *)addr + NEWS4000_PORTB_OFFSET);
201 1.29 tsutsui }
202 1.1 tsubai }
203 1.17 tsutsui return zc;
204 1.1 tsubai }
205 1.1 tsubai
206 1.1 tsubai void
207 1.17 tsutsui zs_ap_delay(void)
208 1.1 tsubai {
209 1.13 tsutsui
210 1.1 tsubai ZS_DELAY();
211 1.1 tsubai }
212 1.1 tsubai
213 1.1 tsubai /****************************************************************
214 1.1 tsubai * Autoconfig
215 1.1 tsubai ****************************************************************/
216 1.1 tsubai
217 1.1 tsubai /* Definition of the driver for autoconfig. */
218 1.24 tsutsui int zs_ap_match(device_t, cfdata_t, void *);
219 1.24 tsutsui void zs_ap_attach(device_t, device_t, void *);
220 1.1 tsubai
221 1.24 tsutsui CFATTACH_DECL_NEW(zsc_ap, sizeof(struct zsc_softc),
222 1.8 thorpej zs_ap_match, zs_ap_attach, NULL, NULL);
223 1.1 tsubai
224 1.1 tsubai /*
225 1.1 tsubai * Is the zs chip present?
226 1.1 tsubai */
227 1.1 tsubai int
228 1.24 tsutsui zs_ap_match(device_t parent, cfdata_t cf, void *aux)
229 1.1 tsubai {
230 1.1 tsubai struct apbus_attach_args *apa = aux;
231 1.1 tsubai
232 1.29 tsutsui if (strcmp("esccf", apa->apa_name) == 0 ||
233 1.29 tsutsui strcmp("esccg", apa->apa_name) == 0)
234 1.29 tsutsui return 1;
235 1.1 tsubai
236 1.29 tsutsui return 0;
237 1.1 tsubai }
238 1.1 tsubai
239 1.1 tsubai /*
240 1.1 tsubai * Attach a found zs.
241 1.1 tsubai *
242 1.1 tsubai * Match slave number to zs unit number, so that misconfiguration will
243 1.1 tsubai * not set up the keyboard as ttya, etc.
244 1.1 tsubai */
245 1.1 tsubai void
246 1.24 tsutsui zs_ap_attach(device_t parent, device_t self, void *aux)
247 1.1 tsubai {
248 1.24 tsutsui struct zsc_softc *zsc = device_private(self);
249 1.1 tsubai struct apbus_attach_args *apa = aux;
250 1.1 tsubai struct zsc_attach_args zsc_args;
251 1.1 tsubai volatile struct zschan *zc;
252 1.1 tsubai struct zs_chanstate *cs;
253 1.1 tsubai int s, zs_unit, channel;
254 1.29 tsutsui volatile uint32_t *txBfifo;
255 1.29 tsutsui volatile uint32_t *rxBfifo;
256 1.29 tsutsui volatile uint32_t *txAfifo;
257 1.29 tsutsui volatile uint32_t *rxAfifo;
258 1.29 tsutsui volatile uint32_t *portBctl;
259 1.29 tsutsui volatile uint32_t *portActl;
260 1.29 tsutsui volatile uint32_t *esccregs;
261 1.1 tsubai
262 1.24 tsutsui zsc->zsc_dev = self;
263 1.24 tsutsui zs_unit = device_unit(self);
264 1.20 christos zsaddr[zs_unit] = (void *)apa->apa_hwbase;
265 1.1 tsubai
266 1.24 tsutsui aprint_normal(" slot%d addr 0x%lx\n", apa->apa_slotno, apa->apa_hwbase);
267 1.1 tsubai
268 1.29 tsutsui /* XXX: appease gcc -Wuninitialized */
269 1.29 tsutsui txBfifo = (void *)(apa->apa_hwbase);
270 1.29 tsutsui rxBfifo = (void *)(apa->apa_hwbase);
271 1.29 tsutsui txAfifo = (void *)(apa->apa_hwbase);
272 1.29 tsutsui rxAfifo = (void *)(apa->apa_hwbase);
273 1.29 tsutsui portBctl = (void *)(apa->apa_hwbase);
274 1.29 tsutsui portActl = (void *)(apa->apa_hwbase);
275 1.29 tsutsui esccregs = (void *)(apa->apa_hwbase);
276 1.29 tsutsui
277 1.29 tsutsui if (systype == NEWS5000) {
278 1.29 tsutsui txBfifo = (void *)(apa->apa_hwbase + NEWS5000_PORTB_TXPORT);
279 1.29 tsutsui rxBfifo = (void *)(apa->apa_hwbase + NEWS5000_PORTB_RXPORT);
280 1.29 tsutsui txAfifo = (void *)(apa->apa_hwbase + NEWS5000_PORTA_TXPORT);
281 1.29 tsutsui rxAfifo = (void *)(apa->apa_hwbase + NEWS5000_PORTA_RXPORT);
282 1.29 tsutsui portBctl = (void *)(apa->apa_hwbase + NEWS5000_PORTB_OFFSET);
283 1.29 tsutsui portActl = (void *)(apa->apa_hwbase + NEWS5000_PORTA_OFFSET);
284 1.29 tsutsui esccregs = (void *)(apa->apa_hwbase + NEWS5000_ESCC_REG);
285 1.29 tsutsui }
286 1.29 tsutsui if (systype == NEWS4000) {
287 1.29 tsutsui txBfifo = (void *)(apa->apa_hwbase + NEWS4000_PORTB_TXPORT);
288 1.29 tsutsui rxBfifo = (void *)(apa->apa_hwbase + NEWS4000_PORTB_RXPORT);
289 1.29 tsutsui txAfifo = (void *)(apa->apa_hwbase + NEWS4000_PORTA_TXPORT);
290 1.29 tsutsui rxAfifo = (void *)(apa->apa_hwbase + NEWS4000_PORTA_RXPORT);
291 1.29 tsutsui portBctl = (void *)(apa->apa_hwbase + NEWS4000_PORTB_CTL);
292 1.29 tsutsui portActl = (void *)(apa->apa_hwbase + NEWS4000_PORTA_CTL);
293 1.29 tsutsui esccregs = (void *)(apa->apa_hwbase + NEWS4000_ESCC_REG);
294 1.29 tsutsui }
295 1.1 tsubai
296 1.29 tsutsui if (systype == NEWS5000) {
297 1.29 tsutsui txAfifo[NEWS5000_DMA_MODE_REG] = NEWS5000_DMA_EXTRDY;
298 1.29 tsutsui rxAfifo[NEWS5000_DMA_MODE_REG] = NEWS5000_DMA_EXTRDY;
299 1.29 tsutsui txBfifo[NEWS5000_DMA_MODE_REG] = NEWS5000_DMA_EXTRDY;
300 1.29 tsutsui rxBfifo[NEWS5000_DMA_MODE_REG] = NEWS5000_DMA_EXTRDY;
301 1.29 tsutsui
302 1.29 tsutsui /* assert DTR */ /* XXX */
303 1.29 tsutsui portBctl[NEWS5000_PORT_CTL] = NEWS5000_PORTCTL_DTR;
304 1.29 tsutsui portActl[NEWS5000_PORT_CTL] = NEWS5000_PORTCTL_DTR;
305 1.1 tsubai
306 1.29 tsutsui /* select RS-232C (ch1 only) */
307 1.29 tsutsui portActl[NEWS5000_PORT_SEL] = NEWS5000_PORTSEL_RS232C;
308 1.1 tsubai
309 1.29 tsutsui /* enable SCC interrupts */
310 1.29 tsutsui esccregs[NEWS5000_ESCCREG_INTMASK] = NEWS5000_INTMASK_SCC;
311 1.29 tsutsui }
312 1.29 tsutsui
313 1.29 tsutsui if (systype == NEWS4000) {
314 1.29 tsutsui txAfifo[NEWS4000_DMA_MODE_REG] = NEWS4000_DMA_EXTRDY;
315 1.29 tsutsui rxAfifo[NEWS4000_DMA_MODE_REG] = NEWS4000_DMA_EXTRDY;
316 1.29 tsutsui txBfifo[NEWS4000_DMA_MODE_REG] = NEWS4000_DMA_EXTRDY;
317 1.29 tsutsui rxBfifo[NEWS4000_DMA_MODE_REG] = NEWS4000_DMA_EXTRDY;
318 1.29 tsutsui
319 1.29 tsutsui #if 1 /* XXX: zsc on news4000 seems mangled by these ops */
320 1.29 tsutsui /* assert DTR */ /* XXX */
321 1.29 tsutsui portBctl[NEWS4000_PORT_CTL] = NEWS4000_PORTCTL_DTR;
322 1.29 tsutsui portActl[NEWS4000_PORT_CTL] = NEWS4000_PORTCTL_DTR;
323 1.29 tsutsui
324 1.29 tsutsui /* select RS-232C (ch1 only) */
325 1.29 tsutsui portActl[NEWS4000_PORT_SEL] = NEWS4000_PORTSEL_RS232C;
326 1.29 tsutsui #endif
327 1.29 tsutsui
328 1.29 tsutsui /* enable SCC interrupts */
329 1.29 tsutsui esccregs[NEWS4000_ESCCREG_INTMASK] = NEWS4000_INTMASK_SCC;
330 1.29 tsutsui }
331 1.1 tsubai
332 1.1 tsubai zs_delay = zs_ap_delay;
333 1.1 tsubai
334 1.1 tsubai /*
335 1.1 tsubai * Initialize software state for each channel.
336 1.1 tsubai */
337 1.1 tsubai for (channel = 0; channel < 2; channel++) {
338 1.1 tsubai zsc_args.channel = channel;
339 1.1 tsubai cs = &zsc->zsc_cs_store[channel];
340 1.1 tsubai zsc->zsc_cs[channel] = cs;
341 1.1 tsubai
342 1.22 ad zs_lock_init(cs);
343 1.1 tsubai cs->cs_channel = channel;
344 1.1 tsubai cs->cs_private = NULL;
345 1.1 tsubai cs->cs_ops = &zsops_null;
346 1.1 tsubai cs->cs_brg_clk = PCLK / 16;
347 1.1 tsubai
348 1.1 tsubai zc = zs_get_chan_addr(zs_unit, channel);
349 1.1 tsubai
350 1.30 tsutsui if (zc == zc_ap_cons) {
351 1.30 tsutsui memcpy(cs, zs_ap_conschan, sizeof(struct zs_chanstate));
352 1.30 tsutsui zs_ap_conschan = cs;
353 1.30 tsutsui zsc_args.hwflags = ZS_HWFLAG_CONSOLE;
354 1.30 tsutsui } else {
355 1.30 tsutsui cs->cs_reg_csr = &zc->zc_csr;
356 1.30 tsutsui cs->cs_reg_data = &zc->zc_data;
357 1.30 tsutsui memcpy(cs->cs_creg, zs_init_reg, 16);
358 1.30 tsutsui memcpy(cs->cs_preg, zs_init_reg, 16);
359 1.1 tsubai cs->cs_defspeed = zs_defspeed;
360 1.30 tsutsui zsc_args.hwflags = 0;
361 1.30 tsutsui }
362 1.1 tsubai cs->cs_defcflag = zs_def_cflag;
363 1.1 tsubai
364 1.1 tsubai /* Make these correspond to cs_defcflag (-crtscts) */
365 1.1 tsubai cs->cs_rr0_dcd = ZSRR0_DCD;
366 1.1 tsubai cs->cs_rr0_cts = 0;
367 1.1 tsubai cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
368 1.1 tsubai cs->cs_wr5_rts = 0;
369 1.1 tsubai
370 1.1 tsubai /*
371 1.1 tsubai * Clear the master interrupt enable.
372 1.1 tsubai * The INTENA is common to both channels,
373 1.1 tsubai * so just do it on the A channel.
374 1.1 tsubai */
375 1.1 tsubai if (channel == 0) {
376 1.1 tsubai zs_write_reg(cs, 9, 0);
377 1.1 tsubai }
378 1.1 tsubai
379 1.1 tsubai /*
380 1.1 tsubai * Look for a child driver for this channel.
381 1.1 tsubai * The child attach will setup the hardware.
382 1.1 tsubai */
383 1.1 tsubai if (!config_found(self, (void *)&zsc_args, zs_print)) {
384 1.1 tsubai /* No sub-driver. Just reset it. */
385 1.24 tsutsui uint8_t reset = (channel == 0) ?
386 1.24 tsutsui ZSWR9_A_RESET : ZSWR9_B_RESET;
387 1.1 tsubai s = splhigh();
388 1.1 tsubai zs_write_reg(cs, 9, reset);
389 1.1 tsubai splx(s);
390 1.1 tsubai }
391 1.1 tsubai }
392 1.1 tsubai
393 1.1 tsubai /*
394 1.26 tsutsui * Now safe to install interrupt handlers.
395 1.1 tsubai */
396 1.27 tsutsui zsc->zsc_si = softint_establish(SOFTINT_SERIAL,
397 1.27 tsutsui (void (*)(void *))zsc_intr_soft, zsc);
398 1.29 tsutsui if (systype == NEWS5000) {
399 1.29 tsutsui apbus_intr_establish(1, /* interrupt level ( 0 or 1 ) */
400 1.29 tsutsui NEWS5000_INT1_SCC,
401 1.29 tsutsui 0, /* priority */
402 1.29 tsutsui zshard_ap, zsc,
403 1.29 tsutsui device_xname(self), apa->apa_ctlnum);
404 1.29 tsutsui }
405 1.29 tsutsui if (systype == NEWS4000) {
406 1.29 tsutsui apbus_intr_establish(1, /* interrupt level ( 0 or 1 ) */
407 1.29 tsutsui 0x0200,
408 1.29 tsutsui 0, /* priority */
409 1.29 tsutsui zshard_ap, zsc,
410 1.29 tsutsui device_xname(self), apa->apa_ctlnum);
411 1.29 tsutsui #ifdef NEWS4000_ZS_AP_POLLING
412 1.29 tsutsui /* XXX: no info how to enable zs ap interrupt for now */
413 1.29 tsutsui callout_init(&zscallout, 0);
414 1.29 tsutsui callout_reset(&zscallout, 1,
415 1.29 tsutsui (void (*)(void *))zshard_ap, (void *)zsc);
416 1.29 tsutsui #endif
417 1.29 tsutsui }
418 1.1 tsubai /* XXX; evcnt_attach() ? */
419 1.1 tsubai
420 1.1 tsubai #if 0
421 1.1 tsubai {
422 1.1 tsubai u_int x;
423 1.1 tsubai
424 1.1 tsubai /* determine SCC/ESCC type */
425 1.1 tsubai x = zs_read_reg(cs, 15);
426 1.1 tsubai zs_write_reg(cs, 15, x | ZSWR15_ENABLE_ENHANCED);
427 1.1 tsubai
428 1.1 tsubai if (zs_read_reg(cs, 15) & ZSWR15_ENABLE_ENHANCED) { /* ESCC Z85230 */
429 1.1 tsubai zs_write_reg(cs, 7, ZSWR7P_EXTEND_READ | ZSWR7P_TX_FIFO);
430 1.1 tsubai }
431 1.1 tsubai }
432 1.1 tsubai #endif
433 1.1 tsubai
434 1.1 tsubai /*
435 1.1 tsubai * Set the master interrupt enable and interrupt vector.
436 1.1 tsubai * (common to both channels, do it on A)
437 1.1 tsubai */
438 1.1 tsubai cs = zsc->zsc_cs[0];
439 1.1 tsubai s = splhigh();
440 1.1 tsubai /* interrupt vector */
441 1.1 tsubai zs_write_reg(cs, 2, zs_init_reg[2]);
442 1.1 tsubai /* master interrupt control (enable) */
443 1.1 tsubai zs_write_reg(cs, 9, zs_init_reg[9]);
444 1.1 tsubai splx(s);
445 1.1 tsubai }
446 1.1 tsubai
447 1.5 onoe static int
448 1.17 tsutsui zshard_ap(void *arg)
449 1.1 tsubai {
450 1.13 tsutsui
451 1.3 tsubai zshard(arg);
452 1.29 tsutsui #ifdef NEWS4000_ZS_AP_POLLING
453 1.29 tsutsui if (systype == NEWS4000) {
454 1.29 tsutsui callout_schedule(&zscallout, 1);
455 1.29 tsutsui }
456 1.29 tsutsui #endif
457 1.5 onoe return 1;
458 1.1 tsubai }
459 1.1 tsubai
460 1.1 tsubai /*
461 1.1 tsubai * Polled input char.
462 1.1 tsubai */
463 1.1 tsubai int
464 1.17 tsutsui zs_getc(void *arg)
465 1.1 tsubai {
466 1.13 tsutsui volatile struct zschan *zc = arg;
467 1.24 tsutsui int s, c;
468 1.24 tsutsui uint8_t rr0;
469 1.1 tsubai
470 1.1 tsubai s = splhigh();
471 1.1 tsubai /* Wait for a character to arrive. */
472 1.1 tsubai do {
473 1.1 tsubai rr0 = zc->zc_csr;
474 1.1 tsubai ZS_DELAY();
475 1.1 tsubai } while ((rr0 & ZSRR0_RX_READY) == 0);
476 1.1 tsubai
477 1.1 tsubai c = zc->zc_data;
478 1.1 tsubai ZS_DELAY();
479 1.1 tsubai splx(s);
480 1.1 tsubai
481 1.1 tsubai /*
482 1.1 tsubai * This is used by the kd driver to read scan codes,
483 1.1 tsubai * so don't translate '\r' ==> '\n' here...
484 1.1 tsubai */
485 1.17 tsutsui return c;
486 1.1 tsubai }
487 1.1 tsubai
488 1.1 tsubai /*
489 1.1 tsubai * Polled output char.
490 1.1 tsubai */
491 1.1 tsubai void
492 1.17 tsutsui zs_putc(void *arg, int c)
493 1.1 tsubai {
494 1.13 tsutsui volatile struct zschan *zc = arg;
495 1.24 tsutsui int s;
496 1.24 tsutsui uint8_t rr0;
497 1.1 tsubai
498 1.1 tsubai s = splhigh();
499 1.1 tsubai /* Wait for transmitter to become ready. */
500 1.1 tsubai do {
501 1.1 tsubai rr0 = zc->zc_csr;
502 1.1 tsubai ZS_DELAY();
503 1.1 tsubai } while ((rr0 & ZSRR0_TX_READY) == 0);
504 1.1 tsubai
505 1.1 tsubai zc->zc_data = c;
506 1.1 tsubai ZS_DELAY();
507 1.1 tsubai splx(s);
508 1.1 tsubai }
509 1.1 tsubai
510 1.1 tsubai /*****************************************************************/
511 1.1 tsubai
512 1.17 tsutsui static void zscnprobe(struct consdev *);
513 1.17 tsutsui static void zscninit(struct consdev *);
514 1.17 tsutsui static int zscngetc(dev_t);
515 1.17 tsutsui static void zscnputc(dev_t, int);
516 1.1 tsubai
517 1.1 tsubai struct consdev consdev_zs_ap = {
518 1.1 tsubai zscnprobe,
519 1.1 tsubai zscninit,
520 1.1 tsubai zscngetc,
521 1.1 tsubai zscnputc,
522 1.13 tsutsui nullcnpollc,
523 1.13 tsutsui NULL,
524 1.13 tsutsui NULL,
525 1.4 thorpej NULL,
526 1.13 tsutsui NODEV,
527 1.13 tsutsui CN_DEAD
528 1.1 tsubai };
529 1.1 tsubai
530 1.13 tsutsui static void
531 1.17 tsutsui zscnprobe(struct consdev *cn)
532 1.1 tsubai {
533 1.1 tsubai }
534 1.1 tsubai
535 1.13 tsutsui static void
536 1.17 tsutsui zscninit(struct consdev *cn)
537 1.1 tsubai {
538 1.6 gehenna extern const struct cdevsw zstty_cdevsw;
539 1.30 tsutsui struct zs_chanstate *cs;
540 1.30 tsutsui u_int tconst;
541 1.30 tsutsui
542 1.30 tsutsui /* Wait a while for PROM console output to complete */
543 1.30 tsutsui DELAY(20000);
544 1.6 gehenna
545 1.6 gehenna cn->cn_dev = makedev(cdevsw_lookup_major(&zstty_cdevsw), 0);
546 1.1 tsubai cn->cn_pri = CN_REMOTE;
547 1.30 tsutsui
548 1.30 tsutsui zc_ap_cons = sccport0a;
549 1.30 tsutsui zs_delay = zs_ap_delay;
550 1.30 tsutsui
551 1.30 tsutsui zs_ap_conschan = cs = &zs_ap_conschan_store;
552 1.30 tsutsui
553 1.30 tsutsui /* Setup temporary chanstate. */
554 1.30 tsutsui cs->cs_reg_csr = &zc_ap_cons->zc_csr;
555 1.30 tsutsui cs->cs_reg_data = &zc_ap_cons->zc_data;
556 1.30 tsutsui
557 1.30 tsutsui /* Initialize the pending registers. */
558 1.30 tsutsui memcpy(cs->cs_preg, zs_init_reg, 16);
559 1.30 tsutsui cs->cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS;
560 1.30 tsutsui
561 1.30 tsutsui cs->cs_brg_clk = PCLK / 16;
562 1.30 tsutsui cs->cs_defspeed = 9600; /* PROM use 9600 bps */
563 1.30 tsutsui tconst = BPS_TO_TCONST(cs->cs_brg_clk, cs->cs_defspeed);
564 1.30 tsutsui cs->cs_preg[12] = tconst;
565 1.30 tsutsui cs->cs_preg[13] = tconst >> 8;
566 1.30 tsutsui
567 1.30 tsutsui /* Clear the master interrupt enable. */
568 1.30 tsutsui zs_write_reg(cs, 9, 0);
569 1.30 tsutsui
570 1.30 tsutsui /* Reset the whole SCC chip. */
571 1.30 tsutsui zs_write_reg(cs, 9, ZSWR9_HARD_RESET);
572 1.30 tsutsui
573 1.30 tsutsui /* Copy "pending" to "current" and H/W */
574 1.30 tsutsui zs_loadchannelregs(cs);
575 1.1 tsubai }
576 1.1 tsubai
577 1.13 tsutsui static int
578 1.17 tsutsui zscngetc(dev_t dev)
579 1.1 tsubai {
580 1.29 tsutsui
581 1.29 tsutsui return zs_getc(sccport0a);
582 1.1 tsubai }
583 1.1 tsubai
584 1.13 tsutsui static void
585 1.17 tsutsui zscnputc(dev_t dev, int c)
586 1.1 tsubai {
587 1.13 tsutsui
588 1.29 tsutsui zs_putc(sccport0a, c);
589 1.1 tsubai }
590