source: mainline/kernel/genarch/src/drivers/ns16550/ns16550.c@ 24abb85d

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 24abb85d was 24abb85d, checked in by Jakub Jermar <jakub@…>, 8 years ago

Remove SYS_DEVICE_ASSIGN_DEVNO

  • Property mode set to 100644
File size: 4.8 KB
RevLine 
[8b4be29]1/*
[4c7257b]2 * Copyright (c) 2009 Jakub Jermar
[8b4be29]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 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - 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 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
[3c79afe]29/** @addtogroup genarch
[8b4be29]30 * @{
31 */
32/**
33 * @file
[3c79afe]34 * @brief NS 16550 serial controller driver.
[8b4be29]35 */
36
[63e27ef]37#include <assert.h>
[411b6a6]38#include <genarch/drivers/ns16550/ns16550.h>
[7dcf22a]39#include <ddi/irq.h>
[8b4be29]40#include <arch/asm.h>
41#include <console/chardev.h>
[013c4d6]42#include <mm/slab.h>
[6bbe470]43#include <str.h>
[8b4be29]44
[3c79afe]45#define LSR_DATA_READY 0x01
[6bbe470]46#define LSR_TH_READY 0x20
[3c79afe]47
48static irq_ownership_t ns16550_claim(irq_t *irq)
49{
50 ns16550_instance_t *instance = irq->instance;
51 ns16550_t *dev = instance->ns16550;
52
53 if (pio_read_8(&dev->lsr) & LSR_DATA_READY)
54 return IRQ_ACCEPT;
55 else
56 return IRQ_DECLINE;
57}
58
59static void ns16550_irq_handler(irq_t *irq)
60{
61 ns16550_instance_t *instance = irq->instance;
62 ns16550_t *dev = instance->ns16550;
63
64 if (pio_read_8(&dev->lsr) & LSR_DATA_READY) {
[c2417bc]65 uint8_t data = pio_read_8(&dev->rbr);
[6bbe470]66 indev_push_character(instance->input, data);
[3c79afe]67 }
68}
[8b4be29]69
[c2417bc]70/**< Clear input buffer. */
71static void ns16550_clear_buffer(ns16550_t *dev)
72{
73 while ((pio_read_8(&dev->lsr) & LSR_DATA_READY))
74 (void) pio_read_8(&dev->rbr);
75}
76
[6bbe470]77static void ns16550_sendb(ns16550_t *dev, uint8_t byte)
78{
79 while (!(pio_read_8(&dev->lsr) & LSR_TH_READY))
80 ;
81 pio_write_8(&dev->thr, byte);
82}
83
84static void ns16550_putchar(outdev_t *dev, wchar_t ch)
85{
86 ns16550_instance_t *instance = (ns16550_instance_t *) dev->data;
87
88 if ((!instance->parea.mapped) || (console_override)) {
89 if (ascii_check(ch))
90 ns16550_sendb(instance->ns16550, (uint8_t) ch);
91 else
92 ns16550_sendb(instance->ns16550, U_SPECIAL);
93 }
94}
95
96static outdev_operations_t ns16550_ops = {
97 .write = ns16550_putchar,
98 .redraw = NULL
99};
100
[63530c62]101/** Initialize ns16550.
102 *
[3c79afe]103 * @param dev Addrress of the beginning of the device in I/O space.
104 * @param inr Interrupt number.
105 * @param cir Clear interrupt function.
106 * @param cir_arg First argument to cir.
[21b6307]107 * @param output Where to store pointer to the output device
108 * or NULL if the caller is not interested in
109 * writing to the serial port.
[3c79afe]110 *
[c2417bc]111 * @return Keyboard instance or NULL on failure.
[013c4d6]112 *
[63530c62]113 */
[21b6307]114ns16550_instance_t *ns16550_init(ns16550_t *dev, inr_t inr, cir_t cir,
115 void *cir_arg, outdev_t **output)
[8b4be29]116{
[3c79afe]117 ns16550_instance_t *instance
118 = malloc(sizeof(ns16550_instance_t), FRAME_ATOMIC);
[c2417bc]119 if (instance) {
120 instance->ns16550 = dev;
[6bbe470]121 instance->input = NULL;
122 instance->output = NULL;
[c2417bc]123
[21b6307]124 if (output) {
125 instance->output = malloc(sizeof(outdev_t),
126 FRAME_ATOMIC);
127 if (!instance->output) {
128 free(instance);
129 return NULL;
130 }
131
132 outdev_initialize("ns16550", instance->output,
133 &ns16550_ops);
134 instance->output->data = instance;
135 *output = instance->output;
136 }
137
[c2417bc]138 irq_initialize(&instance->irq);
139 instance->irq.inr = inr;
140 instance->irq.claim = ns16550_claim;
141 instance->irq.handler = ns16550_irq_handler;
142 instance->irq.instance = instance;
143 instance->irq.cir = cir;
144 instance->irq.cir_arg = cir_arg;
[6bbe470]145
146 instance->parea.pbase = (uintptr_t) dev;
147 instance->parea.frames = 1;
148 instance->parea.unpriv = false;
149 instance->parea.mapped = false;
150 ddi_parea_register(&instance->parea);
[c2417bc]151 }
[3c79afe]152
[c2417bc]153 return instance;
154}
155
[6bbe470]156void ns16550_wire(ns16550_instance_t *instance, indev_t *input)
[c2417bc]157{
[63e27ef]158 assert(instance);
159 assert(input);
[63530c62]160
[6bbe470]161 instance->input = input;
[dc22844]162 irq_register(&instance->irq);
[3c79afe]163
[c2417bc]164 ns16550_clear_buffer(instance->ns16550);
[63530c62]165
[3e53ab7]166 /* Enable interrupts */
[c2417bc]167 pio_write_8(&instance->ns16550->ier, IER_ERBFI);
168 pio_write_8(&instance->ns16550->mcr, MCR_OUT2);
[0d107f31]169}
170
[8b4be29]171/** @}
172 */
Note: See TracBrowser for help on using the repository browser.