ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/src/trunk/sys/dev/uart/uart_core.c
Revision: 10057
Committed: Sun May 27 22:53:06 2018 UTC (5 years, 11 months ago) by laffer1
Content type: text/plain
File size: 20819 byte(s)
Log Message:
update ubsec and uart

File Contents

# Content
1 /* $MidnightBSD$ */
2 /*-
3 * Copyright (c) 2003 Marcel Moolenaar
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 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_core.c 294229 2016-01-17 18:18:01Z ian $");
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/bus.h>
34 #include <sys/conf.h>
35 #include <sys/cons.h>
36 #include <sys/fcntl.h>
37 #include <sys/interrupt.h>
38 #include <sys/kdb.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/queue.h>
42 #include <sys/reboot.h>
43 #include <sys/sysctl.h>
44 #include <machine/bus.h>
45 #include <sys/rman.h>
46 #include <machine/resource.h>
47 #include <machine/stdarg.h>
48
49 #include <dev/uart/uart.h>
50 #include <dev/uart/uart_bus.h>
51 #include <dev/uart/uart_cpu.h>
52 #include <dev/uart/uart_ppstypes.h>
53
54 #include "uart_if.h"
55
56 devclass_t uart_devclass;
57 const char uart_driver_name[] = "uart";
58
59 SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs =
60 SLIST_HEAD_INITIALIZER(uart_sysdevs);
61
62 static MALLOC_DEFINE(M_UART, "UART", "UART driver");
63
64 #ifndef UART_POLL_FREQ
65 #define UART_POLL_FREQ 50
66 #endif
67 static int uart_poll_freq = UART_POLL_FREQ;
68 TUNABLE_INT("debug.uart_poll_freq", &uart_poll_freq);
69
70 static inline int
71 uart_pps_mode_valid(int pps_mode)
72 {
73 int opt;
74
75 switch(pps_mode & UART_PPS_SIGNAL_MASK) {
76 case UART_PPS_DISABLED:
77 case UART_PPS_CTS:
78 case UART_PPS_DCD:
79 break;
80 default:
81 return (false);
82 }
83
84 opt = pps_mode & UART_PPS_OPTION_MASK;
85 if ((opt & ~(UART_PPS_INVERT_PULSE | UART_PPS_NARROW_PULSE)) != 0)
86 return (false);
87
88 return (true);
89 }
90
91 static void
92 uart_pps_print_mode(struct uart_softc *sc)
93 {
94
95 device_printf(sc->sc_dev, "PPS capture mode: ");
96 switch(sc->sc_pps_mode) {
97 case UART_PPS_DISABLED:
98 printf("disabled");
99 case UART_PPS_CTS:
100 printf("CTS");
101 case UART_PPS_DCD:
102 printf("DCD");
103 default:
104 printf("invalid");
105 }
106 if (sc->sc_pps_mode & UART_PPS_INVERT_PULSE)
107 printf("-Inverted");
108 if (sc->sc_pps_mode & UART_PPS_NARROW_PULSE)
109 printf("-NarrowPulse");
110 printf("\n");
111 }
112
113 static int
114 uart_pps_mode_sysctl(SYSCTL_HANDLER_ARGS)
115 {
116 struct uart_softc *sc;
117 int err, tmp;
118
119 sc = arg1;
120 tmp = sc->sc_pps_mode;
121 err = sysctl_handle_int(oidp, &tmp, 0, req);
122 if (err != 0 || req->newptr == NULL)
123 return (err);
124 if (!uart_pps_mode_valid(tmp))
125 return (EINVAL);
126 sc->sc_pps_mode = tmp;
127 return(0);
128 }
129
130 static void
131 uart_pps_process(struct uart_softc *sc, int ser_sig)
132 {
133 sbintime_t now;
134 int is_assert, pps_sig;
135
136 /* Which signal is configured as PPS? Early out if none. */
137 switch(sc->sc_pps_mode & UART_PPS_SIGNAL_MASK) {
138 case UART_PPS_CTS:
139 pps_sig = SER_CTS;
140 break;
141 case UART_PPS_DCD:
142 pps_sig = SER_DCD;
143 break;
144 default:
145 return;
146 }
147
148 /* Early out if there is no change in the signal configured as PPS. */
149 if ((ser_sig & SER_DELTA(pps_sig)) == 0)
150 return;
151
152 /*
153 * In narrow-pulse mode we need to synthesize both capture and clear
154 * events from a single "delta occurred" indication from the uart
155 * hardware because the pulse width is too narrow to reliably detect
156 * both edges. However, when the pulse width is close to our interrupt
157 * processing latency we might intermittantly catch both edges. To
158 * guard against generating spurious events when that happens, we use a
159 * separate timer to ensure at least half a second elapses before we
160 * generate another event.
161 */
162 pps_capture(&sc->sc_pps);
163 if (sc->sc_pps_mode & UART_PPS_NARROW_PULSE) {
164 now = getsbinuptime();
165 if (now > sc->sc_pps_captime + 500 * SBT_1MS) {
166 sc->sc_pps_captime = now;
167 pps_event(&sc->sc_pps, PPS_CAPTUREASSERT);
168 pps_event(&sc->sc_pps, PPS_CAPTURECLEAR);
169 }
170 } else {
171 is_assert = ser_sig & pps_sig;
172 if (sc->sc_pps_mode & UART_PPS_INVERT_PULSE)
173 is_assert = !is_assert;
174 pps_event(&sc->sc_pps, is_assert ? PPS_CAPTUREASSERT :
175 PPS_CAPTURECLEAR);
176 }
177 }
178
179 static void
180 uart_pps_init(struct uart_softc *sc)
181 {
182 struct sysctl_ctx_list *ctx;
183 struct sysctl_oid *tree;
184
185 ctx = device_get_sysctl_ctx(sc->sc_dev);
186 tree = device_get_sysctl_tree(sc->sc_dev);
187
188 /*
189 * The historical default for pps capture mode is either DCD or CTS,
190 * depending on the UART_PPS_ON_CTS kernel option. Start with that,
191 * then try to fetch the tunable that overrides the mode for all uart
192 * devices, then try to fetch the sysctl-tunable that overrides the mode
193 * for one specific device.
194 */
195 #ifdef UART_PPS_ON_CTS
196 sc->sc_pps_mode = UART_PPS_CTS;
197 #else
198 sc->sc_pps_mode = UART_PPS_DCD;
199 #endif
200 TUNABLE_INT_FETCH("hw.uart.pps_mode", &sc->sc_pps_mode);
201 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "pps_mode",
202 CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0, uart_pps_mode_sysctl, "I",
203 "pulse mode: 0/1/2=disabled/CTS/DCD; "
204 "add 0x10 to invert, 0x20 for narrow pulse");
205
206 if (!uart_pps_mode_valid(sc->sc_pps_mode)) {
207 device_printf(sc->sc_dev,
208 "Invalid pps_mode 0x%02x configured; disabling PPS capture\n",
209 sc->sc_pps_mode);
210 sc->sc_pps_mode = UART_PPS_DISABLED;
211 } else if (bootverbose) {
212 uart_pps_print_mode(sc);
213 }
214
215 sc->sc_pps.ppscap = PPS_CAPTUREBOTH;
216 sc->sc_pps.driver_mtx = uart_tty_getlock(sc);
217 sc->sc_pps.driver_abi = PPS_ABI_VERSION;
218 pps_init_abi(&sc->sc_pps);
219 }
220
221 void
222 uart_add_sysdev(struct uart_devinfo *di)
223 {
224 SLIST_INSERT_HEAD(&uart_sysdevs, di, next);
225 }
226
227 const char *
228 uart_getname(struct uart_class *uc)
229 {
230 return ((uc != NULL) ? uc->name : NULL);
231 }
232
233 struct uart_ops *
234 uart_getops(struct uart_class *uc)
235 {
236 return ((uc != NULL) ? uc->uc_ops : NULL);
237 }
238
239 int
240 uart_getrange(struct uart_class *uc)
241 {
242 return ((uc != NULL) ? uc->uc_range : 0);
243 }
244
245 /*
246 * Schedule a soft interrupt. We do this on the 0 to !0 transition
247 * of the TTY pending interrupt status.
248 */
249 void
250 uart_sched_softih(struct uart_softc *sc, uint32_t ipend)
251 {
252 uint32_t new, old;
253
254 do {
255 old = sc->sc_ttypend;
256 new = old | ipend;
257 } while (!atomic_cmpset_32(&sc->sc_ttypend, old, new));
258
259 if ((old & SER_INT_MASK) == 0)
260 swi_sched(sc->sc_softih, 0);
261 }
262
263 /*
264 * A break condition has been detected. We treat the break condition as
265 * a special case that should not happen during normal operation. When
266 * the break condition is to be passed to higher levels in the form of
267 * a NUL character, we really want the break to be in the right place in
268 * the input stream. The overhead to achieve that is not in relation to
269 * the exceptional nature of the break condition, so we permit ourselves
270 * to be sloppy.
271 */
272 static __inline int
273 uart_intr_break(void *arg)
274 {
275 struct uart_softc *sc = arg;
276
277 #if defined(KDB)
278 if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) {
279 if (kdb_break())
280 return (0);
281 }
282 #endif
283 if (sc->sc_opened)
284 uart_sched_softih(sc, SER_INT_BREAK);
285 return (0);
286 }
287
288 /*
289 * Handle a receiver overrun situation. We lost at least 1 byte in the
290 * input stream and it's our job to contain the situation. We grab as
291 * much of the data we can, but otherwise flush the receiver FIFO to
292 * create some breathing room. The net effect is that we avoid the
293 * overrun condition to happen for the next X characters, where X is
294 * related to the FIFO size at the cost of losing data right away.
295 * So, instead of having multiple overrun interrupts in close proximity
296 * to each other and possibly pessimizing UART interrupt latency for
297 * other UARTs in a multiport configuration, we create a longer segment
298 * of missing characters by freeing up the FIFO.
299 * Each overrun condition is marked in the input buffer by a token. The
300 * token represents the loss of at least one, but possible more bytes in
301 * the input stream.
302 */
303 static __inline int
304 uart_intr_overrun(void *arg)
305 {
306 struct uart_softc *sc = arg;
307
308 if (sc->sc_opened) {
309 UART_RECEIVE(sc);
310 if (uart_rx_put(sc, UART_STAT_OVERRUN))
311 sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
312 uart_sched_softih(sc, SER_INT_RXREADY);
313 }
314 UART_FLUSH(sc, UART_FLUSH_RECEIVER);
315 return (0);
316 }
317
318 /*
319 * Received data ready.
320 */
321 static __inline int
322 uart_intr_rxready(void *arg)
323 {
324 struct uart_softc *sc = arg;
325 int rxp;
326
327 rxp = sc->sc_rxput;
328 UART_RECEIVE(sc);
329 #if defined(KDB)
330 if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) {
331 while (rxp != sc->sc_rxput) {
332 kdb_alt_break(sc->sc_rxbuf[rxp++], &sc->sc_altbrk);
333 if (rxp == sc->sc_rxbufsz)
334 rxp = 0;
335 }
336 }
337 #endif
338 if (sc->sc_opened)
339 uart_sched_softih(sc, SER_INT_RXREADY);
340 else
341 sc->sc_rxput = sc->sc_rxget; /* Ignore received data. */
342 return (1);
343 }
344
345 /*
346 * Line or modem status change (OOB signalling).
347 * We pass the signals to the software interrupt handler for further
348 * processing. Note that we merge the delta bits, but set the state
349 * bits. This is to avoid losing state transitions due to having more
350 * than 1 hardware interrupt between software interrupts.
351 */
352 static __inline int
353 uart_intr_sigchg(void *arg)
354 {
355 struct uart_softc *sc = arg;
356 int new, old, sig;
357
358 sig = UART_GETSIG(sc);
359
360 /*
361 * Time pulse counting support, invoked whenever the PPS parameters are
362 * currently set to capture either edge of the signal.
363 */
364 if (sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) {
365 uart_pps_process(sc, sig);
366 }
367
368 /*
369 * Keep track of signal changes, even when the device is not
370 * opened. This allows us to inform upper layers about a
371 * possible loss of DCD and thus the existence of a (possibly)
372 * different connection when we have DCD back, during the time
373 * that the device was closed.
374 */
375 do {
376 old = sc->sc_ttypend;
377 new = old & ~SER_MASK_STATE;
378 new |= sig & SER_INT_SIGMASK;
379 } while (!atomic_cmpset_32(&sc->sc_ttypend, old, new));
380
381 if (sc->sc_opened)
382 uart_sched_softih(sc, SER_INT_SIGCHG);
383 return (1);
384 }
385
386 /*
387 * The transmitter can accept more data.
388 */
389 static __inline int
390 uart_intr_txidle(void *arg)
391 {
392 struct uart_softc *sc = arg;
393
394 if (sc->sc_txbusy) {
395 sc->sc_txbusy = 0;
396 uart_sched_softih(sc, SER_INT_TXIDLE);
397 }
398 return (0);
399 }
400
401 static int
402 uart_intr(void *arg)
403 {
404 struct uart_softc *sc = arg;
405 int cnt, ipend, testintr;
406
407 if (sc->sc_leaving)
408 return (FILTER_STRAY);
409
410 cnt = 0;
411 testintr = sc->sc_testintr;
412 while ((!testintr || cnt < 20) && (ipend = UART_IPEND(sc)) != 0) {
413 cnt++;
414 if (ipend & SER_INT_OVERRUN)
415 uart_intr_overrun(sc);
416 if (ipend & SER_INT_BREAK)
417 uart_intr_break(sc);
418 if (ipend & SER_INT_RXREADY)
419 uart_intr_rxready(sc);
420 if (ipend & SER_INT_SIGCHG)
421 uart_intr_sigchg(sc);
422 if (ipend & SER_INT_TXIDLE)
423 uart_intr_txidle(sc);
424 }
425
426 if (sc->sc_polled) {
427 callout_reset(&sc->sc_timer, hz / uart_poll_freq,
428 (timeout_t *)uart_intr, sc);
429 }
430
431 return ((cnt == 0) ? FILTER_STRAY :
432 ((testintr && cnt == 20) ? FILTER_SCHEDULE_THREAD :
433 FILTER_HANDLED));
434 }
435
436 serdev_intr_t *
437 uart_bus_ihand(device_t dev, int ipend)
438 {
439
440 switch (ipend) {
441 case SER_INT_BREAK:
442 return (uart_intr_break);
443 case SER_INT_OVERRUN:
444 return (uart_intr_overrun);
445 case SER_INT_RXREADY:
446 return (uart_intr_rxready);
447 case SER_INT_SIGCHG:
448 return (uart_intr_sigchg);
449 case SER_INT_TXIDLE:
450 return (uart_intr_txidle);
451 }
452 return (NULL);
453 }
454
455 int
456 uart_bus_ipend(device_t dev)
457 {
458 struct uart_softc *sc;
459
460 sc = device_get_softc(dev);
461 return (UART_IPEND(sc));
462 }
463
464 int
465 uart_bus_sysdev(device_t dev)
466 {
467 struct uart_softc *sc;
468
469 sc = device_get_softc(dev);
470 return ((sc->sc_sysdev != NULL) ? 1 : 0);
471 }
472
473 int
474 uart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan)
475 {
476 struct uart_softc *sc;
477 struct uart_devinfo *sysdev;
478 int error;
479
480 sc = device_get_softc(dev);
481
482 /*
483 * All uart_class references are weak. Check that the needed
484 * class has been compiled-in. Fail if not.
485 */
486 if (sc->sc_class == NULL)
487 return (ENXIO);
488
489 /*
490 * Initialize the instance. Note that the instance (=softc) does
491 * not necessarily match the hardware specific softc. We can't do
492 * anything about it now, because we may not attach to the device.
493 * Hardware drivers cannot use any of the class specific fields
494 * while probing.
495 */
496 kobj_init((kobj_t)sc, (kobj_class_t)sc->sc_class);
497 sc->sc_dev = dev;
498 if (device_get_desc(dev) == NULL)
499 device_set_desc(dev, uart_getname(sc->sc_class));
500
501 /*
502 * Allocate the register resource. We assume that all UARTs have
503 * a single register window in either I/O port space or memory
504 * mapped I/O space. Any UART that needs multiple windows will
505 * consequently not be supported by this driver as-is. We try I/O
506 * port space first because that's the common case.
507 */
508 sc->sc_rrid = rid;
509 sc->sc_rtype = SYS_RES_IOPORT;
510 sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid,
511 0, ~0, uart_getrange(sc->sc_class), RF_ACTIVE);
512 if (sc->sc_rres == NULL) {
513 sc->sc_rrid = rid;
514 sc->sc_rtype = SYS_RES_MEMORY;
515 sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype,
516 &sc->sc_rrid, 0, ~0, uart_getrange(sc->sc_class),
517 RF_ACTIVE);
518 if (sc->sc_rres == NULL)
519 return (ENXIO);
520 }
521
522 /*
523 * Fill in the bus access structure and compare this device with
524 * a possible console device and/or a debug port. We set the flags
525 * in the softc so that the hardware dependent probe can adjust
526 * accordingly. In general, you don't want to permanently disrupt
527 * console I/O.
528 */
529 sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
530 sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);
531 sc->sc_bas.chan = chan;
532 sc->sc_bas.regshft = regshft;
533 sc->sc_bas.rclk = (rclk == 0) ? sc->sc_class->uc_rclk : rclk;
534
535 SLIST_FOREACH(sysdev, &uart_sysdevs, next) {
536 if (chan == sysdev->bas.chan &&
537 uart_cpu_eqres(&sc->sc_bas, &sysdev->bas)) {
538 /* XXX check if ops matches class. */
539 sc->sc_sysdev = sysdev;
540 sysdev->bas.rclk = sc->sc_bas.rclk;
541 }
542 }
543
544 error = UART_PROBE(sc);
545 bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
546 return ((error) ? error : BUS_PROBE_DEFAULT);
547 }
548
549 int
550 uart_bus_attach(device_t dev)
551 {
552 struct uart_softc *sc, *sc0;
553 const char *sep;
554 int error, filt;
555
556 /*
557 * The sc_class field defines the type of UART we're going to work
558 * with and thus the size of the softc. Replace the generic softc
559 * with one that matches the UART now that we're certain we handle
560 * the device.
561 */
562 sc0 = device_get_softc(dev);
563 if (sc0->sc_class->size > sizeof(*sc)) {
564 sc = malloc(sc0->sc_class->size, M_UART, M_WAITOK|M_ZERO);
565 bcopy(sc0, sc, sizeof(*sc));
566 device_set_softc(dev, sc);
567 } else
568 sc = sc0;
569
570 /*
571 * Now that we know the softc for this device, connect the back
572 * pointer from the sysdev for this device, if any
573 */
574 if (sc->sc_sysdev != NULL)
575 sc->sc_sysdev->sc = sc;
576
577 /*
578 * Protect ourselves against interrupts while we're not completely
579 * finished attaching and initializing. We don't expect interrupts
580 * until after UART_ATTACH(), though.
581 */
582 sc->sc_leaving = 1;
583
584 mtx_init(&sc->sc_hwmtx_s, "uart_hwmtx", NULL, MTX_SPIN);
585 if (sc->sc_hwmtx == NULL)
586 sc->sc_hwmtx = &sc->sc_hwmtx_s;
587
588 /*
589 * Re-allocate. We expect that the softc contains the information
590 * collected by uart_bus_probe() intact.
591 */
592 sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid,
593 0, ~0, uart_getrange(sc->sc_class), RF_ACTIVE);
594 if (sc->sc_rres == NULL) {
595 mtx_destroy(&sc->sc_hwmtx_s);
596 return (ENXIO);
597 }
598 sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
599 sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);
600
601 /*
602 * Ensure there is room for at least three full FIFOs of data in the
603 * receive buffer (handles the case of low-level drivers with huge
604 * FIFOs), and also ensure that there is no less than the historical
605 * size of 384 bytes (handles the typical small-FIFO case).
606 */
607 sc->sc_rxbufsz = MAX(384, sc->sc_rxfifosz * 3);
608 sc->sc_rxbuf = malloc(sc->sc_rxbufsz * sizeof(*sc->sc_rxbuf),
609 M_UART, M_WAITOK);
610 sc->sc_txbuf = malloc(sc->sc_txfifosz * sizeof(*sc->sc_txbuf),
611 M_UART, M_WAITOK);
612
613 error = UART_ATTACH(sc);
614 if (error)
615 goto fail;
616
617 if (sc->sc_hwiflow || sc->sc_hwoflow) {
618 sep = "";
619 device_print_prettyname(dev);
620 if (sc->sc_hwiflow) {
621 printf("%sRTS iflow", sep);
622 sep = ", ";
623 }
624 if (sc->sc_hwoflow) {
625 printf("%sCTS oflow", sep);
626 sep = ", ";
627 }
628 printf("\n");
629 }
630
631 if (sc->sc_sysdev != NULL) {
632 if (sc->sc_sysdev->baudrate == 0) {
633 if (UART_IOCTL(sc, UART_IOCTL_BAUD,
634 (intptr_t)&sc->sc_sysdev->baudrate) != 0)
635 sc->sc_sysdev->baudrate = -1;
636 }
637 switch (sc->sc_sysdev->type) {
638 case UART_DEV_CONSOLE:
639 device_printf(dev, "console");
640 break;
641 case UART_DEV_DBGPORT:
642 device_printf(dev, "debug port");
643 break;
644 case UART_DEV_KEYBOARD:
645 device_printf(dev, "keyboard");
646 break;
647 default:
648 device_printf(dev, "unknown system device");
649 break;
650 }
651 printf(" (%d,%c,%d,%d)\n", sc->sc_sysdev->baudrate,
652 "noems"[sc->sc_sysdev->parity], sc->sc_sysdev->databits,
653 sc->sc_sysdev->stopbits);
654 }
655
656 sc->sc_leaving = 0;
657 sc->sc_testintr = 1;
658 filt = uart_intr(sc);
659 sc->sc_testintr = 0;
660
661 /*
662 * Don't use interrupts if we couldn't clear any pending interrupt
663 * conditions. We may have broken H/W and polling is probably the
664 * safest thing to do.
665 */
666 if (filt != FILTER_SCHEDULE_THREAD) {
667 sc->sc_irid = 0;
668 sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
669 &sc->sc_irid, RF_ACTIVE | RF_SHAREABLE);
670 }
671 if (sc->sc_ires != NULL) {
672 error = bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_TTY,
673 uart_intr, NULL, sc, &sc->sc_icookie);
674 sc->sc_fastintr = (error == 0) ? 1 : 0;
675
676 if (!sc->sc_fastintr)
677 error = bus_setup_intr(dev, sc->sc_ires,
678 INTR_TYPE_TTY | INTR_MPSAFE, NULL,
679 (driver_intr_t *)uart_intr, sc, &sc->sc_icookie);
680
681 if (error) {
682 device_printf(dev, "could not activate interrupt\n");
683 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
684 sc->sc_ires);
685 sc->sc_ires = NULL;
686 }
687 }
688 if (sc->sc_ires == NULL) {
689 /* No interrupt resource. Force polled mode. */
690 sc->sc_polled = 1;
691 callout_init(&sc->sc_timer, 1);
692 }
693
694 if (bootverbose && (sc->sc_fastintr || sc->sc_polled)) {
695 sep = "";
696 device_print_prettyname(dev);
697 if (sc->sc_fastintr) {
698 printf("%sfast interrupt", sep);
699 sep = ", ";
700 }
701 if (sc->sc_polled) {
702 printf("%spolled mode (%dHz)", sep, uart_poll_freq);
703 sep = ", ";
704 }
705 printf("\n");
706 }
707
708 if (sc->sc_sysdev != NULL && sc->sc_sysdev->attach != NULL) {
709 if ((error = sc->sc_sysdev->attach(sc)) != 0)
710 goto fail;
711 } else {
712 if ((error = uart_tty_attach(sc)) != 0)
713 goto fail;
714 uart_pps_init(sc);
715 }
716
717 if (sc->sc_sysdev != NULL)
718 sc->sc_sysdev->hwmtx = sc->sc_hwmtx;
719
720 return (0);
721
722 fail:
723 free(sc->sc_txbuf, M_UART);
724 free(sc->sc_rxbuf, M_UART);
725
726 if (sc->sc_ires != NULL) {
727 bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
728 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
729 sc->sc_ires);
730 }
731 bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
732
733 mtx_destroy(&sc->sc_hwmtx_s);
734
735 return (error);
736 }
737
738 int
739 uart_bus_detach(device_t dev)
740 {
741 struct uart_softc *sc;
742
743 sc = device_get_softc(dev);
744
745 sc->sc_leaving = 1;
746
747 if (sc->sc_sysdev != NULL)
748 sc->sc_sysdev->hwmtx = NULL;
749
750 UART_DETACH(sc);
751
752 if (sc->sc_sysdev != NULL && sc->sc_sysdev->detach != NULL)
753 (*sc->sc_sysdev->detach)(sc);
754 else
755 uart_tty_detach(sc);
756
757 free(sc->sc_txbuf, M_UART);
758 free(sc->sc_rxbuf, M_UART);
759
760 if (sc->sc_ires != NULL) {
761 bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
762 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
763 sc->sc_ires);
764 }
765 bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
766
767 mtx_destroy(&sc->sc_hwmtx_s);
768
769 if (sc->sc_class->size > sizeof(*sc)) {
770 device_set_softc(dev, NULL);
771 free(sc, M_UART);
772 } else
773 device_set_softc(dev, NULL);
774
775 return (0);
776 }
777
778 int
779 uart_bus_resume(device_t dev)
780 {
781 struct uart_softc *sc;
782
783 sc = device_get_softc(dev);
784 return (UART_ATTACH(sc));
785 }
786
787 void
788 uart_grab(struct uart_devinfo *di)
789 {
790
791 if (di->sc)
792 UART_GRAB(di->sc);
793 }
794
795 void
796 uart_ungrab(struct uart_devinfo *di)
797 {
798
799 if (di->sc)
800 UART_UNGRAB(di->sc);
801 }

Properties

Name Value
svn:keywords MidnightBSD=%H