]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/dev/uart/uart_core.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / dev / uart / uart_core.c
1 /*-
2  * Copyright (c) 2003 Marcel Moolenaar
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
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  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #ifndef KLD_MODULE
31 #include "opt_comconsole.h"
32 #endif
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/bus.h>
37 #include <sys/conf.h>
38 #include <sys/cons.h>
39 #include <sys/fcntl.h>
40 #include <sys/interrupt.h>
41 #include <sys/kdb.h>
42 #include <sys/kernel.h>
43 #include <sys/malloc.h>
44 #include <sys/queue.h>
45 #include <sys/reboot.h>
46 #include <machine/bus.h>
47 #include <sys/rman.h>
48 #include <sys/termios.h>
49 #include <machine/resource.h>
50 #include <machine/stdarg.h>
51
52 #include <dev/uart/uart.h>
53 #include <dev/uart/uart_bus.h>
54 #include <dev/uart/uart_cpu.h>
55
56 #include "uart_if.h"
57
58 devclass_t uart_devclass;
59 char uart_driver_name[] = "uart";
60
61 SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs =
62     SLIST_HEAD_INITIALIZER(uart_sysdevs);
63
64 MALLOC_DEFINE(M_UART, "UART", "UART driver");
65
66 void
67 uart_add_sysdev(struct uart_devinfo *di)
68 {
69         SLIST_INSERT_HEAD(&uart_sysdevs, di, next);
70 }
71
72 const char *
73 uart_getname(struct uart_class *uc)
74 {
75         return ((uc != NULL) ? uc->name : NULL);
76 }
77
78 struct uart_ops *
79 uart_getops(struct uart_class *uc)
80 {
81         return ((uc != NULL) ? uc->uc_ops : NULL);
82 }
83
84 int
85 uart_getrange(struct uart_class *uc)
86 {
87         return ((uc != NULL) ? uc->uc_range : 0);
88 }
89
90 /*
91  * Schedule a soft interrupt. We do this on the 0 to !0 transition
92  * of the TTY pending interrupt status.
93  */
94 void
95 uart_sched_softih(struct uart_softc *sc, uint32_t ipend)
96 {
97         uint32_t new, old;
98
99         do {
100                 old = sc->sc_ttypend;
101                 new = old | ipend;
102         } while (!atomic_cmpset_32(&sc->sc_ttypend, old, new));
103
104         if ((old & SER_INT_MASK) == 0)
105                 swi_sched(sc->sc_softih, 0);
106 }
107
108 /*
109  * A break condition has been detected. We treat the break condition as
110  * a special case that should not happen during normal operation. When
111  * the break condition is to be passed to higher levels in the form of
112  * a NUL character, we really want the break to be in the right place in
113  * the input stream. The overhead to achieve that is not in relation to
114  * the exceptional nature of the break condition, so we permit ourselves
115  * to be sloppy.
116  */
117 static __inline int
118 uart_intr_break(void *arg)
119 {
120         struct uart_softc *sc = arg;
121
122 #if defined(KDB) && defined(BREAK_TO_DEBUGGER)
123         if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) {
124                 kdb_enter(KDB_WHY_BREAK, "Line break on console");
125                 return (0);
126         }
127 #endif
128         if (sc->sc_opened)
129                 uart_sched_softih(sc, SER_INT_BREAK);
130         return (0);
131 }
132
133 /*
134  * Handle a receiver overrun situation. We lost at least 1 byte in the
135  * input stream and it's our job to contain the situation. We grab as
136  * much of the data we can, but otherwise flush the receiver FIFO to
137  * create some breathing room. The net effect is that we avoid the
138  * overrun condition to happen for the next X characters, where X is
139  * related to the FIFO size at the cost of loosing data right away.
140  * So, instead of having multiple overrun interrupts in close proximity
141  * to each other and possibly pessimizing UART interrupt latency for
142  * other UARTs in a multiport configuration, we create a longer segment
143  * of missing characters by freeing up the FIFO.
144  * Each overrun condition is marked in the input buffer by a token. The
145  * token represents the loss of at least one, but possible more bytes in
146  * the input stream.
147  */
148 static __inline int
149 uart_intr_overrun(void *arg)
150 {
151         struct uart_softc *sc = arg;
152
153         if (sc->sc_opened) {
154                 UART_RECEIVE(sc);
155                 if (uart_rx_put(sc, UART_STAT_OVERRUN))
156                         sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
157                 uart_sched_softih(sc, SER_INT_RXREADY);
158         }
159         UART_FLUSH(sc, UART_FLUSH_RECEIVER);
160         return (0);
161 }
162
163 /*
164  * Received data ready.
165  */
166 static __inline int
167 uart_intr_rxready(void *arg)
168 {
169         struct uart_softc *sc = arg;
170         int rxp;
171
172         rxp = sc->sc_rxput;
173         UART_RECEIVE(sc);
174 #if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
175         if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) {
176                 while (rxp != sc->sc_rxput) {
177                         int kdb_brk;
178
179                         if ((kdb_brk = kdb_alt_break(sc->sc_rxbuf[rxp++],
180                             &sc->sc_altbrk)) != 0) {
181                                 switch (kdb_brk) {
182                                 case KDB_REQ_DEBUGGER:
183                                         kdb_enter(KDB_WHY_BREAK,
184                                             "Break sequence on console");
185                                         break;
186                                 case KDB_REQ_PANIC:
187                                         kdb_panic("Panic sequence on console");
188                                         break;
189                                 case KDB_REQ_REBOOT:
190                                         kdb_reboot();
191                                         break;
192                                 }
193                         }
194                         if (rxp == sc->sc_rxbufsz)
195                                 rxp = 0;
196                 }
197         }
198 #endif
199         if (sc->sc_opened)
200                 uart_sched_softih(sc, SER_INT_RXREADY);
201         else
202                 sc->sc_rxput = sc->sc_rxget;    /* Ignore received data. */
203         return (1);
204 }
205
206 /*
207  * Line or modem status change (OOB signalling).
208  * We pass the signals to the software interrupt handler for further
209  * processing. Note that we merge the delta bits, but set the state
210  * bits. This is to avoid loosing state transitions due to having more
211  * than 1 hardware interrupt between software interrupts.
212  */
213 static __inline int
214 uart_intr_sigchg(void *arg)
215 {
216         struct uart_softc *sc = arg;
217         int new, old, sig;
218
219         sig = UART_GETSIG(sc);
220
221         if (sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) {
222                 if (sig & UART_SIG_DPPS) {
223                         pps_capture(&sc->sc_pps);
224                         pps_event(&sc->sc_pps, (sig & UART_SIG_PPS) ?
225                             PPS_CAPTUREASSERT : PPS_CAPTURECLEAR);
226                 }
227         }
228
229         /*
230          * Keep track of signal changes, even when the device is not
231          * opened. This allows us to inform upper layers about a
232          * possible loss of DCD and thus the existence of a (possibly)
233          * different connection when we have DCD back, during the time
234          * that the device was closed.
235          */
236         do {
237                 old = sc->sc_ttypend;
238                 new = old & ~SER_MASK_STATE;
239                 new |= sig & SER_INT_SIGMASK;
240         } while (!atomic_cmpset_32(&sc->sc_ttypend, old, new));
241
242         if (sc->sc_opened)
243                 uart_sched_softih(sc, SER_INT_SIGCHG);
244         return (1);
245 }
246
247 /*
248  * The transmitter can accept more data.
249  */
250 static __inline int
251 uart_intr_txidle(void *arg)
252 {
253         struct uart_softc *sc = arg;
254
255         if (sc->sc_txbusy) {
256                 sc->sc_txbusy = 0;
257                 uart_sched_softih(sc, SER_INT_TXIDLE);
258         }
259         return (0);
260 }
261
262 static int
263 uart_intr(void *arg)
264 {
265         struct uart_softc *sc = arg;
266         int flag = 0, ipend;
267
268         while (!sc->sc_leaving && (ipend = UART_IPEND(sc)) != 0) {
269                 flag = 1;
270                 if (ipend & SER_INT_OVERRUN)
271                         uart_intr_overrun(sc);
272                 if (ipend & SER_INT_BREAK)
273                         uart_intr_break(sc);
274                 if (ipend & SER_INT_RXREADY)
275                         uart_intr_rxready(sc);
276                 if (ipend & SER_INT_SIGCHG)
277                         uart_intr_sigchg(sc);
278                 if (ipend & SER_INT_TXIDLE)
279                         uart_intr_txidle(sc);           
280         }
281         return((flag)?FILTER_HANDLED:FILTER_STRAY);
282 }
283
284 serdev_intr_t *
285 uart_bus_ihand(device_t dev, int ipend)
286 {
287
288         switch (ipend) {
289         case SER_INT_BREAK:
290                 return (uart_intr_break);
291         case SER_INT_OVERRUN:
292                 return (uart_intr_overrun);
293         case SER_INT_RXREADY:
294                 return (uart_intr_rxready);
295         case SER_INT_SIGCHG:
296                 return (uart_intr_sigchg);
297         case SER_INT_TXIDLE:
298                 return (uart_intr_txidle);
299         }
300         return (NULL);
301 }
302
303 int
304 uart_bus_ipend(device_t dev)
305 {
306         struct uart_softc *sc;
307
308         sc = device_get_softc(dev);
309         return (UART_IPEND(sc));
310 }
311
312 int
313 uart_bus_sysdev(device_t dev)
314 {
315         struct uart_softc *sc;
316
317         sc = device_get_softc(dev);
318         return ((sc->sc_sysdev != NULL) ? 1 : 0);
319 }
320
321 int
322 uart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan)
323 {
324         struct uart_softc *sc;
325         struct uart_devinfo *sysdev;
326         int error;
327
328         sc = device_get_softc(dev);
329
330         /*
331          * All uart_class references are weak. Check that the needed
332          * class has been compiled-in. Fail if not.
333          */
334         if (sc->sc_class == NULL)
335                 return (ENXIO);
336
337         /*
338          * Initialize the instance. Note that the instance (=softc) does
339          * not necessarily match the hardware specific softc. We can't do
340          * anything about it now, because we may not attach to the device.
341          * Hardware drivers cannot use any of the class specific fields
342          * while probing.
343          */
344         kobj_init((kobj_t)sc, (kobj_class_t)sc->sc_class);
345         sc->sc_dev = dev;
346         if (device_get_desc(dev) == NULL)
347                 device_set_desc(dev, uart_getname(sc->sc_class));
348
349         /*
350          * Allocate the register resource. We assume that all UARTs have
351          * a single register window in either I/O port space or memory
352          * mapped I/O space. Any UART that needs multiple windows will
353          * consequently not be supported by this driver as-is. We try I/O
354          * port space first because that's the common case.
355          */
356         sc->sc_rrid = rid;
357         sc->sc_rtype = SYS_RES_IOPORT;
358         sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid,
359             0, ~0, uart_getrange(sc->sc_class), RF_ACTIVE);
360         if (sc->sc_rres == NULL) {
361                 sc->sc_rrid = rid;
362                 sc->sc_rtype = SYS_RES_MEMORY;
363                 sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype,
364                     &sc->sc_rrid, 0, ~0, uart_getrange(sc->sc_class),
365                     RF_ACTIVE);
366                 if (sc->sc_rres == NULL)
367                         return (ENXIO);
368         }
369
370         /*
371          * Fill in the bus access structure and compare this device with
372          * a possible console device and/or a debug port. We set the flags
373          * in the softc so that the hardware dependent probe can adjust
374          * accordingly. In general, you don't want to permanently disrupt
375          * console I/O.
376          */
377         sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
378         sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);
379         sc->sc_bas.chan = chan;
380         sc->sc_bas.regshft = regshft;
381         sc->sc_bas.rclk = (rclk == 0) ? sc->sc_class->uc_rclk : rclk;
382
383         SLIST_FOREACH(sysdev, &uart_sysdevs, next) {
384                 if (chan == sysdev->bas.chan &&
385                     uart_cpu_eqres(&sc->sc_bas, &sysdev->bas)) {
386                         /* XXX check if ops matches class. */
387                         sc->sc_sysdev = sysdev;
388                         sysdev->bas.rclk = sc->sc_bas.rclk;
389                 }
390         }
391
392         error = UART_PROBE(sc);
393         bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
394         return ((error) ? error : BUS_PROBE_DEFAULT);
395 }
396
397 int
398 uart_bus_attach(device_t dev)
399 {
400         struct uart_softc *sc, *sc0;
401         const char *sep;
402         int error;
403
404         /*
405          * The sc_class field defines the type of UART we're going to work
406          * with and thus the size of the softc. Replace the generic softc
407          * with one that matches the UART now that we're certain we handle
408          * the device.
409          */
410         sc0 = device_get_softc(dev);
411         if (sc0->sc_class->size > sizeof(*sc)) {
412                 sc = malloc(sc0->sc_class->size, M_UART, M_WAITOK|M_ZERO);
413                 bcopy(sc0, sc, sizeof(*sc));
414                 device_set_softc(dev, sc);
415         } else
416                 sc = sc0;
417
418         /*
419          * Protect ourselves against interrupts while we're not completely
420          * finished attaching and initializing. We don't expect interrupts
421          * until after UART_ATTACH() though.
422          */
423         sc->sc_leaving = 1;
424
425         mtx_init(&sc->sc_hwmtx_s, "uart_hwmtx", NULL, MTX_SPIN);
426         if (sc->sc_hwmtx == NULL)
427                 sc->sc_hwmtx = &sc->sc_hwmtx_s;
428
429         /*
430          * Re-allocate. We expect that the softc contains the information
431          * collected by uart_bus_probe() intact.
432          */
433         sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid,
434             0, ~0, uart_getrange(sc->sc_class), RF_ACTIVE);
435         if (sc->sc_rres == NULL) {
436                 mtx_destroy(&sc->sc_hwmtx_s);
437                 return (ENXIO);
438         }
439         sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
440         sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);
441
442         sc->sc_irid = 0;
443         sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
444             RF_ACTIVE | RF_SHAREABLE);
445         if (sc->sc_ires != NULL) {
446                 error = bus_setup_intr(dev,
447                     sc->sc_ires, INTR_TYPE_TTY, 
448                     uart_intr, NULL, sc, &sc->sc_icookie);                  
449                 if (error)
450                         error = bus_setup_intr(dev,
451                             sc->sc_ires, INTR_TYPE_TTY | INTR_MPSAFE,
452                             NULL, (driver_intr_t *)uart_intr, sc, &sc->sc_icookie);
453                 else
454                         sc->sc_fastintr = 1;
455
456                 if (error) {
457                         device_printf(dev, "could not activate interrupt\n");
458                         bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
459                             sc->sc_ires);
460                         sc->sc_ires = NULL;
461                 }
462         }
463         if (sc->sc_ires == NULL) {
464                 /* XXX no interrupt resource. Force polled mode. */
465                 sc->sc_polled = 1;
466         }
467
468         sc->sc_rxbufsz = 384;
469         sc->sc_rxbuf = malloc(sc->sc_rxbufsz * sizeof(*sc->sc_rxbuf),
470             M_UART, M_WAITOK);
471         sc->sc_txbuf = malloc(sc->sc_txfifosz * sizeof(*sc->sc_txbuf),
472             M_UART, M_WAITOK);
473
474         error = UART_ATTACH(sc);
475         if (error)
476                 goto fail;
477
478         if (sc->sc_hwiflow || sc->sc_hwoflow) {
479                 sep = "";
480                 device_print_prettyname(dev);
481                 if (sc->sc_hwiflow) {
482                         printf("%sRTS iflow", sep);
483                         sep = ", ";
484                 }
485                 if (sc->sc_hwoflow) {
486                         printf("%sCTS oflow", sep);
487                         sep = ", ";
488                 }
489                 printf("\n");
490         }
491
492         if (bootverbose && (sc->sc_fastintr || sc->sc_polled)) {
493                 sep = "";
494                 device_print_prettyname(dev);
495                 if (sc->sc_fastintr) {
496                         printf("%sfast interrupt", sep);
497                         sep = ", ";
498                 }
499                 if (sc->sc_polled) {
500                         printf("%spolled mode", sep);
501                         sep = ", ";
502                 }
503                 printf("\n");
504         }
505
506         if (sc->sc_sysdev != NULL) {
507                 if (sc->sc_sysdev->baudrate == 0) {
508                         if (UART_IOCTL(sc, UART_IOCTL_BAUD,
509                             (intptr_t)&sc->sc_sysdev->baudrate) != 0)
510                                 sc->sc_sysdev->baudrate = -1;
511                 }
512                 switch (sc->sc_sysdev->type) {
513                 case UART_DEV_CONSOLE:
514                         device_printf(dev, "console");
515                         break;
516                 case UART_DEV_DBGPORT:
517                         device_printf(dev, "debug port");
518                         break;
519                 case UART_DEV_KEYBOARD:
520                         device_printf(dev, "keyboard");
521                         break;
522                 default:
523                         device_printf(dev, "unknown system device");
524                         break;
525                 }
526                 printf(" (%d,%c,%d,%d)\n", sc->sc_sysdev->baudrate,
527                     "noems"[sc->sc_sysdev->parity], sc->sc_sysdev->databits,
528                     sc->sc_sysdev->stopbits);
529         }
530
531         sc->sc_pps.ppscap = PPS_CAPTUREBOTH;
532         pps_init(&sc->sc_pps);
533
534         error = (sc->sc_sysdev != NULL && sc->sc_sysdev->attach != NULL)
535             ? (*sc->sc_sysdev->attach)(sc) : uart_tty_attach(sc);
536         if (error)
537                 goto fail;
538
539         if (sc->sc_sysdev != NULL)
540                 sc->sc_sysdev->hwmtx = sc->sc_hwmtx;
541
542         sc->sc_leaving = 0;
543         uart_intr(sc);
544         return (0);
545
546  fail:
547         free(sc->sc_txbuf, M_UART);
548         free(sc->sc_rxbuf, M_UART);
549
550         if (sc->sc_ires != NULL) {
551                 bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
552                 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
553                     sc->sc_ires);
554         }
555         bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
556
557         mtx_destroy(&sc->sc_hwmtx_s);
558
559         return (error);
560 }
561
562 int
563 uart_bus_detach(device_t dev)
564 {
565         struct uart_softc *sc;
566
567         sc = device_get_softc(dev);
568
569         sc->sc_leaving = 1;
570
571         if (sc->sc_sysdev != NULL)
572                 sc->sc_sysdev->hwmtx = NULL;
573
574         UART_DETACH(sc);
575
576         if (sc->sc_sysdev != NULL && sc->sc_sysdev->detach != NULL)
577                 (*sc->sc_sysdev->detach)(sc);
578         else
579                 uart_tty_detach(sc);
580
581         free(sc->sc_txbuf, M_UART);
582         free(sc->sc_rxbuf, M_UART);
583
584         if (sc->sc_ires != NULL) {
585                 bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
586                 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
587                     sc->sc_ires);
588         }
589         bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
590
591         mtx_destroy(&sc->sc_hwmtx_s);
592
593         if (sc->sc_class->size > sizeof(*sc)) {
594                 device_set_softc(dev, NULL);
595                 free(sc, M_UART);
596         } else
597                 device_set_softc(dev, NULL);
598
599         return (0);
600 }