1 1.14 riastrad /* $Id: at91usart.c,v 1.14 2022/10/26 23:38:06 riastradh Exp $ */ 2 1.14 riastrad /* $NetBSD: at91usart.c,v 1.14 2022/10/26 23:38:06 riastradh Exp $ */ 3 1.2 matt 4 1.2 matt /* 5 1.2 matt * Copyright (c) 2007 Embedtronics Oy. All rights reserved. 6 1.2 matt * 7 1.2 matt * Copyright (c) 1998, 1999, 2001, 2002, 2004 The NetBSD Foundation, Inc. 8 1.2 matt * All rights reserved. 9 1.2 matt * 10 1.2 matt * This code is derived from software contributed to The NetBSD Foundation 11 1.2 matt * by Jesse Off 12 1.2 matt * 13 1.2 matt * This code is derived from software contributed to The NetBSD Foundation 14 1.2 matt * by Ichiro FUKUHARA and Naoto Shimazaki. 15 1.2 matt * 16 1.2 matt * This code is derived from software contributed to The NetBSD Foundation 17 1.2 matt * by IWAMOTO Toshihiro. 18 1.2 matt * 19 1.2 matt * This code is derived from software contributed to The NetBSD Foundation 20 1.2 matt * by Charles M. Hannum. 21 1.2 matt * 22 1.2 matt * Redistribution and use in source and binary forms, with or without 23 1.2 matt * modification, are permitted provided that the following conditions 24 1.2 matt * are met: 25 1.2 matt * 1. Redistributions of source code must retain the above copyright 26 1.2 matt * notice, this list of conditions and the following disclaimer. 27 1.2 matt * 2. Redistributions in binary form must reproduce the above copyright 28 1.2 matt * notice, this list of conditions and the following disclaimer in the 29 1.2 matt * documentation and/or other materials provided with the distribution. 30 1.2 matt * 31 1.2 matt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 32 1.2 matt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 33 1.2 matt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 34 1.2 matt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 35 1.2 matt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 36 1.2 matt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 1.2 matt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 1.2 matt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 39 1.2 matt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40 1.2 matt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 1.2 matt * POSSIBILITY OF SUCH DAMAGE. 42 1.2 matt */ 43 1.2 matt 44 1.2 matt /* 45 1.2 matt * Copyright (c) 1991 The Regents of the University of California. 46 1.2 matt * All rights reserved. 47 1.2 matt * 48 1.2 matt * Redistribution and use in source and binary forms, with or without 49 1.2 matt * modification, are permitted provided that the following conditions 50 1.2 matt * are met: 51 1.2 matt * 1. Redistributions of source code must retain the above copyright 52 1.2 matt * notice, this list of conditions and the following disclaimer. 53 1.2 matt * 2. Redistributions in binary form must reproduce the above copyright 54 1.2 matt * notice, this list of conditions and the following disclaimer in the 55 1.2 matt * documentation and/or other materials provided with the distribution. 56 1.2 matt * 3. Neither the name of the University nor the names of its contributors 57 1.2 matt * may be used to endorse or promote products derived from this software 58 1.2 matt * without specific prior written permission. 59 1.2 matt * 60 1.2 matt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 61 1.2 matt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 62 1.2 matt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 63 1.2 matt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 64 1.2 matt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 65 1.2 matt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 66 1.2 matt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 67 1.2 matt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 68 1.2 matt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 69 1.2 matt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 70 1.2 matt * SUCH DAMAGE. 71 1.2 matt * 72 1.2 matt * @(#)com.c 7.5 (Berkeley) 5/16/91 73 1.2 matt */ 74 1.2 matt 75 1.2 matt /* 76 1.2 matt * TODO: hardware flow control 77 1.2 matt */ 78 1.2 matt 79 1.2 matt #include <sys/cdefs.h> 80 1.14 riastrad __KERNEL_RCSID(0, "$NetBSD: at91usart.c,v 1.14 2022/10/26 23:38:06 riastradh Exp $"); 81 1.2 matt 82 1.2 matt #include "opt_kgdb.h" 83 1.2 matt 84 1.6 tls #ifdef RND_COM 85 1.13 riastrad #include <sys/rndsource.h> 86 1.2 matt #endif 87 1.2 matt 88 1.2 matt #ifdef NOTYET 89 1.2 matt /* 90 1.2 matt * Override cnmagic(9) macro before including <sys/systm.h>. 91 1.2 matt * We need to know if cn_check_magic triggered debugger, so set a flag. 92 1.2 matt * Callers of cn_check_magic must declare int cn_trapped = 0; 93 1.2 matt * XXX: this is *ugly*! 94 1.2 matt */ 95 1.2 matt #define cn_trap() \ 96 1.2 matt do { \ 97 1.2 matt console_debugger(); \ 98 1.2 matt cn_trapped = 1; \ 99 1.2 matt } while (/* CONSTCOND */ 0) 100 1.2 matt #endif /* NOTYET */ 101 1.2 matt 102 1.2 matt 103 1.2 matt #include <sys/param.h> 104 1.2 matt #include <sys/systm.h> 105 1.2 matt #include <sys/types.h> 106 1.2 matt #include <sys/conf.h> 107 1.2 matt #include <sys/file.h> 108 1.2 matt #include <sys/device.h> 109 1.2 matt #include <sys/kernel.h> 110 1.2 matt #include <sys/tty.h> 111 1.2 matt #include <sys/uio.h> 112 1.2 matt #include <sys/vnode.h> 113 1.2 matt #include <sys/kauth.h> 114 1.2 matt 115 1.2 matt #include <machine/intr.h> 116 1.5 dyoung #include <sys/bus.h> 117 1.2 matt 118 1.14 riastrad #include <ddb/db_active.h> 119 1.14 riastrad 120 1.2 matt #include <arm/at91/at91reg.h> 121 1.2 matt #include <arm/at91/at91var.h> 122 1.2 matt #include <arm/at91/at91usartreg.h> 123 1.2 matt #include <arm/at91/at91usartvar.h> 124 1.2 matt 125 1.2 matt #include <dev/cons.h> 126 1.2 matt 127 1.2 matt static int at91usart_param(struct tty *, struct termios *); 128 1.2 matt static void at91usart_start(struct tty *); 129 1.2 matt static int at91usart_hwiflow(struct tty *, int); 130 1.2 matt 131 1.2 matt #if 0 132 1.2 matt static u_int cflag2lcrhi(tcflag_t); 133 1.2 matt #endif 134 1.2 matt static void at91usart_set(struct at91usart_softc *); 135 1.2 matt 136 1.2 matt #if NOTYET 137 1.2 matt int at91usart_cn_getc(dev_t); 138 1.2 matt void at91usart_cn_putc(dev_t, int); 139 1.2 matt void at91usart_cn_pollc(dev_t, int); 140 1.2 matt void at91usart_cn_probe(struct consdev *); 141 1.2 matt void at91usart_cn_init(struct consdev *); 142 1.2 matt 143 1.2 matt static struct at91usart_cons_softc { 144 1.2 matt bus_space_tag_t sc_iot; 145 1.2 matt bus_space_handle_t sc_ioh; 146 1.2 matt bus_addr_t sc_hwbase; 147 1.2 matt int sc_ospeed; 148 1.2 matt tcflag_t sc_cflag; 149 1.2 matt int sc_attached; 150 1.2 matt 151 1.8 skrll uint8_t *sc_rx_ptr; 152 1.8 skrll uint8_t sc_rx_fifo[64]; 153 1.2 matt } usart_cn_sc; 154 1.2 matt 155 1.2 matt static struct cnm_state at91usart_cnm_state; 156 1.2 matt #endif /* NOTYET */ 157 1.2 matt 158 1.2 matt static void at91usart_soft(void* arg); 159 1.2 matt inline static void at91usart_txsoft(struct at91usart_softc *, struct tty *); 160 1.2 matt inline static void at91usart_rxsoft(struct at91usart_softc *, struct tty *, unsigned csr); 161 1.2 matt 162 1.2 matt #define PDC_BLOCK_SIZE 64 163 1.2 matt 164 1.7 chs //CFATTACH_DECL_NEW(at91usart, sizeof(struct at91usart_softc), 165 1.2 matt // at91usart_match, at91usart_attach, NULL, NULL); 166 1.2 matt 167 1.2 matt //#define USART_DEBUG 10 168 1.2 matt 169 1.2 matt #ifdef USART_DEBUG 170 1.2 matt int usart_debug = USART_DEBUG; 171 1.2 matt #define DPRINTFN(n,fmt) if (usart_debug >= (n)) printf fmt 172 1.2 matt #else 173 1.2 matt #define DPRINTFN(n,fmt) 174 1.2 matt #endif 175 1.2 matt 176 1.2 matt extern struct cfdriver at91usart_cd; 177 1.2 matt 178 1.2 matt dev_type_open(at91usart_open); 179 1.2 matt dev_type_close(at91usart_close); 180 1.2 matt dev_type_read(at91usart_read); 181 1.2 matt dev_type_write(at91usart_write); 182 1.2 matt dev_type_ioctl(at91usart_ioctl); 183 1.2 matt dev_type_stop(at91usart_stop); 184 1.2 matt dev_type_tty(at91usart_tty); 185 1.2 matt dev_type_poll(at91usart_poll); 186 1.2 matt 187 1.2 matt const struct cdevsw at91usart_cdevsw = { 188 1.9 dholland .d_open = at91usart_open, 189 1.9 dholland .d_close = at91usart_close, 190 1.9 dholland .d_read = at91usart_read, 191 1.9 dholland .d_write = at91usart_write, 192 1.9 dholland .d_ioctl = at91usart_ioctl, 193 1.9 dholland .d_stop = at91usart_stop, 194 1.9 dholland .d_tty = at91usart_tty, 195 1.9 dholland .d_poll = at91usart_poll, 196 1.9 dholland .d_mmap = nommap, 197 1.9 dholland .d_kqfilter = ttykqfilter, 198 1.10 dholland .d_discard = nodiscard, 199 1.9 dholland .d_flag = D_TTY 200 1.2 matt }; 201 1.2 matt 202 1.2 matt #if NOTYET 203 1.2 matt struct consdev at91usart_cons = { 204 1.2 matt at91usart_cn_probe, NULL, at91usart_cn_getc, at91usart_cn_putc, at91usart_cn_pollc, NULL, 205 1.2 matt NULL, NULL, NODEV, CN_REMOTE 206 1.2 matt }; 207 1.2 matt #endif /* NOTYET */ 208 1.2 matt 209 1.2 matt #ifndef DEFAULT_COMSPEED 210 1.2 matt #define DEFAULT_COMSPEED 115200 211 1.2 matt #endif 212 1.2 matt 213 1.12 christos #define COMUNIT(x) TTUNIT(x) 214 1.12 christos #define COMDIALOUT(x) TTDIALOUT(x) 215 1.2 matt 216 1.2 matt #define COM_ISALIVE(sc) ((sc)->enabled != 0 && device_is_active((sc)->sc_dev)) 217 1.2 matt 218 1.2 matt static inline void 219 1.2 matt at91usart_writereg(struct at91usart_softc *sc, int reg, u_int val) 220 1.2 matt { 221 1.2 matt bus_space_write_4(sc->sc_iot, sc->sc_ioh, reg, val); 222 1.2 matt } 223 1.2 matt 224 1.2 matt static inline u_int 225 1.2 matt at91usart_readreg(struct at91usart_softc *sc, int reg) 226 1.2 matt { 227 1.2 matt return bus_space_read_4(sc->sc_iot, sc->sc_ioh, reg); 228 1.2 matt } 229 1.2 matt #if 0 230 1.2 matt static int 231 1.2 matt at91usart_match(device_t parent, cfdata_t cf, void *aux) 232 1.2 matt { 233 1.2 matt if (strcmp(cf->cf_name, "at91usart") == 0) 234 1.2 matt return 1; 235 1.2 matt return 0; 236 1.2 matt } 237 1.2 matt #endif 238 1.2 matt static int at91usart_intr(void* arg); 239 1.2 matt 240 1.2 matt void 241 1.2 matt at91usart_attach_subr(struct at91usart_softc *sc, struct at91bus_attach_args *sa) 242 1.2 matt { 243 1.2 matt struct tty *tp; 244 1.2 matt int err; 245 1.2 matt 246 1.2 matt printf("\n"); 247 1.2 matt 248 1.2 matt if (bus_space_map(sa->sa_iot, sa->sa_addr, sa->sa_size, 0, &sc->sc_ioh)) 249 1.2 matt panic("%s: Cannot map registers", device_xname(sc->sc_dev)); 250 1.2 matt 251 1.2 matt sc->sc_iot = sa->sa_iot; 252 1.2 matt sc->sc_hwbase = sa->sa_addr; 253 1.2 matt sc->sc_dmat = sa->sa_dmat; 254 1.2 matt sc->sc_pid = sa->sa_pid; 255 1.2 matt 256 1.2 matt /* allocate fifos */ 257 1.2 matt err = at91pdc_alloc_fifo(sc->sc_dmat, &sc->sc_rx_fifo, AT91USART_RING_SIZE, BUS_DMA_READ | BUS_DMA_STREAMING); 258 1.2 matt if (err) 259 1.2 matt panic("%s: cannot allocate rx fifo", device_xname(sc->sc_dev)); 260 1.2 matt 261 1.2 matt err = at91pdc_alloc_fifo(sc->sc_dmat, &sc->sc_tx_fifo, AT91USART_RING_SIZE, BUS_DMA_WRITE | BUS_DMA_STREAMING); 262 1.2 matt if (err) 263 1.2 matt panic("%s: cannot allocate tx fifo", device_xname(sc->sc_dev)); 264 1.2 matt 265 1.2 matt /* initialize uart */ 266 1.2 matt at91_peripheral_clock(sc->sc_pid, 1); 267 1.2 matt 268 1.2 matt at91usart_writereg(sc, US_IDR, -1); 269 1.2 matt at91usart_writereg(sc, US_RTOR, 12); // 12-bit timeout 270 1.2 matt at91usart_writereg(sc, US_PDC + PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS); 271 1.2 matt at91_intr_establish(sa->sa_pid, IPL_TTY, INTR_HIGH_LEVEL, at91usart_intr, sc); 272 1.2 matt USART_INIT(sc, 115200U); 273 1.2 matt 274 1.2 matt #ifdef NOTYET 275 1.2 matt if (sc->sc_iot == usart_cn_sc.sc_iot 276 1.2 matt && sc->sc_hwbase == usart_cn_sc.sc_hwbase) { 277 1.2 matt usart_cn_sc.sc_attached = 1; 278 1.2 matt /* Make sure the console is always "hardwired". */ 279 1.2 matt delay(10000); /* wait for output to finish */ 280 1.2 matt SET(sc->sc_hwflags, COM_HW_CONSOLE); 281 1.2 matt SET(sc->sc_swflags, TIOCFLAG_SOFTCAR); 282 1.2 matt SET(sc->sc_ier, USART_INT_RXRDY); 283 1.2 matt USARTREG(USART_IER) = USART_INT_RXRDY; // @@@@@ 284 1.2 matt } 285 1.2 matt #endif // NOTYET 286 1.2 matt 287 1.4 rmind tp = tty_alloc(); 288 1.2 matt tp->t_oproc = at91usart_start; 289 1.2 matt tp->t_param = at91usart_param; 290 1.2 matt tp->t_hwiflow = at91usart_hwiflow; 291 1.2 matt 292 1.2 matt sc->sc_tty = tp; 293 1.2 matt 294 1.2 matt tty_attach(tp); 295 1.2 matt 296 1.2 matt #if NOTYET 297 1.2 matt if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { 298 1.2 matt int maj; 299 1.2 matt 300 1.2 matt /* locate the major number */ 301 1.2 matt maj = cdevsw_lookup_major(&at91usart_cdevsw); 302 1.2 matt 303 1.2 matt cn_tab->cn_dev = makedev(maj, device_unit(sc->sc_dev)); 304 1.2 matt 305 1.2 matt aprint_normal("%s: console (maj %u min %u cn_dev %u)\n", 306 1.2 matt device_xname(sc->sc_dev), maj, device_unit(sc->sc_dev), 307 1.2 matt cn_tab->cn_dev); 308 1.2 matt } 309 1.2 matt #endif /* NOTYET */ 310 1.2 matt 311 1.2 matt sc->sc_si = softint_establish(SOFTINT_SERIAL, at91usart_soft, sc); 312 1.2 matt 313 1.6 tls #ifdef RND_COM 314 1.2 matt rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), 315 1.11 tls RND_TYPE_TTY, RND_FLAG_DEFAULT); 316 1.2 matt #endif 317 1.2 matt 318 1.2 matt /* if there are no enable/disable functions, assume the device 319 1.2 matt is always enabled */ 320 1.2 matt if (!sc->enable) 321 1.2 matt sc->enabled = 1; 322 1.2 matt 323 1.2 matt /* XXX configure register */ 324 1.2 matt /* xxx_config(sc) */ 325 1.2 matt 326 1.2 matt SET(sc->sc_hwflags, COM_HW_DEV_OK); 327 1.2 matt } 328 1.2 matt 329 1.2 matt static int 330 1.2 matt at91usart_param(struct tty *tp, struct termios *t) 331 1.2 matt { 332 1.2 matt struct at91usart_softc *sc 333 1.2 matt = device_lookup_private(&at91usart_cd, COMUNIT(tp->t_dev)); 334 1.2 matt int s; 335 1.2 matt 336 1.2 matt if (COM_ISALIVE(sc) == 0) 337 1.2 matt return (EIO); 338 1.2 matt 339 1.2 matt if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 340 1.2 matt return (EINVAL); 341 1.2 matt 342 1.2 matt /* 343 1.2 matt * For the console, always force CLOCAL and !HUPCL, so that the port 344 1.2 matt * is always active. 345 1.2 matt */ 346 1.2 matt if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || 347 1.2 matt ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { 348 1.2 matt SET(t->c_cflag, CLOCAL); 349 1.2 matt CLR(t->c_cflag, HUPCL); 350 1.2 matt } 351 1.2 matt 352 1.2 matt /* 353 1.2 matt * If there were no changes, don't do anything. This avoids dropping 354 1.2 matt * input and improves performance when all we did was frob things like 355 1.2 matt * VMIN and VTIME. 356 1.2 matt */ 357 1.2 matt if (tp->t_ospeed == t->c_ospeed && 358 1.2 matt tp->t_cflag == t->c_cflag) 359 1.2 matt return (0); 360 1.2 matt 361 1.2 matt s = spltty(); 362 1.2 matt 363 1.2 matt sc->sc_brgr = (AT91_MSTCLK / 16 + t->c_ospeed / 2) / t->c_ospeed; 364 1.2 matt 365 1.2 matt /* And copy to tty. */ 366 1.2 matt tp->t_ispeed = 0; 367 1.2 matt tp->t_ospeed = t->c_ospeed; 368 1.2 matt tp->t_cflag = t->c_cflag; 369 1.2 matt at91usart_set(sc); 370 1.2 matt 371 1.2 matt splx(s); 372 1.2 matt 373 1.2 matt /* 374 1.2 matt * Update the tty layer's idea of the carrier bit. 375 1.2 matt * We tell tty the carrier is always on. 376 1.2 matt */ 377 1.2 matt (void) (*tp->t_linesw->l_modem)(tp, 1); 378 1.2 matt 379 1.2 matt #ifdef COM_DEBUG 380 1.2 matt if (com_debug) 381 1.2 matt comstatus(sc, "comparam "); 382 1.2 matt #endif 383 1.2 matt 384 1.2 matt /* tell the upper layer about hwflow.. */ 385 1.2 matt if (sc->hwflow) 386 1.2 matt (*sc->hwflow)(sc, t->c_cflag); 387 1.2 matt 388 1.2 matt return (0); 389 1.2 matt } 390 1.2 matt 391 1.2 matt static int 392 1.2 matt at91usart_hwiflow(struct tty *tp, int block) 393 1.2 matt { 394 1.2 matt if (block) { 395 1.2 matt /* tty discipline wants to block */ 396 1.2 matt } else { 397 1.2 matt /* tty discipline wants to unblock */ 398 1.2 matt } 399 1.2 matt return (0); 400 1.2 matt } 401 1.2 matt 402 1.2 matt static __inline void 403 1.2 matt at91usart_start_tx(struct at91usart_softc *sc) 404 1.2 matt { 405 1.2 matt if (!sc->start_tx) 406 1.2 matt at91usart_writereg(sc, US_PDC + PDC_PTCR, PDC_PTCR_TXTEN); 407 1.2 matt else 408 1.2 matt (*sc->start_tx)(sc); 409 1.2 matt } 410 1.2 matt 411 1.2 matt static __inline void 412 1.2 matt at91usart_stop_tx(struct at91usart_softc *sc) 413 1.2 matt { 414 1.2 matt if (!sc->stop_tx) 415 1.2 matt at91usart_writereg(sc, US_PDC + PDC_PTCR, PDC_PTCR_TXTDIS); 416 1.2 matt else 417 1.2 matt (*sc->stop_tx)(sc); 418 1.2 matt } 419 1.2 matt 420 1.2 matt static __inline void 421 1.2 matt at91usart_rx_started(struct at91usart_softc *sc) 422 1.2 matt { 423 1.2 matt if (sc->rx_started) 424 1.2 matt (*sc->rx_started)(sc); 425 1.2 matt } 426 1.2 matt 427 1.2 matt static __inline void 428 1.2 matt at91usart_rx_stopped(struct at91usart_softc *sc) 429 1.2 matt { 430 1.2 matt if (sc->rx_stopped) 431 1.2 matt (*sc->rx_stopped)(sc); 432 1.2 matt } 433 1.2 matt 434 1.2 matt static __inline void 435 1.2 matt at91usart_rx_rts_ctl(struct at91usart_softc *sc, int enabled) 436 1.2 matt { 437 1.2 matt if (sc->rx_rts_ctl) 438 1.2 matt (*sc->rx_rts_ctl)(sc, enabled); 439 1.2 matt } 440 1.2 matt 441 1.2 matt static void 442 1.2 matt at91usart_filltx(struct at91usart_softc *sc) 443 1.2 matt { 444 1.2 matt struct tty *tp = sc->sc_tty; 445 1.2 matt int len; 446 1.2 matt void *dst; 447 1.2 matt 448 1.2 matt // post write handler 449 1.2 matt AT91PDC_FIFO_POSTWRITE(sc->sc_iot, sc->sc_ioh, sc->sc_dmat, US_PDC, 450 1.2 matt &sc->sc_tx_fifo); 451 1.2 matt 452 1.2 matt // copy more data to fifo: 453 1.2 matt if (sc->sc_tbc > 0 454 1.2 matt && (dst = AT91PDC_FIFO_WRPTR(&sc->sc_tx_fifo, &len)) != NULL) { 455 1.2 matt // copy data to fifo 456 1.2 matt if (len > sc->sc_tbc) 457 1.2 matt len = sc->sc_tbc; 458 1.2 matt memcpy(dst, sc->sc_tba, len); 459 1.2 matt sc->sc_tba += len; 460 1.2 matt if ((sc->sc_tbc -= len) <= 0) 461 1.2 matt CLR(tp->t_state, TS_BUSY); 462 1.2 matt // update fifo 463 1.2 matt AT91PDC_FIFO_WRITTEN(&sc->sc_tx_fifo, len); 464 1.2 matt // tell tty interface we've sent some bytes 465 1.2 matt ndflush(&tp->t_outq, len); 466 1.2 matt } 467 1.2 matt 468 1.2 matt // start sending data... 469 1.2 matt if (AT91PDC_FIFO_PREWRITE(sc->sc_iot, sc->sc_ioh, sc->sc_dmat, 470 1.2 matt US_PDC, &sc->sc_tx_fifo, PDC_BLOCK_SIZE)) { 471 1.2 matt at91usart_start_tx(sc); 472 1.2 matt SET(sc->sc_ier, US_CSR_TXEMPTY | US_CSR_ENDTX); 473 1.2 matt } else { 474 1.2 matt CLR(sc->sc_ier, US_CSR_ENDTX); 475 1.2 matt } 476 1.2 matt } 477 1.2 matt 478 1.2 matt static void 479 1.2 matt at91usart_start(struct tty *tp) 480 1.2 matt { 481 1.2 matt struct at91usart_softc *sc 482 1.2 matt = device_lookup_private(&at91usart_cd, COMUNIT(tp->t_dev)); 483 1.2 matt int s; 484 1.2 matt 485 1.2 matt if (COM_ISALIVE(sc) == 0) { 486 1.2 matt DPRINTFN(5, ("%s: %s / COM_ISALIVE == 0\n", device_xname(sc->sc_dev), __FUNCTION__)); 487 1.2 matt return; 488 1.2 matt } 489 1.2 matt 490 1.2 matt s = spltty(); 491 1.2 matt if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) { 492 1.2 matt DPRINTFN(5, ("%s: %s: TS_BUSY || TS_TIMEOUT || TS_TTSTOP\n", device_xname(sc->sc_dev), __FUNCTION__)); 493 1.2 matt goto out; 494 1.2 matt } 495 1.2 matt 496 1.2 matt if (!ttypull(tp)) 497 1.2 matt goto out; 498 1.2 matt 499 1.2 matt /* Grab the first contiguous region of buffer space. */ 500 1.2 matt { 501 1.2 matt u_char *tba; 502 1.2 matt int tbc; 503 1.2 matt 504 1.2 matt tba = tp->t_outq.c_cf; 505 1.2 matt tbc = ndqb(&tp->t_outq, 0); 506 1.2 matt 507 1.2 matt sc->sc_tba = tba; 508 1.2 matt sc->sc_tbc = tbc; 509 1.2 matt } 510 1.2 matt 511 1.2 matt SET(tp->t_state, TS_BUSY); 512 1.2 matt 513 1.2 matt /* Output the first chunk of the contiguous buffer. */ 514 1.2 matt at91usart_filltx(sc); 515 1.2 matt at91usart_writereg(sc, US_IER, sc->sc_ier); 516 1.2 matt DPRINTFN(5, ("%s: %s, ier=%08x (csr=%08x)\n", device_xname(sc->sc_dev), __FUNCTION__, sc->sc_ier, at91usart_readreg(sc, US_CSR))); 517 1.2 matt 518 1.2 matt out: 519 1.2 matt splx(s); 520 1.2 matt 521 1.2 matt return; 522 1.2 matt } 523 1.2 matt 524 1.2 matt static __inline__ void 525 1.2 matt at91usart_break(struct at91usart_softc *sc, int onoff) 526 1.2 matt { 527 1.2 matt at91usart_writereg(sc, US_CR, onoff ? US_CR_STTBRK : US_CR_STPBRK); 528 1.2 matt } 529 1.2 matt 530 1.2 matt static void 531 1.2 matt at91usart_shutdown(struct at91usart_softc *sc) 532 1.2 matt { 533 1.2 matt int s; 534 1.2 matt 535 1.2 matt s = spltty(); 536 1.2 matt 537 1.2 matt /* turn of dma */ 538 1.2 matt at91usart_writereg(sc, US_PDC + PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS); 539 1.2 matt at91usart_writereg(sc, US_PDC + PDC_TNCR, 0); 540 1.2 matt at91usart_writereg(sc, US_PDC + PDC_TCR, 0); 541 1.2 matt at91usart_writereg(sc, US_PDC + PDC_RNCR, 0); 542 1.2 matt at91usart_writereg(sc, US_PDC + PDC_RCR, 0); 543 1.2 matt 544 1.2 matt /* Turn off interrupts. */ 545 1.2 matt at91usart_writereg(sc, US_IDR, -1); 546 1.2 matt 547 1.2 matt /* Clear any break condition set with TIOCSBRK. */ 548 1.2 matt at91usart_break(sc, 0); 549 1.2 matt at91usart_set(sc); 550 1.2 matt 551 1.2 matt if (sc->disable) { 552 1.2 matt #ifdef DIAGNOSTIC 553 1.2 matt if (!sc->enabled) 554 1.2 matt panic("at91usart_shutdown: not enabled?"); 555 1.2 matt #endif 556 1.2 matt (*sc->disable)(sc); 557 1.2 matt sc->enabled = 0; 558 1.2 matt } 559 1.2 matt splx(s); 560 1.2 matt } 561 1.2 matt 562 1.2 matt int 563 1.2 matt at91usart_open(dev_t dev, int flag, int mode, struct lwp *l) 564 1.2 matt { 565 1.2 matt struct at91usart_softc *sc; 566 1.2 matt struct tty *tp; 567 1.2 matt int s; 568 1.2 matt int error; 569 1.2 matt 570 1.2 matt sc = device_lookup_private(&at91usart_cd, COMUNIT(dev)); 571 1.2 matt if (sc == NULL || !ISSET(sc->sc_hwflags, COM_HW_DEV_OK)) 572 1.2 matt return (ENXIO); 573 1.2 matt 574 1.2 matt if (!device_is_active(sc->sc_dev)) 575 1.2 matt return (ENXIO); 576 1.2 matt 577 1.2 matt #ifdef KGDB 578 1.2 matt /* 579 1.2 matt * If this is the kgdb port, no other use is permitted. 580 1.2 matt */ 581 1.2 matt if (ISSET(sc->sc_hwflags, COM_HW_KGDB)) 582 1.2 matt return (EBUSY); 583 1.2 matt #endif 584 1.2 matt 585 1.2 matt tp = sc->sc_tty; 586 1.2 matt 587 1.2 matt if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 588 1.2 matt return (EBUSY); 589 1.2 matt 590 1.2 matt s = spltty(); 591 1.2 matt 592 1.2 matt /* 593 1.2 matt * Do the following iff this is a first open. 594 1.2 matt */ 595 1.2 matt if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 596 1.2 matt struct termios t; 597 1.2 matt 598 1.2 matt tp->t_dev = dev; 599 1.2 matt 600 1.2 matt if (sc->enable) { 601 1.2 matt if ((*sc->enable)(sc)) { 602 1.2 matt splx(s); 603 1.2 matt printf("%s: device enable failed\n", 604 1.2 matt device_xname(sc->sc_dev)); 605 1.2 matt return (EIO); 606 1.2 matt } 607 1.2 matt sc->enabled = 1; 608 1.2 matt #if 0 609 1.2 matt /* XXXXXXXXXXXXXXX */ 610 1.2 matt com_config(sc); 611 1.2 matt #endif 612 1.2 matt } 613 1.2 matt 614 1.2 matt /* reset fifos: */ 615 1.2 matt AT91PDC_RESET_FIFO(sc->sc_iot, sc->sc_ioh, sc->sc_dmat, US_PDC, &sc->sc_rx_fifo, 0); 616 1.2 matt AT91PDC_RESET_FIFO(sc->sc_iot, sc->sc_ioh, sc->sc_dmat, US_PDC, &sc->sc_tx_fifo, 1); 617 1.2 matt 618 1.2 matt /* reset receive */ 619 1.2 matt at91usart_writereg(sc, US_CR, US_CR_RSTSTA | US_CR_STTTO); 620 1.2 matt 621 1.2 matt /* Turn on interrupts. */ 622 1.2 matt sc->sc_ier = US_CSR_ENDRX|US_CSR_RXBUFF|US_CSR_TIMEOUT|US_CSR_RXBRK; 623 1.2 matt at91usart_writereg(sc, US_IER, sc->sc_ier); 624 1.2 matt 625 1.2 matt /* enable DMA: */ 626 1.2 matt at91usart_writereg(sc, US_PDC + PDC_PTCR, PDC_PTCR_RXTEN); 627 1.2 matt 628 1.2 matt /* 629 1.2 matt * Initialize the termios status to the defaults. Add in the 630 1.2 matt * sticky bits from TIOCSFLAGS. 631 1.2 matt */ 632 1.2 matt t.c_ispeed = 0; 633 1.2 matt /* if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { 634 1.2 matt t.c_ospeed = usart_cn_sc.sc_ospeed; 635 1.2 matt t.c_cflag = usart_cn_sc.sc_cflag; 636 1.2 matt } else*/ { 637 1.2 matt t.c_ospeed = TTYDEF_SPEED; 638 1.2 matt t.c_cflag = TTYDEF_CFLAG; 639 1.2 matt } 640 1.2 matt if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) 641 1.2 matt SET(t.c_cflag, CLOCAL); 642 1.2 matt if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) 643 1.2 matt SET(t.c_cflag, CRTSCTS); 644 1.2 matt if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) 645 1.2 matt SET(t.c_cflag, MDMBUF); 646 1.2 matt 647 1.2 matt /* Make sure at91usart_param() will do something. */ 648 1.2 matt tp->t_ospeed = 0; 649 1.2 matt (void) at91usart_param(tp, &t); 650 1.2 matt tp->t_iflag = TTYDEF_IFLAG; 651 1.2 matt tp->t_oflag = TTYDEF_OFLAG; 652 1.2 matt tp->t_lflag = TTYDEF_LFLAG; 653 1.2 matt ttychars(tp); 654 1.2 matt ttsetwater(tp); 655 1.2 matt 656 1.2 matt /* and unblock. */ 657 1.2 matt CLR(sc->sc_rx_flags, RX_ANY_BLOCK); 658 1.2 matt 659 1.2 matt #ifdef COM_DEBUG 660 1.2 matt if (at91usart_debug) 661 1.2 matt comstatus(sc, "at91usart_open "); 662 1.2 matt #endif 663 1.2 matt 664 1.2 matt } 665 1.2 matt 666 1.2 matt splx(s); 667 1.2 matt 668 1.2 matt error = ttyopen(tp, COMDIALOUT(dev), ISSET(flag, O_NONBLOCK)); 669 1.2 matt if (error) 670 1.2 matt goto bad; 671 1.2 matt 672 1.2 matt error = (*tp->t_linesw->l_open)(dev, tp); 673 1.2 matt if (error) 674 1.2 matt goto bad; 675 1.2 matt 676 1.2 matt return (0); 677 1.2 matt 678 1.2 matt bad: 679 1.2 matt if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 680 1.2 matt /* 681 1.2 matt * We failed to open the device, and nobody else had it opened. 682 1.2 matt * Clean up the state as appropriate. 683 1.2 matt */ 684 1.2 matt at91usart_shutdown(sc); 685 1.2 matt } 686 1.2 matt 687 1.2 matt return (error); 688 1.2 matt } 689 1.2 matt 690 1.2 matt int 691 1.2 matt at91usart_close(dev_t dev, int flag, int mode, struct lwp *l) 692 1.2 matt { 693 1.2 matt struct at91usart_softc *sc = device_lookup_private(&at91usart_cd, COMUNIT(dev)); 694 1.2 matt struct tty *tp = sc->sc_tty; 695 1.2 matt 696 1.2 matt /* XXX This is for cons.c. */ 697 1.2 matt if (!ISSET(tp->t_state, TS_ISOPEN)) 698 1.2 matt return (0); 699 1.2 matt 700 1.2 matt (*tp->t_linesw->l_close)(tp, flag); 701 1.2 matt ttyclose(tp); 702 1.2 matt 703 1.2 matt if (COM_ISALIVE(sc) == 0) 704 1.2 matt return (0); 705 1.2 matt 706 1.2 matt if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 707 1.2 matt /* 708 1.2 matt * Although we got a last close, the device may still be in 709 1.2 matt * use; e.g. if this was the dialout node, and there are still 710 1.2 matt * processes waiting for carrier on the non-dialout node. 711 1.2 matt */ 712 1.2 matt at91usart_shutdown(sc); 713 1.2 matt } 714 1.2 matt 715 1.2 matt return (0); 716 1.2 matt } 717 1.2 matt 718 1.2 matt int 719 1.2 matt at91usart_read(dev_t dev, struct uio *uio, int flag) 720 1.2 matt { 721 1.2 matt struct at91usart_softc *sc = device_lookup_private(&at91usart_cd, COMUNIT(dev)); 722 1.2 matt struct tty *tp = sc->sc_tty; 723 1.2 matt 724 1.2 matt if (COM_ISALIVE(sc) == 0) 725 1.2 matt return (EIO); 726 1.2 matt 727 1.2 matt return ((*tp->t_linesw->l_read)(tp, uio, flag)); 728 1.2 matt } 729 1.2 matt 730 1.2 matt int 731 1.2 matt at91usart_write(dev_t dev, struct uio *uio, int flag) 732 1.2 matt { 733 1.2 matt struct at91usart_softc *sc = device_lookup_private(&at91usart_cd, COMUNIT(dev)); 734 1.2 matt struct tty *tp = sc->sc_tty; 735 1.2 matt 736 1.2 matt if (COM_ISALIVE(sc) == 0) 737 1.2 matt return (EIO); 738 1.2 matt 739 1.2 matt return ((*tp->t_linesw->l_write)(tp, uio, flag)); 740 1.2 matt } 741 1.2 matt 742 1.2 matt int 743 1.2 matt at91usart_poll(dev_t dev, int events, struct lwp *l) 744 1.2 matt { 745 1.2 matt struct at91usart_softc *sc = device_lookup_private(&at91usart_cd, COMUNIT(dev)); 746 1.2 matt struct tty *tp = sc->sc_tty; 747 1.2 matt 748 1.2 matt if (COM_ISALIVE(sc) == 0) 749 1.2 matt return (EIO); 750 1.2 matt 751 1.2 matt return ((*tp->t_linesw->l_poll)(tp, events, l)); 752 1.2 matt } 753 1.2 matt 754 1.2 matt struct tty * 755 1.2 matt at91usart_tty(dev_t dev) 756 1.2 matt { 757 1.2 matt struct at91usart_softc *sc = device_lookup_private(&at91usart_cd, COMUNIT(dev)); 758 1.2 matt struct tty *tp = sc->sc_tty; 759 1.2 matt 760 1.2 matt return (tp); 761 1.2 matt } 762 1.2 matt 763 1.2 matt int 764 1.2 matt at91usart_ioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 765 1.2 matt { 766 1.2 matt struct at91usart_softc *sc = device_lookup_private(&at91usart_cd, COMUNIT(dev)); 767 1.2 matt struct tty *tp = sc->sc_tty; 768 1.2 matt int error; 769 1.2 matt int s; 770 1.2 matt 771 1.2 matt if (COM_ISALIVE(sc) == 0) 772 1.2 matt return (EIO); 773 1.2 matt 774 1.2 matt error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 775 1.2 matt if (error != EPASSTHROUGH) 776 1.2 matt return (error); 777 1.2 matt 778 1.2 matt error = ttioctl(tp, cmd, data, flag, l); 779 1.2 matt if (error != EPASSTHROUGH) 780 1.2 matt return (error); 781 1.2 matt 782 1.2 matt error = 0; 783 1.2 matt 784 1.2 matt s = spltty(); 785 1.2 matt 786 1.2 matt switch (cmd) { 787 1.2 matt case TIOCSBRK: 788 1.2 matt at91usart_break(sc, 1); 789 1.2 matt break; 790 1.2 matt 791 1.2 matt case TIOCCBRK: 792 1.2 matt at91usart_break(sc, 0); 793 1.2 matt break; 794 1.2 matt 795 1.2 matt case TIOCGFLAGS: 796 1.2 matt *(int *)data = sc->sc_swflags; 797 1.2 matt break; 798 1.2 matt 799 1.2 matt case TIOCSFLAGS: 800 1.2 matt error = kauth_authorize_device_tty(l->l_cred, 801 1.2 matt KAUTH_DEVICE_TTY_PRIVSET, tp); 802 1.2 matt if (error) 803 1.2 matt break; 804 1.2 matt sc->sc_swflags = *(int *)data; 805 1.2 matt break; 806 1.2 matt 807 1.2 matt default: 808 1.2 matt error = EPASSTHROUGH; 809 1.2 matt break; 810 1.2 matt } 811 1.2 matt 812 1.2 matt splx(s); 813 1.2 matt 814 1.2 matt return (error); 815 1.2 matt } 816 1.2 matt 817 1.2 matt /* 818 1.2 matt * Stop output on a line. 819 1.2 matt */ 820 1.2 matt void 821 1.2 matt at91usart_stop(struct tty *tp, int flag) 822 1.2 matt { 823 1.2 matt struct at91usart_softc *sc 824 1.2 matt = device_lookup_private(&at91usart_cd, COMUNIT(tp->t_dev)); 825 1.2 matt int s; 826 1.2 matt 827 1.2 matt s = spltty(); 828 1.2 matt if (ISSET(tp->t_state, TS_BUSY)) { 829 1.2 matt /* Stop transmitting at the next chunk. */ 830 1.2 matt sc->sc_tbc = 0; 831 1.2 matt if (!ISSET(tp->t_state, TS_TTSTOP)) 832 1.2 matt SET(tp->t_state, TS_FLUSH); 833 1.2 matt } 834 1.2 matt splx(s); 835 1.2 matt } 836 1.2 matt 837 1.2 matt #if 0 838 1.2 matt static u_int 839 1.2 matt cflag2lcrhi(tcflag_t cflag) 840 1.2 matt { 841 1.8 skrll uint32_t mr; 842 1.2 matt 843 1.2 matt switch (cflag & CSIZE) { 844 1.2 matt default: 845 1.2 matt mr = 0x0; 846 1.2 matt break; 847 1.2 matt } 848 1.2 matt #if 0 849 1.2 matt mr |= (cflag & PARENB) ? LinCtrlHigh_PEN : 0; 850 1.2 matt mr |= (cflag & PARODD) ? 0 : LinCtrlHigh_EPS; 851 1.2 matt mr |= (cflag & CSTOPB) ? LinCtrlHigh_STP2 : 0; 852 1.2 matt mr |= LinCtrlHigh_FEN; /* FIFO always enabled */ 853 1.2 matt #endif 854 1.2 matt mr |= USART_MR_PAR_NONE; 855 1.2 matt return (mr); 856 1.2 matt } 857 1.2 matt #endif 858 1.2 matt 859 1.2 matt 860 1.2 matt static void 861 1.2 matt at91usart_set(struct at91usart_softc *sc) 862 1.2 matt { 863 1.2 matt at91usart_writereg(sc, US_MR, US_MR_CHRL_8 | US_MR_PAR_NONE | US_MR_NBSTOP_1); 864 1.2 matt at91usart_writereg(sc, US_BRGR, sc->sc_brgr); 865 1.2 matt at91usart_writereg(sc, US_CR, US_CR_TXEN | US_CR_RXEN); // @@@ just in case 866 1.2 matt } 867 1.2 matt 868 1.2 matt #if NOTYET 869 1.2 matt int 870 1.2 matt at91usart_cn_attach(bus_space_tag_t iot, bus_addr_t iobase, bus_space_handle_t ioh, 871 1.8 skrll uint32_t mstclk, int ospeed, tcflag_t cflag) 872 1.2 matt { 873 1.2 matt cn_tab = &at91usart_cons; 874 1.2 matt cn_init_magic(&at91usart_cnm_state); 875 1.2 matt cn_set_magic("\047\001"); 876 1.2 matt 877 1.2 matt usart_cn_sc.sc_iot = iot; 878 1.2 matt usart_cn_sc.sc_ioh = ioh; 879 1.2 matt usart_cn_sc.sc_hwbase = iobase; 880 1.2 matt usart_cn_sc.sc_ospeed = ospeed; 881 1.2 matt usart_cn_sc.sc_cflag = cflag; 882 1.2 matt 883 1.2 matt USART_INIT(mstclk, ospeed); 884 1.2 matt 885 1.2 matt return (0); 886 1.2 matt } 887 1.2 matt 888 1.2 matt void 889 1.2 matt at91usart_cn_probe(struct consdev *cp) 890 1.2 matt { 891 1.2 matt cp->cn_pri = CN_REMOTE; 892 1.2 matt } 893 1.2 matt 894 1.2 matt void 895 1.2 matt at91usart_cn_pollc(dev_t dev, int on) 896 1.2 matt { 897 1.2 matt if (on) { 898 1.2 matt // enable polling mode 899 1.2 matt USARTREG(US_IDR) = USART_INT_RXRDY; 900 1.2 matt } else { 901 1.2 matt // disable polling mode 902 1.2 matt USARTREG(US_IER) = USART_INT_RXRDY; 903 1.2 matt } 904 1.2 matt } 905 1.2 matt 906 1.2 matt void 907 1.2 matt at91usart_cn_putc(dev_t dev, int c) 908 1.2 matt { 909 1.2 matt int s; 910 1.2 matt #if 0 911 1.2 matt bus_space_tag_t iot = usart_cn_sc.sc_iot; 912 1.2 matt bus_space_handle_t ioh = usart_cn_sc.sc_ioh; 913 1.2 matt #endif 914 1.2 matt s = spltty(); 915 1.2 matt 916 1.2 matt USART_PUTC(c); 917 1.2 matt 918 1.2 matt #ifdef DEBUG 919 1.2 matt if (c == '\r') { 920 1.2 matt while((USARTREG(USART_SR) & USART_SR_TXEMPTY) == 0) 921 1.2 matt ; 922 1.2 matt } 923 1.2 matt #endif 924 1.2 matt 925 1.2 matt splx(s); 926 1.2 matt } 927 1.2 matt 928 1.2 matt int 929 1.2 matt at91usart_cn_getc(dev_t dev) 930 1.2 matt { 931 1.2 matt int c, sr; 932 1.2 matt int s; 933 1.2 matt #if 0 934 1.2 matt bus_space_tag_t iot = usart_cn_sc.sc_iot; 935 1.2 matt bus_space_handle_t ioh = usart_cn_sc.sc_ioh; 936 1.2 matt #endif 937 1.2 matt 938 1.2 matt s = spltty(); 939 1.2 matt 940 1.2 matt while ((c = USART_PEEKC()) == -1) { 941 1.2 matt splx(s); 942 1.2 matt s = spltty(); 943 1.2 matt } 944 1.2 matt ; 945 1.2 matt sr = USARTREG(USART_SR); 946 1.2 matt if (ISSET(sr, USART_SR_FRAME) && c == 0) { 947 1.2 matt USARTREG(USART_CR) = USART_CR_RSTSTA; // reset status bits 948 1.2 matt c = CNC_BREAK; 949 1.2 matt } 950 1.14 riastrad if (!db_active) { 951 1.14 riastrad int cn_trapped __unused = 0; 952 1.2 matt 953 1.2 matt cn_check_magic(dev, c, at91usart_cnm_state); 954 1.2 matt } 955 1.2 matt splx(s); 956 1.2 matt 957 1.2 matt c &= 0xff; 958 1.2 matt 959 1.2 matt return (c); 960 1.2 matt } 961 1.2 matt #endif /* NOTYET */ 962 1.2 matt 963 1.2 matt inline static void 964 1.2 matt at91usart_rxsoft(struct at91usart_softc *sc, struct tty *tp, unsigned csr) 965 1.2 matt { 966 1.2 matt u_char *start, *get, *end; 967 1.2 matt int cc; 968 1.2 matt 969 1.2 matt AT91PDC_FIFO_POSTREAD(sc->sc_iot, sc->sc_ioh, sc->sc_dmat, US_PDC, 970 1.2 matt &sc->sc_rx_fifo); 971 1.2 matt 972 1.2 matt if (ISSET(csr, US_CSR_TIMEOUT | US_CSR_RXBRK)) 973 1.2 matt at91usart_rx_stopped(sc); 974 1.2 matt 975 1.2 matt while ((start = AT91PDC_FIFO_RDPTR(&sc->sc_rx_fifo, &cc)) != NULL) { 976 1.2 matt int (*rint)(int, struct tty *) = tp->t_linesw->l_rint; 977 1.2 matt int code; 978 1.2 matt 979 1.2 matt if (!ISSET(csr, US_CSR_TIMEOUT | US_CSR_RXBRK)) 980 1.2 matt at91usart_rx_started(sc); 981 1.2 matt 982 1.2 matt for (get = start, end = start + cc; get < end; get++) { 983 1.2 matt code = *get; 984 1.2 matt if ((*rint)(code, tp) == -1) { 985 1.2 matt /* 986 1.2 matt * The line discipline's buffer is out of space. 987 1.2 matt */ 988 1.2 matt if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) { 989 1.2 matt /* 990 1.2 matt * We're either not using flow control, or the 991 1.2 matt * line discipline didn't tell us to block for 992 1.2 matt * some reason. Either way, we have no way to 993 1.2 matt * know when there's more space available, so 994 1.2 matt * just drop the rest of the data. 995 1.2 matt */ 996 1.2 matt get = end; 997 1.2 matt printf("%s: receive missing data!\n", 998 1.2 matt device_xname(sc->sc_dev)); 999 1.2 matt } else { 1000 1.2 matt /* 1001 1.2 matt * Don't schedule any more receive processing 1002 1.2 matt * until the line discipline tells us there's 1003 1.2 matt * space available (through comhwiflow()). 1004 1.2 matt * Leave the rest of the data in the input 1005 1.2 matt * buffer. 1006 1.2 matt */ 1007 1.2 matt SET(sc->sc_rx_flags, RX_TTY_OVERFLOWED); 1008 1.2 matt } 1009 1.2 matt break; 1010 1.2 matt } 1011 1.2 matt } 1012 1.2 matt 1013 1.2 matt // tell we've read some bytes... 1014 1.2 matt AT91PDC_FIFO_READ(&sc->sc_rx_fifo, get - start); 1015 1.2 matt 1016 1.2 matt if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) 1017 1.2 matt break; 1018 1.2 matt } 1019 1.2 matt 1020 1.2 matt // h/w flow control hook: 1021 1.2 matt if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) 1022 1.2 matt at91usart_rx_rts_ctl(sc, (AT91PDC_FIFO_SPACE(&sc->sc_rx_fifo) > PDC_BLOCK_SIZE * 2)); 1023 1.2 matt 1024 1.2 matt // write next pointer if USART is ready: 1025 1.2 matt if (AT91PDC_FIFO_PREREAD(sc->sc_iot, sc->sc_ioh, sc->sc_dmat, US_PDC, 1026 1.2 matt &sc->sc_rx_fifo, PDC_BLOCK_SIZE)) { 1027 1.2 matt SET(sc->sc_ier, US_CSR_ENDRX | US_CSR_RXBUFF | US_CSR_TIMEOUT | US_CSR_RXBRK); 1028 1.2 matt } else { 1029 1.2 matt CLR(sc->sc_ier, US_CSR_ENDRX | US_CSR_RXBUFF | US_CSR_TIMEOUT | US_CSR_RXBRK); 1030 1.2 matt } 1031 1.2 matt } 1032 1.2 matt 1033 1.2 matt inline static void 1034 1.2 matt at91usart_txsoft(struct at91usart_softc *sc, struct tty *tp) 1035 1.2 matt { 1036 1.2 matt at91usart_filltx(sc); 1037 1.2 matt if (!ISSET(tp->t_state, TS_BUSY)) 1038 1.2 matt (*tp->t_linesw->l_start)(tp); 1039 1.2 matt } 1040 1.2 matt 1041 1.2 matt 1042 1.2 matt static void 1043 1.2 matt at91usart_soft(void* arg) 1044 1.2 matt { 1045 1.2 matt struct at91usart_softc *sc = arg; 1046 1.2 matt int s; 1047 1.2 matt u_int csr; 1048 1.2 matt 1049 1.2 matt if (COM_ISALIVE(sc) == 0) 1050 1.2 matt return; 1051 1.2 matt 1052 1.2 matt s = spltty(); 1053 1.2 matt csr = sc->sc_csr; 1054 1.2 matt while (csr != 0) { 1055 1.2 matt if ((csr &= sc->sc_ier) == 0) 1056 1.2 matt break; 1057 1.2 matt // splx(s); 1058 1.2 matt DPRINTFN(5, ("%s: %s / csr = 0x%08x\n", device_xname(sc->sc_dev), __FUNCTION__, csr)); 1059 1.2 matt if (ISSET(csr, US_CSR_ENDRX | US_CSR_RXBUFF | US_CSR_TIMEOUT | US_CSR_RXBRK)) { 1060 1.2 matt /* receive interrupt */ 1061 1.2 matt if (ISSET(csr, US_CSR_RXBRK)) { 1062 1.2 matt // break received! 1063 1.2 matt at91usart_writereg(sc, US_CR, US_CR_RSTSTA | US_CR_STTTO); 1064 1.2 matt } else if (ISSET(csr, US_CSR_TIMEOUT)) { 1065 1.2 matt // timeout received 1066 1.2 matt at91usart_writereg(sc, US_CR, US_CR_STTTO); 1067 1.2 matt } 1068 1.2 matt at91usart_rxsoft(sc, sc->sc_tty, csr); 1069 1.2 matt } 1070 1.2 matt if (ISSET(csr, US_CSR_TXEMPTY)) { 1071 1.2 matt at91usart_stop_tx(sc); 1072 1.2 matt CLR(sc->sc_ier, US_CSR_TXEMPTY); 1073 1.2 matt if (AT91PDC_FIFO_EMPTY(&sc->sc_tx_fifo)) { 1074 1.2 matt // everything sent! 1075 1.2 matt if (ISSET(sc->sc_tty->t_state, TS_FLUSH)) 1076 1.2 matt CLR(sc->sc_tty->t_state, TS_FLUSH); 1077 1.2 matt } 1078 1.2 matt } 1079 1.2 matt if (ISSET(csr, US_CSR_TXEMPTY | US_CSR_ENDTX)) { 1080 1.2 matt /* transmit interrupt! */ 1081 1.2 matt at91usart_txsoft(sc, sc->sc_tty); 1082 1.2 matt } 1083 1.2 matt // s = spltty(); 1084 1.2 matt csr = at91usart_readreg(sc, US_CSR); 1085 1.2 matt } 1086 1.2 matt sc->sc_csr = 0; 1087 1.2 matt at91usart_writereg(sc, US_IER, sc->sc_ier); // re-enable interrupts 1088 1.2 matt splx(s); 1089 1.2 matt } 1090 1.2 matt 1091 1.2 matt 1092 1.2 matt static int 1093 1.2 matt at91usart_intr(void* arg) 1094 1.2 matt { 1095 1.2 matt struct at91usart_softc *sc = arg; 1096 1.2 matt u_int csr, imr; 1097 1.2 matt 1098 1.2 matt // get out if interrupts are not enabled 1099 1.2 matt imr = at91usart_readreg(sc, US_IMR); 1100 1.2 matt if (!imr) 1101 1.2 matt return 0; 1102 1.2 matt // get out if pending interrupt is not enabled 1103 1.2 matt csr = at91usart_readreg(sc, US_CSR); 1104 1.2 matt DPRINTFN(6,("%s: csr=%08X imr=%08X\n", device_xname(sc->sc_dev), csr, imr)); 1105 1.2 matt if (!ISSET(csr, imr)) 1106 1.2 matt return 0; 1107 1.2 matt 1108 1.2 matt // ok, we DO have some interrupts to serve! let softint do it 1109 1.2 matt sc->sc_csr = csr; 1110 1.2 matt at91usart_writereg(sc, US_IDR, -1); 1111 1.2 matt 1112 1.2 matt /* Wake up the poller. */ 1113 1.2 matt softint_schedule(sc->sc_si); 1114 1.2 matt 1115 1.2 matt /* we're done for now */ 1116 1.2 matt return (1); 1117 1.2 matt 1118 1.2 matt } 1119