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