FreeBSD/Linux Kernel Cross Reference
sys/dev/zs/zs_macio.c
1 /*-
2 * Copyright (c) 2003 Jake Burkholder, Benno Rice.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD: releng/6.4/sys/dev/zs/zs_macio.c 133589 2004-08-12 17:41:33Z marius $");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/module.h>
33 #include <sys/bus.h>
34 #include <sys/interrupt.h>
35 #include <sys/kernel.h>
36 #include <machine/bus.h>
37 #include <machine/resource.h>
38 #include <sys/rman.h>
39
40 #include <dev/ofw/ofw_bus.h>
41 #include <dev/ofw/openfirm.h>
42
43 #include <dev/zs/z8530reg.h>
44 #include <dev/zs/z8530var.h>
45
46 #define ZS_MACIO_CHAN_A 32
47 #define ZS_MACIO_CHAN_B 0
48
49 #define ZS_MACIO_CSR 0
50 #define ZS_MACIO_DATA 16
51
52 #define ZS_MACIO_DEF_SPEED (57600)
53
54 #define ZS_MACIO_CLOCK (9600 * 384)
55 #define ZS_MACIO_CLOCK_DIV (16)
56
57 struct zs_macio_softc {
58 struct zs_softc sc_zs;
59 struct resource *sc_irqres1, *sc_irqres2;
60 int sc_irqrid1, sc_irqrid2;
61 void *sc_ih1, *sc_ih2;
62 struct resource *sc_memres;
63 int sc_memrid;
64 };
65
66 static int zs_macio_attach(device_t dev);
67 static int zs_macio_detach(device_t dev);
68 static int zs_macio_probe(device_t dev);
69
70 static int zstty_macio_attach(device_t dev);
71 static int zstty_macio_probe(device_t dev);
72
73 static device_method_t zs_macio_methods[] = {
74 DEVMETHOD(device_probe, zs_macio_probe),
75 DEVMETHOD(device_attach, zs_macio_attach),
76 DEVMETHOD(device_detach, zs_macio_detach),
77
78 DEVMETHOD(bus_print_child, bus_generic_print_child),
79
80 { 0, 0 }
81 };
82
83 static device_method_t zstty_macio_methods[] = {
84 DEVMETHOD(device_probe, zstty_macio_probe),
85 DEVMETHOD(device_attach, zstty_macio_attach),
86 DEVMETHOD(device_detach, bus_generic_detach),
87
88 { 0, 0}
89 };
90
91 static driver_t zs_macio_driver = {
92 "zs",
93 zs_macio_methods,
94 sizeof(struct zs_macio_softc),
95 };
96
97 static driver_t zstty_macio_driver = {
98 "zstty",
99 zstty_macio_methods,
100 sizeof(struct zstty_softc),
101 };
102
103 static devclass_t zs_macio_devclass;
104 static devclass_t zstty_macio_devclass;
105
106 DRIVER_MODULE(zstty, zs, zstty_macio_driver, zstty_macio_devclass, 0, 0);
107 DRIVER_MODULE(zs, macio, zs_macio_driver, zs_macio_devclass, 0, 0);
108
109 static u_char zs_macio_init_reg[16] = {
110 0, /* 0: CMD (reset, etc.) */
111 0, /* 1: No interrupts yet. */
112 0, /* IVECT */
113 ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
114 ZSWR4_CLK_X16 | ZSWR4_ONESB,
115 ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
116 0, /* 6: TXSYNC/SYNCLO */
117 0, /* 7: RXSYNC/SYNCHI */
118 0, /* 8: alias for data port */
119 ZSWR9_MASTER_IE | ZSWR9_NO_VECTOR,
120 0, /*10: Misc. TX/RX control bits */
121 ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
122 #if 0
123 ((ZS_MACIO_CLOCK/32)/ZS_MACIO_DEF_SPEED)-2,
124 #endif
125 BPS_TO_TCONST((ZS_MACIO_CLOCK / ZS_MACIO_CLOCK_DIV), ZS_MACIO_DEF_SPEED),
126 0,
127 ZSWR14_BAUD_ENA,
128 ZSWR15_BREAK_IE,
129 };
130
131 static int
132 zs_macio_probe(device_t dev)
133 {
134
135 if (strcmp(ofw_bus_get_name(dev), "escc") != 0 ||
136 device_get_unit(dev) != 0)
137 return (ENXIO);
138 return (zs_probe(dev));
139 }
140
141 static int
142 zs_macio_attach(device_t dev)
143 {
144 struct zs_macio_softc *sc;
145
146 sc = device_get_softc(dev);
147
148 sc->sc_memres = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
149 &sc->sc_memrid, RF_ACTIVE);
150 if (sc->sc_memres == NULL) {
151 device_printf(dev, "could not allocate memory\n");
152 goto error;
153 }
154 sc->sc_irqrid1 = 0;
155 sc->sc_irqres1 = bus_alloc_resource_any(dev, SYS_RES_IRQ,
156 &sc->sc_irqrid1, RF_ACTIVE);
157 if (sc->sc_irqres1 == NULL) {
158 device_printf(dev, "could not allocate interrupt 1\n");
159 goto error;
160 }
161 if (bus_setup_intr(dev, sc->sc_irqres1, INTR_TYPE_TTY | INTR_FAST,
162 zs_intr, sc, &sc->sc_ih1) != 0) {
163 device_printf(dev, "could not setup interrupt 1\n");
164 goto error;
165 }
166 sc->sc_irqrid2 = 1;
167 sc->sc_irqres2 = bus_alloc_resource_any(dev, SYS_RES_IRQ,
168 &sc->sc_irqrid2, RF_ACTIVE);
169 if (sc->sc_irqres2 == NULL) {
170 device_printf(dev, "could not allocate interrupt 2\n");
171 goto error;
172 }
173 if (bus_setup_intr(dev, sc->sc_irqres2, INTR_TYPE_TTY | INTR_FAST,
174 zs_intr, sc, &sc->sc_ih2) != 0) {
175 device_printf(dev, "could not setup interrupt 2\n");
176 goto error;
177 }
178 sc->sc_zs.sc_bt = rman_get_bustag(sc->sc_memres);
179 sc->sc_zs.sc_bh = rman_get_bushandle(sc->sc_memres);
180 return (zs_attach(dev));
181
182 error:
183 zs_macio_detach(dev);
184 return (ENXIO);
185 }
186
187 static int
188 zs_macio_detach(device_t dev)
189 {
190 struct zs_macio_softc *sc;
191
192 sc = device_get_softc(dev);
193 if (sc->sc_irqres2 != NULL) {
194 if (sc->sc_ih2 != NULL)
195 bus_teardown_intr(dev, sc->sc_irqres2, sc->sc_ih2);
196 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqrid2,
197 sc->sc_irqres2);
198 }
199 if (sc->sc_irqres1 != NULL) {
200 if (sc->sc_ih1 != NULL)
201 bus_teardown_intr(dev, sc->sc_irqres1, sc->sc_ih1);
202 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqrid1,
203 sc->sc_irqres1);
204 }
205 if (sc->sc_memres != NULL)
206 bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_memrid,
207 sc->sc_memres);
208 return (0);
209 }
210
211 static int
212 zstty_macio_probe(device_t dev)
213 {
214
215 if ((device_get_unit(dev) & 1) == 0)
216 device_set_desc(dev, "ttya");
217 else
218 device_set_desc(dev, "ttyb");
219
220 return (zstty_probe(dev));
221 }
222
223 static int
224 zstty_macio_attach(device_t dev)
225 {
226 struct zstty_softc *sc;
227
228 sc = device_get_softc(dev);
229 sc->sc_parent = device_get_softc(device_get_parent(dev));
230 sc->sc_bt = sc->sc_parent->sc_bt;
231 sc->sc_brg_clk = ZS_MACIO_CLOCK / ZS_MACIO_CLOCK_DIV;
232
233 switch (device_get_unit(dev) & 1) {
234 case 0:
235 bus_space_subregion(sc->sc_bt, sc->sc_parent->sc_bh,
236 ZS_MACIO_CHAN_A + ZS_MACIO_CSR, 1, &sc->sc_csr);
237 bus_space_subregion(sc->sc_bt, sc->sc_parent->sc_bh,
238 ZS_MACIO_CHAN_A + ZS_MACIO_DATA, 1, &sc->sc_data);
239 break;
240
241 case 1:
242 bus_space_subregion(sc->sc_bt, sc->sc_parent->sc_bh,
243 ZS_MACIO_CHAN_B + ZS_MACIO_CSR, 1, &sc->sc_csr);
244 bus_space_subregion(sc->sc_bt, sc->sc_parent->sc_bh,
245 ZS_MACIO_CHAN_B + ZS_MACIO_DATA, 1, &sc->sc_data);
246 break;
247 }
248
249 bcopy(zs_macio_init_reg, sc->sc_creg, 16);
250 bcopy(zs_macio_init_reg, sc->sc_preg, 16);
251
252 return (zstty_attach(dev));
253 }
254
255 void
256 zstty_set_speed(struct zstty_softc *sc, int ospeed)
257 {
258
259 sc->sc_preg[12] = ospeed;
260 sc->sc_preg[13] = ospeed >> 8;
261 }
262
263 int
264 zstty_console(device_t dev, char *mode, int len)
265 {
266 phandle_t chosen, options, parent;
267 ihandle_t stdin, stdout;
268 phandle_t stdinp, stdoutp;
269 char input[32], output[32];
270 const char *desc;
271
272 chosen = OF_finddevice("/chosen");
273 options = OF_finddevice("/options");
274 parent = ofw_bus_get_node(device_get_parent(dev));
275 if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) == -1 ||
276 OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1 ||
277 OF_getprop(options, "input-device", input, sizeof(input)) == -1 ||
278 OF_getprop(options, "output-device", output,
279 sizeof(output)) == -1) {
280 return (0);
281 }
282 stdinp = OF_parent(OF_instance_to_package(stdin));
283 stdoutp = OF_parent(OF_instance_to_package(stdout));
284 desc = device_get_desc(dev);
285 if (parent == stdinp && parent == stdoutp &&
286 input[3] == desc[3] && output[3] == desc[3]) {
287 if (mode != NULL)
288 strlcpy(mode, "57600,8,n,1,-", len);
289
290 return (1);
291 }
292
293 return (0);
294 }
Cache object: 2f983030bca0509a06e0d0826c2ffaa9
|