Subversion Repositories HelenOS

Rev

Rev 3549 | Rev 3618 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3549 Rev 3582
1
/*
1
/*
2
 * Copyright (c) 2006 Ondrej Palkovsky
2
 * Copyright (c) 2006 Ondrej Palkovsky
3
 * Copyright (c) 2008 Martin Decky
3
 * Copyright (c) 2008 Martin Decky
4
 * Copyright (c) 2008 Pavel Rimsky
4
 * Copyright (c) 2008 Pavel Rimsky
5
 * All rights reserved.
5
 * All rights reserved.
6
 *
6
 *
7
 * Redistribution and use in source and binary forms, with or without
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
8
 * modification, are permitted provided that the following conditions
9
 * are met:
9
 * are met:
10
 *
10
 *
11
 * - Redistributions of source code must retain the above copyright
11
 * - Redistributions of source code must retain the above copyright
12
 *   notice, this list of conditions and the following disclaimer.
12
 *   notice, this list of conditions and the following disclaimer.
13
 * - Redistributions in binary form must reproduce the above copyright
13
 * - Redistributions in binary form must reproduce the above copyright
14
 *   notice, this list of conditions and the following disclaimer in the
14
 *   notice, this list of conditions and the following disclaimer in the
15
 *   documentation and/or other materials provided with the distribution.
15
 *   documentation and/or other materials provided with the distribution.
16
 * - The name of the author may not be used to endorse or promote products
16
 * - The name of the author may not be used to endorse or promote products
17
 *   derived from this software without specific prior written permission.
17
 *   derived from this software without specific prior written permission.
18
 *
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
 */
29
 */
30
 
30
 
31
/** @defgroup sgcnfb SGCN
31
/** @defgroup sgcnfb SGCN
32
 * @brief   userland driver of the Serengeti console output
32
 * @brief   userland driver of the Serengeti console output
33
 * @{
33
 * @{
34
 */
34
 */
35
/** @file
35
/** @file
36
 */
36
 */
37
 
37
 
38
#include <async.h>
38
#include <async.h>
39
#include <ipc/ipc.h>
39
#include <ipc/ipc.h>
40
#include <ipc/fb.h>
40
#include <ipc/fb.h>
41
#include <sysinfo.h>
41
#include <sysinfo.h>
42
#include <as.h>
42
#include <as.h>
43
#include <errno.h>
43
#include <errno.h>
44
#include <stdio.h>
44
#include <stdio.h>
45
#include <ddi.h>
45
#include <ddi.h>
46
 
46
 
-
 
47
#include "serial_console.h"
47
#include "sgcn.h"
48
#include "sgcn.h"
48
 
49
 
49
#define WIDTH 80
50
#define WIDTH 80
50
#define HEIGHT 24
51
#define HEIGHT 24
51
 
52
 
52
#define MAX_CONTROL 20
-
 
53
 
-
 
54
/**
53
/**
55
 * Virtual address mapped to SRAM.
54
 * Virtual address mapped to SRAM.
56
 */
55
 */
57
static uintptr_t sram_virt_addr;
56
static uintptr_t sram_virt_addr;
58
 
57
 
59
/**
58
/**
60
 * SGCN buffer offset within SGCN.
59
 * SGCN buffer offset within SGCN.
61
 */
60
 */
62
static uintptr_t sram_buffer_offset;
61
static uintptr_t sram_buffer_offset;
63
 
62
 
64
/* Allow only 1 connection */
63
/* Allow only 1 connection */
65
static int client_connected = 0;
64
static int client_connected = 0;
66
 
65
 
67
/**
66
/**
68
 * SGCN buffer header. It is placed at the very beginning of the SGCN
67
 * SGCN buffer header. It is placed at the very beginning of the SGCN
69
 * buffer.
68
 * buffer.
70
 */
69
 */
71
typedef struct {
70
typedef struct {
72
    /** hard-wired to "CON" */
71
    /** hard-wired to "CON" */
73
    char magic[4];
72
    char magic[4];
74
   
73
   
75
    /** we don't need this */
74
    /** we don't need this */
76
    char unused[8];
75
    char unused[24];
77
   
-
 
78
    /** offset within the SGCN buffer of the input buffer start */
-
 
79
    uint32_t in_begin;
-
 
80
   
-
 
81
    /** offset within the SGCN buffer of the input buffer end */
-
 
82
    uint32_t in_end;
-
 
83
   
-
 
84
    /** offset within the SGCN buffer of the input buffer read pointer */
-
 
85
    uint32_t in_rdptr;
-
 
86
   
-
 
87
    /** offset within the SGCN buffer of the input buffer write pointer */
-
 
88
    uint32_t in_wrptr;
-
 
89
 
76
 
90
    /** offset within the SGCN buffer of the output buffer start */
77
    /** offset within the SGCN buffer of the output buffer start */
91
    uint32_t out_begin;
78
    uint32_t out_begin;
92
   
79
   
93
    /** offset within the SGCN buffer of the output buffer end */
80
    /** offset within the SGCN buffer of the output buffer end */
94
    uint32_t out_end;
81
    uint32_t out_end;
95
   
82
   
96
    /** offset within the SGCN buffer of the output buffer read pointer */
83
    /** offset within the SGCN buffer of the output buffer read pointer */
97
    uint32_t out_rdptr;
84
    uint32_t out_rdptr;
98
   
85
   
99
    /** offset within the SGCN buffer of the output buffer write pointer */
86
    /** offset within the SGCN buffer of the output buffer write pointer */
100
    uint32_t out_wrptr;
87
    uint32_t out_wrptr;
101
} __attribute__ ((packed)) sgcn_buffer_header_t;
88
} __attribute__ ((packed)) sgcn_buffer_header_t;
102
 
89
 
103
// TODO it is suggested to extract the common parts of this file and the msim.c file
-
 
104
// into a separate file and place that file to the genarch directory
-
 
105
 
90
 
106
/*
91
/*
107
 * Returns a pointer to the object of a given type which is placed at the given
92
 * Returns a pointer to the object of a given type which is placed at the given
108
 * offset from the console buffer beginning.
93
 * offset from the console buffer beginning.
109
 */
94
 */
110
#define SGCN_BUFFER(type, offset) \
95
#define SGCN_BUFFER(type, offset) \
111
        ((type *) (sram_virt_addr + sram_buffer_offset + (offset)))
96
        ((type *) (sram_virt_addr + sram_buffer_offset + (offset)))
112
 
97
 
113
/** Returns a pointer to the console buffer header. */
98
/** Returns a pointer to the console buffer header. */
114
#define SGCN_BUFFER_HEADER  (SGCN_BUFFER(sgcn_buffer_header_t, 0))
99
#define SGCN_BUFFER_HEADER  (SGCN_BUFFER(sgcn_buffer_header_t, 0))
115
 
100
 
116
static void sgcn_putc(char c)
101
static void sgcn_putc(char c)
117
{
102
{
118
    uint32_t begin = SGCN_BUFFER_HEADER->out_begin;
103
    uint32_t begin = SGCN_BUFFER_HEADER->out_begin;
119
    uint32_t end = SGCN_BUFFER_HEADER->out_end;
104
    uint32_t end = SGCN_BUFFER_HEADER->out_end;
120
    uint32_t size = end - begin;
105
    uint32_t size = end - begin;
121
   
106
   
122
    /* we need pointers to volatile variables */
107
    /* we need pointers to volatile variables */
123
    volatile char *buf_ptr = (volatile char *)
108
    volatile char *buf_ptr = (volatile char *)
124
        SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr);
109
        SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr);
125
    volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr);
110
    volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr);
126
    volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr);
111
    volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr);
127
 
112
 
128
    uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin;
113
    uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin;
129
    while (*out_rdptr_ptr == new_wrptr)
114
    while (*out_rdptr_ptr == new_wrptr)
130
        ;
115
        ;
131
    *buf_ptr = c;
116
    *buf_ptr = c;
132
    *out_wrptr_ptr = new_wrptr;
117
    *out_wrptr_ptr = new_wrptr;
133
}
118
}
134
 
119
 
135
static void sgcn_puts(char *str)
-
 
136
{
-
 
137
    while (*str)
-
 
138
        sgcn_putc(*(str++));
-
 
139
}
-
 
140
 
-
 
141
static void sgcn_goto(const unsigned int row, const unsigned int col)
-
 
142
{
-
 
143
    if ((row > HEIGHT) || (col > WIDTH))
-
 
144
        return;
-
 
145
   
-
 
146
    char control[20];
-
 
147
    snprintf(control, 20, "\033[%u;%uf", row + 1, col + 1);
-
 
148
    sgcn_puts(control);
-
 
149
}
-
 
150
 
-
 
151
static void sgcn_clrscr(void)
-
 
152
{
-
 
153
    sgcn_puts("\033[2J");
-
 
154
}
-
 
155
 
-
 
156
static void sgcn_scroll(int i)
-
 
157
{
-
 
158
    if (i > 0) {
-
 
159
        sgcn_goto(HEIGHT - 1, 0);
-
 
160
        while (i--)
-
 
161
            sgcn_puts("\033D");
-
 
162
    } else if (i < 0) {
-
 
163
        sgcn_goto(0, 0);
-
 
164
        while (i++)
-
 
165
            sgcn_puts("\033M");
-
 
166
    }
-
 
167
}
-
 
168
 
-
 
169
static void sgcn_set_style(const unsigned int mode)
-
 
170
{
-
 
171
    char control[MAX_CONTROL];
-
 
172
    snprintf(control, MAX_CONTROL, "\033[%um", mode);
-
 
173
    sgcn_puts(control);
-
 
174
}
-
 
175
 
-
 
176
static void sgcn_cursor_disable(void)
-
 
177
{
-
 
178
    sgcn_puts("\033[?25l");
-
 
179
}
-
 
180
 
-
 
181
static void sgcn_cursor_enable(void)
-
 
182
{
-
 
183
    sgcn_puts("\033[?25h");
-
 
184
}
-
 
185
 
-
 
186
static void sgcn_client_connection(ipc_callid_t iid, ipc_call_t *icall)
120
static void sgcn_client_connection(ipc_callid_t iid, ipc_call_t *icall)
187
{
121
{
188
    int retval;
122
    int retval;
189
    ipc_callid_t callid;
123
    ipc_callid_t callid;
190
    ipc_call_t call;
124
    ipc_call_t call;
191
    char c;
125
    char c;
192
    int lastcol = 0;
126
    int lastcol = 0;
193
    int lastrow = 0;
127
    int lastrow = 0;
194
    int newcol;
128
    int newcol;
195
    int newrow;
129
    int newrow;
196
    int fgcolor;
130
    int fgcolor;
197
    int bgcolor;
131
    int bgcolor;
198
    int i;
132
    int i;
199
   
133
   
200
    if (client_connected) {
134
    if (client_connected) {
201
        ipc_answer_0(iid, ELIMIT);
135
        ipc_answer_0(iid, ELIMIT);
202
        return;
136
        return;
203
    }
137
    }
204
   
138
   
205
    client_connected = 1;
139
    client_connected = 1;
206
    ipc_answer_0(iid, EOK);
140
    ipc_answer_0(iid, EOK);
207
   
141
   
208
    /* Clear the terminal, set scrolling region
142
    /* Clear the terminal, set scrolling region
209
       to 0 - 24 lines */
143
       to 0 - 24 lines */
210
    sgcn_clrscr();
144
    serial_clrscr();
211
    sgcn_goto(0, 0);
145
    serial_goto(0, 0);
212
    sgcn_puts("\033[0;24r");
146
    serial_puts("\033[0;24r");
213
   
147
   
214
    while (true) {
148
    while (true) {
215
        callid = async_get_call(&call);
149
        callid = async_get_call(&call);
216
        switch (IPC_GET_METHOD(call)) {
150
        switch (IPC_GET_METHOD(call)) {
217
        case IPC_M_PHONE_HUNGUP:
151
        case IPC_M_PHONE_HUNGUP:
218
            client_connected = 0;
152
            client_connected = 0;
219
            ipc_answer_0(callid, EOK);
153
            ipc_answer_0(callid, EOK);
220
            return;
154
            return;
221
        case FB_PUTCHAR:
155
        case FB_PUTCHAR:
222
            c = IPC_GET_ARG1(call);
156
            c = IPC_GET_ARG1(call);
223
            newrow = IPC_GET_ARG2(call);
157
            newrow = IPC_GET_ARG2(call);
224
            newcol = IPC_GET_ARG3(call);
158
            newcol = IPC_GET_ARG3(call);
225
            if ((lastcol != newcol) || (lastrow != newrow))
159
            if ((lastcol != newcol) || (lastrow != newrow))
226
                sgcn_goto(newrow, newcol);
160
                serial_goto(newrow, newcol);
227
            lastcol = newcol + 1;
161
            lastcol = newcol + 1;
228
            lastrow = newrow;
162
            lastrow = newrow;
229
            sgcn_putc(c);
163
            sgcn_putc(c);
230
            retval = 0;
164
            retval = 0;
231
            break;
165
            break;
232
        case FB_CURSOR_GOTO:
166
        case FB_CURSOR_GOTO:
233
            newrow = IPC_GET_ARG1(call);
167
            newrow = IPC_GET_ARG1(call);
234
            newcol = IPC_GET_ARG2(call);
168
            newcol = IPC_GET_ARG2(call);
235
            sgcn_goto(newrow, newcol);
169
            serial_goto(newrow, newcol);
236
            lastrow = newrow;
170
            lastrow = newrow;
237
            lastcol = newcol;
171
            lastcol = newcol;
238
            retval = 0;
172
            retval = 0;
239
            break;
173
            break;
240
        case FB_GET_CSIZE:
174
        case FB_GET_CSIZE:
241
            ipc_answer_2(callid, EOK, HEIGHT, WIDTH);
175
            ipc_answer_2(callid, EOK, HEIGHT, WIDTH);
242
            continue;
176
            continue;
243
        case FB_CLEAR:
177
        case FB_CLEAR:
244
            sgcn_clrscr();
178
            serial_clrscr();
245
            retval = 0;
179
            retval = 0;
246
            break;
180
            break;
247
        case FB_SET_STYLE:
181
        case FB_SET_STYLE:
248
            fgcolor = IPC_GET_ARG1(call);
182
            fgcolor = IPC_GET_ARG1(call);
249
            bgcolor = IPC_GET_ARG2(call);
183
            bgcolor = IPC_GET_ARG2(call);
250
            if (fgcolor < bgcolor)
184
            if (fgcolor < bgcolor)
251
                sgcn_set_style(0);
185
                serial_set_style(0);
252
            else
186
            else
253
                sgcn_set_style(7);
187
                serial_set_style(7);
254
            retval = 0;
188
            retval = 0;
255
            break;
189
            break;
256
        case FB_SCROLL:
190
        case FB_SCROLL:
257
            i = IPC_GET_ARG1(call);
191
            i = IPC_GET_ARG1(call);
258
            if ((i > HEIGHT) || (i < -HEIGHT)) {
192
            if ((i > HEIGHT) || (i < -HEIGHT)) {
259
                retval = EINVAL;
193
                retval = EINVAL;
260
                break;
194
                break;
261
            }
195
            }
262
            sgcn_scroll(i);
196
            serial_scroll(i);
263
            sgcn_goto(lastrow, lastcol);
197
            serial_goto(lastrow, lastcol);
264
            retval = 0;
198
            retval = 0;
265
            break;
199
            break;
266
        case FB_CURSOR_VISIBILITY:
200
        case FB_CURSOR_VISIBILITY:
267
            if(IPC_GET_ARG1(call))
201
            if(IPC_GET_ARG1(call))
268
                sgcn_cursor_enable();
202
                serial_cursor_enable();
269
            else
203
            else
270
                sgcn_cursor_disable();
204
                serial_cursor_disable();
271
            retval = 0;
205
            retval = 0;
272
            break;
206
            break;
273
        default:
207
        default:
274
            retval = ENOENT;
208
            retval = ENOENT;
275
        }
209
        }
276
        ipc_answer_0(callid, retval);
210
        ipc_answer_0(callid, retval);
277
    }
211
    }
278
}
212
}
279
 
213
 
280
int sgcn_init(void)
214
int sgcn_init(void)
281
{
215
{
282
    sram_virt_addr = (uintptr_t) as_get_mappable_page(sysinfo_value("sram.area.size"));
216
    sram_virt_addr = (uintptr_t) as_get_mappable_page(sysinfo_value("sram.area.size"));
283
    int result = physmem_map(
217
    int result = physmem_map(
284
        (void *) sysinfo_value("sram.address.physical"),
218
        (void *) sysinfo_value("sram.address.physical"),
285
        (void *) sram_virt_addr,
219
        (void *) sram_virt_addr,
286
        sysinfo_value("sram.area.size") / PAGE_SIZE,
220
        sysinfo_value("sram.area.size") / PAGE_SIZE,
287
        AS_AREA_READ | AS_AREA_WRITE
221
        AS_AREA_READ | AS_AREA_WRITE
288
        );
222
        );
289
    if (result != 0) {
223
    if (result != 0) {
290
        printf("SGCN: uspace driver couldn't map physical memory: %d\n",
224
        printf("SGCN: uspace driver couldn't map physical memory: %d\n",
291
            result);
225
            result);
292
    }
226
    }
293
   
227
   
-
 
228
    serial_console_init(sgcn_putc, WIDTH, HEIGHT);
-
 
229
   
294
    sram_buffer_offset = sysinfo_value("sram.buffer.offset");
230
    sram_buffer_offset = sysinfo_value("sram.buffer.offset");
295
   
231
   
296
    async_set_client_connection(sgcn_client_connection);
232
    async_set_client_connection(sgcn_client_connection);
297
    return 0;
233
    return 0;
298
}
234
}
299
 
235
 
300
/**
236
/**
301
 * @}
237
 * @}
302
 */
238
 */
303
 
239