1/**
2 * \file
3 * \brief Serial port driver.
4 */
5
6/*
7 * Copyright (c) 2007, 2008, 2010, 2011, 2012, ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, CAB F.78, Universitaetstrasse 6, CH-8092 Zurich,
13 * Attn: Systems Group.
14 */
15
16#include <barrelfish/barrelfish.h>
17#include <barrelfish/inthandler.h>
18#include <int_route/int_route_client.h>
19#include <driverkit/driverkit.h>
20#include "serial.h"
21#include "serial_debug.h"
22#include <pci/pci.h>
23
24struct serial_kernel {
25    struct serial_common m;
26};
27
28static void
29serial_interrupt(void *arg) {
30    struct serial_kernel * sk = arg;
31    char c;
32    errval_t err = sys_getchar(&c);
33    assert(err_is_ok(err));
34    serial_input(&sk->m, &c, 1);
35}
36
37static void
38serial_write(void *m, const char *c, size_t len)
39{
40    sys_print(c, len);
41}
42
43static errval_t
44serial_kernel_init(struct serial_kernel *sk, struct capref irq_src)
45{
46    errval_t err;
47
48    sk->m.output = serial_write;
49    sk->m.output_arg = sk;
50
51    // Register interrupt handler
52    if (!capref_is_null(irq_src)) {
53        err = int_route_client_route_and_connect(irq_src, 0, get_default_waitset(),
54                                                 serial_interrupt, sk);
55        if (err_is_fail(err)) {
56            USER_PANIC_ERR(err, "interrupt setup failed.");
57        }
58    }
59
60    // offer service now we're up
61    start_service(&sk->m);
62    return SYS_ERR_OK;
63}
64
65static errval_t
66init_kernel(struct bfdriver_instance* bfi, uint64_t flags, iref_t *dev)
67{
68    errval_t err;
69    struct serial_kernel *sk = malloc(sizeof(struct serial_kernel));
70    init_serial_common(&sk->m);
71
72    bfi->dstate = sk;
73
74    struct capref irq_src;
75    irq_src.cnode = bfi->argcn;
76    irq_src.slot = PCIARG_SLOT_INT;
77    if (flags == 1) {
78        irq_src = NULL_CAP;
79    } else {
80        irq_src.cnode = bfi->argcn;
81        irq_src.slot = PCIARG_SLOT_INT;
82    }
83
84    // Initialize serial driver
85    err = serial_kernel_init(sk, irq_src);
86    if (err_is_fail(err)) {
87        DEBUG_ERR(err, "serial_init");
88        return err;
89    }
90
91    SERIAL_DEBUG("Kernel Serial driver initialized.\n");
92
93    return SYS_ERR_OK;
94}
95
96static errval_t attach(struct bfdriver_instance* bfi) {
97    return SYS_ERR_OK;
98}
99
100static errval_t detach(struct bfdriver_instance* bfi) {
101    return SYS_ERR_OK;
102}
103
104static errval_t set_sleep_level(struct bfdriver_instance* bfi, uint32_t level) {
105    return SYS_ERR_OK;
106}
107
108static errval_t destroy(struct bfdriver_instance* bfi) {
109    struct serial_common * m = bfi->dstate;
110    free(m);
111    bfi->dstate = NULL;
112    // XXX: Tear-down the service
113    bfi->device = 0x0;
114    return SYS_ERR_OK;
115}
116
117static errval_t get_ep(struct bfdriver_instance* bfi, bool lmp, struct capref* ret_cap)
118{
119    USER_PANIC("NIY \n");
120    return SYS_ERR_OK;
121}
122
123DEFINE_MODULE(serial_kernel, init_kernel, attach, detach, set_sleep_level, destroy, get_ep);
124
125