| @@ -1,1109 +1,1109 @@ | | | @@ -1,1109 +1,1109 @@ |
1 | /* $NetBSD: spif.c,v 1.18 2008/06/11 21:25:31 drochner Exp $ */ | | 1 | /* $NetBSD: spif.c,v 1.18.6.1 2011/01/07 03:52:34 riz Exp $ */ |
2 | /* $OpenBSD: spif.c,v 1.12 2003/10/03 16:44:51 miod Exp $ */ | | 2 | /* $OpenBSD: spif.c,v 1.12 2003/10/03 16:44:51 miod Exp $ */ |
3 | | | 3 | |
4 | /* | | 4 | /* |
5 | * Copyright (c) 1999-2002 Jason L. Wright (jason@thought.net) | | 5 | * Copyright (c) 1999-2002 Jason L. Wright (jason@thought.net) |
6 | * All rights reserved. | | 6 | * All rights reserved. |
7 | * | | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | | 9 | * modification, are permitted provided that the following conditions |
10 | * are met: | | 10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright | | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | | 14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. | | 15 | * documentation and/or other materials provided with the distribution. |
16 | * | | 16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | | 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | | 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
20 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, | | 20 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, |
21 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | | 21 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | | 22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | | 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
25 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | | 25 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
26 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 26 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
27 | * POSSIBILITY OF SUCH DAMAGE. | | 27 | * POSSIBILITY OF SUCH DAMAGE. |
28 | * | | 28 | * |
29 | * Effort sponsored in part by the Defense Advanced Research Projects | | 29 | * Effort sponsored in part by the Defense Advanced Research Projects |
30 | * Agency (DARPA) and Air Force Research Laboratory, Air Force | | 30 | * Agency (DARPA) and Air Force Research Laboratory, Air Force |
31 | * Materiel Command, USAF, under agreement number F30602-01-2-0537. | | 31 | * Materiel Command, USAF, under agreement number F30602-01-2-0537. |
32 | * | | 32 | * |
33 | */ | | 33 | */ |
34 | | | 34 | |
35 | /* | | 35 | /* |
36 | * Driver for the SUNW,spif: 8 serial, 1 parallel sbus board | | 36 | * Driver for the SUNW,spif: 8 serial, 1 parallel sbus board |
37 | * based heavily on Iain Hibbert's driver for the MAGMA cards | | 37 | * based heavily on Iain Hibbert's driver for the MAGMA cards |
38 | */ | | 38 | */ |
39 | | | 39 | |
40 | /* Ported to NetBSD 2.0 by Hauke Fath */ | | 40 | /* Ported to NetBSD 2.0 by Hauke Fath */ |
41 | | | 41 | |
42 | | | 42 | |
43 | #include <sys/cdefs.h> | | 43 | #include <sys/cdefs.h> |
44 | __KERNEL_RCSID(0, "$NetBSD: spif.c,v 1.18 2008/06/11 21:25:31 drochner Exp $"); | | 44 | __KERNEL_RCSID(0, "$NetBSD: spif.c,v 1.18.6.1 2011/01/07 03:52:34 riz Exp $"); |
45 | | | 45 | |
46 | #include "spif.h" | | 46 | #include "spif.h" |
47 | #if NSPIF > 0 | | 47 | #if NSPIF > 0 |
48 | | | 48 | |
49 | #include <sys/param.h> | | 49 | #include <sys/param.h> |
50 | #include <sys/systm.h> | | 50 | #include <sys/systm.h> |
51 | #include <sys/proc.h> | | 51 | #include <sys/proc.h> |
52 | #include <sys/device.h> | | 52 | #include <sys/device.h> |
53 | #include <sys/file.h> | | 53 | #include <sys/file.h> |
54 | #include <sys/ioctl.h> | | 54 | #include <sys/ioctl.h> |
55 | #include <sys/malloc.h> | | 55 | #include <sys/malloc.h> |
56 | #include <sys/tty.h> | | 56 | #include <sys/tty.h> |
57 | #include <sys/time.h> | | 57 | #include <sys/time.h> |
58 | #include <sys/kernel.h> | | 58 | #include <sys/kernel.h> |
59 | #include <sys/syslog.h> | | 59 | #include <sys/syslog.h> |
60 | #include <sys/conf.h> | | 60 | #include <sys/conf.h> |
61 | #include <sys/errno.h> | | 61 | #include <sys/errno.h> |
62 | #include <sys/kauth.h> | | 62 | #include <sys/kauth.h> |
63 | #include <sys/intr.h> | | 63 | #include <sys/intr.h> |
64 | | | 64 | |
65 | #include <sys/bus.h> | | 65 | #include <sys/bus.h> |
66 | #include <machine/autoconf.h> | | 66 | #include <machine/autoconf.h> |
67 | #include <machine/promlib.h> | | 67 | #include <machine/promlib.h> |
68 | | | 68 | |
69 | #include <dev/sbus/sbusvar.h> | | 69 | #include <dev/sbus/sbusvar.h> |
70 | | | 70 | |
71 | #include <dev/sbus/spifvar.h> | | 71 | #include <dev/sbus/spifvar.h> |
72 | #include <dev/sbus/spifreg.h> | | 72 | #include <dev/sbus/spifreg.h> |
73 | | | 73 | |
74 | | | 74 | |
75 | /* Autoconfig stuff */ | | 75 | /* Autoconfig stuff */ |
76 | | | 76 | |
77 | CFATTACH_DECL(spif, sizeof(struct spif_softc), | | 77 | CFATTACH_DECL(spif, sizeof(struct spif_softc), |
78 | spif_match, spif_attach, NULL, NULL); | | 78 | spif_match, spif_attach, NULL, NULL); |
79 | | | 79 | |
80 | CFATTACH_DECL(stty, sizeof(struct stty_softc), | | 80 | CFATTACH_DECL(stty, sizeof(struct stty_softc), |
81 | stty_match, stty_attach, NULL, NULL); | | 81 | stty_match, stty_attach, NULL, NULL); |
82 | | | 82 | |
83 | CFATTACH_DECL(sbpp, sizeof(struct sbpp_softc), | | 83 | CFATTACH_DECL(sbpp, sizeof(struct sbpp_softc), |
84 | sbpp_match, sbpp_attach, NULL, NULL); | | 84 | sbpp_match, sbpp_attach, NULL, NULL); |
85 | | | 85 | |
86 | extern struct cfdriver spif_cd; | | 86 | extern struct cfdriver spif_cd; |
87 | extern struct cfdriver stty_cd; | | 87 | extern struct cfdriver stty_cd; |
88 | extern struct cfdriver sbpp_cd; | | 88 | extern struct cfdriver sbpp_cd; |
89 | | | 89 | |
90 | dev_type_open(stty_open); | | 90 | dev_type_open(stty_open); |
91 | dev_type_close(stty_close); | | 91 | dev_type_close(stty_close); |
92 | dev_type_read(stty_read); | | 92 | dev_type_read(stty_read); |
93 | dev_type_write(stty_write); | | 93 | dev_type_write(stty_write); |
94 | dev_type_ioctl(stty_ioctl); | | 94 | dev_type_ioctl(stty_ioctl); |
95 | dev_type_stop(stty_stop); | | 95 | dev_type_stop(stty_stop); |
96 | dev_type_tty(stty_tty); | | 96 | dev_type_tty(stty_tty); |
97 | dev_type_poll(stty_poll); | | 97 | dev_type_poll(stty_poll); |
98 | | | 98 | |
99 | const struct cdevsw stty_cdevsw = { | | 99 | const struct cdevsw stty_cdevsw = { |
100 | stty_open, stty_close, stty_read, stty_write, stty_ioctl, | | 100 | stty_open, stty_close, stty_read, stty_write, stty_ioctl, |
101 | stty_stop, stty_tty, stty_poll, nommap, ttykqfilter, D_TTY | | 101 | stty_stop, stty_tty, stty_poll, nommap, ttykqfilter, D_TTY |
102 | }; | | 102 | }; |
103 | | | 103 | |
104 | dev_type_open(sbpp_open); | | 104 | dev_type_open(sbpp_open); |
105 | dev_type_close(sbpp_close); | | 105 | dev_type_close(sbpp_close); |
106 | dev_type_read(sbpp_read); | | 106 | dev_type_read(sbpp_read); |
107 | dev_type_write(sbpp_write); | | 107 | dev_type_write(sbpp_write); |
108 | dev_type_ioctl(sbpp_ioctl); | | 108 | dev_type_ioctl(sbpp_ioctl); |
109 | dev_type_poll(sbpp_poll); | | 109 | dev_type_poll(sbpp_poll); |
110 | | | 110 | |
111 | const struct cdevsw sbpp_cdevsw = { | | 111 | const struct cdevsw sbpp_cdevsw = { |
112 | sbpp_open, sbpp_close, sbpp_read, sbpp_write, sbpp_ioctl, | | 112 | sbpp_open, sbpp_close, sbpp_read, sbpp_write, sbpp_ioctl, |
113 | nostop, notty, sbpp_poll, nommap, nokqfilter, | | 113 | nostop, notty, sbpp_poll, nommap, nokqfilter, D_OTHER |
114 | }; | | 114 | }; |
115 | | | 115 | |
116 | | | 116 | |
117 | /* normal STC access */ | | 117 | /* normal STC access */ |
118 | #define STC_WRITE(sc,r,v) \ | | 118 | #define STC_WRITE(sc,r,v) \ |
119 | bus_space_write_1((sc)->sc_bustag, (sc)->sc_stch, (r), (v)) | | 119 | bus_space_write_1((sc)->sc_bustag, (sc)->sc_stch, (r), (v)) |
120 | #define STC_READ(sc,r) \ | | 120 | #define STC_READ(sc,r) \ |
121 | bus_space_read_1((sc)->sc_bustag, (sc)->sc_stch, (r)) | | 121 | bus_space_read_1((sc)->sc_bustag, (sc)->sc_stch, (r)) |
122 | | | 122 | |
123 | /* IACK STC access */ | | 123 | /* IACK STC access */ |
124 | #define ISTC_WRITE(sc,r,v) \ | | 124 | #define ISTC_WRITE(sc,r,v) \ |
125 | bus_space_write_1((sc)->sc_bustag, (sc)->sc_istch, (r), (v)) | | 125 | bus_space_write_1((sc)->sc_bustag, (sc)->sc_istch, (r), (v)) |
126 | #define ISTC_READ(sc,r) \ | | 126 | #define ISTC_READ(sc,r) \ |
127 | bus_space_read_1((sc)->sc_bustag, (sc)->sc_istch, (r)) | | 127 | bus_space_read_1((sc)->sc_bustag, (sc)->sc_istch, (r)) |
128 | | | 128 | |
129 | /* PPC access */ | | 129 | /* PPC access */ |
130 | #define PPC_WRITE(sc,r,v) \ | | 130 | #define PPC_WRITE(sc,r,v) \ |
131 | bus_space_write_1((sc)->sc_bustag, (sc)->sc_ppch, (r), (v)) | | 131 | bus_space_write_1((sc)->sc_bustag, (sc)->sc_ppch, (r), (v)) |
132 | #define PPC_READ(sc,r) \ | | 132 | #define PPC_READ(sc,r) \ |
133 | bus_space_read_1((sc)->sc_bustag, (sc)->sc_ppch, (r)) | | 133 | bus_space_read_1((sc)->sc_bustag, (sc)->sc_ppch, (r)) |
134 | | | 134 | |
135 | #define DTR_WRITE(sc,port,v) \ | | 135 | #define DTR_WRITE(sc,port,v) \ |
136 | do { \ | | 136 | do { \ |
137 | sc->sc_ttys->sc_port[(port)].sp_dtr = v; \ | | 137 | sc->sc_ttys->sc_port[(port)].sp_dtr = v; \ |
138 | bus_space_write_1((sc)->sc_bustag, \ | | 138 | bus_space_write_1((sc)->sc_bustag, \ |
139 | sc->sc_dtrh, port, (v == 0) ? 1 : 0); \ | | 139 | sc->sc_dtrh, port, (v == 0) ? 1 : 0); \ |
140 | } while (0) | | 140 | } while (0) |
141 | | | 141 | |
142 | #define DTR_READ(sc,port) ((sc)->sc_ttys->sc_port[(port)].sp_dtr) | | 142 | #define DTR_READ(sc,port) ((sc)->sc_ttys->sc_port[(port)].sp_dtr) |
143 | | | 143 | |
144 | | | 144 | |
145 | int | | 145 | int |
146 | spif_match(parent, vcf, aux) | | 146 | spif_match(parent, vcf, aux) |
147 | struct device *parent; | | 147 | struct device *parent; |
148 | struct cfdata *vcf; | | 148 | struct cfdata *vcf; |
149 | void *aux; | | 149 | void *aux; |
150 | { | | 150 | { |
151 | struct sbus_attach_args *sa = aux; | | 151 | struct sbus_attach_args *sa = aux; |
152 | | | 152 | |
153 | if (strcmp(vcf->cf_name, sa->sa_name) && | | 153 | if (strcmp(vcf->cf_name, sa->sa_name) && |
154 | strcmp("SUNW,spif", sa->sa_name)) | | 154 | strcmp("SUNW,spif", sa->sa_name)) |
155 | return (0); | | 155 | return (0); |
156 | return (1); | | 156 | return (1); |
157 | } | | 157 | } |
158 | | | 158 | |
159 | void | | 159 | void |
160 | spif_attach(parent, self, aux) | | 160 | spif_attach(parent, self, aux) |
161 | struct device *parent, *self; | | 161 | struct device *parent, *self; |
162 | void *aux; | | 162 | void *aux; |
163 | { | | 163 | { |
164 | struct spif_softc *sc = device_private(self); | | 164 | struct spif_softc *sc = device_private(self); |
165 | struct sbus_attach_args *sa = aux; | | 165 | struct sbus_attach_args *sa = aux; |
166 | | | 166 | |
167 | if (sa->sa_nintr != 2) { | | 167 | if (sa->sa_nintr != 2) { |
168 | printf(": expected %d interrupts, got %d\n", 2, sa->sa_nintr); | | 168 | printf(": expected %d interrupts, got %d\n", 2, sa->sa_nintr); |
169 | return; | | 169 | return; |
170 | } | | 170 | } |
171 | | | 171 | |
172 | if (sa->sa_nreg != 1) { | | 172 | if (sa->sa_nreg != 1) { |
173 | printf(": expected %d registers, got %d\n", 1, sa->sa_nreg); | | 173 | printf(": expected %d registers, got %d\n", 1, sa->sa_nreg); |
174 | return; | | 174 | return; |
175 | } | | 175 | } |
176 | | | 176 | |
177 | sc->sc_bustag = sa->sa_bustag; | | 177 | sc->sc_bustag = sa->sa_bustag; |
178 | if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, | | 178 | if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, |
179 | sa->sa_offset, sa->sa_size, | | 179 | sa->sa_offset, sa->sa_size, |
180 | 0, &sc->sc_regh) != 0) { | | 180 | 0, &sc->sc_regh) != 0) { |
181 | printf(": can't map registers\n"); | | 181 | printf(": can't map registers\n"); |
182 | return; | | 182 | return; |
183 | } | | 183 | } |
184 | | | 184 | |
185 | if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, | | 185 | if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, |
186 | DTR_REG_OFFSET, DTR_REG_LEN, &sc->sc_dtrh) != 0) { | | 186 | DTR_REG_OFFSET, DTR_REG_LEN, &sc->sc_dtrh) != 0) { |
187 | printf(": can't map dtr regs\n"); | | 187 | printf(": can't map dtr regs\n"); |
188 | goto fail_unmapregs; | | 188 | goto fail_unmapregs; |
189 | } | | 189 | } |
190 | | | 190 | |
191 | if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, | | 191 | if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, |
192 | STC_REG_OFFSET, STC_REG_LEN, &sc->sc_stch) != 0) { | | 192 | STC_REG_OFFSET, STC_REG_LEN, &sc->sc_stch) != 0) { |
193 | printf(": can't map dtr regs\n"); | | 193 | printf(": can't map dtr regs\n"); |
194 | goto fail_unmapregs; | | 194 | goto fail_unmapregs; |
195 | } | | 195 | } |
196 | | | 196 | |
197 | if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, | | 197 | if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, |
198 | ISTC_REG_OFFSET, ISTC_REG_LEN, &sc->sc_istch) != 0) { | | 198 | ISTC_REG_OFFSET, ISTC_REG_LEN, &sc->sc_istch) != 0) { |
199 | printf(": can't map dtr regs\n"); | | 199 | printf(": can't map dtr regs\n"); |
200 | goto fail_unmapregs; | | 200 | goto fail_unmapregs; |
201 | } | | 201 | } |
202 | | | 202 | |
203 | if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, | | 203 | if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, |
204 | PPC_REG_OFFSET, PPC_REG_LEN, &sc->sc_ppch) != 0) { | | 204 | PPC_REG_OFFSET, PPC_REG_LEN, &sc->sc_ppch) != 0) { |
205 | printf(": can't map dtr regs\n"); | | 205 | printf(": can't map dtr regs\n"); |
206 | goto fail_unmapregs; | | 206 | goto fail_unmapregs; |
207 | } | | 207 | } |
208 | | | 208 | |
209 | sc->sc_ppcih = bus_intr_establish(sa->sa_bustag, | | 209 | sc->sc_ppcih = bus_intr_establish(sa->sa_bustag, |
210 | sa->sa_intr[PARALLEL_INTR].oi_pri, IPL_SERIAL, spif_ppcintr, sc); | | 210 | sa->sa_intr[PARALLEL_INTR].oi_pri, IPL_SERIAL, spif_ppcintr, sc); |
211 | if (sc->sc_ppcih == NULL) { | | 211 | if (sc->sc_ppcih == NULL) { |
212 | printf(": failed to establish ppc interrupt\n"); | | 212 | printf(": failed to establish ppc interrupt\n"); |
213 | goto fail_unmapregs; | | 213 | goto fail_unmapregs; |
214 | } | | 214 | } |
215 | | | 215 | |
216 | sc->sc_stcih = bus_intr_establish(sa->sa_bustag, | | 216 | sc->sc_stcih = bus_intr_establish(sa->sa_bustag, |
217 | sa->sa_intr[SERIAL_INTR].oi_pri, IPL_SERIAL, spif_stcintr, sc); | | 217 | sa->sa_intr[SERIAL_INTR].oi_pri, IPL_SERIAL, spif_stcintr, sc); |
218 | if (sc->sc_stcih == NULL) { | | 218 | if (sc->sc_stcih == NULL) { |
219 | printf(": failed to establish stc interrupt\n"); | | 219 | printf(": failed to establish stc interrupt\n"); |
220 | goto fail_unmapregs; | | 220 | goto fail_unmapregs; |
221 | } | | 221 | } |
222 | | | 222 | |
223 | sc->sc_softih = softint_establish(SOFTINT_SERIAL, spif_softintr, sc); | | 223 | sc->sc_softih = softint_establish(SOFTINT_SERIAL, spif_softintr, sc); |
224 | if (sc->sc_softih == NULL) { | | 224 | if (sc->sc_softih == NULL) { |
225 | printf(": can't get soft intr\n"); | | 225 | printf(": can't get soft intr\n"); |
226 | goto fail_unmapregs; | | 226 | goto fail_unmapregs; |
227 | } | | 227 | } |
228 | | | 228 | |
229 | sc->sc_node = sa->sa_node; | | 229 | sc->sc_node = sa->sa_node; |
230 | | | 230 | |
231 | sc->sc_rev = prom_getpropint(sc->sc_node, "revlev", 0); | | 231 | sc->sc_rev = prom_getpropint(sc->sc_node, "revlev", 0); |
232 | | | 232 | |
233 | sc->sc_osc = prom_getpropint(sc->sc_node, "verosc", 0); | | 233 | sc->sc_osc = prom_getpropint(sc->sc_node, "verosc", 0); |
234 | switch (sc->sc_osc) { | | 234 | switch (sc->sc_osc) { |
235 | case SPIF_OSC10: | | 235 | case SPIF_OSC10: |
236 | sc->sc_osc = 10000000; | | 236 | sc->sc_osc = 10000000; |
237 | break; | | 237 | break; |
238 | case SPIF_OSC9: | | 238 | case SPIF_OSC9: |
239 | default: | | 239 | default: |
240 | sc->sc_osc = 9830400; | | 240 | sc->sc_osc = 9830400; |
241 | break; | | 241 | break; |
242 | } | | 242 | } |
243 | | | 243 | |
244 | sc->sc_nser = 8; | | 244 | sc->sc_nser = 8; |
245 | sc->sc_npar = 1; | | 245 | sc->sc_npar = 1; |
246 | | | 246 | |
247 | sc->sc_rev2 = STC_READ(sc, STC_GFRCR); | | 247 | sc->sc_rev2 = STC_READ(sc, STC_GFRCR); |
248 | STC_WRITE(sc, STC_GSVR, 0); | | 248 | STC_WRITE(sc, STC_GSVR, 0); |
249 | | | 249 | |
250 | stty_write_ccr(sc, CD180_CCR_CMD_RESET | CD180_CCR_RESETALL); | | 250 | stty_write_ccr(sc, CD180_CCR_CMD_RESET | CD180_CCR_RESETALL); |
251 | while (STC_READ(sc, STC_GSVR) != 0xff); | | 251 | while (STC_READ(sc, STC_GSVR) != 0xff); |
252 | while (STC_READ(sc, STC_GFRCR) != sc->sc_rev2); | | 252 | while (STC_READ(sc, STC_GFRCR) != sc->sc_rev2); |
253 | | | 253 | |
254 | STC_WRITE(sc, STC_PPRH, CD180_PPRH); | | 254 | STC_WRITE(sc, STC_PPRH, CD180_PPRH); |
255 | STC_WRITE(sc, STC_PPRL, CD180_PPRL); | | 255 | STC_WRITE(sc, STC_PPRL, CD180_PPRL); |
256 | STC_WRITE(sc, STC_MSMR, SPIF_MSMR); | | 256 | STC_WRITE(sc, STC_MSMR, SPIF_MSMR); |
257 | STC_WRITE(sc, STC_TSMR, SPIF_TSMR); | | 257 | STC_WRITE(sc, STC_TSMR, SPIF_TSMR); |
258 | STC_WRITE(sc, STC_RSMR, SPIF_RSMR); | | 258 | STC_WRITE(sc, STC_RSMR, SPIF_RSMR); |
259 | STC_WRITE(sc, STC_GSVR, 0); | | 259 | STC_WRITE(sc, STC_GSVR, 0); |
260 | STC_WRITE(sc, STC_GSCR1, 0); | | 260 | STC_WRITE(sc, STC_GSCR1, 0); |
261 | STC_WRITE(sc, STC_GSCR2, 0); | | 261 | STC_WRITE(sc, STC_GSCR2, 0); |
262 | STC_WRITE(sc, STC_GSCR3, 0); | | 262 | STC_WRITE(sc, STC_GSCR3, 0); |
263 | | | 263 | |
264 | printf(": rev %x chiprev %x osc %sMHz\n", | | 264 | printf(": rev %x chiprev %x osc %sMHz\n", |
265 | sc->sc_rev, sc->sc_rev2, clockfreq(sc->sc_osc)); | | 265 | sc->sc_rev, sc->sc_rev2, clockfreq(sc->sc_osc)); |
266 | | | 266 | |
267 | (void)config_found(self, stty_match, NULL); | | 267 | (void)config_found(self, stty_match, NULL); |
268 | (void)config_found(self, sbpp_match, NULL); | | 268 | (void)config_found(self, sbpp_match, NULL); |
269 | | | 269 | |
270 | return; | | 270 | return; |
271 | | | 271 | |
272 | fail_unmapregs: | | 272 | fail_unmapregs: |
273 | bus_space_unmap(sa->sa_bustag, sc->sc_regh, sa->sa_size); | | 273 | bus_space_unmap(sa->sa_bustag, sc->sc_regh, sa->sa_size); |
274 | } | | 274 | } |
275 | | | 275 | |
276 | int | | 276 | int |
277 | stty_match(parent, vcf, aux) | | 277 | stty_match(parent, vcf, aux) |
278 | struct device *parent; | | 278 | struct device *parent; |
279 | struct cfdata *vcf; | | 279 | struct cfdata *vcf; |
280 | void *aux; | | 280 | void *aux; |
281 | { | | 281 | { |
282 | struct spif_softc *sc = device_private(parent); | | 282 | struct spif_softc *sc = device_private(parent); |
283 | | | 283 | |
284 | return (aux == stty_match && sc->sc_ttys == NULL); | | 284 | return (aux == stty_match && sc->sc_ttys == NULL); |
285 | } | | 285 | } |
286 | | | 286 | |
287 | void | | 287 | void |
288 | stty_attach(parent, dev, aux) | | 288 | stty_attach(parent, dev, aux) |
289 | struct device *parent, *dev; | | 289 | struct device *parent, *dev; |
290 | void *aux; | | 290 | void *aux; |
291 | { | | 291 | { |
292 | struct spif_softc *sc = device_private(parent); | | 292 | struct spif_softc *sc = device_private(parent); |
293 | struct stty_softc *ssc = device_private(dev); | | 293 | struct stty_softc *ssc = device_private(dev); |
294 | int port; | | 294 | int port; |
295 | | | 295 | |
296 | sc->sc_ttys = ssc; | | 296 | sc->sc_ttys = ssc; |
297 | | | 297 | |
298 | for (port = 0; port < sc->sc_nser; port++) { | | 298 | for (port = 0; port < sc->sc_nser; port++) { |
299 | struct stty_port *sp = &ssc->sc_port[port]; | | 299 | struct stty_port *sp = &ssc->sc_port[port]; |
300 | struct tty *tp; | | 300 | struct tty *tp; |
301 | | | 301 | |
302 | DTR_WRITE(sc, port, 0); | | 302 | DTR_WRITE(sc, port, 0); |
303 | | | 303 | |
304 | tp = ttymalloc(); | | 304 | tp = ttymalloc(); |
305 | | | 305 | |
306 | tp->t_oproc = stty_start; | | 306 | tp->t_oproc = stty_start; |
307 | tp->t_param = stty_param; | | 307 | tp->t_param = stty_param; |
308 | | | 308 | |
309 | sp->sp_tty = tp; | | 309 | sp->sp_tty = tp; |
310 | sp->sp_sc = sc; | | 310 | sp->sp_sc = sc; |
311 | sp->sp_channel = port; | | 311 | sp->sp_channel = port; |
312 | | | 312 | |
313 | sp->sp_rbuf = malloc(STTY_RBUF_SIZE, M_DEVBUF, M_NOWAIT); | | 313 | sp->sp_rbuf = malloc(STTY_RBUF_SIZE, M_DEVBUF, M_NOWAIT); |
314 | if(sp->sp_rbuf == NULL) | | 314 | if(sp->sp_rbuf == NULL) |
315 | break; | | 315 | break; |
316 | | | 316 | |
317 | sp->sp_rend = sp->sp_rbuf + STTY_RBUF_SIZE; | | 317 | sp->sp_rend = sp->sp_rbuf + STTY_RBUF_SIZE; |
318 | } | | 318 | } |
319 | | | 319 | |
320 | ssc->sc_nports = port; | | 320 | ssc->sc_nports = port; |
321 | | | 321 | |
322 | printf(": %d tty%s\n", port, port == 1 ? "" : "s"); | | 322 | printf(": %d tty%s\n", port, port == 1 ? "" : "s"); |
323 | } | | 323 | } |
324 | | | 324 | |
325 | int | | 325 | int |
326 | stty_open(dev_t dev, int flags, int mode, struct lwp *l) | | 326 | stty_open(dev_t dev, int flags, int mode, struct lwp *l) |
327 | { | | 327 | { |
328 | struct spif_softc *csc; | | 328 | struct spif_softc *csc; |
329 | struct stty_softc *sc; | | 329 | struct stty_softc *sc; |
330 | struct stty_port *sp; | | 330 | struct stty_port *sp; |
331 | struct tty *tp; | | 331 | struct tty *tp; |
332 | int card = SPIF_CARD(dev); | | 332 | int card = SPIF_CARD(dev); |
333 | int port = SPIF_PORT(dev); | | 333 | int port = SPIF_PORT(dev); |
334 | | | 334 | |
335 | sc = device_lookup_private(&stty_cd, card); | | 335 | sc = device_lookup_private(&stty_cd, card); |
336 | csc = device_lookup_private(&spif_cd, card); | | 336 | csc = device_lookup_private(&spif_cd, card); |
337 | if (sc == NULL || csc == NULL) | | 337 | if (sc == NULL || csc == NULL) |
338 | return (ENXIO); | | 338 | return (ENXIO); |
339 | | | 339 | |
340 | if (port >= sc->sc_nports) | | 340 | if (port >= sc->sc_nports) |
341 | return (ENXIO); | | 341 | return (ENXIO); |
342 | | | 342 | |
343 | sp = &sc->sc_port[port]; | | 343 | sp = &sc->sc_port[port]; |
344 | tp = sp->sp_tty; | | 344 | tp = sp->sp_tty; |
345 | tp->t_dev = dev; | | 345 | tp->t_dev = dev; |
346 | | | 346 | |
347 | if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) | | 347 | if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) |
348 | return (EBUSY); | | 348 | return (EBUSY); |
349 | | | 349 | |
350 | mutex_spin_enter(&tty_lock); | | 350 | mutex_spin_enter(&tty_lock); |
351 | if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { | | 351 | if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { |
352 | ttychars(tp); | | 352 | ttychars(tp); |
353 | tp->t_iflag = TTYDEF_IFLAG; | | 353 | tp->t_iflag = TTYDEF_IFLAG; |
354 | tp->t_oflag = TTYDEF_OFLAG; | | 354 | tp->t_oflag = TTYDEF_OFLAG; |
355 | tp->t_cflag = TTYDEF_CFLAG; | | 355 | tp->t_cflag = TTYDEF_CFLAG; |
356 | if (ISSET(sp->sp_openflags, TIOCFLAG_CLOCAL)) | | 356 | if (ISSET(sp->sp_openflags, TIOCFLAG_CLOCAL)) |
357 | SET(tp->t_cflag, CLOCAL); | | 357 | SET(tp->t_cflag, CLOCAL); |
358 | if (ISSET(sp->sp_openflags, TIOCFLAG_CRTSCTS)) | | 358 | if (ISSET(sp->sp_openflags, TIOCFLAG_CRTSCTS)) |
359 | SET(tp->t_cflag, CRTSCTS); | | 359 | SET(tp->t_cflag, CRTSCTS); |
360 | if (ISSET(sp->sp_openflags, TIOCFLAG_MDMBUF)) | | 360 | if (ISSET(sp->sp_openflags, TIOCFLAG_MDMBUF)) |
361 | SET(tp->t_cflag, MDMBUF); | | 361 | SET(tp->t_cflag, MDMBUF); |
362 | tp->t_lflag = TTYDEF_LFLAG; | | 362 | tp->t_lflag = TTYDEF_LFLAG; |
363 | tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; | | 363 | tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; |
364 | | | 364 | |
365 | sp->sp_rput = sp->sp_rget = sp->sp_rbuf; | | 365 | sp->sp_rput = sp->sp_rget = sp->sp_rbuf; |
366 | | | 366 | |
367 | STC_WRITE(csc, STC_CAR, sp->sp_channel); | | 367 | STC_WRITE(csc, STC_CAR, sp->sp_channel); |
368 | stty_write_ccr(csc, CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN); | | 368 | stty_write_ccr(csc, CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN); |
369 | STC_WRITE(csc, STC_CAR, sp->sp_channel); | | 369 | STC_WRITE(csc, STC_CAR, sp->sp_channel); |
370 | | | 370 | |
371 | stty_param(tp, &tp->t_termios); | | 371 | stty_param(tp, &tp->t_termios); |
372 | | | 372 | |
373 | ttsetwater(tp); | | 373 | ttsetwater(tp); |
374 | | | 374 | |
375 | STC_WRITE(csc, STC_SRER, CD180_SRER_CD | CD180_SRER_RXD); | | 375 | STC_WRITE(csc, STC_SRER, CD180_SRER_CD | CD180_SRER_RXD); |
376 | | | 376 | |
377 | if (ISSET(sp->sp_openflags, TIOCFLAG_SOFTCAR) || sp->sp_carrier) | | 377 | if (ISSET(sp->sp_openflags, TIOCFLAG_SOFTCAR) || sp->sp_carrier) |
378 | SET(tp->t_state, TS_CARR_ON); | | 378 | SET(tp->t_state, TS_CARR_ON); |
379 | else | | 379 | else |
380 | CLR(tp->t_state, TS_CARR_ON); | | 380 | CLR(tp->t_state, TS_CARR_ON); |
381 | } | | 381 | } |
382 | | | 382 | |
383 | if (!ISSET(flags, O_NONBLOCK)) { | | 383 | if (!ISSET(flags, O_NONBLOCK)) { |
384 | while (!ISSET(tp->t_cflag, CLOCAL) && | | 384 | while (!ISSET(tp->t_cflag, CLOCAL) && |
385 | !ISSET(tp->t_state, TS_CARR_ON)) { | | 385 | !ISSET(tp->t_state, TS_CARR_ON)) { |
386 | int error; | | 386 | int error; |
387 | error = ttysleep(tp, &tp->t_rawcv, true, 0); | | 387 | error = ttysleep(tp, &tp->t_rawcv, true, 0); |
388 | if (error != 0) { | | 388 | if (error != 0) { |
389 | mutex_spin_exit(&tty_lock); | | 389 | mutex_spin_exit(&tty_lock); |
390 | return (error); | | 390 | return (error); |
391 | } | | 391 | } |
392 | } | | 392 | } |
393 | } | | 393 | } |
394 | mutex_spin_exit(&tty_lock); | | 394 | mutex_spin_exit(&tty_lock); |
395 | | | 395 | |
396 | return ((*tp->t_linesw->l_open)(dev, tp)); | | 396 | return ((*tp->t_linesw->l_open)(dev, tp)); |
397 | } | | 397 | } |
398 | | | 398 | |
399 | int | | 399 | int |
400 | stty_close(dev_t dev, int flags, int mode, struct lwp *l) | | 400 | stty_close(dev_t dev, int flags, int mode, struct lwp *l) |
401 | { | | 401 | { |
402 | struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev)); | | 402 | struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev)); |
403 | struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; | | 403 | struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; |
404 | struct spif_softc *csc = sp->sp_sc; | | 404 | struct spif_softc *csc = sp->sp_sc; |
405 | struct tty *tp = sp->sp_tty; | | 405 | struct tty *tp = sp->sp_tty; |
406 | int port = SPIF_PORT(dev); | | 406 | int port = SPIF_PORT(dev); |
407 | int s; | | 407 | int s; |
408 | | | 408 | |
409 | (*tp->t_linesw->l_close)(tp, flags); | | 409 | (*tp->t_linesw->l_close)(tp, flags); |
410 | s = spltty(); | | 410 | s = spltty(); |
411 | | | 411 | |
412 | if (ISSET(tp->t_cflag, HUPCL) || !ISSET(tp->t_state, TS_ISOPEN)) { | | 412 | if (ISSET(tp->t_cflag, HUPCL) || !ISSET(tp->t_state, TS_ISOPEN)) { |
413 | stty_modem_control(sp, 0, DMSET); | | 413 | stty_modem_control(sp, 0, DMSET); |
414 | STC_WRITE(csc, STC_CAR, port); | | 414 | STC_WRITE(csc, STC_CAR, port); |
415 | STC_WRITE(csc, STC_CCR, | | 415 | STC_WRITE(csc, STC_CCR, |
416 | CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN); | | 416 | CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN); |
417 | } | | 417 | } |
418 | | | 418 | |
419 | splx(s); | | 419 | splx(s); |
420 | ttyclose(tp); | | 420 | ttyclose(tp); |
421 | return (0); | | 421 | return (0); |
422 | } | | 422 | } |
423 | | | 423 | |
424 | int | | 424 | int |
425 | stty_ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) | | 425 | stty_ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) |
426 | { | | 426 | { |
427 | struct stty_softc *stc = device_lookup_private(&stty_cd, | | 427 | struct stty_softc *stc = device_lookup_private(&stty_cd, |
428 | SPIF_CARD(dev)); | | 428 | SPIF_CARD(dev)); |
429 | struct stty_port *sp = &stc->sc_port[SPIF_PORT(dev)]; | | 429 | struct stty_port *sp = &stc->sc_port[SPIF_PORT(dev)]; |
430 | struct spif_softc *sc = sp->sp_sc; | | 430 | struct spif_softc *sc = sp->sp_sc; |
431 | struct tty *tp = sp->sp_tty; | | 431 | struct tty *tp = sp->sp_tty; |
432 | int error; | | 432 | int error; |
433 | | | 433 | |
434 | error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flags, l); | | 434 | error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flags, l); |
435 | if (error >= 0) | | 435 | if (error >= 0) |
436 | return (error); | | 436 | return (error); |
437 | | | 437 | |
438 | error = ttioctl(tp, cmd, data, flags, l); | | 438 | error = ttioctl(tp, cmd, data, flags, l); |
439 | if (error >= 0) | | 439 | if (error >= 0) |
440 | return (error); | | 440 | return (error); |
441 | | | 441 | |
442 | error = 0; | | 442 | error = 0; |
443 | | | 443 | |
444 | switch (cmd) { | | 444 | switch (cmd) { |
445 | case TIOCSBRK: | | 445 | case TIOCSBRK: |
446 | SET(sp->sp_flags, STTYF_SET_BREAK); | | 446 | SET(sp->sp_flags, STTYF_SET_BREAK); |
447 | STC_WRITE(sc, STC_CAR, sp->sp_channel); | | 447 | STC_WRITE(sc, STC_CAR, sp->sp_channel); |
448 | STC_WRITE(sc, STC_SRER, | | 448 | STC_WRITE(sc, STC_SRER, |
449 | STC_READ(sc, STC_SRER) | CD180_SRER_TXD); | | 449 | STC_READ(sc, STC_SRER) | CD180_SRER_TXD); |
450 | break; | | 450 | break; |
451 | case TIOCCBRK: | | 451 | case TIOCCBRK: |
452 | SET(sp->sp_flags, STTYF_CLR_BREAK); | | 452 | SET(sp->sp_flags, STTYF_CLR_BREAK); |
453 | STC_WRITE(sc, STC_CAR, sp->sp_channel); | | 453 | STC_WRITE(sc, STC_CAR, sp->sp_channel); |
454 | STC_WRITE(sc, STC_SRER, | | 454 | STC_WRITE(sc, STC_SRER, |
455 | STC_READ(sc, STC_SRER) | CD180_SRER_TXD); | | 455 | STC_READ(sc, STC_SRER) | CD180_SRER_TXD); |
456 | break; | | 456 | break; |
457 | case TIOCSDTR: | | 457 | case TIOCSDTR: |
458 | stty_modem_control(sp, TIOCM_DTR, DMBIS); | | 458 | stty_modem_control(sp, TIOCM_DTR, DMBIS); |
459 | break; | | 459 | break; |
460 | case TIOCCDTR: | | 460 | case TIOCCDTR: |
461 | stty_modem_control(sp, TIOCM_DTR, DMBIC); | | 461 | stty_modem_control(sp, TIOCM_DTR, DMBIC); |
462 | break; | | 462 | break; |
463 | case TIOCMBIS: | | 463 | case TIOCMBIS: |
464 | stty_modem_control(sp, *((int *)data), DMBIS); | | 464 | stty_modem_control(sp, *((int *)data), DMBIS); |
465 | break; | | 465 | break; |
466 | case TIOCMBIC: | | 466 | case TIOCMBIC: |
467 | stty_modem_control(sp, *((int *)data), DMBIC); | | 467 | stty_modem_control(sp, *((int *)data), DMBIC); |
468 | break; | | 468 | break; |
469 | case TIOCMGET: | | 469 | case TIOCMGET: |
470 | *((int *)data) = stty_modem_control(sp, 0, DMGET); | | 470 | *((int *)data) = stty_modem_control(sp, 0, DMGET); |
471 | break; | | 471 | break; |
472 | case TIOCMSET: | | 472 | case TIOCMSET: |
473 | stty_modem_control(sp, *((int *)data), DMSET); | | 473 | stty_modem_control(sp, *((int *)data), DMSET); |
474 | break; | | 474 | break; |
475 | case TIOCGFLAGS: | | 475 | case TIOCGFLAGS: |
476 | *((int *)data) = sp->sp_openflags; | | 476 | *((int *)data) = sp->sp_openflags; |
477 | break; | | 477 | break; |
478 | case TIOCSFLAGS: | | 478 | case TIOCSFLAGS: |
479 | if (kauth_authorize_device_tty(l->l_cred, | | 479 | if (kauth_authorize_device_tty(l->l_cred, |
480 | KAUTH_DEVICE_TTY_PRIVSET, tp)) | | 480 | KAUTH_DEVICE_TTY_PRIVSET, tp)) |
481 | error = EPERM; | | 481 | error = EPERM; |
482 | else | | 482 | else |
483 | sp->sp_openflags = *((int *)data) & | | 483 | sp->sp_openflags = *((int *)data) & |
484 | (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | | | 484 | (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | |
485 | TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF); | | 485 | TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF); |
486 | break; | | 486 | break; |
487 | default: | | 487 | default: |
488 | error = ENOTTY; | | 488 | error = ENOTTY; |
489 | } | | 489 | } |
490 | | | 490 | |
491 | return (error); | | 491 | return (error); |
492 | } | | 492 | } |
493 | | | 493 | |
494 | int | | 494 | int |
495 | stty_modem_control(sp, bits, how) | | 495 | stty_modem_control(sp, bits, how) |
496 | struct stty_port *sp; | | 496 | struct stty_port *sp; |
497 | int bits, how; | | 497 | int bits, how; |
498 | { | | 498 | { |
499 | struct spif_softc *csc = sp->sp_sc; | | 499 | struct spif_softc *csc = sp->sp_sc; |
500 | struct tty *tp = sp->sp_tty; | | 500 | struct tty *tp = sp->sp_tty; |
501 | int s, msvr; | | 501 | int s, msvr; |
502 | | | 502 | |
503 | s = spltty(); | | 503 | s = spltty(); |
504 | STC_WRITE(csc, STC_CAR, sp->sp_channel); | | 504 | STC_WRITE(csc, STC_CAR, sp->sp_channel); |
505 | | | 505 | |
506 | switch (how) { | | 506 | switch (how) { |
507 | case DMGET: | | 507 | case DMGET: |
508 | bits = TIOCM_LE; | | 508 | bits = TIOCM_LE; |
509 | if (DTR_READ(csc, sp->sp_channel)) | | 509 | if (DTR_READ(csc, sp->sp_channel)) |
510 | bits |= TIOCM_DTR; | | 510 | bits |= TIOCM_DTR; |
511 | msvr = STC_READ(csc, STC_MSVR); | | 511 | msvr = STC_READ(csc, STC_MSVR); |
512 | if (ISSET(msvr, CD180_MSVR_DSR)) | | 512 | if (ISSET(msvr, CD180_MSVR_DSR)) |
513 | bits |= TIOCM_DSR; | | 513 | bits |= TIOCM_DSR; |
514 | if (ISSET(msvr, CD180_MSVR_CD)) | | 514 | if (ISSET(msvr, CD180_MSVR_CD)) |
515 | bits |= TIOCM_CD; | | 515 | bits |= TIOCM_CD; |
516 | if (ISSET(msvr, CD180_MSVR_CTS)) | | 516 | if (ISSET(msvr, CD180_MSVR_CTS)) |
517 | bits |= TIOCM_CTS; | | 517 | bits |= TIOCM_CTS; |
518 | if (ISSET(msvr, CD180_MSVR_RTS)) | | 518 | if (ISSET(msvr, CD180_MSVR_RTS)) |
519 | bits |= TIOCM_RTS; | | 519 | bits |= TIOCM_RTS; |
520 | break; | | 520 | break; |
521 | case DMSET: | | 521 | case DMSET: |
522 | DTR_WRITE(csc, sp->sp_channel, ISSET(bits, TIOCM_DTR) ? 1 : 0); | | 522 | DTR_WRITE(csc, sp->sp_channel, ISSET(bits, TIOCM_DTR) ? 1 : 0); |
523 | if (ISSET(bits, TIOCM_RTS)) | | 523 | if (ISSET(bits, TIOCM_RTS)) |
524 | STC_WRITE(csc, STC_MSVR, | | 524 | STC_WRITE(csc, STC_MSVR, |
525 | STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS)); | | 525 | STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS)); |
526 | else | | 526 | else |
527 | STC_WRITE(csc, STC_MSVR, | | 527 | STC_WRITE(csc, STC_MSVR, |
528 | STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS); | | 528 | STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS); |
529 | break; | | 529 | break; |
530 | case DMBIS: | | 530 | case DMBIS: |
531 | if (ISSET(bits, TIOCM_DTR)) | | 531 | if (ISSET(bits, TIOCM_DTR)) |
532 | DTR_WRITE(csc, sp->sp_channel, 1); | | 532 | DTR_WRITE(csc, sp->sp_channel, 1); |
533 | if (ISSET(bits, TIOCM_RTS) && !ISSET(tp->t_cflag, CRTSCTS)) | | 533 | if (ISSET(bits, TIOCM_RTS) && !ISSET(tp->t_cflag, CRTSCTS)) |
534 | STC_WRITE(csc, STC_MSVR, | | 534 | STC_WRITE(csc, STC_MSVR, |
535 | STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS)); | | 535 | STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS)); |
536 | break; | | 536 | break; |
537 | case DMBIC: | | 537 | case DMBIC: |
538 | if (ISSET(bits, TIOCM_DTR)) | | 538 | if (ISSET(bits, TIOCM_DTR)) |
539 | DTR_WRITE(csc, sp->sp_channel, 0); | | 539 | DTR_WRITE(csc, sp->sp_channel, 0); |
540 | if (ISSET(bits, TIOCM_RTS)) | | 540 | if (ISSET(bits, TIOCM_RTS)) |
541 | STC_WRITE(csc, STC_MSVR, | | 541 | STC_WRITE(csc, STC_MSVR, |
542 | STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS); | | 542 | STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS); |
543 | break; | | 543 | break; |
544 | } | | 544 | } |
545 | | | 545 | |
546 | splx(s); | | 546 | splx(s); |
547 | return (bits); | | 547 | return (bits); |
548 | } | | 548 | } |
549 | | | 549 | |
550 | int | | 550 | int |
551 | stty_param(struct tty *tp, struct termios *t) | | 551 | stty_param(struct tty *tp, struct termios *t) |
552 | { | | 552 | { |
553 | struct stty_softc *st = device_lookup_private(&stty_cd, | | 553 | struct stty_softc *st = device_lookup_private(&stty_cd, |
554 | SPIF_CARD(tp->t_dev)); | | 554 | SPIF_CARD(tp->t_dev)); |
555 | struct stty_port *sp = &st->sc_port[SPIF_PORT(tp->t_dev)]; | | 555 | struct stty_port *sp = &st->sc_port[SPIF_PORT(tp->t_dev)]; |
556 | struct spif_softc *sc = sp->sp_sc; | | 556 | struct spif_softc *sc = sp->sp_sc; |
557 | u_int8_t rbprl, rbprh, tbprl, tbprh; | | 557 | u_int8_t rbprl, rbprh, tbprl, tbprh; |
558 | int s, opt; | | 558 | int s, opt; |
559 | | | 559 | |
560 | if (t->c_ospeed && | | 560 | if (t->c_ospeed && |
561 | stty_compute_baud(t->c_ospeed, sc->sc_osc, &tbprl, &tbprh)) | | 561 | stty_compute_baud(t->c_ospeed, sc->sc_osc, &tbprl, &tbprh)) |
562 | return (EINVAL); | | 562 | return (EINVAL); |
563 | | | 563 | |
564 | if (t->c_ispeed && | | 564 | if (t->c_ispeed && |
565 | stty_compute_baud(t->c_ispeed, sc->sc_osc, &rbprl, &rbprh)) | | 565 | stty_compute_baud(t->c_ispeed, sc->sc_osc, &rbprl, &rbprh)) |
566 | return (EINVAL); | | 566 | return (EINVAL); |
567 | | | 567 | |
568 | s = spltty(); | | 568 | s = spltty(); |
569 | | | 569 | |
570 | /* hang up line if ospeed is zero, otherwise raise DTR */ | | 570 | /* hang up line if ospeed is zero, otherwise raise DTR */ |
571 | stty_modem_control(sp, TIOCM_DTR, | | 571 | stty_modem_control(sp, TIOCM_DTR, |
572 | (t->c_ospeed == 0 ? DMBIC : DMBIS)); | | 572 | (t->c_ospeed == 0 ? DMBIC : DMBIS)); |
573 | | | 573 | |
574 | STC_WRITE(sc, STC_CAR, sp->sp_channel); | | 574 | STC_WRITE(sc, STC_CAR, sp->sp_channel); |
575 | | | 575 | |
576 | opt = 0; | | 576 | opt = 0; |
577 | if (ISSET(t->c_cflag, PARENB)) { | | 577 | if (ISSET(t->c_cflag, PARENB)) { |
578 | opt |= CD180_COR1_PARMODE_NORMAL; | | 578 | opt |= CD180_COR1_PARMODE_NORMAL; |
579 | opt |= (ISSET(t->c_cflag, PARODD) ? | | 579 | opt |= (ISSET(t->c_cflag, PARODD) ? |
580 | CD180_COR1_ODDPAR : | | 580 | CD180_COR1_ODDPAR : |
581 | CD180_COR1_EVENPAR); | | 581 | CD180_COR1_EVENPAR); |
582 | } | | 582 | } |
583 | else | | 583 | else |
584 | opt |= CD180_COR1_PARMODE_NO; | | 584 | opt |= CD180_COR1_PARMODE_NO; |
585 | | | 585 | |
586 | if (!ISSET(t->c_iflag, INPCK)) | | 586 | if (!ISSET(t->c_iflag, INPCK)) |
587 | opt |= CD180_COR1_IGNPAR; | | 587 | opt |= CD180_COR1_IGNPAR; |
588 | | | 588 | |
589 | if (ISSET(t->c_cflag, CSTOPB)) | | 589 | if (ISSET(t->c_cflag, CSTOPB)) |
590 | opt |= CD180_COR1_STOP2; | | 590 | opt |= CD180_COR1_STOP2; |
591 | | | 591 | |
592 | switch (t->c_cflag & CSIZE) { | | 592 | switch (t->c_cflag & CSIZE) { |
593 | case CS5: | | 593 | case CS5: |
594 | opt |= CD180_COR1_CS5; | | 594 | opt |= CD180_COR1_CS5; |
595 | break; | | 595 | break; |
596 | case CS6: | | 596 | case CS6: |
597 | opt |= CD180_COR1_CS6; | | 597 | opt |= CD180_COR1_CS6; |
598 | break; | | 598 | break; |
599 | case CS7: | | 599 | case CS7: |
600 | opt |= CD180_COR1_CS7; | | 600 | opt |= CD180_COR1_CS7; |
601 | break; | | 601 | break; |
602 | default: | | 602 | default: |
603 | opt |= CD180_COR1_CS8; | | 603 | opt |= CD180_COR1_CS8; |
604 | break; | | 604 | break; |
605 | } | | 605 | } |
606 | STC_WRITE(sc, STC_COR1, opt); | | 606 | STC_WRITE(sc, STC_COR1, opt); |
607 | stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG1); | | 607 | stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG1); |
608 | | | 608 | |
609 | opt = CD180_COR2_ETC; | | 609 | opt = CD180_COR2_ETC; |
610 | if (ISSET(t->c_cflag, CRTSCTS)) | | 610 | if (ISSET(t->c_cflag, CRTSCTS)) |
611 | opt |= CD180_COR2_CTSAE; | | 611 | opt |= CD180_COR2_CTSAE; |
612 | STC_WRITE(sc, STC_COR2, opt); | | 612 | STC_WRITE(sc, STC_COR2, opt); |
613 | stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG2); | | 613 | stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG2); |
614 | | | 614 | |
615 | STC_WRITE(sc, STC_COR3, STTY_RX_FIFO_THRESHOLD); | | 615 | STC_WRITE(sc, STC_COR3, STTY_RX_FIFO_THRESHOLD); |
616 | stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG3); | | 616 | stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG3); |
617 | | | 617 | |
618 | STC_WRITE(sc, STC_SCHR1, 0x11); | | 618 | STC_WRITE(sc, STC_SCHR1, 0x11); |
619 | STC_WRITE(sc, STC_SCHR2, 0x13); | | 619 | STC_WRITE(sc, STC_SCHR2, 0x13); |
620 | STC_WRITE(sc, STC_SCHR3, 0x11); | | 620 | STC_WRITE(sc, STC_SCHR3, 0x11); |
621 | STC_WRITE(sc, STC_SCHR4, 0x13); | | 621 | STC_WRITE(sc, STC_SCHR4, 0x13); |
622 | STC_WRITE(sc, STC_RTPR, 0x12); | | 622 | STC_WRITE(sc, STC_RTPR, 0x12); |
623 | | | 623 | |
624 | STC_WRITE(sc, STC_MCOR1, CD180_MCOR1_CDZD | STTY_RX_DTR_THRESHOLD); | | 624 | STC_WRITE(sc, STC_MCOR1, CD180_MCOR1_CDZD | STTY_RX_DTR_THRESHOLD); |
625 | STC_WRITE(sc, STC_MCOR2, CD180_MCOR2_CDOD); | | 625 | STC_WRITE(sc, STC_MCOR2, CD180_MCOR2_CDOD); |
626 | STC_WRITE(sc, STC_MCR, 0); | | 626 | STC_WRITE(sc, STC_MCR, 0); |
627 | | | 627 | |
628 | if (t->c_ospeed) { | | 628 | if (t->c_ospeed) { |
629 | STC_WRITE(sc, STC_TBPRH, tbprh); | | 629 | STC_WRITE(sc, STC_TBPRH, tbprh); |
630 | STC_WRITE(sc, STC_TBPRL, tbprl); | | 630 | STC_WRITE(sc, STC_TBPRL, tbprl); |
631 | } | | 631 | } |
632 | | | 632 | |
633 | if (t->c_ispeed) { | | 633 | if (t->c_ispeed) { |
634 | STC_WRITE(sc, STC_RBPRH, rbprh); | | 634 | STC_WRITE(sc, STC_RBPRH, rbprh); |
635 | STC_WRITE(sc, STC_RBPRL, rbprl); | | 635 | STC_WRITE(sc, STC_RBPRL, rbprl); |
636 | } | | 636 | } |
637 | | | 637 | |
638 | stty_write_ccr(sc, CD180_CCR_CMD_CHAN | | | 638 | stty_write_ccr(sc, CD180_CCR_CMD_CHAN | |
639 | CD180_CCR_CHAN_TXEN | CD180_CCR_CHAN_RXEN); | | 639 | CD180_CCR_CHAN_TXEN | CD180_CCR_CHAN_RXEN); |
640 | | | 640 | |
641 | sp->sp_carrier = STC_READ(sc, STC_MSVR) & CD180_MSVR_CD; | | 641 | sp->sp_carrier = STC_READ(sc, STC_MSVR) & CD180_MSVR_CD; |
642 | | | 642 | |
643 | splx(s); | | 643 | splx(s); |
644 | return (0); | | 644 | return (0); |
645 | } | | 645 | } |
646 | | | 646 | |
647 | int | | 647 | int |
648 | stty_read(dev_t dev, struct uio *uio, int flags) | | 648 | stty_read(dev_t dev, struct uio *uio, int flags) |
649 | { | | 649 | { |
650 | struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev)); | | 650 | struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev)); |
651 | struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; | | 651 | struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; |
652 | struct tty *tp = sp->sp_tty; | | 652 | struct tty *tp = sp->sp_tty; |
653 | | | 653 | |
654 | return ((*tp->t_linesw->l_read)(tp, uio, flags)); | | 654 | return ((*tp->t_linesw->l_read)(tp, uio, flags)); |
655 | } | | 655 | } |
656 | | | 656 | |
657 | int | | 657 | int |
658 | stty_write(dev_t dev, struct uio *uio, int flags) | | 658 | stty_write(dev_t dev, struct uio *uio, int flags) |
659 | { | | 659 | { |
660 | struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev)); | | 660 | struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev)); |
661 | struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; | | 661 | struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; |
662 | struct tty *tp = sp->sp_tty; | | 662 | struct tty *tp = sp->sp_tty; |
663 | | | 663 | |
664 | return ((*tp->t_linesw->l_write)(tp, uio, flags)); | | 664 | return ((*tp->t_linesw->l_write)(tp, uio, flags)); |
665 | } | | 665 | } |
666 | | | 666 | |
667 | int | | 667 | int |
668 | stty_poll(dev_t dev, int events, struct lwp *l) | | 668 | stty_poll(dev_t dev, int events, struct lwp *l) |
669 | { | | 669 | { |
670 | struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev)); | | 670 | struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev)); |
671 | struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; | | 671 | struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; |
672 | struct tty *tp = sp->sp_tty; | | 672 | struct tty *tp = sp->sp_tty; |
673 | | | 673 | |
674 | return ((*tp->t_linesw->l_poll)(tp, events, l)); | | 674 | return ((*tp->t_linesw->l_poll)(tp, events, l)); |
675 | } | | 675 | } |
676 | | | 676 | |
677 | struct tty * | | 677 | struct tty * |
678 | stty_tty(dev_t dev) | | 678 | stty_tty(dev_t dev) |
679 | { | | 679 | { |
680 | struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev)); | | 680 | struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev)); |
681 | struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; | | 681 | struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; |
682 | | | 682 | |
683 | return (sp->sp_tty); | | 683 | return (sp->sp_tty); |
684 | } | | 684 | } |
685 | | | 685 | |
686 | void | | 686 | void |
687 | stty_stop(struct tty *tp, int flags) | | 687 | stty_stop(struct tty *tp, int flags) |
688 | { | | 688 | { |
689 | struct stty_softc *sc = device_lookup_private(&stty_cd, | | 689 | struct stty_softc *sc = device_lookup_private(&stty_cd, |
690 | SPIF_CARD(tp->t_dev)); | | 690 | SPIF_CARD(tp->t_dev)); |
691 | struct stty_port *sp = &sc->sc_port[SPIF_PORT(tp->t_dev)]; | | 691 | struct stty_port *sp = &sc->sc_port[SPIF_PORT(tp->t_dev)]; |
692 | int s; | | 692 | int s; |
693 | | | 693 | |
694 | s = spltty(); | | 694 | s = spltty(); |
695 | if (ISSET(tp->t_state, TS_BUSY)) { | | 695 | if (ISSET(tp->t_state, TS_BUSY)) { |
696 | if (!ISSET(tp->t_state, TS_TTSTOP)) | | 696 | if (!ISSET(tp->t_state, TS_TTSTOP)) |
697 | SET(tp->t_state, TS_FLUSH); | | 697 | SET(tp->t_state, TS_FLUSH); |
698 | SET(sp->sp_flags, STTYF_STOP); | | 698 | SET(sp->sp_flags, STTYF_STOP); |
699 | } | | 699 | } |
700 | splx(s); | | 700 | splx(s); |
701 | } | | 701 | } |
702 | | | 702 | |
703 | void | | 703 | void |
704 | stty_start(struct tty *tp) | | 704 | stty_start(struct tty *tp) |
705 | { | | 705 | { |
706 | struct stty_softc *stc = device_lookup_private(&stty_cd, | | 706 | struct stty_softc *stc = device_lookup_private(&stty_cd, |
707 | SPIF_CARD(tp->t_dev)); | | 707 | SPIF_CARD(tp->t_dev)); |
708 | struct stty_port *sp = &stc->sc_port[SPIF_PORT(tp->t_dev)]; | | 708 | struct stty_port *sp = &stc->sc_port[SPIF_PORT(tp->t_dev)]; |
709 | struct spif_softc *sc = sp->sp_sc; | | 709 | struct spif_softc *sc = sp->sp_sc; |
710 | int s; | | 710 | int s; |
711 | | | 711 | |
712 | s = spltty(); | | 712 | s = spltty(); |
713 | | | 713 | |
714 | if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) { | | 714 | if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) { |
715 | if (ttypull(tp)) { | | 715 | if (ttypull(tp)) { |
716 | sp->sp_txc = ndqb(&tp->t_outq, 0); | | 716 | sp->sp_txc = ndqb(&tp->t_outq, 0); |
717 | sp->sp_txp = tp->t_outq.c_cf; | | 717 | sp->sp_txp = tp->t_outq.c_cf; |
718 | SET(tp->t_state, TS_BUSY); | | 718 | SET(tp->t_state, TS_BUSY); |
719 | STC_WRITE(sc, STC_CAR, sp->sp_channel); | | 719 | STC_WRITE(sc, STC_CAR, sp->sp_channel); |
720 | STC_WRITE(sc, STC_SRER, | | 720 | STC_WRITE(sc, STC_SRER, |
721 | STC_READ(sc, STC_SRER) | CD180_SRER_TXD); | | 721 | STC_READ(sc, STC_SRER) | CD180_SRER_TXD); |
722 | } | | 722 | } |
723 | } | | 723 | } |
724 | | | 724 | |
725 | splx(s); | | 725 | splx(s); |
726 | } | | 726 | } |
727 | | | 727 | |
728 | int | | 728 | int |
729 | spif_stcintr_rxexception(sc, needsoftp) | | 729 | spif_stcintr_rxexception(sc, needsoftp) |
730 | struct spif_softc *sc; | | 730 | struct spif_softc *sc; |
731 | int *needsoftp; | | 731 | int *needsoftp; |
732 | { | | 732 | { |
733 | struct stty_port *sp; | | 733 | struct stty_port *sp; |
734 | u_int8_t channel, *ptr; | | 734 | u_int8_t channel, *ptr; |
735 | | | 735 | |
736 | channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); | | 736 | channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); |
737 | sp = &sc->sc_ttys->sc_port[channel]; | | 737 | sp = &sc->sc_ttys->sc_port[channel]; |
738 | ptr = sp->sp_rput; | | 738 | ptr = sp->sp_rput; |
739 | *ptr++ = STC_READ(sc, STC_RCSR); | | 739 | *ptr++ = STC_READ(sc, STC_RCSR); |
740 | *ptr++ = STC_READ(sc, STC_RDR); | | 740 | *ptr++ = STC_READ(sc, STC_RDR); |
741 | if (ptr == sp->sp_rend) | | 741 | if (ptr == sp->sp_rend) |
742 | ptr = sp->sp_rbuf; | | 742 | ptr = sp->sp_rbuf; |
743 | if (ptr == sp->sp_rget) { | | 743 | if (ptr == sp->sp_rget) { |
744 | if (ptr == sp->sp_rbuf) | | 744 | if (ptr == sp->sp_rbuf) |
745 | ptr = sp->sp_rend; | | 745 | ptr = sp->sp_rend; |
746 | ptr -= 2; | | 746 | ptr -= 2; |
747 | SET(sp->sp_flags, STTYF_RING_OVERFLOW); | | 747 | SET(sp->sp_flags, STTYF_RING_OVERFLOW); |
748 | } | | 748 | } |
749 | STC_WRITE(sc, STC_EOSRR, 0); | | 749 | STC_WRITE(sc, STC_EOSRR, 0); |
750 | *needsoftp = 1; | | 750 | *needsoftp = 1; |
751 | sp->sp_rput = ptr; | | 751 | sp->sp_rput = ptr; |
752 | return (1); | | 752 | return (1); |
753 | } | | 753 | } |
754 | | | 754 | |
755 | int | | 755 | int |
756 | spif_stcintr_rx(sc, needsoftp) | | 756 | spif_stcintr_rx(sc, needsoftp) |
757 | struct spif_softc *sc; | | 757 | struct spif_softc *sc; |
758 | int *needsoftp; | | 758 | int *needsoftp; |
759 | { | | 759 | { |
760 | struct stty_port *sp; | | 760 | struct stty_port *sp; |
761 | u_int8_t channel, *ptr, cnt, rcsr; | | 761 | u_int8_t channel, *ptr, cnt, rcsr; |
762 | int i; | | 762 | int i; |
763 | | | 763 | |
764 | channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); | | 764 | channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); |
765 | sp = &sc->sc_ttys->sc_port[channel]; | | 765 | sp = &sc->sc_ttys->sc_port[channel]; |
766 | ptr = sp->sp_rput; | | 766 | ptr = sp->sp_rput; |
767 | cnt = STC_READ(sc, STC_RDCR); | | 767 | cnt = STC_READ(sc, STC_RDCR); |
768 | for (i = 0; i < cnt; i++) { | | 768 | for (i = 0; i < cnt; i++) { |
769 | *ptr++ = 0; | | 769 | *ptr++ = 0; |
770 | rcsr = STC_READ(sc, STC_RCSR); | | 770 | rcsr = STC_READ(sc, STC_RCSR); |
771 | *ptr++ = STC_READ(sc, STC_RDR); | | 771 | *ptr++ = STC_READ(sc, STC_RDR); |
772 | if (ptr == sp->sp_rend) | | 772 | if (ptr == sp->sp_rend) |
773 | ptr = sp->sp_rbuf; | | 773 | ptr = sp->sp_rbuf; |
774 | if (ptr == sp->sp_rget) { | | 774 | if (ptr == sp->sp_rget) { |
775 | if (ptr == sp->sp_rbuf) | | 775 | if (ptr == sp->sp_rbuf) |
776 | ptr = sp->sp_rend; | | 776 | ptr = sp->sp_rend; |
777 | ptr -= 2; | | 777 | ptr -= 2; |
778 | SET(sp->sp_flags, STTYF_RING_OVERFLOW); | | 778 | SET(sp->sp_flags, STTYF_RING_OVERFLOW); |
779 | break; | | 779 | break; |
780 | } | | 780 | } |
781 | } | | 781 | } |
782 | STC_WRITE(sc, STC_EOSRR, 0); | | 782 | STC_WRITE(sc, STC_EOSRR, 0); |
783 | if (cnt) { | | 783 | if (cnt) { |
784 | *needsoftp = 1; | | 784 | *needsoftp = 1; |
785 | sp->sp_rput = ptr; | | 785 | sp->sp_rput = ptr; |
786 | } | | 786 | } |
787 | return (1); | | 787 | return (1); |
788 | } | | 788 | } |
789 | | | 789 | |
790 | int | | 790 | int |
791 | spif_stcintr_tx(sc, needsoftp) | | 791 | spif_stcintr_tx(sc, needsoftp) |
792 | struct spif_softc *sc; | | 792 | struct spif_softc *sc; |
793 | int *needsoftp; | | 793 | int *needsoftp; |
794 | { | | 794 | { |
795 | struct stty_port *sp; | | 795 | struct stty_port *sp; |
796 | u_int8_t channel, ch; | | 796 | u_int8_t channel, ch; |
797 | int cnt = 0; | | 797 | int cnt = 0; |
798 | | | 798 | |
799 | channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); | | 799 | channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); |
800 | sp = &sc->sc_ttys->sc_port[channel]; | | 800 | sp = &sc->sc_ttys->sc_port[channel]; |
801 | if (!ISSET(sp->sp_flags, STTYF_STOP)) { | | 801 | if (!ISSET(sp->sp_flags, STTYF_STOP)) { |
802 | if (ISSET(sp->sp_flags, STTYF_SET_BREAK)) { | | 802 | if (ISSET(sp->sp_flags, STTYF_SET_BREAK)) { |
803 | STC_WRITE(sc, STC_TDR, 0); | | 803 | STC_WRITE(sc, STC_TDR, 0); |
804 | STC_WRITE(sc, STC_TDR, 0x81); | | 804 | STC_WRITE(sc, STC_TDR, 0x81); |
805 | CLR(sp->sp_flags, STTYF_SET_BREAK); | | 805 | CLR(sp->sp_flags, STTYF_SET_BREAK); |
806 | cnt += 2; | | 806 | cnt += 2; |
807 | } | | 807 | } |
808 | if (ISSET(sp->sp_flags, STTYF_CLR_BREAK)) { | | 808 | if (ISSET(sp->sp_flags, STTYF_CLR_BREAK)) { |
809 | STC_WRITE(sc, STC_TDR, 0); | | 809 | STC_WRITE(sc, STC_TDR, 0); |
810 | STC_WRITE(sc, STC_TDR, 0x83); | | 810 | STC_WRITE(sc, STC_TDR, 0x83); |
811 | CLR(sp->sp_flags, STTYF_CLR_BREAK); | | 811 | CLR(sp->sp_flags, STTYF_CLR_BREAK); |
812 | cnt += 2; | | 812 | cnt += 2; |
813 | } | | 813 | } |
814 | | | 814 | |
815 | while (sp->sp_txc > 0 && cnt < (CD180_TX_FIFO_SIZE-1)) { | | 815 | while (sp->sp_txc > 0 && cnt < (CD180_TX_FIFO_SIZE-1)) { |
816 | ch = *sp->sp_txp; | | 816 | ch = *sp->sp_txp; |
817 | sp->sp_txc--; | | 817 | sp->sp_txc--; |
818 | sp->sp_txp++; | | 818 | sp->sp_txp++; |
819 | | | 819 | |
820 | if (ch == 0) { | | 820 | if (ch == 0) { |
821 | STC_WRITE(sc, STC_TDR, ch); | | 821 | STC_WRITE(sc, STC_TDR, ch); |
822 | cnt++; | | 822 | cnt++; |
823 | } | | 823 | } |
824 | STC_WRITE(sc, STC_TDR, ch); | | 824 | STC_WRITE(sc, STC_TDR, ch); |
825 | cnt++; | | 825 | cnt++; |
826 | } | | 826 | } |
827 | } | | 827 | } |
828 | | | 828 | |
829 | if (sp->sp_txc == 0 || | | 829 | if (sp->sp_txc == 0 || |
830 | ISSET(sp->sp_flags, STTYF_STOP)) { | | 830 | ISSET(sp->sp_flags, STTYF_STOP)) { |
831 | STC_WRITE(sc, STC_SRER, STC_READ(sc, STC_SRER) & | | 831 | STC_WRITE(sc, STC_SRER, STC_READ(sc, STC_SRER) & |
832 | (~CD180_SRER_TXD)); | | 832 | (~CD180_SRER_TXD)); |
833 | CLR(sp->sp_flags, STTYF_STOP); | | 833 | CLR(sp->sp_flags, STTYF_STOP); |
834 | SET(sp->sp_flags, STTYF_DONE); | | 834 | SET(sp->sp_flags, STTYF_DONE); |
835 | *needsoftp = 1; | | 835 | *needsoftp = 1; |
836 | } | | 836 | } |
837 | | | 837 | |
838 | STC_WRITE(sc, STC_EOSRR, 0); | | 838 | STC_WRITE(sc, STC_EOSRR, 0); |
839 | | | 839 | |
840 | return (1); | | 840 | return (1); |
841 | } | | 841 | } |
842 | | | 842 | |
843 | int | | 843 | int |
844 | spif_stcintr_mx(sc, needsoftp) | | 844 | spif_stcintr_mx(sc, needsoftp) |
845 | struct spif_softc *sc; | | 845 | struct spif_softc *sc; |
846 | int *needsoftp; | | 846 | int *needsoftp; |
847 | { | | 847 | { |
848 | struct stty_port *sp; | | 848 | struct stty_port *sp; |
849 | u_int8_t channel, mcr; | | 849 | u_int8_t channel, mcr; |
850 | | | 850 | |
851 | channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); | | 851 | channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); |
852 | sp = &sc->sc_ttys->sc_port[channel]; | | 852 | sp = &sc->sc_ttys->sc_port[channel]; |
853 | mcr = STC_READ(sc, STC_MCR); | | 853 | mcr = STC_READ(sc, STC_MCR); |
854 | if (mcr & CD180_MCR_CD) { | | 854 | if (mcr & CD180_MCR_CD) { |
855 | SET(sp->sp_flags, STTYF_CDCHG); | | 855 | SET(sp->sp_flags, STTYF_CDCHG); |
856 | *needsoftp = 1; | | 856 | *needsoftp = 1; |
857 | } | | 857 | } |
858 | STC_WRITE(sc, STC_MCR, 0); | | 858 | STC_WRITE(sc, STC_MCR, 0); |
859 | STC_WRITE(sc, STC_EOSRR, 0); | | 859 | STC_WRITE(sc, STC_EOSRR, 0); |
860 | return (1); | | 860 | return (1); |
861 | } | | 861 | } |
862 | | | 862 | |
863 | int | | 863 | int |
864 | spif_stcintr(vsc) | | 864 | spif_stcintr(vsc) |
865 | void *vsc; | | 865 | void *vsc; |
866 | { | | 866 | { |
867 | struct spif_softc *sc = (struct spif_softc *)vsc; | | 867 | struct spif_softc *sc = (struct spif_softc *)vsc; |
868 | int needsoft = 0, r = 0, i; | | 868 | int needsoft = 0, r = 0, i; |
869 | u_int8_t ar; | | 869 | u_int8_t ar; |
870 | | | 870 | |
871 | for (i = 0; i < 8; i++) { | | 871 | for (i = 0; i < 8; i++) { |
872 | ar = ISTC_READ(sc, STC_RRAR) & CD180_GSVR_IMASK; | | 872 | ar = ISTC_READ(sc, STC_RRAR) & CD180_GSVR_IMASK; |
873 | if (ar == CD180_GSVR_RXGOOD) | | 873 | if (ar == CD180_GSVR_RXGOOD) |
874 | r |= spif_stcintr_rx(sc, &needsoft); | | 874 | r |= spif_stcintr_rx(sc, &needsoft); |
875 | else if (ar == CD180_GSVR_RXEXCEPTION) | | 875 | else if (ar == CD180_GSVR_RXEXCEPTION) |
876 | r |= spif_stcintr_rxexception(sc, &needsoft); | | 876 | r |= spif_stcintr_rxexception(sc, &needsoft); |
877 | } | | 877 | } |
878 | | | 878 | |
879 | for (i = 0; i < 8; i++) { | | 879 | for (i = 0; i < 8; i++) { |
880 | ar = ISTC_READ(sc, STC_TRAR) & CD180_GSVR_IMASK; | | 880 | ar = ISTC_READ(sc, STC_TRAR) & CD180_GSVR_IMASK; |
881 | if (ar == CD180_GSVR_TXDATA) | | 881 | if (ar == CD180_GSVR_TXDATA) |
882 | r |= spif_stcintr_tx(sc, &needsoft); | | 882 | r |= spif_stcintr_tx(sc, &needsoft); |
883 | } | | 883 | } |
884 | | | 884 | |
885 | for (i = 0; i < 8; i++) { | | 885 | for (i = 0; i < 8; i++) { |
886 | ar = ISTC_READ(sc, STC_MRAR) & CD180_GSVR_IMASK; | | 886 | ar = ISTC_READ(sc, STC_MRAR) & CD180_GSVR_IMASK; |
887 | if (ar == CD180_GSVR_STATCHG) | | 887 | if (ar == CD180_GSVR_STATCHG) |
888 | r |= spif_stcintr_mx(sc, &needsoft); | | 888 | r |= spif_stcintr_mx(sc, &needsoft); |
889 | } | | 889 | } |
890 | | | 890 | |
891 | if (needsoft) | | 891 | if (needsoft) |
892 | softint_schedule(sc->sc_softih); | | 892 | softint_schedule(sc->sc_softih); |
893 | return (r); | | 893 | return (r); |
894 | } | | 894 | } |
895 | | | 895 | |
896 | void | | 896 | void |
897 | spif_softintr(vsc) | | 897 | spif_softintr(vsc) |
898 | void *vsc; | | 898 | void *vsc; |
899 | { | | 899 | { |
900 | struct spif_softc *sc = (struct spif_softc *)vsc; | | 900 | struct spif_softc *sc = (struct spif_softc *)vsc; |
901 | struct stty_softc *stc = sc->sc_ttys; | | 901 | struct stty_softc *stc = sc->sc_ttys; |
902 | int r = 0, i, data, s, flags; | | 902 | int r = 0, i, data, s, flags; |
903 | u_int8_t stat, msvr; | | 903 | u_int8_t stat, msvr; |
904 | struct stty_port *sp; | | 904 | struct stty_port *sp; |
905 | struct tty *tp; | | 905 | struct tty *tp; |
906 | | | 906 | |
907 | if (stc != NULL) { | | 907 | if (stc != NULL) { |
908 | for (i = 0; i < stc->sc_nports; i++) { | | 908 | for (i = 0; i < stc->sc_nports; i++) { |
909 | sp = &stc->sc_port[i]; | | 909 | sp = &stc->sc_port[i]; |
910 | tp = sp->sp_tty; | | 910 | tp = sp->sp_tty; |
911 | | | 911 | |
912 | if (!ISSET(tp->t_state, TS_ISOPEN)) | | 912 | if (!ISSET(tp->t_state, TS_ISOPEN)) |
913 | continue; | | 913 | continue; |
914 | | | 914 | |
915 | while (sp->sp_rget != sp->sp_rput) { | | 915 | while (sp->sp_rget != sp->sp_rput) { |
916 | stat = sp->sp_rget[0]; | | 916 | stat = sp->sp_rget[0]; |
917 | data = sp->sp_rget[1]; | | 917 | data = sp->sp_rget[1]; |
918 | sp->sp_rget += 2; | | 918 | sp->sp_rget += 2; |
919 | if (sp->sp_rget == sp->sp_rend) | | 919 | if (sp->sp_rget == sp->sp_rend) |
920 | sp->sp_rget = sp->sp_rbuf; | | 920 | sp->sp_rget = sp->sp_rbuf; |
921 | | | 921 | |
922 | if (stat & (CD180_RCSR_BE | CD180_RCSR_FE)) | | 922 | if (stat & (CD180_RCSR_BE | CD180_RCSR_FE)) |
923 | data |= TTY_FE; | | 923 | data |= TTY_FE; |
924 | | | 924 | |
925 | if (stat & CD180_RCSR_PE) | | 925 | if (stat & CD180_RCSR_PE) |
926 | data |= TTY_PE; | | 926 | data |= TTY_PE; |
927 | | | 927 | |
928 | (*tp->t_linesw->l_rint)(data, tp); | | 928 | (*tp->t_linesw->l_rint)(data, tp); |
929 | r = 1; | | 929 | r = 1; |
930 | } | | 930 | } |
931 | | | 931 | |
932 | s = splhigh(); | | 932 | s = splhigh(); |
933 | flags = sp->sp_flags; | | 933 | flags = sp->sp_flags; |
934 | CLR(sp->sp_flags, STTYF_DONE | STTYF_CDCHG | | | 934 | CLR(sp->sp_flags, STTYF_DONE | STTYF_CDCHG | |
935 | STTYF_RING_OVERFLOW); | | 935 | STTYF_RING_OVERFLOW); |
936 | splx(s); | | 936 | splx(s); |
937 | | | 937 | |
938 | if (ISSET(flags, STTYF_CDCHG)) { | | 938 | if (ISSET(flags, STTYF_CDCHG)) { |
939 | s = spltty(); | | 939 | s = spltty(); |
940 | STC_WRITE(sc, STC_CAR, i); | | 940 | STC_WRITE(sc, STC_CAR, i); |
941 | msvr = STC_READ(sc, STC_MSVR); | | 941 | msvr = STC_READ(sc, STC_MSVR); |
942 | splx(s); | | 942 | splx(s); |
943 | | | 943 | |
944 | sp->sp_carrier = msvr & CD180_MSVR_CD; | | 944 | sp->sp_carrier = msvr & CD180_MSVR_CD; |
945 | (*tp->t_linesw->l_modem)(tp, | | 945 | (*tp->t_linesw->l_modem)(tp, |
946 | sp->sp_carrier); | | 946 | sp->sp_carrier); |
947 | r = 1; | | 947 | r = 1; |
948 | } | | 948 | } |
949 | | | 949 | |
950 | if (ISSET(flags, STTYF_RING_OVERFLOW)) { | | 950 | if (ISSET(flags, STTYF_RING_OVERFLOW)) { |
951 | log(LOG_WARNING, "%s-%x: ring overflow\n", | | 951 | log(LOG_WARNING, "%s-%x: ring overflow\n", |
952 | device_xname(&stc->sc_dev), i); | | 952 | device_xname(&stc->sc_dev), i); |
953 | r = 1; | | 953 | r = 1; |
954 | } | | 954 | } |
955 | | | 955 | |
956 | if (ISSET(flags, STTYF_DONE)) { | | 956 | if (ISSET(flags, STTYF_DONE)) { |
957 | ndflush(&tp->t_outq, | | 957 | ndflush(&tp->t_outq, |
958 | sp->sp_txp - tp->t_outq.c_cf); | | 958 | sp->sp_txp - tp->t_outq.c_cf); |
959 | CLR(tp->t_state, TS_BUSY); | | 959 | CLR(tp->t_state, TS_BUSY); |
960 | (*tp->t_linesw->l_start)(tp); | | 960 | (*tp->t_linesw->l_start)(tp); |
961 | r = 1; | | 961 | r = 1; |
962 | } | | 962 | } |
963 | } | | 963 | } |
964 | } | | 964 | } |
965 | } | | 965 | } |
966 | | | 966 | |
967 | void | | 967 | void |
968 | stty_write_ccr(sc, val) | | 968 | stty_write_ccr(sc, val) |
969 | struct spif_softc *sc; | | 969 | struct spif_softc *sc; |
970 | u_int8_t val; | | 970 | u_int8_t val; |
971 | { | | 971 | { |
972 | int tries = 100000; | | 972 | int tries = 100000; |
973 | | | 973 | |
974 | while (STC_READ(sc, STC_CCR) && tries--) | | 974 | while (STC_READ(sc, STC_CCR) && tries--) |
975 | /*EMPTY*/; | | 975 | /*EMPTY*/; |
976 | if (tries == 0) | | 976 | if (tries == 0) |
977 | aprint_error_dev(&sc->sc_dev, "ccr timeout\n"); | | 977 | aprint_error_dev(&sc->sc_dev, "ccr timeout\n"); |
978 | STC_WRITE(sc, STC_CCR, val); | | 978 | STC_WRITE(sc, STC_CCR, val); |
979 | } | | 979 | } |
980 | | | 980 | |
981 | int | | 981 | int |
982 | stty_compute_baud(speed, clock, bprlp, bprhp) | | 982 | stty_compute_baud(speed, clock, bprlp, bprhp) |
983 | speed_t speed; | | 983 | speed_t speed; |
984 | int clock; | | 984 | int clock; |
985 | u_int8_t *bprlp, *bprhp; | | 985 | u_int8_t *bprlp, *bprhp; |
986 | { | | 986 | { |
987 | u_int32_t rate; | | 987 | u_int32_t rate; |
988 | | | 988 | |
989 | rate = (2 * clock) / (16 * speed); | | 989 | rate = (2 * clock) / (16 * speed); |
990 | if (rate & 1) | | 990 | if (rate & 1) |
991 | rate = (rate >> 1) + 1; | | 991 | rate = (rate >> 1) + 1; |
992 | else | | 992 | else |
993 | rate = rate >> 1; | | 993 | rate = rate >> 1; |
994 | | | 994 | |
995 | if (rate > 0xffff || rate == 0) | | 995 | if (rate > 0xffff || rate == 0) |
996 | return (1); | | 996 | return (1); |
997 | | | 997 | |
998 | *bprlp = rate & 0xff; | | 998 | *bprlp = rate & 0xff; |
999 | *bprhp = (rate >> 8) & 0xff; | | 999 | *bprhp = (rate >> 8) & 0xff; |
1000 | return (0); | | 1000 | return (0); |
1001 | } | | 1001 | } |
1002 | | | 1002 | |
1003 | int | | 1003 | int |
1004 | sbpp_match(parent, vcf, aux) | | 1004 | sbpp_match(parent, vcf, aux) |
1005 | struct device *parent; | | 1005 | struct device *parent; |
1006 | struct cfdata *vcf; | | 1006 | struct cfdata *vcf; |
1007 | void *aux; | | 1007 | void *aux; |
1008 | { | | 1008 | { |
1009 | struct spif_softc *sc = device_private(parent); | | 1009 | struct spif_softc *sc = device_private(parent); |
1010 | | | 1010 | |
1011 | return (aux == sbpp_match && sc->sc_bpps == NULL); | | 1011 | return (aux == sbpp_match && sc->sc_bpps == NULL); |
1012 | } | | 1012 | } |
1013 | | | 1013 | |
1014 | void | | 1014 | void |
1015 | sbpp_attach(parent, dev, aux) | | 1015 | sbpp_attach(parent, dev, aux) |
1016 | struct device *parent, *dev; | | 1016 | struct device *parent, *dev; |
1017 | void *aux; | | 1017 | void *aux; |
1018 | { | | 1018 | { |
1019 | struct spif_softc *sc = device_private(parent); | | 1019 | struct spif_softc *sc = device_private(parent); |
1020 | struct sbpp_softc *psc = device_private(dev); | | 1020 | struct sbpp_softc *psc = device_private(dev); |
1021 | int port; | | 1021 | int port; |
1022 | | | 1022 | |
1023 | sc->sc_bpps = psc; | | 1023 | sc->sc_bpps = psc; |
1024 | | | 1024 | |
1025 | for (port = 0; port < sc->sc_npar; port++) { | | 1025 | for (port = 0; port < sc->sc_npar; port++) { |
1026 | } | | 1026 | } |
1027 | | | 1027 | |
1028 | psc->sc_nports = port; | | 1028 | psc->sc_nports = port; |
1029 | printf(": %d port%s\n", port, port == 1 ? "" : "s"); | | 1029 | printf(": %d port%s\n", port, port == 1 ? "" : "s"); |
1030 | } | | 1030 | } |
1031 | | | 1031 | |
1032 | int | | 1032 | int |
1033 | sbpp_open(dev, flags, mode, l) | | 1033 | sbpp_open(dev, flags, mode, l) |
1034 | dev_t dev; | | 1034 | dev_t dev; |
1035 | int flags; | | 1035 | int flags; |
1036 | int mode; | | 1036 | int mode; |
1037 | struct lwp *l; | | 1037 | struct lwp *l; |
1038 | { | | 1038 | { |
1039 | return (ENXIO); | | 1039 | return (ENXIO); |
1040 | } | | 1040 | } |
1041 | | | 1041 | |
1042 | int | | 1042 | int |
1043 | sbpp_close(dev, flags, mode, l) | | 1043 | sbpp_close(dev, flags, mode, l) |
1044 | dev_t dev; | | 1044 | dev_t dev; |
1045 | int flags; | | 1045 | int flags; |
1046 | int mode; | | 1046 | int mode; |
1047 | struct lwp *l; | | 1047 | struct lwp *l; |
1048 | { | | 1048 | { |
1049 | return (ENXIO); | | 1049 | return (ENXIO); |
1050 | } | | 1050 | } |
1051 | | | 1051 | |
1052 | int | | 1052 | int |
1053 | spif_ppcintr(v) | | 1053 | spif_ppcintr(v) |
1054 | void *v; | | 1054 | void *v; |
1055 | { | | 1055 | { |
1056 | return (0); | | 1056 | return (0); |
1057 | } | | 1057 | } |
1058 | | | 1058 | |
1059 | int | | 1059 | int |
1060 | sbpp_read(dev, uio, flags) | | 1060 | sbpp_read(dev, uio, flags) |
1061 | dev_t dev; | | 1061 | dev_t dev; |
1062 | struct uio *uio; | | 1062 | struct uio *uio; |
1063 | int flags; | | 1063 | int flags; |
1064 | { | | 1064 | { |
1065 | return (sbpp_rw(dev, uio)); | | 1065 | return (sbpp_rw(dev, uio)); |
1066 | } | | 1066 | } |
1067 | | | 1067 | |
1068 | int | | 1068 | int |
1069 | sbpp_write(dev, uio, flags) | | 1069 | sbpp_write(dev, uio, flags) |
1070 | dev_t dev; | | 1070 | dev_t dev; |
1071 | struct uio *uio; | | 1071 | struct uio *uio; |
1072 | int flags; | | 1072 | int flags; |
1073 | { | | 1073 | { |
1074 | return (sbpp_rw(dev, uio)); | | 1074 | return (sbpp_rw(dev, uio)); |
1075 | } | | 1075 | } |
1076 | | | 1076 | |
1077 | int | | 1077 | int |
1078 | sbpp_rw(dev, uio) | | 1078 | sbpp_rw(dev, uio) |
1079 | dev_t dev; | | 1079 | dev_t dev; |
1080 | struct uio *uio; | | 1080 | struct uio *uio; |
1081 | { | | 1081 | { |
1082 | return (ENXIO); | | 1082 | return (ENXIO); |
1083 | } | | 1083 | } |
1084 | | | 1084 | |
1085 | int | | 1085 | int |
1086 | sbpp_poll(dev, events, l) | | 1086 | sbpp_poll(dev, events, l) |
1087 | dev_t dev; | | 1087 | dev_t dev; |
1088 | int events; | | 1088 | int events; |
1089 | struct lwp *l; | | 1089 | struct lwp *l; |
1090 | { | | 1090 | { |
1091 | return (seltrue(dev, events, l)); | | 1091 | return (seltrue(dev, events, l)); |
1092 | } | | 1092 | } |
1093 | | | 1093 | |
1094 | int | | 1094 | int |
1095 | sbpp_ioctl(dev, cmd, data, flags, l) | | 1095 | sbpp_ioctl(dev, cmd, data, flags, l) |
1096 | dev_t dev; | | 1096 | dev_t dev; |
1097 | u_long cmd; | | 1097 | u_long cmd; |
1098 | void *data; | | 1098 | void *data; |
1099 | int flags; | | 1099 | int flags; |
1100 | struct lwp *l; | | 1100 | struct lwp *l; |
1101 | { | | 1101 | { |
1102 | int error; | | 1102 | int error; |
1103 | | | 1103 | |
1104 | error = ENOTTY; | | 1104 | error = ENOTTY; |
1105 | | | 1105 | |
1106 | return (error); | | 1106 | return (error); |
1107 | } | | 1107 | } |
1108 | | | 1108 | |
1109 | #endif /* NSPIF */ | | 1109 | #endif /* NSPIF */ |