]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/serial-drv/server/src/main.cc
update
[l4.git] / l4 / pkg / serial-drv / server / src / main.cc
1 /*
2  * (c) 2010 Alexander Warg <warg@os.inf.tu-dresden.de>,
3  *          Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
4  *     economic rights: Technische Universität Dresden (Germany)
5  *
6  * This file is part of TUD:OS and distributed under the terms of the
7  * GNU General Public License 2.
8  * Please see the COPYING-GPL-2 file for details.
9  */
10 #include <l4/drivers/uart_pl011.h>
11 #include <l4/drivers/uart_omap35x.h>
12 #include <l4/io/io.h>
13 #include <l4/re/env>
14 #include <l4/re/error_helper>
15 #include <l4/re/namespace>
16 #include <l4/re/util/cap_alloc>
17 #include <l4/re/util/object_registry>
18 #include <l4/re/util/icu_svr>
19 #include <l4/re/util/vcon_svr>
20 #include <l4/sys/irq>
21 #include <l4/util/util.h>
22
23 #include <cstdlib>
24 #include <cstdio>
25
26
27 static L4::Cap<void> srv_rcv_cap;
28
29 class Loop_hooks :
30   public L4::Ipc_svr::Ignore_errors,
31   public L4::Ipc_svr::Default_timeout,
32   public L4::Ipc_svr::Compound_reply
33 {
34 public:
35   void setup_wait(L4::Ipc::Istream &istr, bool)
36   {
37     istr.reset();
38     istr << L4::Ipc::Small_buf(srv_rcv_cap.cap(), L4_RCV_ITEM_LOCAL_ID);
39     l4_utcb_br_u(istr.utcb())->bdr = 0;
40   }
41 };
42
43 using L4Re::Env;
44 using L4Re::Util::Registry_server;
45
46 static Registry_server<Loop_hooks> server(l4_utcb(),
47                                           Env::env()->main_thread(),
48                                           Env::env()->factory());
49
50 using L4Re::Util::Vcon_svr;
51 using L4Re::Util::Icu_cap_array_svr;
52
53 class Serial_drv :
54   public Vcon_svr<Serial_drv>,
55   public Icu_cap_array_svr<Serial_drv>,
56   public L4::Server_object
57 {
58 public:
59   Serial_drv();
60   virtual ~Serial_drv() throw() {}
61
62   bool running() const { return _running; }
63
64   int vcon_write(const char *buffer, unsigned size);
65   unsigned vcon_read(char *buffer, unsigned size);
66
67   L4::Cap<void> rcv_cap() { return srv_rcv_cap; }
68
69   int handle_irq();
70
71   bool init();
72   int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
73
74 private:
75   bool _running;
76   L4::Uart *_uart;
77   L4::Cap<L4::Irq> _uart_irq;
78   Icu_cap_array_svr<Serial_drv>::Irq _irq;
79 };
80
81 Serial_drv::Serial_drv()
82   : Icu_cap_array_svr<Serial_drv>(1, &_irq),
83     _running(false), _uart(0), _uart_irq(L4_INVALID_CAP),
84     _irq()
85 {
86   if (init())
87     _running = true;
88 }
89
90 int
91 Serial_drv::vcon_write(const char *buffer, unsigned size)
92 {
93   _uart->write(buffer, size);
94   return -L4_EOK;
95 }
96
97 unsigned
98 Serial_drv::vcon_read(char *buffer, unsigned size)
99 {
100   unsigned i = 0;
101   while (_uart->char_avail() && size)
102     {
103       int c = _uart->get_char(false);
104       if (c >= 0)
105         {
106           buffer[i++] = (char)c;
107           size--;
108         }
109       else
110         break;
111     }
112   // if there still some data available send this info to the client
113   if (_uart->char_avail())
114     i++;
115   else
116     _uart_irq->unmask();
117   return i;
118 }
119
120 int
121 Serial_drv::handle_irq()
122 {
123   if (_irq.cap().is_valid())
124     _irq.cap()->trigger();
125
126   //_uart_irq->unmask();
127
128   return L4_EOK;
129 }
130
131 bool
132 Serial_drv::init()
133 {
134   int irq_num = 37;
135   l4_addr_t phys_base = 0x1000a000;
136 #if 0
137   int irq_num = 74;
138   l4_addr_t phys_base = 0x49020000;
139 #endif
140   l4_addr_t virt_base = 0;
141
142   if (l4io_request_iomem(phys_base, 0x1000, L4IO_MEM_NONCACHED, &virt_base))
143     {
144       printf("serial-drv: request io-memory from l4io failed.\n");
145       return false;
146     }
147   printf("serial-drv: virtual base at:%lx\n", virt_base);
148
149   L4::Io_register_block_mmio *regs = new L4::Io_register_block_mmio(virt_base);
150   _uart = new (malloc(sizeof(L4::Uart_pl011))) L4::Uart_pl011(24019200);
151   //_uart = new (malloc(sizeof(L4::Uart_omap35x))) L4::Uart_omap35x;
152   _uart->startup(regs);
153
154   _uart_irq = L4Re::Util::cap_alloc.alloc<L4::Irq>();
155   if (!_uart_irq.is_valid())
156     {
157       printf("serial-drv: Alloc capability for uart-irq failed.\n");
158       return false;
159     }
160
161   if (l4io_request_irq(irq_num, _uart_irq.cap()))
162     {
163       printf("serial-drv: request uart-irq from l4io failed\n");
164       return false;
165     }
166
167   /* setting IRQ type to L4_IRQ_F_POS_EDGE seems to be wrong place */
168   if (l4_error(_uart_irq->attach((l4_umword_t)static_cast<L4::Server_object *>(this),
169           L4Re::Env::env()->main_thread())))
170     {
171       printf("serial-drv: attach to uart-irq failed.\n");
172       return false;
173     }
174
175   if ((l4_ipc_error(_uart_irq->unmask(), l4_utcb())))
176     {
177       printf("serial-drv: unmask uart-irq failed.\n");
178       return false;
179     }
180   _uart->enable_rx_irq(true);
181
182   srv_rcv_cap = L4Re::Util::cap_alloc.alloc<void>();
183   if (!srv_rcv_cap.is_valid())
184     {
185       printf("serial-drv: Alloc capability for rcv-cap failed.\\n");
186       return false;
187     }
188   
189   return true;
190 }
191
192 int
193 Serial_drv::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
194 {
195   l4_msgtag_t tag;
196   ios >> tag;
197   switch (tag.label())
198     {
199     case L4_PROTO_IRQ:
200       if (!L4Re::Util::Icu_svr<Serial_drv>::dispatch(obj, ios))
201         return handle_irq();
202     case L4_PROTO_LOG:
203       return L4Re::Util::Vcon_svr<Serial_drv>::dispatch(obj, ios);
204     default:
205       return -L4_EBADPROTO;
206     }
207 }
208
209 int main()
210 {
211   Serial_drv serial_drv;
212
213   if (!server.registry()->register_obj(&serial_drv, "vcon"))
214     {
215       printf("Failed to register serial driver; Aborting.\n");
216       return 1;
217     }
218
219   if (!serial_drv.running())
220     {
221       printf("Failed to initialize serial driver; Aborting.\n");
222       return 1;
223     }
224
225   printf("Starting server loop\n");
226   server.loop();
227
228   return 0;
229 }