Subversion Repositories HelenOS

Rev

Rev 3618 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3618 Rev 3742
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>
-
 
40
#include <ipc/fb.h>
-
 
41
#include <sysinfo.h>
39
#include <sysinfo.h>
42
#include <as.h>
40
#include <as.h>
43
#include <errno.h>
41
#include <errno.h>
44
#include <stdio.h>
42
#include <stdio.h>
45
#include <ddi.h>
43
#include <ddi.h>
46
 
44
 
47
#include "serial_console.h"
45
#include "serial_console.h"
48
#include "sgcn.h"
46
#include "sgcn.h"
49
 
47
 
50
#define WIDTH 80
48
#define WIDTH 80
51
#define HEIGHT 24
49
#define HEIGHT 24
52
 
50
 
53
/**
51
/**
54
 * Virtual address mapped to SRAM.
52
 * Virtual address mapped to SRAM.
55
 */
53
 */
56
static uintptr_t sram_virt_addr;
54
static uintptr_t sram_virt_addr;
57
 
55
 
58
/**
56
/**
59
 * SGCN buffer offset within SGCN.
57
 * SGCN buffer offset within SGCN.
60
 */
58
 */
61
static uintptr_t sram_buffer_offset;
59
static uintptr_t sram_buffer_offset;
62
 
60
 
63
/* Allow only 1 connection */
-
 
64
static int client_connected = 0;
-
 
65
 
-
 
66
/**
61
/**
67
 * SGCN buffer header. It is placed at the very beginning of the SGCN
62
 * SGCN buffer header. It is placed at the very beginning of the SGCN
68
 * buffer.
63
 * buffer.
69
 */
64
 */
70
typedef struct {
65
typedef struct {
71
    /** hard-wired to "CON" */
66
    /** hard-wired to "CON" */
72
    char magic[4];
67
    char magic[4];
73
   
68
   
74
    /** we don't need this */
69
    /** we don't need this */
75
    char unused[24];
70
    char unused[24];
76
 
71
 
77
    /** offset within the SGCN buffer of the output buffer start */
72
    /** offset within the SGCN buffer of the output buffer start */
78
    uint32_t out_begin;
73
    uint32_t out_begin;
79
   
74
   
80
    /** offset within the SGCN buffer of the output buffer end */
75
    /** offset within the SGCN buffer of the output buffer end */
81
    uint32_t out_end;
76
    uint32_t out_end;
82
   
77
   
83
    /** offset within the SGCN buffer of the output buffer read pointer */
78
    /** offset within the SGCN buffer of the output buffer read pointer */
84
    uint32_t out_rdptr;
79
    uint32_t out_rdptr;
85
   
80
   
86
    /** offset within the SGCN buffer of the output buffer write pointer */
81
    /** offset within the SGCN buffer of the output buffer write pointer */
87
    uint32_t out_wrptr;
82
    uint32_t out_wrptr;
88
} __attribute__ ((packed)) sgcn_buffer_header_t;
83
} __attribute__ ((packed)) sgcn_buffer_header_t;
89
 
84
 
90
 
85
 
91
/*
86
/*
92
 * Returns a pointer to the object of a given type which is placed at the given
87
 * Returns a pointer to the object of a given type which is placed at the given
93
 * offset from the console buffer beginning.
88
 * offset from the console buffer beginning.
94
 */
89
 */
95
#define SGCN_BUFFER(type, offset) \
90
#define SGCN_BUFFER(type, offset) \
96
        ((type *) (sram_virt_addr + sram_buffer_offset + (offset)))
91
        ((type *) (sram_virt_addr + sram_buffer_offset + (offset)))
97
 
92
 
98
/** Returns a pointer to the console buffer header. */
93
/** Returns a pointer to the console buffer header. */
99
#define SGCN_BUFFER_HEADER  (SGCN_BUFFER(sgcn_buffer_header_t, 0))
94
#define SGCN_BUFFER_HEADER  (SGCN_BUFFER(sgcn_buffer_header_t, 0))
100
 
95
 
101
/**
96
/**
102
 * Pushes the character to the SGCN serial.
97
 * Pushes the character to the SGCN serial.
103
 * @param c character to be pushed
98
 * @param c character to be pushed
104
 */
99
 */
105
static void sgcn_putc(char c)
100
static void sgcn_putc(char c)
106
{
101
{
107
    uint32_t begin = SGCN_BUFFER_HEADER->out_begin;
102
    uint32_t begin = SGCN_BUFFER_HEADER->out_begin;
108
    uint32_t end = SGCN_BUFFER_HEADER->out_end;
103
    uint32_t end = SGCN_BUFFER_HEADER->out_end;
109
    uint32_t size = end - begin;
104
    uint32_t size = end - begin;
110
   
105
   
111
    /* we need pointers to volatile variables */
106
    /* we need pointers to volatile variables */
112
    volatile char *buf_ptr = (volatile char *)
107
    volatile char *buf_ptr = (volatile char *)
113
        SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr);
108
        SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr);
114
    volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr);
109
    volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr);
115
    volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr);
110
    volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr);
116
 
111
 
117
    uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin;
112
    uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin;
118
    while (*out_rdptr_ptr == new_wrptr)
113
    while (*out_rdptr_ptr == new_wrptr)
119
        ;
114
        ;
120
    *buf_ptr = c;
115
    *buf_ptr = c;
121
    *out_wrptr_ptr = new_wrptr;
116
    *out_wrptr_ptr = new_wrptr;
122
}
117
}
123
 
118
 
124
/**
119
/**
125
 * Main function of the thread serving client connections.
-
 
126
 */
-
 
127
static void sgcn_client_connection(ipc_callid_t iid, ipc_call_t *icall)
-
 
128
{
-
 
129
    int retval;
-
 
130
    ipc_callid_t callid;
-
 
131
    ipc_call_t call;
-
 
132
    char c;
-
 
133
    int lastcol = 0;
-
 
134
    int lastrow = 0;
-
 
135
    int newcol;
-
 
136
    int newrow;
-
 
137
    int fgcolor;
-
 
138
    int bgcolor;
-
 
139
    int i;
-
 
140
   
-
 
141
    if (client_connected) {
-
 
142
        ipc_answer_0(iid, ELIMIT);
-
 
143
        return;
-
 
144
    }
-
 
145
   
-
 
146
    client_connected = 1;
-
 
147
    ipc_answer_0(iid, EOK);
-
 
148
   
-
 
149
    /* Clear the terminal, set scrolling region
-
 
150
       to 0 - 24 lines */
-
 
151
    serial_clrscr();
-
 
152
    serial_goto(0, 0);
-
 
153
    serial_puts("\033[0;24r");
-
 
154
   
-
 
155
    while (true) {
-
 
156
        callid = async_get_call(&call);
-
 
157
        switch (IPC_GET_METHOD(call)) {
-
 
158
        case IPC_M_PHONE_HUNGUP:
-
 
159
            client_connected = 0;
-
 
160
            ipc_answer_0(callid, EOK);
-
 
161
            return;
-
 
162
        case FB_PUTCHAR:
-
 
163
            c = IPC_GET_ARG1(call);
-
 
164
            newrow = IPC_GET_ARG2(call);
-
 
165
            newcol = IPC_GET_ARG3(call);
-
 
166
            if ((lastcol != newcol) || (lastrow != newrow))
-
 
167
                serial_goto(newrow, newcol);
-
 
168
            lastcol = newcol + 1;
-
 
169
            lastrow = newrow;
-
 
170
            sgcn_putc(c);
-
 
171
            retval = 0;
-
 
172
            break;
-
 
173
        case FB_CURSOR_GOTO:
-
 
174
            newrow = IPC_GET_ARG1(call);
-
 
175
            newcol = IPC_GET_ARG2(call);
-
 
176
            serial_goto(newrow, newcol);
-
 
177
            lastrow = newrow;
-
 
178
            lastcol = newcol;
-
 
179
            retval = 0;
-
 
180
            break;
-
 
181
        case FB_GET_CSIZE:
-
 
182
            ipc_answer_2(callid, EOK, HEIGHT, WIDTH);
-
 
183
            continue;
-
 
184
        case FB_CLEAR:
-
 
185
            serial_clrscr();
-
 
186
            retval = 0;
-
 
187
            break;
-
 
188
        case FB_SET_STYLE:
-
 
189
            fgcolor = IPC_GET_ARG1(call);
-
 
190
            bgcolor = IPC_GET_ARG2(call);
-
 
191
            if (fgcolor < bgcolor)
-
 
192
                serial_set_style(0);
-
 
193
            else
-
 
194
                serial_set_style(7);
-
 
195
            retval = 0;
-
 
196
            break;
-
 
197
        case FB_SCROLL:
-
 
198
            i = IPC_GET_ARG1(call);
-
 
199
            if ((i > HEIGHT) || (i < -HEIGHT)) {
-
 
200
                retval = EINVAL;
-
 
201
                break;
-
 
202
            }
-
 
203
            serial_scroll(i);
-
 
204
            serial_goto(lastrow, lastcol);
-
 
205
            retval = 0;
-
 
206
            break;
-
 
207
        case FB_CURSOR_VISIBILITY:
-
 
208
            if(IPC_GET_ARG1(call))
-
 
209
                serial_cursor_enable();
-
 
210
            else
-
 
211
                serial_cursor_disable();
-
 
212
            retval = 0;
-
 
213
            break;
-
 
214
        default:
-
 
215
            retval = ENOENT;
-
 
216
        }
-
 
217
        ipc_answer_0(callid, retval);
-
 
218
    }
-
 
219
}
-
 
220
 
-
 
221
/**
-
 
222
 * Initializes the SGCN serial driver.
120
 * Initializes the SGCN serial driver.
223
 */
121
 */
224
int sgcn_init(void)
122
int sgcn_init(void)
225
{
123
{
226
    sram_virt_addr = (uintptr_t) as_get_mappable_page(
124
    sram_virt_addr = (uintptr_t) as_get_mappable_page(
227
        sysinfo_value("sram.area.size"));
125
        sysinfo_value("sram.area.size"));
228
    int result = physmem_map(
126
    int result = physmem_map(
229
        (void *) sysinfo_value("sram.address.physical"),
127
        (void *) sysinfo_value("sram.address.physical"),
230
        (void *) sram_virt_addr,
128
        (void *) sram_virt_addr,
231
        sysinfo_value("sram.area.size") / PAGE_SIZE,
129
        sysinfo_value("sram.area.size") / PAGE_SIZE,
232
        AS_AREA_READ | AS_AREA_WRITE
130
        AS_AREA_READ | AS_AREA_WRITE
233
        );
131
        );
234
    if (result != 0) {
132
    if (result != 0) {
235
        printf("SGCN: uspace driver couldn't map physical memory: %d\n",
133
        printf("SGCN: uspace driver couldn't map physical memory: %d\n",
236
            result);
134
            result);
237
    }
135
    }
238
   
136
   
239
    serial_console_init(sgcn_putc, WIDTH, HEIGHT);
137
    serial_console_init(sgcn_putc, WIDTH, HEIGHT);
240
   
138
   
241
    sram_buffer_offset = sysinfo_value("sram.buffer.offset");
139
    sram_buffer_offset = sysinfo_value("sram.buffer.offset");
242
   
140
   
243
    async_set_client_connection(sgcn_client_connection);
141
    async_set_client_connection(serial_client_connection);
244
    return 0;
142
    return 0;
245
}
143
}
246
 
144
 
247
/**
145
/**
248
 * @}
146
 * @}
249
 */
147
 */
250
 
148
 
251
 
149