File: | dev/ic/cy.c |
Warning: | line 191, column 2 Value stored to 'card' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: cy.c,v 1.41 2021/09/01 16:10:39 jan Exp $ */ |
2 | /* |
3 | * Copyright (c) 1996 Timo Rossi. |
4 | * All rights reserved. |
5 | * |
6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions |
8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. |
14 | * 3. Neither the name of the author nor the names of contributors |
15 | * may be used to endorse or promote products derived from this software |
16 | * without specific prior written permission. |
17 | * |
18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
24 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
28 | * SUCH DAMAGE. |
29 | */ |
30 | |
31 | /* |
32 | * cy.c |
33 | * |
34 | * Driver for Cyclades Cyclom-8/16/32 multiport serial cards |
35 | * (currently not tested with Cyclom-32 cards) |
36 | * |
37 | * Timo Rossi, 1996 |
38 | * |
39 | * Supports both ISA and PCI Cyclom cards |
40 | * |
41 | * Uses CD1400 automatic CTS flow control, and |
42 | * if CY_HW_RTS is defined, uses CD1400 automatic input flow control. |
43 | * This requires a special cable that exchanges the RTS and DTR lines. |
44 | * |
45 | * Lots of debug output can be enabled by defining CY_DEBUG |
46 | * Some debugging counters (number of receive/transmit interrupts etc.) |
47 | * can be enabled by defining CY_DEBUG1 |
48 | * |
49 | * This version uses the bus_space/io_??() stuff |
50 | * |
51 | */ |
52 | |
53 | #include <sys/param.h> |
54 | #include <sys/ioctl.h> |
55 | #include <sys/syslog.h> |
56 | #include <sys/fcntl.h> |
57 | #include <sys/tty.h> |
58 | #include <sys/conf.h> |
59 | #include <sys/selinfo.h> |
60 | #include <sys/device.h> |
61 | #include <sys/malloc.h> |
62 | #include <sys/systm.h> |
63 | |
64 | #include <machine/bus.h> |
65 | #include <machine/intr.h> |
66 | |
67 | #include <dev/ic/cd1400reg.h> |
68 | #include <dev/ic/cyreg.h> |
69 | |
70 | |
71 | int cy_intr(void *); |
72 | int cyparam(struct tty *, struct termios *); |
73 | void cystart(struct tty *); |
74 | void cy_poll(void *); |
75 | int cy_modem_control(struct cy_port *, int, int); |
76 | void cy_enable_transmitter(struct cy_port *); |
77 | void cd1400_channel_cmd(struct cy_port *, int); |
78 | int cy_speed(speed_t, int *, int *, int); |
79 | |
80 | struct cfdriver cy_cd = { |
81 | NULL((void *)0), "cy", DV_TTY |
82 | }; |
83 | |
84 | /* |
85 | * Common probe routine |
86 | * |
87 | * returns the number of chips found. |
88 | */ |
89 | int |
90 | cy_probe_common(bus_space_tag_t memt, bus_space_handle_t memh, int bustype) |
91 | { |
92 | int cy_chip, chip_offs; |
93 | u_char firmware_ver; |
94 | int nchips; |
95 | |
96 | /* Cyclom card hardware reset */ |
97 | bus_space_write_1(memt, memh, CY16_RESET<<bustype, 0)((memt)->write_1((memh), (0x1400<<bustype), (0))); |
98 | DELAY(500)(*delay_func)(500); /* wait for reset to complete */ |
99 | bus_space_write_1(memt, memh, CY_CLEAR_INTR<<bustype, 0)((memt)->write_1((memh), (0x1800<<bustype), (0))); |
100 | |
101 | #ifdef CY_DEBUG |
102 | printf("cy: card reset done\n"); |
103 | #endif |
104 | |
105 | nchips = 0; |
106 | |
107 | for (cy_chip = 0, chip_offs = 0; |
108 | cy_chip < CY_MAX_CD1400s8; |
109 | cy_chip++, chip_offs += (CY_CD1400_MEMSPACING0x400 << bustype)) { |
110 | int i; |
111 | |
112 | /* the last 4 cd1400s are 'interleaved' |
113 | with the first 4 on 32-port boards */ |
114 | if (cy_chip == 4) |
115 | chip_offs -= (CY32_ADDR_FIX0xe00 << bustype); |
116 | |
117 | #ifdef CY_DEBUG |
118 | printf("cy: probe chip %d offset 0x%x ... ", |
119 | cy_chip, chip_offs); |
120 | #endif |
121 | |
122 | /* wait until the chip is ready for command */ |
123 | DELAY(1000)(*delay_func)(1000); |
124 | if (bus_space_read_1(memt, memh, chip_offs +((memt)->read_1((memh), (chip_offs + ((0x05 << 1) << bustype)))) |
125 | ((CD1400_CCR << 1) << bustype))((memt)->read_1((memh), (chip_offs + ((0x05 << 1) << bustype)))) != 0) { |
126 | #ifdef CY_DEBUG |
127 | printf("not ready for command\n"); |
128 | #endif |
129 | break; |
130 | } |
131 | |
132 | /* clear the firmware version reg. */ |
133 | bus_space_write_1(memt, memh, chip_offs +((memt)->write_1((memh), (chip_offs + ((0x40 << 1) << bustype)), (0))) |
134 | ((CD1400_GFRCR << 1) << bustype), 0)((memt)->write_1((memh), (chip_offs + ((0x40 << 1) << bustype)), (0))); |
135 | |
136 | /* |
137 | * On Cyclom-16 references to non-existent chip 4 |
138 | * actually access chip 0 (address line 9 not decoded). |
139 | * Here we check if the clearing of chip 4 GFRCR actually |
140 | * cleared chip 0 GFRCR. In that case we have a 16 port card. |
141 | */ |
142 | if (cy_chip == 4 && |
143 | bus_space_read_1(memt, memh, chip_offs +((memt)->read_1((memh), (chip_offs + ((0x40 << 1) << bustype)))) |
144 | ((CD1400_GFRCR << 1) << bustype))((memt)->read_1((memh), (chip_offs + ((0x40 << 1) << bustype)))) == 0) |
145 | break; |
146 | |
147 | /* reset the chip */ |
148 | bus_space_write_1(memt, memh, chip_offs +((memt)->write_1((memh), (chip_offs + ((0x05 << 1) << bustype)), ((1<<7) | (1<<0)))) |
149 | ((CD1400_CCR << 1) << bustype),((memt)->write_1((memh), (chip_offs + ((0x05 << 1) << bustype)), ((1<<7) | (1<<0)))) |
150 | CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET)((memt)->write_1((memh), (chip_offs + ((0x05 << 1) << bustype)), ((1<<7) | (1<<0)))); |
151 | |
152 | /* wait for the chip to initialize itself */ |
153 | for (i = 0; i < 200; i++) { |
154 | DELAY(50)(*delay_func)(50); |
155 | firmware_ver = bus_space_read_1(memt, memh, chip_offs +((memt)->read_1((memh), (chip_offs + ((0x40 << 1) << bustype)))) |
156 | ((CD1400_GFRCR << 1) << bustype))((memt)->read_1((memh), (chip_offs + ((0x40 << 1) << bustype)))); |
157 | if ((firmware_ver & 0xf0) == 0x40) /* found a CD1400 */ |
158 | break; |
159 | } |
160 | #ifdef CY_DEBUG |
161 | printf("firmware version 0x%x\n", firmware_ver); |
162 | #endif |
163 | |
164 | if ((firmware_ver & 0xf0) != 0x40) |
165 | break; |
166 | |
167 | /* firmware version OK, CD1400 found */ |
168 | nchips++; |
169 | } |
170 | |
171 | if (nchips == 0) { |
172 | #ifdef CY_DEBUG |
173 | printf("no CD1400s found\n"); |
174 | #endif |
175 | return (0); |
176 | } |
177 | |
178 | #ifdef CY_DEBUG |
179 | printf("found %d CD1400s\n", nchips); |
180 | #endif |
181 | |
182 | return (nchips); |
183 | } |
184 | |
185 | void |
186 | cy_attach(struct device *parent, struct device *self) |
187 | { |
188 | int card, port, cy_chip, num_chips, cdu, chip_offs, cy_clock; |
189 | struct cy_softc *sc = (void *)self; |
190 | |
191 | card = sc->sc_dev.dv_unit; |
Value stored to 'card' is never read | |
192 | num_chips = sc->sc_nr_cd1400s; |
193 | if (num_chips == 0) |
194 | return; |
195 | |
196 | timeout_set(&sc->sc_poll_to, cy_poll, sc); |
197 | bzero(sc->sc_ports, sizeof(sc->sc_ports))__builtin_bzero((sc->sc_ports), (sizeof(sc->sc_ports))); |
198 | sc->sc_nports = num_chips * CD1400_NO_OF_CHANNELS4; |
199 | |
200 | port = 0; |
201 | for (cy_chip = 0, chip_offs = 0; |
202 | cy_chip < num_chips; |
203 | cy_chip++, chip_offs += (CY_CD1400_MEMSPACING0x400<<sc->sc_bustype)) { |
204 | if (cy_chip == 4) |
205 | chip_offs -= (CY32_ADDR_FIX0xe00<<sc->sc_bustype); |
206 | |
207 | #ifdef CY_DEBUG |
208 | printf("attach CD1400 #%d offset 0x%x\n", cy_chip, chip_offs); |
209 | #endif |
210 | sc->sc_cd1400_offs[cy_chip] = chip_offs; |
211 | |
212 | /* configure port 0 as serial port |
213 | (should already be after reset) */ |
214 | cd_write_reg_sc(sc, cy_chip, CD1400_GCR, 0)((sc->sc_memt)->write_1((sc->sc_memh), (sc->sc_cd1400_offs [cy_chip]+ (((0x4B<<1))<<sc->sc_bustype)), ((0 )))); |
215 | |
216 | /* Set cy_clock depending on firmware version */ |
217 | if (cd_read_reg_sc(sc, cy_chip, CD1400_GFRCR)((sc->sc_memt)->read_1((sc->sc_memh), (sc->sc_cd1400_offs [cy_chip]+ (((0x40<<1))<<sc->sc_bustype)))) <= 0x46) |
218 | cy_clock = CY_CLOCK25000000; |
219 | else |
220 | cy_clock = CY_CLOCK_6060000000; |
221 | |
222 | /* set up a receive timeout period (1ms) */ |
223 | cd_write_reg_sc(sc, cy_chip, CD1400_PPR,((sc->sc_memt)->write_1((sc->sc_memh), (sc->sc_cd1400_offs [cy_chip]+ (((0x7E<<1))<<sc->sc_bustype)), ((( cy_clock / 512 / 1000) + 1)))) |
224 | (cy_clock / CD1400_PPR_PRESCALER / 1000) + 1)((sc->sc_memt)->write_1((sc->sc_memh), (sc->sc_cd1400_offs [cy_chip]+ (((0x7E<<1))<<sc->sc_bustype)), ((( cy_clock / 512 / 1000) + 1)))); |
225 | |
226 | for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS4; cdu++) { |
227 | sc->sc_ports[port].cy_port_num = port; |
228 | sc->sc_ports[port].cy_memt = sc->sc_memt; |
229 | sc->sc_ports[port].cy_memh = sc->sc_memh; |
230 | sc->sc_ports[port].cy_chip_offs = chip_offs; |
231 | sc->sc_ports[port].cy_bustype = sc->sc_bustype; |
232 | sc->sc_ports[port].cy_clock = cy_clock; |
233 | |
234 | /* should we initialize anything else here? */ |
235 | port++; |
236 | } /* for(each port on one CD1400...) */ |
237 | |
238 | } /* for(each CD1400 on a card... ) */ |
239 | |
240 | printf(": %d ports\n", port); |
241 | |
242 | /* ensure an edge for the next interrupt */ |
243 | bus_space_write_1(sc->sc_memt, sc->sc_memh,((sc->sc_memt)->write_1((sc->sc_memh), (0x1800<< sc->sc_bustype), (0))) |
244 | CY_CLEAR_INTR<<sc->sc_bustype, 0)((sc->sc_memt)->write_1((sc->sc_memh), (0x1800<< sc->sc_bustype), (0))); |
245 | } |
246 | |
247 | /* |
248 | * open routine. returns zero if successful, else error code |
249 | */ |
250 | int cyopen(dev_t, int, int, struct proc *); |
251 | int cyclose(dev_t, int, int, struct proc *); |
252 | int cyread(dev_t, struct uio *, int); |
253 | int cywrite(dev_t, struct uio *, int); |
254 | struct tty *cytty(dev_t); |
255 | int cyioctl(dev_t, u_long, caddr_t, int, struct proc *); |
256 | int cystop(struct tty *, int flag); |
257 | |
258 | int |
259 | cyopen(dev_t dev, int flag, int mode, struct proc *p) |
260 | { |
261 | int card = CY_CARD(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >> 8)) >> 5) & 3); |
262 | int port = CY_PORT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >> 8)) & 0xf); |
263 | struct cy_softc *sc; |
264 | struct cy_port *cy; |
265 | struct tty *tp; |
266 | int s, error; |
267 | |
268 | if (card >= cy_cd.cd_ndevs || |
269 | (sc = cy_cd.cd_devs[card]) == NULL((void *)0)) { |
270 | return (ENXIO6); |
271 | } |
272 | |
273 | #ifdef CY_DEBUG |
274 | printf("%s open port %d flag 0x%x mode 0x%x\n", sc->sc_dev.dv_xname, |
275 | port, flag, mode); |
276 | #endif |
277 | |
278 | cy = &sc->sc_ports[port]; |
279 | |
280 | s = spltty()splraise(0x9); |
281 | if (cy->cy_tty == NULL((void *)0)) { |
282 | cy->cy_tty = ttymalloc(0); |
283 | } |
284 | splx(s)spllower(s); |
285 | |
286 | tp = cy->cy_tty; |
287 | tp->t_oproc = cystart; |
288 | tp->t_param = cyparam; |
289 | tp->t_dev = dev; |
290 | |
291 | if (!ISSET(tp->t_state, TS_ISOPEN)((tp->t_state) & (0x00020))) { |
292 | SET(tp->t_state, TS_WOPEN)((tp->t_state) |= (0x00200)); |
293 | ttychars(tp); |
294 | tp->t_iflagt_termios.c_iflag = TTYDEF_IFLAG(0x00000002 | 0x00000100 | 0x00002000 | 0x00000200 | 0x00000800 ); |
295 | tp->t_oflagt_termios.c_oflag = TTYDEF_OFLAG(0x00000001 | 0x00000002); |
296 | tp->t_cflagt_termios.c_cflag = TTYDEF_CFLAG(0x00000800 | 0x00000300 | 0x00004000); |
297 | if (ISSET(cy->cy_openflags, TIOCFLAG_CLOCAL)((cy->cy_openflags) & (0x02))) |
298 | SET(tp->t_cflag, CLOCAL)((tp->t_termios.c_cflag) |= (0x00008000)); |
299 | if (ISSET(cy->cy_openflags, TIOCFLAG_CRTSCTS)((cy->cy_openflags) & (0x04))) |
300 | SET(tp->t_cflag, CRTSCTS)((tp->t_termios.c_cflag) |= (0x00010000)); |
301 | if (ISSET(cy->cy_openflags, TIOCFLAG_MDMBUF)((cy->cy_openflags) & (0x08))) |
302 | SET(tp->t_cflag, MDMBUF)((tp->t_termios.c_cflag) |= (0x00100000)); |
303 | tp->t_lflagt_termios.c_lflag = TTYDEF_LFLAG(0x00000008 | 0x00000100 | 0x00000080 | 0x00000400 | 0x00000002 |0x00000001|0x00000040); |
304 | tp->t_ispeedt_termios.c_ispeed = tp->t_ospeedt_termios.c_ospeed = TTYDEF_SPEED(9600); |
305 | |
306 | s = spltty()splraise(0x9); |
307 | |
308 | /* |
309 | * Allocate input ring buffer if we don't already have one |
310 | */ |
311 | if (cy->cy_ibuf == NULL((void *)0)) { |
312 | cy->cy_ibuf = malloc(IBUF_SIZE(2*512), M_DEVBUF2, M_NOWAIT0x0002); |
313 | if (cy->cy_ibuf == NULL((void *)0)) { |
314 | printf("%s: (port %d) can't allocate input buffer\n", |
315 | sc->sc_dev.dv_xname, port); |
316 | splx(s)spllower(s); |
317 | return (ENOMEM12); |
318 | } |
319 | cy->cy_ibuf_end = cy->cy_ibuf + IBUF_SIZE(2*512); |
320 | } |
321 | |
322 | /* mark the ring buffer as empty */ |
323 | cy->cy_ibuf_rd_ptr = cy->cy_ibuf_wr_ptr = cy->cy_ibuf; |
324 | |
325 | /* select CD1400 channel */ |
326 | cd_write_reg(cy, CD1400_CAR, port & CD1400_CAR_CHAN)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x68<<1))<<cy->cy_bustype)), ((port & ( 3<<0))))); |
327 | /* reset the channel */ |
328 | cd1400_channel_cmd(cy, CD1400_CCR_CMDRESET(1<<7)); |
329 | /* encode unit (port) number in LIVR */ |
330 | /* there is just enough space for 5 bits (32 ports) */ |
331 | cd_write_reg(cy, CD1400_LIVR, port << 3)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x18<<1))<<cy->cy_bustype)), ((port << 3)))); |
332 | |
333 | cy->cy_channel_control = 0; |
334 | |
335 | if (!timeout_pending(&sc->sc_poll_to)((&sc->sc_poll_to)->to_flags & 0x02)) |
336 | timeout_add(&sc->sc_poll_to, 1); |
337 | |
338 | /* this sets parameters and raises DTR */ |
339 | cyparam(tp, &tp->t_termios); |
340 | |
341 | ttsetwater(tp); |
342 | |
343 | /* raise RTS too */ |
344 | cy_modem_control(cy, TIOCM_RTS0004, DMBIS1); |
345 | |
346 | cy->cy_carrier_stat = cd_read_reg(cy, CD1400_MSVR2)((cy->cy_memt)->read_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6D<<1))<<cy->cy_bustype)))); |
347 | |
348 | /* enable receiver and modem change interrupts */ |
349 | cd_write_reg(cy, CD1400_SRER,((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x06<<1))<<cy->cy_bustype)), (((1<<7 ) | (1<<4))))) |
350 | CD1400_SRER_MDMCH | CD1400_SRER_RXDATA)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x06<<1))<<cy->cy_bustype)), (((1<<7 ) | (1<<4))))); |
351 | |
352 | if (CY_DIALOUT(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >> 8)) & 0x80) != 0) || |
353 | ISSET(cy->cy_openflags, TIOCFLAG_SOFTCAR)((cy->cy_openflags) & (0x01)) || |
354 | ISSET(tp->t_cflag, MDMBUF)((tp->t_termios.c_cflag) & (0x00100000)) || |
355 | ISSET(cy->cy_carrier_stat, CD1400_MSVR2_CD)((cy->cy_carrier_stat) & ((1<<4)))) |
356 | SET(tp->t_state, TS_CARR_ON)((tp->t_state) |= (0x00008)); |
357 | else |
358 | CLR(tp->t_state, TS_CARR_ON)((tp->t_state) &= ~(0x00008)); |
359 | } else if (ISSET(tp->t_state, TS_XCLUDE)((tp->t_state) & (0x00400)) && suser(p) != 0) { |
360 | return (EBUSY16); |
361 | } else { |
362 | s = spltty()splraise(0x9); |
363 | } |
364 | |
365 | /* wait for carrier if necessary */ |
366 | if (!ISSET(flag, O_NONBLOCK)((flag) & (0x0004))) { |
367 | while (!ISSET(tp->t_cflag, CLOCAL)((tp->t_termios.c_cflag) & (0x00008000)) && |
368 | !ISSET(tp->t_state, TS_CARR_ON)((tp->t_state) & (0x00008))) { |
369 | SET(tp->t_state, TS_WOPEN)((tp->t_state) |= (0x00200)); |
370 | error = ttysleep(tp, &tp->t_rawq, TTIPRI25 | PCATCH0x100, |
371 | ttopen); |
372 | if (error != 0) { |
373 | splx(s)spllower(s); |
374 | CLR(tp->t_state, TS_WOPEN)((tp->t_state) &= ~(0x00200)); |
375 | return (error); |
376 | } |
377 | } |
378 | } |
379 | |
380 | splx(s)spllower(s); |
381 | |
382 | return (*linesw[tp->t_line].l_open)(dev, tp, p); |
383 | } |
384 | |
385 | /* |
386 | * close routine. returns zero if successful, else error code |
387 | */ |
388 | int |
389 | cyclose(dev_t dev, int flag, int mode, struct proc *p) |
390 | { |
391 | int card = CY_CARD(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >> 8)) >> 5) & 3); |
392 | int port = CY_PORT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >> 8)) & 0xf); |
393 | struct cy_softc *sc = cy_cd.cd_devs[card]; |
394 | struct cy_port *cy = &sc->sc_ports[port]; |
395 | struct tty *tp = cy->cy_tty; |
396 | int s; |
397 | |
398 | #ifdef CY_DEBUG |
399 | printf("%s close port %d, flag 0x%x, mode 0x%x\n", sc->sc_dev.dv_xname, |
400 | port, flag, mode); |
401 | #endif |
402 | |
403 | (*linesw[tp->t_line].l_close)(tp, flag, p); |
404 | s = spltty()splraise(0x9); |
405 | |
406 | if (ISSET(tp->t_cflag, HUPCL)((tp->t_termios.c_cflag) & (0x00004000)) && |
407 | !ISSET(cy->cy_openflags, TIOCFLAG_SOFTCAR)((cy->cy_openflags) & (0x01))) { |
408 | /* drop DTR and RTS |
409 | (should we wait for output buffer to become empty first?) */ |
410 | cy_modem_control(cy, 0, DMSET0); |
411 | } |
412 | |
413 | /* |
414 | * XXX should we disable modem change and |
415 | * receive interrupts here or somewhere ? |
416 | */ |
417 | CLR(tp->t_state, TS_BUSY | TS_FLUSH)((tp->t_state) &= ~(0x00004 | 0x00010)); |
418 | |
419 | splx(s)spllower(s); |
420 | ttyclose(tp); |
421 | |
422 | return (0); |
423 | } |
424 | |
425 | /* |
426 | * Read routine |
427 | */ |
428 | int |
429 | cyread(dev_t dev, struct uio *uio, int flag) |
430 | { |
431 | int card = CY_CARD(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >> 8)) >> 5) & 3); |
432 | int port = CY_PORT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >> 8)) & 0xf); |
433 | struct cy_softc *sc = cy_cd.cd_devs[card]; |
434 | struct cy_port *cy = &sc->sc_ports[port]; |
435 | struct tty *tp = cy->cy_tty; |
436 | |
437 | #ifdef CY_DEBUG |
438 | printf("%s read port %d uio %p flag 0x%x\n", sc->sc_dev.dv_xname, |
439 | port, uio, flag); |
440 | #endif |
441 | |
442 | return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); |
443 | } |
444 | |
445 | /* |
446 | * Write routine |
447 | */ |
448 | int |
449 | cywrite(dev_t dev, struct uio *uio, int flag) |
450 | { |
451 | int card = CY_CARD(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >> 8)) >> 5) & 3); |
452 | int port = CY_PORT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >> 8)) & 0xf); |
453 | struct cy_softc *sc = cy_cd.cd_devs[card]; |
454 | struct cy_port *cy = &sc->sc_ports[port]; |
455 | struct tty *tp = cy->cy_tty; |
456 | |
457 | #ifdef CY_DEBUG |
458 | printf("%s write port %d uio %p flag 0x%x\n", sc->sc_dev.dv_xname, |
459 | port, uio, flag); |
460 | #endif |
461 | |
462 | return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); |
463 | } |
464 | |
465 | /* |
466 | * return tty pointer |
467 | */ |
468 | struct tty * |
469 | cytty(dev_t dev) |
470 | { |
471 | int card = CY_CARD(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >> 8)) >> 5) & 3); |
472 | int port = CY_PORT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >> 8)) & 0xf); |
473 | struct cy_softc *sc = cy_cd.cd_devs[card]; |
474 | struct cy_port *cy = &sc->sc_ports[port]; |
475 | struct tty *tp = cy->cy_tty; |
476 | |
477 | return (tp); |
478 | } |
479 | |
480 | /* |
481 | * ioctl routine |
482 | */ |
483 | int |
484 | cyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) |
485 | { |
486 | int card = CY_CARD(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >> 8)) >> 5) & 3); |
487 | int port = CY_PORT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >> 8)) & 0xf); |
488 | struct cy_softc *sc = cy_cd.cd_devs[card]; |
489 | struct cy_port *cy = &sc->sc_ports[port]; |
490 | struct tty *tp = cy->cy_tty; |
491 | int error; |
492 | |
493 | #ifdef CY_DEBUG |
494 | printf("%s port %d ioctl cmd 0x%lx data %p flag 0x%x\n", |
495 | sc->sc_dev.dv_xname, port, cmd, data, flag); |
496 | #endif |
497 | |
498 | error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); |
499 | if (error >= 0) |
500 | return (error); |
501 | |
502 | error = ttioctl(tp, cmd, data, flag, p); |
503 | if (error >= 0) |
504 | return (error); |
505 | |
506 | /* XXX should not allow dropping DTR when dialin? */ |
507 | |
508 | switch (cmd) { |
509 | case TIOCSBRK((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((123))): /* start break */ |
510 | SET(cy->cy_flags, CYF_START_BREAK)((cy->cy_flags) |= (0x02)); |
511 | cy_enable_transmitter(cy); |
512 | break; |
513 | |
514 | case TIOCCBRK((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((122))): /* stop break */ |
515 | SET(cy->cy_flags, CYF_END_BREAK)((cy->cy_flags) |= (0x04)); |
516 | cy_enable_transmitter(cy); |
517 | break; |
518 | |
519 | case TIOCSDTR((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((121))): /* DTR on */ |
520 | cy_modem_control(cy, TIOCM_DTR0002, DMBIS1); |
521 | break; |
522 | |
523 | case TIOCCDTR((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('t')) << 8) | ((120))): /* DTR off */ |
524 | cy_modem_control(cy, TIOCM_DTR0002, DMBIC2); |
525 | break; |
526 | |
527 | case TIOCMSET((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) | ((('t')) << 8) | ((109))): /* set new modem control line values */ |
528 | cy_modem_control(cy, *((int *)data), DMSET0); |
529 | break; |
530 | |
531 | case TIOCMBIS((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) | ((('t')) << 8) | ((108))): /* turn modem control bits on */ |
532 | cy_modem_control(cy, *((int *)data), DMBIS1); |
533 | break; |
534 | |
535 | case TIOCMBIC((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) | ((('t')) << 8) | ((107))): /* turn modem control bits off */ |
536 | cy_modem_control(cy, *((int *)data), DMBIC2); |
537 | break; |
538 | |
539 | case TIOCMGET((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) << 16) | ((('t')) << 8) | ((106))): /* get modem control/status line state */ |
540 | *((int *)data) = cy_modem_control(cy, 0, DMGET3); |
541 | break; |
542 | |
543 | case TIOCGFLAGS((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) << 16) | ((('t')) << 8) | ((93))): |
544 | *((int *)data) = cy->cy_openflags | |
545 | (CY_DIALOUT(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >> 8)) & 0x80) != 0) ? TIOCFLAG_SOFTCAR0x01 : 0); |
546 | break; |
547 | |
548 | case TIOCSFLAGS((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) | ((('t')) << 8) | ((92))): |
549 | error = suser(p); |
550 | if (error != 0) |
551 | return (EPERM1); |
552 | |
553 | cy->cy_openflags = *((int *)data) & |
554 | (TIOCFLAG_SOFTCAR0x01 | TIOCFLAG_CLOCAL0x02 | |
555 | TIOCFLAG_CRTSCTS0x04 | TIOCFLAG_MDMBUF0x08); |
556 | break; |
557 | |
558 | default: |
559 | return (ENOTTY25); |
560 | } |
561 | |
562 | return (0); |
563 | } |
564 | |
565 | /* |
566 | * start output |
567 | */ |
568 | void |
569 | cystart(struct tty *tp) |
570 | { |
571 | int card = CY_CARD(tp->t_dev)((((unsigned)((tp->t_dev) & 0xff) | (((tp->t_dev) & 0xffff0000) >> 8)) >> 5) & 3); |
572 | int port = CY_PORT(tp->t_dev)(((unsigned)((tp->t_dev) & 0xff) | (((tp->t_dev) & 0xffff0000) >> 8)) & 0xf); |
573 | struct cy_softc *sc = cy_cd.cd_devs[card]; |
574 | struct cy_port *cy = &sc->sc_ports[port]; |
575 | int s; |
576 | |
577 | #ifdef CY_DEBUG |
578 | printf("%s port %d start, tty %p\n", sc->sc_dev.dv_xname, port, tp); |
579 | #endif |
580 | |
581 | s = spltty()splraise(0x9); |
582 | |
583 | #ifdef CY_DEBUG1 |
584 | cy->cy_start_count++; |
585 | #endif |
586 | |
587 | if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)((tp->t_state) & (0x00100 | 0x00080 | 0x00004))) { |
588 | ttwakeupwr(tp); |
589 | if (tp->t_outq.c_cc == 0) |
590 | goto out; |
591 | |
592 | SET(tp->t_state, TS_BUSY)((tp->t_state) |= (0x00004)); |
593 | cy_enable_transmitter(cy); |
594 | } |
595 | out: |
596 | |
597 | splx(s)spllower(s); |
598 | } |
599 | |
600 | /* |
601 | * stop output |
602 | */ |
603 | int |
604 | cystop(struct tty *tp, int flag) |
605 | { |
606 | int card = CY_CARD(tp->t_dev)((((unsigned)((tp->t_dev) & 0xff) | (((tp->t_dev) & 0xffff0000) >> 8)) >> 5) & 3); |
607 | int port = CY_PORT(tp->t_dev)(((unsigned)((tp->t_dev) & 0xff) | (((tp->t_dev) & 0xffff0000) >> 8)) & 0xf); |
608 | struct cy_softc *sc = cy_cd.cd_devs[card]; |
609 | struct cy_port *cy = &sc->sc_ports[port]; |
610 | int s; |
611 | |
612 | #ifdef CY_DEBUG |
613 | printf("%s port %d stop tty %p flag 0x%x\n", sc->sc_dev.dv_xname, |
614 | port, tp, flag); |
615 | #endif |
616 | |
617 | s = spltty()splraise(0x9); |
618 | |
619 | if (ISSET(tp->t_state, TS_BUSY)((tp->t_state) & (0x00004))) { |
620 | if (!ISSET(tp->t_state, TS_TTSTOP)((tp->t_state) & (0x00100))) |
621 | SET(tp->t_state, TS_FLUSH)((tp->t_state) |= (0x00010)); |
622 | |
623 | /* |
624 | * the transmit interrupt routine will disable transmit when it |
625 | * notices that CYF_STOP has been set. |
626 | */ |
627 | SET(cy->cy_flags, CYF_STOP)((cy->cy_flags) |= (0x08)); |
628 | } |
629 | splx(s)spllower(s); |
630 | return (0); |
631 | } |
632 | |
633 | /* |
634 | * parameter setting routine. |
635 | * returns 0 if successful, else returns error code |
636 | */ |
637 | int |
638 | cyparam(struct tty *tp, struct termios *t) |
639 | { |
640 | int card = CY_CARD(tp->t_dev)((((unsigned)((tp->t_dev) & 0xff) | (((tp->t_dev) & 0xffff0000) >> 8)) >> 5) & 3); |
641 | int port = CY_PORT(tp->t_dev)(((unsigned)((tp->t_dev) & 0xff) | (((tp->t_dev) & 0xffff0000) >> 8)) & 0xf); |
642 | struct cy_softc *sc = cy_cd.cd_devs[card]; |
643 | struct cy_port *cy = &sc->sc_ports[port]; |
644 | int ibpr, obpr, i_clk_opt, o_clk_opt; |
645 | int s, opt; |
646 | |
647 | #ifdef CY_DEBUG |
648 | printf("%s port %d param tty %p termios %p\n", sc->sc_dev.dv_xname, |
649 | port, tp, t); |
650 | printf("ispeed %d ospeed %d\n", t->c_ispeed, t->c_ospeed); |
651 | #endif |
652 | |
653 | if (t->c_ospeed != 0 && |
654 | cy_speed(t->c_ospeed, &o_clk_opt, &obpr, cy->cy_clock) < 0) |
655 | return (EINVAL22); |
656 | |
657 | if (t->c_ispeed != 0 && |
658 | cy_speed(t->c_ispeed, &i_clk_opt, &ibpr, cy->cy_clock) < 0) |
659 | return (EINVAL22); |
660 | |
661 | s = spltty()splraise(0x9); |
662 | |
663 | /* hang up the line is ospeed is zero, else turn DTR on */ |
664 | cy_modem_control(cy, TIOCM_DTR0002, (t->c_ospeed == 0 ? DMBIC2 : DMBIS1)); |
665 | |
666 | /* channel was selected by the above call to cy_modem_control() */ |
667 | /* cd_write_reg(cy, CD1400_CAR, port & CD1400_CAR_CHAN); */ |
668 | |
669 | /* set transmit speed */ |
670 | if (t->c_ospeed != 0) { |
671 | cd_write_reg(cy, CD1400_TCOR, o_clk_opt)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x76<<1))<<cy->cy_bustype)), ((o_clk_opt)) )); |
672 | cd_write_reg(cy, CD1400_TBPR, obpr)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x72<<1))<<cy->cy_bustype)), ((obpr)))); |
673 | } |
674 | /* set receive speed */ |
675 | if (t->c_ispeed != 0) { |
676 | cd_write_reg(cy, CD1400_RCOR, i_clk_opt)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x7C<<1))<<cy->cy_bustype)), ((i_clk_opt)) )); |
677 | cd_write_reg(cy, CD1400_RBPR, ibpr)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x78<<1))<<cy->cy_bustype)), ((ibpr)))); |
678 | } |
679 | |
680 | opt = CD1400_CCR_CMDCHANCTL(1<<4) | CD1400_CCR_XMTEN(1<<3) |
681 | | (ISSET(t->c_cflag, CREAD)((t->c_cflag) & (0x00000800)) ? CD1400_CCR_RCVEN(1<<1) : CD1400_CCR_RCVDIS(1<<0)); |
682 | |
683 | if (opt != cy->cy_channel_control) { |
684 | cy->cy_channel_control = opt; |
685 | cd1400_channel_cmd(cy, opt); |
686 | } |
687 | |
688 | /* compute COR1 contents */ |
689 | opt = 0; |
690 | if (ISSET(t->c_cflag, PARENB)((t->c_cflag) & (0x00001000))) { |
691 | if (ISSET(t->c_cflag, PARODD)((t->c_cflag) & (0x00002000))) |
692 | opt |= CD1400_COR1_PARODD(1<<7); |
693 | opt |= CD1400_COR1_PARNORMAL(2<<5); |
694 | } |
695 | |
696 | if (!ISSET(t->c_iflag, INPCK)((t->c_iflag) & (0x00000010))) |
697 | opt |= CD1400_COR1_NOINPCK(1<<4); /* no parity checking */ |
698 | |
699 | if (ISSET(t->c_cflag, CSTOPB)((t->c_cflag) & (0x00000400))) |
700 | opt |= CD1400_COR1_STOP2(2<<2); |
701 | |
702 | switch (t->c_cflag & CSIZE0x00000300) { |
703 | case CS50x00000000: |
704 | opt |= CD1400_COR1_CS5(0<<0); |
705 | break; |
706 | |
707 | case CS60x00000100: |
708 | opt |= CD1400_COR1_CS6(1<<0); |
709 | break; |
710 | |
711 | case CS70x00000200: |
712 | opt |= CD1400_COR1_CS7(2<<0); |
713 | break; |
714 | |
715 | default: |
716 | opt |= CD1400_COR1_CS8(3<<0); |
717 | break; |
718 | } |
719 | |
720 | cd_write_reg(cy, CD1400_COR1, opt)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x08<<1))<<cy->cy_bustype)), ((opt)))); |
721 | |
722 | #ifdef CY_DEBUG |
723 | printf("cor1 = 0x%x...", opt); |
724 | #endif |
725 | |
726 | /* |
727 | * use the CD1400 automatic CTS flow control if CRTSCTS is set |
728 | * |
729 | * CD1400_COR2_ETC is used because breaks are generated with |
730 | * embedded transmit commands |
731 | */ |
732 | cd_write_reg(cy, CD1400_COR2,((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x09<<1))<<cy->cy_bustype)), (((1<<5 ) | (((t->c_cflag) & (0x00010000)) ? (1<<1) : 0) )))) |
733 | CD1400_COR2_ETC |((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x09<<1))<<cy->cy_bustype)), (((1<<5 ) | (((t->c_cflag) & (0x00010000)) ? (1<<1) : 0) )))) |
734 | (ISSET(t->c_cflag, CRTSCTS) ? CD1400_COR2_CCTS_OFLOW : 0))((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x09<<1))<<cy->cy_bustype)), (((1<<5 ) | (((t->c_cflag) & (0x00010000)) ? (1<<1) : 0) )))); |
735 | |
736 | cd_write_reg(cy, CD1400_COR3, RX_FIFO_THRESHOLD)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x0A<<1))<<cy->cy_bustype)), ((6)))); |
737 | |
738 | cd1400_channel_cmd(cy, |
739 | CD1400_CCR_CMDCORCHG(1<<6) | |
740 | CD1400_CCR_COR1(1<<1) | CD1400_CCR_COR2(1<<2) | CD1400_CCR_COR3(1<<3)); |
741 | |
742 | cd_write_reg(cy, CD1400_COR4, CD1400_COR4_PFO_EXCEPTION)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x1E<<1))<<cy->cy_bustype)), (((0<<0 ))))); |
743 | cd_write_reg(cy, CD1400_COR5, 0)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x1F<<1))<<cy->cy_bustype)), ((0)))); |
744 | |
745 | /* |
746 | * set modem change option registers to generate interrupts |
747 | * on carrier detect changes. |
748 | * |
749 | * if hardware RTS handshaking is used (CY_HW_RTS, DTR and RTS lines |
750 | * exchanged), also set the handshaking threshold. |
751 | */ |
752 | #ifdef CY_HW_RTS |
753 | cd_write_reg(cy, CD1400_MCOR1, CD1400_MCOR1_CDzd |((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x15<<1))<<cy->cy_bustype)), (((1<<4 ) | (((t->c_cflag) & (0x00010000)) ? 9 : 0))))) |
754 | (ISSET(t->c_cflag, CRTSCTS) ? RX_DTR_THRESHOLD : 0))((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x15<<1))<<cy->cy_bustype)), (((1<<4 ) | (((t->c_cflag) & (0x00010000)) ? 9 : 0))))); |
755 | #else |
756 | cd_write_reg(cy, CD1400_MCOR1, CD1400_MCOR1_CDzd)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x15<<1))<<cy->cy_bustype)), (((1<<4 ))))); |
757 | #endif /* CY_HW_RTS */ |
758 | |
759 | cd_write_reg(cy, CD1400_MCOR2, CD1400_MCOR2_CDod)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x16<<1))<<cy->cy_bustype)), (((1<<4 ))))); |
760 | |
761 | /* |
762 | * set receive timeout to approx. 2ms |
763 | * could use more complex logic here... |
764 | * (but is it actually needed or even useful?) |
765 | */ |
766 | cd_write_reg(cy, CD1400_RTPR, 2)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x21<<1))<<cy->cy_bustype)), ((2)))); |
767 | |
768 | /* |
769 | * should do anything else here? |
770 | * XXX check MDMBUF handshaking like in com.c? |
771 | */ |
772 | |
773 | splx(s)spllower(s); |
774 | return (0); |
775 | } |
776 | |
777 | /* |
778 | * set/get modem line status |
779 | * |
780 | * bits can be: TIOCM_DTR, TIOCM_RTS, TIOCM_CTS, TIOCM_CD, TIOCM_RI, TIOCM_DSR |
781 | * |
782 | * RTS and DTR are exchanged if CY_HW_RTS is set |
783 | * |
784 | */ |
785 | int |
786 | cy_modem_control(struct cy_port *cy, int bits, int howto) |
787 | { |
788 | int s, msvr; |
789 | |
790 | s = spltty()splraise(0x9); |
791 | |
792 | /* select channel */ |
793 | cd_write_reg(cy, CD1400_CAR, cy->cy_port_num & CD1400_CAR_CHAN)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x68<<1))<<cy->cy_bustype)), ((cy->cy_port_num & (3<<0))))); |
794 | |
795 | /* does not manipulate RTS if it is used for flow control */ |
796 | switch (howto) { |
797 | case DMGET3: |
798 | bits = 0; |
799 | if (cy->cy_channel_control & CD1400_CCR_RCVEN(1<<1)) |
800 | bits |= TIOCM_LE0001; |
801 | msvr = cd_read_reg(cy, CD1400_MSVR2)((cy->cy_memt)->read_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6D<<1))<<cy->cy_bustype)))); |
802 | #ifdef CY_HW_RTS |
803 | if (cd_read_reg(cy, CD1400_MSVR1)((cy->cy_memt)->read_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6C<<1))<<cy->cy_bustype)))) & CD1400_MSVR1_RTS(1<<0)) |
804 | bits |= TIOCM_DTR0002; |
805 | if (msvr & CD1400_MSVR2_DTR(1<<1)) |
806 | bits |= TIOCM_RTS0004; |
807 | #else |
808 | if (cd_read_reg(cy, CD1400_MSVR1)((cy->cy_memt)->read_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6C<<1))<<cy->cy_bustype)))) & CD1400_MSVR1_RTS(1<<0)) |
809 | bits |= TIOCM_RTS0004; |
810 | if (msvr & CD1400_MSVR2_DTR(1<<1)) |
811 | bits |= TIOCM_DTR0002; |
812 | #endif /* CY_HW_RTS */ |
813 | if (msvr & CD1400_MSVR2_CTS(1<<6)) |
814 | bits |= TIOCM_CTS0040; |
815 | if (msvr & CD1400_MSVR2_CD(1<<4)) |
816 | bits |= TIOCM_CD0100; |
817 | if (msvr & CD1400_MSVR2_DSR(1<<7)) /* not connected on some |
818 | Cyclom cards? */ |
819 | bits |= TIOCM_DSR0400; |
820 | if (msvr & CD1400_MSVR2_RI(1<<5)) /* not connected on |
821 | Cyclom-8Y cards? */ |
822 | bits |= TIOCM_RI0200; |
823 | splx(s)spllower(s); |
824 | return (bits); |
825 | |
826 | case DMSET0: /* replace old values with new ones */ |
827 | #ifdef CY_HW_RTS |
828 | if (!ISSET(cy->cy_tty->t_cflag, CRTSCTS)((cy->cy_tty->t_termios.c_cflag) & (0x00010000))) |
829 | cd_write_reg(cy, CD1400_MSVR2,((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6D<<1))<<cy->cy_bustype)), ((((bits & 0004) ? (1<<1) : 0))))) |
830 | ((bits & TIOCM_RTS) ? CD1400_MSVR2_DTR : 0))((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6D<<1))<<cy->cy_bustype)), ((((bits & 0004) ? (1<<1) : 0))))); |
831 | cd_write_reg(cy, CD1400_MSVR1,((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6C<<1))<<cy->cy_bustype)), ((((bits & 0002) ? (1<<0) : 0))))) |
832 | ((bits & TIOCM_DTR) ? CD1400_MSVR1_RTS : 0))((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6C<<1))<<cy->cy_bustype)), ((((bits & 0002) ? (1<<0) : 0))))); |
833 | #else |
834 | if (!ISSET(cy->cy_tty->t_cflag, CRTSCTS)((cy->cy_tty->t_termios.c_cflag) & (0x00010000))) |
835 | cd_write_reg(cy, CD1400_MSVR1,((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6C<<1))<<cy->cy_bustype)), ((((bits & 0004) ? (1<<0) : 0))))) |
836 | ((bits & TIOCM_RTS) ? CD1400_MSVR1_RTS : 0))((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6C<<1))<<cy->cy_bustype)), ((((bits & 0004) ? (1<<0) : 0))))); |
837 | cd_write_reg(cy, CD1400_MSVR2,((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6D<<1))<<cy->cy_bustype)), ((((bits & 0002) ? (1<<1) : 0))))) |
838 | ((bits & TIOCM_DTR) ? CD1400_MSVR2_DTR : 0))((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6D<<1))<<cy->cy_bustype)), ((((bits & 0002) ? (1<<1) : 0))))); |
839 | #endif /* CY_HW_RTS */ |
840 | break; |
841 | |
842 | case DMBIS1: /* set bits */ |
843 | #ifdef CY_HW_RTS |
844 | if (!ISSET(cy->cy_tty->t_cflag, CRTSCTS)((cy->cy_tty->t_termios.c_cflag) & (0x00010000)) && |
845 | (bits & TIOCM_RTS0004) != 0) |
846 | cd_write_reg(cy, CD1400_MSVR2, CD1400_MSVR2_DTR)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6D<<1))<<cy->cy_bustype)), (((1<<1 ))))); |
847 | if (bits & TIOCM_DTR0002) |
848 | cd_write_reg(cy, CD1400_MSVR1, CD1400_MSVR1_RTS)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6C<<1))<<cy->cy_bustype)), (((1<<0 ))))); |
849 | #else |
850 | if (!ISSET(cy->cy_tty->t_cflag, CRTSCTS)((cy->cy_tty->t_termios.c_cflag) & (0x00010000)) && |
851 | (bits & TIOCM_RTS0004) != 0) |
852 | cd_write_reg(cy, CD1400_MSVR1, CD1400_MSVR1_RTS)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6C<<1))<<cy->cy_bustype)), (((1<<0 ))))); |
853 | if (bits & TIOCM_DTR0002) |
854 | cd_write_reg(cy, CD1400_MSVR2, CD1400_MSVR2_DTR)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6D<<1))<<cy->cy_bustype)), (((1<<1 ))))); |
855 | #endif /* CY_HW_RTS */ |
856 | break; |
857 | |
858 | case DMBIC2: /* clear bits */ |
859 | #ifdef CY_HW_RTS |
860 | if (!ISSET(cy->cy_tty->t_cflag, CRTSCTS)((cy->cy_tty->t_termios.c_cflag) & (0x00010000)) && |
861 | (bits & TIOCM_RTS0004)) |
862 | cd_write_reg(cy, CD1400_MSVR2, 0)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6D<<1))<<cy->cy_bustype)), ((0)))); |
863 | if (bits & TIOCM_DTR0002) |
864 | cd_write_reg(cy, CD1400_MSVR1, 0)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6C<<1))<<cy->cy_bustype)), ((0)))); |
865 | #else |
866 | if (!ISSET(cy->cy_tty->t_cflag, CRTSCTS)((cy->cy_tty->t_termios.c_cflag) & (0x00010000)) && |
867 | (bits & TIOCM_RTS0004)) |
868 | cd_write_reg(cy, CD1400_MSVR1, 0)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6C<<1))<<cy->cy_bustype)), ((0)))); |
869 | if (bits & TIOCM_DTR0002) |
870 | cd_write_reg(cy, CD1400_MSVR2, 0)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6D<<1))<<cy->cy_bustype)), ((0)))); |
871 | #endif /* CY_HW_RTS */ |
872 | break; |
873 | } |
874 | splx(s)spllower(s); |
875 | return (0); |
876 | } |
877 | |
878 | /* |
879 | * Upper-level handler loop (called from timer interrupt?) |
880 | * This routine is common for multiple cards |
881 | */ |
882 | void |
883 | cy_poll(void *arg) |
884 | { |
885 | int port; |
886 | struct cy_softc *sc = arg; |
887 | struct cy_port *cy; |
888 | struct tty *tp; |
889 | static int counter = 0; |
890 | #ifdef CY_DEBUG1 |
891 | int did_something; |
892 | #endif |
893 | |
894 | int s; |
895 | |
896 | s = spltty()splraise(0x9); |
897 | |
898 | if (sc->sc_events == 0 && ++counter < 200) { |
899 | splx(s)spllower(s); |
900 | goto out; |
901 | } |
902 | |
903 | sc->sc_events = 0; |
904 | splx(s)spllower(s); |
905 | |
906 | #ifdef CY_DEBUG1 |
907 | sc->sc_poll_count1++; |
908 | did_something = 0; |
909 | #endif |
910 | |
911 | for (port = 0; port < sc->sc_nports; port++) { |
912 | cy = &sc->sc_ports[port]; |
913 | if ((tp = cy->cy_tty) == NULL((void *)0) || cy->cy_ibuf == NULL((void *)0) || |
914 | !ISSET(tp->t_state, TS_ISOPEN | TS_WOPEN)((tp->t_state) & (0x00020 | 0x00200))) |
915 | continue; |
916 | |
917 | /* |
918 | * handle received data |
919 | */ |
920 | while (cy->cy_ibuf_rd_ptr != cy->cy_ibuf_wr_ptr) { |
921 | u_char line_stat; |
922 | int chr; |
923 | |
924 | line_stat = cy->cy_ibuf_rd_ptr[0]; |
925 | chr = cy->cy_ibuf_rd_ptr[1]; |
926 | |
927 | if (line_stat & |
928 | (CD1400_RDSR_BREAK(1<<3)|CD1400_RDSR_FE(1<<1))) |
929 | chr |= TTY_FE0x01000000; |
930 | if (line_stat & CD1400_RDSR_PE(1<<2)) |
931 | chr |= TTY_PE0x02000000; |
932 | |
933 | /* |
934 | * on an overrun error the data is treated as |
935 | * good just as it should be. |
936 | */ |
937 | |
938 | #ifdef CY_DEBUG |
939 | printf("%s port %d ttyinput 0x%x\n", |
940 | sc->sc_dev.dv_xname, port, chr); |
941 | #endif |
942 | |
943 | (*linesw[tp->t_line].l_rint)(chr, tp); |
944 | |
945 | s = spltty()splraise(0x9); /* really necessary? */ |
946 | if ((cy->cy_ibuf_rd_ptr += 2) == |
947 | cy->cy_ibuf_end) |
948 | cy->cy_ibuf_rd_ptr = cy->cy_ibuf; |
949 | splx(s)spllower(s); |
950 | |
951 | #ifdef CY_DEBUG1 |
952 | did_something = 1; |
953 | #endif |
954 | } |
955 | |
956 | #ifndef CY_HW_RTS |
957 | /* |
958 | * If we don't have any received data in ibuf and |
959 | * CRTSCTS is on and RTS is turned off, it is time |
960 | * to turn RTS back on |
961 | */ |
962 | if (ISSET(tp->t_cflag, CRTSCTS)((tp->t_termios.c_cflag) & (0x00010000))) { |
963 | /* we can't use cy_modem_control() here as it |
964 | doesn't change RTS if RTSCTS is on */ |
965 | cd_write_reg(cy, CD1400_CAR,((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x68<<1))<<cy->cy_bustype)), ((port & ( 3<<0))))) |
966 | port & CD1400_CAR_CHAN)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x68<<1))<<cy->cy_bustype)), ((port & ( 3<<0))))); |
967 | |
968 | if ((cd_read_reg(cy,((cy->cy_memt)->read_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6C<<1))<<cy->cy_bustype)))) |
969 | CD1400_MSVR1)((cy->cy_memt)->read_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6C<<1))<<cy->cy_bustype)))) & CD1400_MSVR1_RTS(1<<0)) == 0) { |
970 | cd_write_reg(cy, CD1400_MSVR1,((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6C<<1))<<cy->cy_bustype)), (((1<<0 ))))) |
971 | CD1400_MSVR1_RTS)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6C<<1))<<cy->cy_bustype)), (((1<<0 ))))); |
972 | #ifdef CY_DEBUG1 |
973 | did_something = 1; |
974 | #endif |
975 | } |
976 | } |
977 | #endif /* CY_HW_RTS */ |
978 | |
979 | /* |
980 | * handle carrier changes |
981 | */ |
982 | s = spltty()splraise(0x9); |
983 | if (ISSET(cy->cy_flags, CYF_CARRIER_CHANGED)((cy->cy_flags) & (0x01))) { |
984 | int carrier; |
985 | |
986 | CLR(cy->cy_flags, CYF_CARRIER_CHANGED)((cy->cy_flags) &= ~(0x01)); |
987 | splx(s)spllower(s); |
988 | |
989 | carrier = ((cy->cy_carrier_stat & |
990 | CD1400_MSVR2_CD(1<<4)) != 0); |
991 | |
992 | #ifdef CY_DEBUG |
993 | printf("%s: cy_poll: carrier change " |
994 | "(port %d, carrier %d)\n", |
995 | sc->sc_dev.dv_xname, port, carrier); |
996 | #endif |
997 | if (CY_DIALIN(tp->t_dev)(!((((unsigned)((tp->t_dev) & 0xff) | (((tp->t_dev) & 0xffff0000) >> 8)) & 0x80) != 0)) && |
998 | !(*linesw[tp->t_line].l_modem)(tp, carrier)) |
999 | cy_modem_control(cy, TIOCM_DTR0002, DMBIC2); |
1000 | |
1001 | #ifdef CY_DEBUG1 |
1002 | did_something = 1; |
1003 | #endif |
1004 | } else { |
1005 | splx(s)spllower(s); |
1006 | } |
1007 | |
1008 | s = spltty()splraise(0x9); |
1009 | if (ISSET(cy->cy_flags, CYF_START)((cy->cy_flags) & (0x20))) { |
1010 | CLR(cy->cy_flags, CYF_START)((cy->cy_flags) &= ~(0x20)); |
1011 | splx(s)spllower(s); |
1012 | |
1013 | (*linesw[tp->t_line].l_start)(tp); |
1014 | |
1015 | #ifdef CY_DEBUG1 |
1016 | did_something = 1; |
1017 | #endif |
1018 | } else { |
1019 | splx(s)spllower(s); |
1020 | } |
1021 | |
1022 | /* could move this to even upper level... */ |
1023 | if (cy->cy_fifo_overruns) { |
1024 | cy->cy_fifo_overruns = 0; |
1025 | /* doesn't report overrun count, |
1026 | but shouldn't really matter */ |
1027 | log(LOG_WARNING4, "%s: port %d fifo overrun\n", |
1028 | sc->sc_dev.dv_xname, port); |
1029 | } |
1030 | if (cy->cy_ibuf_overruns) { |
1031 | cy->cy_ibuf_overruns = 0; |
1032 | log(LOG_WARNING4, "%s: port %d ibuf overrun\n", |
1033 | sc->sc_dev.dv_xname, port); |
1034 | } |
1035 | } /* for(port...) */ |
1036 | #ifdef CY_DEBUG1 |
1037 | if (did_something && counter >= 200) |
1038 | sc->sc_poll_count2++; |
1039 | #endif |
1040 | |
1041 | counter = 0; |
1042 | |
1043 | out: |
1044 | timeout_add(&sc->sc_poll_to, 1); |
1045 | } |
1046 | |
1047 | /* |
1048 | * hardware interrupt routine |
1049 | */ |
1050 | int |
1051 | cy_intr(void *arg) |
1052 | { |
1053 | struct cy_softc *sc = arg; |
1054 | struct cy_port *cy; |
1055 | int cy_chip, stat; |
1056 | int int_serviced = -1; |
1057 | |
1058 | /* |
1059 | * Check interrupt status of each CD1400 chip on this card |
1060 | * (multiple cards cannot share the same interrupt) |
1061 | */ |
1062 | for (cy_chip = 0; cy_chip < sc->sc_nr_cd1400s; cy_chip++) { |
1063 | |
1064 | stat = cd_read_reg_sc(sc, cy_chip, CD1400_SVRR)((sc->sc_memt)->read_1((sc->sc_memh), (sc->sc_cd1400_offs [cy_chip]+ (((0x67<<1))<<sc->sc_bustype)))); |
1065 | if (stat == 0) |
1066 | continue; |
1067 | |
1068 | if (ISSET(stat, CD1400_SVRR_RXRDY)((stat) & ((1<<0)))) { |
1069 | u_char save_car, save_rir, serv_type; |
1070 | u_char line_stat, recv_data, n_chars; |
1071 | u_char *buf_p; |
1072 | |
1073 | save_rir = cd_read_reg_sc(sc, cy_chip, CD1400_RIR)((sc->sc_memt)->read_1((sc->sc_memh), (sc->sc_cd1400_offs [cy_chip]+ (((0x6B<<1))<<sc->sc_bustype)))); |
1074 | save_car = cd_read_reg_sc(sc, cy_chip, CD1400_CAR)((sc->sc_memt)->read_1((sc->sc_memh), (sc->sc_cd1400_offs [cy_chip]+ (((0x68<<1))<<sc->sc_bustype)))); |
1075 | /* enter rx service */ |
1076 | cd_write_reg_sc(sc, cy_chip, CD1400_CAR, save_rir)((sc->sc_memt)->write_1((sc->sc_memh), (sc->sc_cd1400_offs [cy_chip]+ (((0x68<<1))<<sc->sc_bustype)), ((save_rir )))); |
1077 | |
1078 | serv_type = cd_read_reg_sc(sc, cy_chip, CD1400_RIVR)((sc->sc_memt)->read_1((sc->sc_memh), (sc->sc_cd1400_offs [cy_chip]+ (((0x43<<1))<<sc->sc_bustype)))); |
1079 | cy = &sc->sc_ports[serv_type >> 3]; |
1080 | |
1081 | #ifdef CY_DEBUG1 |
1082 | cy->cy_rx_int_count++; |
1083 | #endif |
1084 | |
1085 | buf_p = cy->cy_ibuf_wr_ptr; |
1086 | |
1087 | if (ISSET(serv_type, CD1400_RIVR_EXCEPTION)((serv_type) & ((1<<2)))) { |
1088 | line_stat = cd_read_reg(cy, CD1400_RDSR)((cy->cy_memt)->read_1((cy->cy_memh), (cy->cy_chip_offs +(((0x62<<1))<<cy->cy_bustype)))); |
1089 | recv_data = cd_read_reg(cy, CD1400_RDSR)((cy->cy_memt)->read_1((cy->cy_memh), (cy->cy_chip_offs +(((0x62<<1))<<cy->cy_bustype)))); |
1090 | |
1091 | if (cy->cy_tty == NULL((void *)0) || |
1092 | !ISSET(cy->cy_tty->t_state, TS_ISOPEN)((cy->cy_tty->t_state) & (0x00020))) |
1093 | goto end_rx_serv; |
1094 | |
1095 | #ifdef CY_DEBUG |
1096 | printf("%s port %d recv exception, " |
1097 | "line_stat 0x%x, char 0x%x\n", |
1098 | sc->sc_dev.dv_xname, cy->cy_port_num, |
1099 | line_stat, recv_data); |
1100 | #endif |
1101 | if (ISSET(line_stat, CD1400_RDSR_OE)((line_stat) & ((1<<0)))) |
1102 | cy->cy_fifo_overruns++; |
1103 | |
1104 | *buf_p++ = line_stat; |
1105 | *buf_p++ = recv_data; |
1106 | if (buf_p == cy->cy_ibuf_end) |
1107 | buf_p = cy->cy_ibuf; |
1108 | |
1109 | if (buf_p == cy->cy_ibuf_rd_ptr) { |
1110 | if (buf_p == cy->cy_ibuf) |
1111 | buf_p = cy->cy_ibuf_end; |
1112 | buf_p -= 2; |
1113 | cy->cy_ibuf_overruns++; |
1114 | } |
1115 | sc->sc_events = 1; |
1116 | } else { /* no exception, received data OK */ |
1117 | n_chars = cd_read_reg(cy, CD1400_RDCR)((cy->cy_memt)->read_1((cy->cy_memh), (cy->cy_chip_offs +(((0x0E<<1))<<cy->cy_bustype)))); |
1118 | |
1119 | /* If no tty or not open, discard data */ |
1120 | if (cy->cy_tty == NULL((void *)0) || |
1121 | !ISSET(cy->cy_tty->t_state, TS_ISOPEN)((cy->cy_tty->t_state) & (0x00020))) { |
1122 | while (n_chars--) |
1123 | cd_read_reg(cy, CD1400_RDSR)((cy->cy_memt)->read_1((cy->cy_memh), (cy->cy_chip_offs +(((0x62<<1))<<cy->cy_bustype)))); |
1124 | goto end_rx_serv; |
1125 | } |
1126 | |
1127 | #ifdef CY_DEBUG |
1128 | printf("%s port %d receive ok %d chars\n", |
1129 | sc->sc_dev.dv_xname, cy->cy_port_num, |
1130 | n_chars); |
1131 | #endif |
1132 | while (n_chars--) { |
1133 | *buf_p++ = 0; /* status: OK */ |
1134 | *buf_p++ = cd_read_reg(cy,((cy->cy_memt)->read_1((cy->cy_memh), (cy->cy_chip_offs +(((0x62<<1))<<cy->cy_bustype)))) |
1135 | CD1400_RDSR)((cy->cy_memt)->read_1((cy->cy_memh), (cy->cy_chip_offs +(((0x62<<1))<<cy->cy_bustype)))); /* data byte */ |
1136 | if (buf_p == cy->cy_ibuf_end) |
1137 | buf_p = cy->cy_ibuf; |
1138 | if (buf_p == cy->cy_ibuf_rd_ptr) { |
1139 | if (buf_p == cy->cy_ibuf) |
1140 | buf_p = cy->cy_ibuf_end; |
1141 | buf_p -= 2; |
1142 | cy->cy_ibuf_overruns++; |
1143 | break; |
1144 | } |
1145 | } |
1146 | sc->sc_events = 1; |
1147 | } |
1148 | |
1149 | cy->cy_ibuf_wr_ptr = buf_p; |
1150 | |
1151 | #ifndef CY_HW_RTS |
1152 | /* RTS handshaking for incoming data */ |
1153 | if (ISSET(cy->cy_tty->t_cflag, CRTSCTS)((cy->cy_tty->t_termios.c_cflag) & (0x00010000))) { |
1154 | int bf; |
1155 | |
1156 | bf = buf_p - cy->cy_ibuf_rd_ptr; |
1157 | if (bf < 0) |
1158 | bf += IBUF_SIZE(2*512); |
1159 | |
1160 | if (bf > (IBUF_SIZE(2*512)/2)) /* turn RTS off */ |
1161 | cd_write_reg(cy, CD1400_MSVR1, 0)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6C<<1))<<cy->cy_bustype)), ((0)))); |
1162 | } |
1163 | #endif /* CY_HW_RTS */ |
1164 | |
1165 | end_rx_serv: |
1166 | /* terminate service context */ |
1167 | cd_write_reg(cy, CD1400_RIR, save_rir & 0x3f)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6B<<1))<<cy->cy_bustype)), ((save_rir & 0x3f)))); |
1168 | cd_write_reg(cy, CD1400_CAR, save_car)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x68<<1))<<cy->cy_bustype)), ((save_car))) ); |
1169 | int_serviced = 1; |
1170 | } /* if(rx_service...) */ |
1171 | |
1172 | if (ISSET(stat, CD1400_SVRR_MDMCH)((stat) & ((1<<2)))) { |
1173 | u_char save_car, save_mir, serv_type, modem_stat; |
1174 | |
1175 | save_mir = cd_read_reg_sc(sc, cy_chip, CD1400_MIR)((sc->sc_memt)->read_1((sc->sc_memh), (sc->sc_cd1400_offs [cy_chip]+ (((0x69<<1))<<sc->sc_bustype)))); |
1176 | save_car = cd_read_reg_sc(sc, cy_chip, CD1400_CAR)((sc->sc_memt)->read_1((sc->sc_memh), (sc->sc_cd1400_offs [cy_chip]+ (((0x68<<1))<<sc->sc_bustype)))); |
1177 | /* enter modem service */ |
1178 | cd_write_reg_sc(sc, cy_chip, CD1400_CAR, save_mir)((sc->sc_memt)->write_1((sc->sc_memh), (sc->sc_cd1400_offs [cy_chip]+ (((0x68<<1))<<sc->sc_bustype)), ((save_mir )))); |
1179 | |
1180 | serv_type = cd_read_reg_sc(sc, cy_chip, CD1400_MIVR)((sc->sc_memt)->read_1((sc->sc_memh), (sc->sc_cd1400_offs [cy_chip]+ (((0x41<<1))<<sc->sc_bustype)))); |
1181 | cy = &sc->sc_ports[serv_type >> 3]; |
1182 | |
1183 | #ifdef CY_DEBUG1 |
1184 | cy->cy_modem_int_count++; |
1185 | #endif |
1186 | |
1187 | modem_stat = cd_read_reg(cy, CD1400_MSVR2)((cy->cy_memt)->read_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6D<<1))<<cy->cy_bustype)))); |
1188 | |
1189 | #ifdef CY_DEBUG |
1190 | printf("%s port %d modem line change, new stat 0x%x\n", |
1191 | sc->sc_dev.dv_xname, cy->cy_port_num, modem_stat); |
1192 | #endif |
1193 | if (ISSET((cy->cy_carrier_stat ^ modem_stat),(((cy->cy_carrier_stat ^ modem_stat)) & ((1<<4)) ) |
1194 | CD1400_MSVR2_CD)(((cy->cy_carrier_stat ^ modem_stat)) & ((1<<4)) )) { |
1195 | SET(cy->cy_flags, CYF_CARRIER_CHANGED)((cy->cy_flags) |= (0x01)); |
1196 | sc->sc_events = 1; |
1197 | } |
1198 | |
1199 | cy->cy_carrier_stat = modem_stat; |
1200 | |
1201 | /* terminate service context */ |
1202 | cd_write_reg(cy, CD1400_MIR, save_mir & 0x3f)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x69<<1))<<cy->cy_bustype)), ((save_mir & 0x3f)))); |
1203 | cd_write_reg(cy, CD1400_CAR, save_car)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x68<<1))<<cy->cy_bustype)), ((save_car))) ); |
1204 | int_serviced = 1; |
1205 | } /* if(modem_service...) */ |
1206 | |
1207 | if (ISSET(stat, CD1400_SVRR_TXRDY)((stat) & ((1<<1)))) { |
1208 | u_char save_car, save_tir, serv_type, count, ch; |
1209 | struct tty *tp; |
1210 | |
1211 | save_tir = cd_read_reg_sc(sc, cy_chip, CD1400_TIR)((sc->sc_memt)->read_1((sc->sc_memh), (sc->sc_cd1400_offs [cy_chip]+ (((0x6A<<1))<<sc->sc_bustype)))); |
1212 | save_car = cd_read_reg_sc(sc, cy_chip, CD1400_CAR)((sc->sc_memt)->read_1((sc->sc_memh), (sc->sc_cd1400_offs [cy_chip]+ (((0x68<<1))<<sc->sc_bustype)))); |
1213 | /* enter tx service */ |
1214 | cd_write_reg_sc(sc, cy_chip, CD1400_CAR, save_tir)((sc->sc_memt)->write_1((sc->sc_memh), (sc->sc_cd1400_offs [cy_chip]+ (((0x68<<1))<<sc->sc_bustype)), ((save_tir )))); |
1215 | |
1216 | serv_type = cd_read_reg_sc(sc, cy_chip, CD1400_TIVR)((sc->sc_memt)->read_1((sc->sc_memh), (sc->sc_cd1400_offs [cy_chip]+ (((0x42<<1))<<sc->sc_bustype)))); |
1217 | cy = &sc->sc_ports[serv_type >> 3]; |
1218 | |
1219 | #ifdef CY_DEBUG1 |
1220 | cy->cy_tx_int_count++; |
1221 | #endif |
1222 | #ifdef CY_DEBUG |
1223 | printf("%s port %d tx service\n", sc->sc_dev.dv_xname, |
1224 | cy->cy_port_num); |
1225 | #endif |
1226 | |
1227 | /* stop transmitting if no tty or CYF_STOP set */ |
1228 | tp = cy->cy_tty; |
1229 | if (tp == NULL((void *)0) || ISSET(cy->cy_flags, CYF_STOP)((cy->cy_flags) & (0x08))) |
1230 | goto txdone; |
1231 | |
1232 | count = 0; |
1233 | if (ISSET(cy->cy_flags, CYF_SEND_NUL)((cy->cy_flags) & (0x10))) { |
1234 | cd_write_reg(cy, CD1400_TDR, 0)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x63<<1))<<cy->cy_bustype)), ((0)))); |
1235 | cd_write_reg(cy, CD1400_TDR, 0)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x63<<1))<<cy->cy_bustype)), ((0)))); |
1236 | count += 2; |
1237 | CLR(cy->cy_flags, CYF_SEND_NUL)((cy->cy_flags) &= ~(0x10)); |
1238 | } |
1239 | |
1240 | if (tp->t_outq.c_cc > 0) { |
1241 | SET(tp->t_state, TS_BUSY)((tp->t_state) |= (0x00004)); |
1242 | while (tp->t_outq.c_cc > 0 && |
1243 | count < CD1400_TX_FIFO_SIZE12) { |
1244 | ch = getc(&tp->t_outq); |
1245 | /* remember to double NUL characters |
1246 | because embedded transmit commands |
1247 | are enabled */ |
1248 | if (ch == 0) { |
1249 | if (count >= |
1250 | CD1400_TX_FIFO_SIZE12-2) { |
1251 | SET(cy->cy_flags,((cy->cy_flags) |= (0x10)) |
1252 | CYF_SEND_NUL)((cy->cy_flags) |= (0x10)); |
1253 | break; |
1254 | } |
1255 | |
1256 | cd_write_reg(cy, CD1400_TDR, ch)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x63<<1))<<cy->cy_bustype)), ((ch)))); |
1257 | count++; |
1258 | } |
1259 | |
1260 | cd_write_reg(cy, CD1400_TDR, ch)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x63<<1))<<cy->cy_bustype)), ((ch)))); |
1261 | count++; |
1262 | } |
1263 | } else { |
1264 | /* no data to send -- check if we should |
1265 | start/stop a break */ |
1266 | /* XXX does this cause too much delay before |
1267 | breaks? */ |
1268 | if (ISSET(cy->cy_flags, CYF_START_BREAK)((cy->cy_flags) & (0x02))) { |
1269 | cd_write_reg(cy, CD1400_TDR, 0)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x63<<1))<<cy->cy_bustype)), ((0)))); |
1270 | cd_write_reg(cy, CD1400_TDR, 0x81)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x63<<1))<<cy->cy_bustype)), ((0x81)))); |
1271 | CLR(cy->cy_flags, CYF_START_BREAK)((cy->cy_flags) &= ~(0x02)); |
1272 | } |
1273 | if (ISSET(cy->cy_flags, CYF_END_BREAK)((cy->cy_flags) & (0x04))) { |
1274 | cd_write_reg(cy, CD1400_TDR, 0)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x63<<1))<<cy->cy_bustype)), ((0)))); |
1275 | cd_write_reg(cy, CD1400_TDR, 0x83)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x63<<1))<<cy->cy_bustype)), ((0x83)))); |
1276 | CLR(cy->cy_flags, CYF_END_BREAK)((cy->cy_flags) &= ~(0x04)); |
1277 | } |
1278 | } |
1279 | |
1280 | if (tp->t_outq.c_cc == 0) { |
1281 | txdone: |
1282 | /* |
1283 | * No data to send or requested to stop. |
1284 | * Disable transmit interrupt |
1285 | */ |
1286 | cd_write_reg(cy, CD1400_SRER,((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x06<<1))<<cy->cy_bustype)), ((((cy->cy_memt )->read_1((cy->cy_memh), (cy->cy_chip_offs+(((0x06<< 1))<<cy->cy_bustype)))) & ~(1<<2))))) |
1287 | cd_read_reg(cy, CD1400_SRER)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x06<<1))<<cy->cy_bustype)), ((((cy->cy_memt )->read_1((cy->cy_memh), (cy->cy_chip_offs+(((0x06<< 1))<<cy->cy_bustype)))) & ~(1<<2))))) |
1288 | & ~CD1400_SRER_TXRDY)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x06<<1))<<cy->cy_bustype)), ((((cy->cy_memt )->read_1((cy->cy_memh), (cy->cy_chip_offs+(((0x06<< 1))<<cy->cy_bustype)))) & ~(1<<2))))); |
1289 | CLR(cy->cy_flags, CYF_STOP)((cy->cy_flags) &= ~(0x08)); |
1290 | CLR(tp->t_state, TS_BUSY)((tp->t_state) &= ~(0x00004)); |
1291 | } |
1292 | |
1293 | if (tp->t_outq.c_cc <= tp->t_lowat) { |
1294 | SET(cy->cy_flags, CYF_START)((cy->cy_flags) |= (0x20)); |
1295 | sc->sc_events = 1; |
1296 | } |
1297 | |
1298 | /* terminate service context */ |
1299 | cd_write_reg(cy, CD1400_TIR, save_tir & 0x3f)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x6A<<1))<<cy->cy_bustype)), ((save_tir & 0x3f)))); |
1300 | cd_write_reg(cy, CD1400_CAR, save_car)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x68<<1))<<cy->cy_bustype)), ((save_car))) ); |
1301 | int_serviced = 1; |
1302 | } /* if(tx_service...) */ |
1303 | } /* for(...all CD1400s on a card) */ |
1304 | |
1305 | /* ensure an edge for next interrupt */ |
1306 | bus_space_write_1(sc->sc_memt, sc->sc_memh,((sc->sc_memt)->write_1((sc->sc_memh), (0x1800<< sc->sc_bustype), (0))) |
1307 | CY_CLEAR_INTR<<sc->sc_bustype, 0)((sc->sc_memt)->write_1((sc->sc_memh), (0x1800<< sc->sc_bustype), (0))); |
1308 | return (int_serviced); |
1309 | } |
1310 | |
1311 | /* |
1312 | * subroutine to enable CD1400 transmitter |
1313 | */ |
1314 | void |
1315 | cy_enable_transmitter(struct cy_port *cy) |
1316 | { |
1317 | int s; |
1318 | s = spltty()splraise(0x9); |
1319 | cd_write_reg(cy, CD1400_CAR, cy->cy_port_num & CD1400_CAR_CHAN)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x68<<1))<<cy->cy_bustype)), ((cy->cy_port_num & (3<<0))))); |
1320 | cd_write_reg(cy, CD1400_SRER, cd_read_reg(cy, CD1400_SRER)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x06<<1))<<cy->cy_bustype)), ((((cy->cy_memt )->read_1((cy->cy_memh), (cy->cy_chip_offs+(((0x06<< 1))<<cy->cy_bustype)))) | (1<<2))))) |
1321 | | CD1400_SRER_TXRDY)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x06<<1))<<cy->cy_bustype)), ((((cy->cy_memt )->read_1((cy->cy_memh), (cy->cy_chip_offs+(((0x06<< 1))<<cy->cy_bustype)))) | (1<<2))))); |
1322 | splx(s)spllower(s); |
1323 | } |
1324 | |
1325 | /* |
1326 | * Execute a CD1400 channel command |
1327 | */ |
1328 | void |
1329 | cd1400_channel_cmd(struct cy_port *cy, int cmd) |
1330 | { |
1331 | u_int waitcnt = 5 * 8 * 1024; /* approx 5 ms */ |
1332 | |
1333 | #ifdef CY_DEBUG |
1334 | printf("c1400_channel_cmd cy %p command 0x%x\n", cy, cmd); |
1335 | #endif |
1336 | |
1337 | /* wait until cd1400 is ready to process a new command */ |
1338 | while (cd_read_reg(cy, CD1400_CCR)((cy->cy_memt)->read_1((cy->cy_memh), (cy->cy_chip_offs +(((0x05<<1))<<cy->cy_bustype)))) != 0 && waitcnt-- > 0) |
1339 | ; |
1340 | |
1341 | if (waitcnt == 0) |
1342 | log(LOG_ERR3, "cy: channel command timeout\n"); |
1343 | |
1344 | cd_write_reg(cy, CD1400_CCR, cmd)((cy->cy_memt)->write_1((cy->cy_memh), (cy->cy_chip_offs +(((0x05<<1))<<cy->cy_bustype)), ((cmd)))); |
1345 | } |
1346 | |
1347 | /* |
1348 | * Compute clock option register and baud rate register values |
1349 | * for a given speed. Return 0 on success, -1 on failure. |
1350 | * |
1351 | * The error between requested and actual speed seems |
1352 | * to be well within allowed limits (less than 3%) |
1353 | * with every speed value between 50 and 150000 bps. |
1354 | */ |
1355 | int |
1356 | cy_speed(speed_t speed, int *cor, int *bpr, int cy_clock) |
1357 | { |
1358 | int c, co, br; |
1359 | |
1360 | if (speed < 50 || speed > 150000) |
1361 | return (-1); |
1362 | |
1363 | for (c = 0, co = 8; co <= 2048; co <<= 2, c++) { |
1364 | br = (cy_clock + (co * speed) / 2) / (co * speed); |
1365 | if (br < 0x100) { |
1366 | *bpr = br; |
1367 | *cor = c; |
1368 | return (0); |
1369 | } |
1370 | } |
1371 | |
1372 | return (-1); |
1373 | } |