source: trunk/packages/xen-3.1/xen-3.1/xen/arch/powerpc/of_handler/console.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 6.2 KB
Line 
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
15 *
16 * Copyright (C) IBM Corp. 2005
17 *
18 * Authors: Jimi Xenidis <jimix@watson.ibm.com>
19 */
20
21#include "ofh.h"
22#include "papr.h"
23#include <xen/string.h>
24#include <asm/system.h>
25
26union chpack {
27    u64 oct[2];
28    u32 quad[4];
29    char c[16];
30};
31
32/* used for internal printing */
33static struct ofh_ihandle *ofh_ihp;
34
35static s32 ofh_papr_read(s32 chan, void *buf, u32 count, s32 *actual, ulong b)
36{
37    s32 rc;
38    ulong ret[5];
39    ulong sz = 0;
40
41    rc = papr_get_term_char(ret, chan);
42    if (rc == H_Success && ret[0] > 0) {
43        sz = MIN(count, ret[0]);
44        memcpy(buf, &ret[1], sz);
45    }
46    *actual = sz;
47    return OF_SUCCESS;
48}
49
50static s32 ofh_papr_write(s32 chan, const void *buf, u32 count, s32 *actual,
51                          ulong b)
52{
53    const char *str = (const char *)buf;
54    u32 i;
55    union chpack ch;
56    s32 ret;
57
58    for (i = 0; i < count; i++) {
59        int m = i % sizeof(ch);
60        ch.c[m] = str[i];
61        if (m == sizeof(ch) - 1 || i == count - 1) {
62            for (;;) {
63                if (sizeof (ulong) == sizeof (u64)) {
64                    ret = papr_put_term_char(NULL,
65                                             chan,
66                                             m + 1,
67                                             ch.oct[0],
68                                             ch.oct[1]);
69                } else {
70                    ret = papr_put_term_char(NULL,
71                                             chan,
72                                             m + 1,
73                                             ch.quad[0],
74                                             ch.quad[1],
75                                             ch.quad[2],
76                                             ch.quad[3]);
77                }
78                if (ret != H_Busy) {
79                    break;
80                }
81                /* yielding here would be nice */
82            }
83            if (ret != H_Success) {
84                return -1;
85            }
86        }
87    }
88    *actual = count;
89    if (*actual == -1) {
90        return OF_FAILURE;
91    }
92    return OF_SUCCESS;
93}
94
95#define __HYPERVISOR_console_io 18
96#define CONSOLEIO_write         0
97#define CONSOLEIO_read          1
98#define XEN_MARK(a) ((a) | (~0UL << 16))
99extern long xen_hvcall(ulong code, ...);
100
101#define XENCOMM_MINI_AREA (sizeof(struct xencomm_mini) * 2)
102static s32 ofh_xen_dom0_read(s32 chan, void *buf, u32 count, s32 *actual,
103                             ulong b)
104{
105    char __storage[XENCOMM_MINI_AREA];
106    struct xencomm_desc *desc;
107    s32 rc;
108    char *s = buf;
109    s32 ret = 0;
110
111    while (count > 0) {
112        if (xencomm_create_mini(__storage, XENCOMM_MINI_AREA, s, count, &desc))
113            return ret;
114
115        rc = xen_hvcall(XEN_MARK(__HYPERVISOR_console_io), CONSOLEIO_read,
116                        count, desc);
117        if (rc <= 0) {
118            return ret;
119        }
120        count -= rc;
121        s += rc;
122        ret += rc;
123    }
124    *actual = ret;
125    return OF_SUCCESS;
126}
127
128static s32 ofh_xen_dom0_write(s32 chan, const void *buf, u32 count,
129                              s32 *actual, ulong b)
130{
131    char __storage[XENCOMM_MINI_AREA];
132    struct xencomm_desc *desc;
133    s32 rc;
134    char *s = (char *)buf;
135    s32 ret = 0;
136
137    while (count > 0) {
138        if (xencomm_create_mini(__storage, XENCOMM_MINI_AREA, s, count, &desc))
139            return ret;
140
141        rc = xen_hvcall(XEN_MARK(__HYPERVISOR_console_io), CONSOLEIO_write,
142                        count, desc);
143        if (rc <= 0) {
144            return ret;
145        }
146        count -= rc;
147        s += rc;
148        ret += rc;
149    }
150    *actual = ret;
151    if (*actual == -1) {
152        return OF_FAILURE;
153    }
154    return OF_SUCCESS;
155}
156
157static s32 ofh_xen_domu_read(s32 chan, void *buf, u32 count, s32 *actual,
158                             ulong b)
159{
160    struct xencons_interface *intf;
161    XENCONS_RING_IDX cons, prod;
162    s32 ret;
163
164    intf = DRELA(ofh_ihp, b)->ofi_intf;
165    cons = intf->in_cons;
166    prod = intf->in_prod;
167    mb();
168
169    ret = prod - cons;
170
171    if (ret > 0) {
172        ret = (ret < count) ? ret : count;
173        memcpy(buf, intf->in+MASK_XENCONS_IDX(cons,intf->in), ret);
174    }
175
176    *actual = (ret < 0) ? 0 : ret;
177    return OF_SUCCESS;
178}
179
180static s32 ofh_xen_domu_write(s32 chan, const void *buf, u32 count,
181                              s32 *actual, ulong b)
182{
183    struct xencons_interface *intf;
184    XENCONS_RING_IDX cons, prod;
185    s32 ret;
186
187    intf = DRELA(ofh_ihp, b)->ofi_intf;
188    cons = intf->in_cons;
189    prod = intf->in_prod;
190    mb();
191
192    ret = prod - cons;
193    /* FIXME: Do we have to write the whole thing or are partial writes ok? */
194    if (ret > 0) {
195        ret = (ret < count) ? ret : count;
196        memcpy(intf->in+MASK_XENCONS_IDX(cons,intf->in), buf, ret);
197    }
198
199    *actual = (ret < 0) ? 0 : ret;
200    return OF_SUCCESS;
201}
202
203/* for emergency printing in the OFH */
204s32 ofh_cons_write(const void *buf, u32 count, s32 *actual)
205{
206    ulong b = get_base();
207    struct ofh_ihandle *ihp = DRELA(ofh_ihp, b);
208
209    return ihp->ofi_write(ihp->ofi_chan, buf, count, actual, b);
210}
211
212s32 ofh_cons_close(void)
213{
214    return OF_SUCCESS;
215}
216
217void
218ofh_cons_init(struct ofh_ihandle *ihp, ulong b)
219{
220    if (ihp->ofi_chan == OFH_CONS_XEN) {
221        if (ihp->ofi_intf == NULL) {
222            ihp->ofi_write = ofh_xen_dom0_write;
223            ihp->ofi_read = ofh_xen_dom0_read;
224        } else {
225            ihp->ofi_write = ofh_xen_domu_write;
226            ihp->ofi_read = ofh_xen_domu_read;
227        }
228    } else {
229        ihp->ofi_write = ofh_papr_write;
230        ihp->ofi_read = ofh_papr_read;
231    }
232    *DRELA(&ofh_ihp, b) = ihp;
233}
Note: See TracBrowser for help on using the repository browser.