Subversion Repositories HelenOS

Rev

Rev 3863 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3863 Rev 4073
Line 35... Line 35...
35
 */
35
 */
36
 
36
 
37
#include <arch/drivers/niagara.h>
37
#include <arch/drivers/niagara.h>
38
#include <console/chardev.h>
38
#include <console/chardev.h>
39
#include <console/console.h>
39
#include <console/console.h>
-
 
40
#include <ddi/ddi.h>
-
 
41
#include <ddi/device.h>
-
 
42
#include <arch/asm.h>
40
#include <arch/drivers/kbd.h>
43
#include <arch/drivers/kbd.h>
41
#include <arch/sun4v/hypercall.h>
44
#include <arch/sun4v/hypercall.h>
-
 
45
#include <sysinfo/sysinfo.h>
-
 
46
#include <ipc/irq.h>
-
 
47
 
-
 
48
/**
-
 
49
 * The driver is polling based, but in order to notify the userspace
-
 
50
 * of a key being pressed, we need to supply the interface with some
-
 
51
 * interrupt number. The interrupt number can be arbitrary as it it
-
 
52
 * will never be used for identifying HW interrupts, but only in
-
 
53
 * notifying the userspace.
-
 
54
 */
-
 
55
#define FICTIONAL_INR       1
42
 
56
 
43
/* functions referenced from definitions of I/O operations structures */
57
/* functions referenced from definitions of I/O operations structures */
44
static void niagara_putchar(chardev_t *, const char);
58
static void niagara_putchar(chardev_t *, const char);
45
static void niagara_noop(chardev_t *);
59
static void niagara_noop(chardev_t *);
46
static char niagara_read(chardev_t *);
60
static char niagara_read(chardev_t *);
Line 51... Line 65...
51
    .suspend = niagara_noop,
65
    .suspend = niagara_noop,
52
    .resume = niagara_noop,
66
    .resume = niagara_noop,
53
    .read = niagara_read
67
    .read = niagara_read
54
};
68
};
55
 
69
 
-
 
70
/*
-
 
71
 * The driver uses hypercalls to print characters to the console. Since the
-
 
72
 * hypercall cannot be performed from the userspace, we do this:
-
 
73
 * The kernel "little brother" driver (which will be present no matter what the
-
 
74
 * DDI architecture is - as we need the kernel part for the kconsole)
-
 
75
 * defines a shared buffer. Kernel walks through the buffer (in the same thread
-
 
76
 * which is used for polling the keyboard) and prints any pending characters
-
 
77
 * to the console (using hypercalls). The userspace fb server maps this shared
-
 
78
 * buffer to its address space and output operation it does is performed using
-
 
79
 * the mapped buffer. The shared buffer definition follows.
-
 
80
 */
-
 
81
#define OUTPUT_BUFFER_SIZE  ((PAGE_SIZE) - 2 * 8)
-
 
82
static volatile struct {
-
 
83
    uint64_t read_ptr;
-
 
84
    uint64_t write_ptr;
-
 
85
    char data[OUTPUT_BUFFER_SIZE];
-
 
86
}
-
 
87
    __attribute__ ((packed))
-
 
88
    __attribute__ ((aligned(PAGE_SIZE)))
-
 
89
    output_buffer;
-
 
90
 
56
/** Niagara character device */
91
/** Niagara character device */
57
chardev_t niagara_io;
92
chardev_t niagara_io;
58
 
93
 
-
 
94
/**
-
 
95
 * Niagara IRQ structure. So far used only for notifying the userspace of the
-
 
96
 * key being pressed, not for kernel being informed about keyboard interrupts.
-
 
97
 */
-
 
98
static irq_t niagara_irq;
-
 
99
 
59
/** defined in drivers/kbd.c */
100
/** defined in drivers/kbd.c */
60
extern kbd_type_t kbd_type;
101
extern kbd_type_t kbd_type;
61
 
102
 
-
 
103
/**
-
 
104
 * The character read will be stored here until the (notified) uspace
-
 
105
 * driver picks it up.
-
 
106
 */
-
 
107
static char read_char;
-
 
108
 
-
 
109
/**
-
 
110
 * The driver works in polled mode, so no interrupt should be handled by it.
-
 
111
 */
-
 
112
static irq_ownership_t niagara_claim(void)
-
 
113
{
-
 
114
    return IRQ_DECLINE;
-
 
115
}
-
 
116
 
-
 
117
/**
-
 
118
 * The driver works in polled mode, so no interrupt should be handled by it.
-
 
119
 */
-
 
120
static void niagara_irq_handler(irq_t *irq, void *arg, ...)
-
 
121
{
-
 
122
    panic("Not yet implemented, SGCN works in polled mode.\n");
-
 
123
}
-
 
124
 
62
/** Writes a single character to the standard output. */
125
/** Writes a single character to the standard output. */
63
static inline void do_putchar(const char c) {
126
static inline void do_putchar(const char c) {
64
    /* repeat until the buffer is non-full */
127
    /* repeat until the buffer is non-full */
65
    while (__hypercall_fast1(CONS_PUTCHAR, c) == EWOULDBLOCK)
128
    while (__hypercall_fast1(CONS_PUTCHAR, c) == EWOULDBLOCK)
66
        ;
129
        ;
Line 77... Line 140...
77
/**
140
/**
78
 * Grabs the input for kernel.
141
 * Grabs the input for kernel.
79
 */
142
 */
80
void niagara_grab(void)
143
void niagara_grab(void)
81
{
144
{
-
 
145
    ipl_t ipl = interrupts_disable();
-
 
146
    spinlock_lock(&niagara_irq.lock);
-
 
147
    niagara_irq.notif_cfg.notify = false;
-
 
148
    spinlock_unlock(&niagara_irq.lock);
-
 
149
    interrupts_restore(ipl);
82
}
150
}
83
 
151
 
84
/**
152
/**
85
 * Releases the input so that userspace can use it.
153
 * Releases the input so that userspace can use it.
86
 */
154
 */
87
void niagara_release(void)
155
void niagara_release(void)
88
{
156
{
-
 
157
    ipl_t ipl = interrupts_disable();
-
 
158
    spinlock_lock(&niagara_irq.lock);
-
 
159
    if (niagara_irq.notif_cfg.answerbox)
-
 
160
        niagara_irq.notif_cfg.notify = true;
-
 
161
    spinlock_unlock(&niagara_irq.lock);
-
 
162
    interrupts_restore(ipl);
89
}
163
}
90
 
164
 
91
/**
165
/**
92
 * Default suspend/resume operation for the input device.
166
 * Default suspend/resume operation for the input device.
93
 */
167
 */
94
static void niagara_noop(chardev_t *d)
168
static void niagara_noop(chardev_t *d)
95
{
169
{
96
}
170
}
97
 
171
 
98
/**
172
/**
99
 * Called when actively reading the character. Not implemented yet.
173
 * Called when actively reading the character.
100
 */
174
 */
101
static char niagara_read(chardev_t *d)
175
static char niagara_read(chardev_t *d)
102
{
176
{
-
 
177
    uint64_t c;
-
 
178
 
-
 
179
    if (__hypercall_fast_ret1(0, 0, 0, 0, 0, CONS_GETCHAR, &c) == EOK) {
103
    return (char) 0;
180
        return (char) c;
-
 
181
    }
-
 
182
 
-
 
183
    return '\0';
-
 
184
}
-
 
185
 
-
 
186
/**
-
 
187
 * Returns the character last read. This function is called from the
-
 
188
 * pseudocode - the character returned by this function is passed to
-
 
189
 * the userspace keyboard driver.
-
 
190
 */
-
 
191
char niagara_getc(void) {
-
 
192
    return read_char;
104
}
193
}
105
 
194
 
106
/**
195
/**
107
 * Function regularly called by the keyboard polling thread. Asks the
196
 * Function regularly called by the keyboard polling thread. Asks the
108
 * hypervisor whether there is any unread character. If so, it picks it up
197
 * hypervisor whether there is any unread character. If so, it picks it up
109
 * and sends it to the upper layers of HelenOS.
198
 * and sends it to the upper layers of HelenOS.
110
 */
199
 */
111
void niagara_poll(void)
200
void niagara_poll(void)
112
{
201
{
-
 
202
    while (output_buffer.read_ptr != output_buffer.write_ptr) {
-
 
203
        do_putchar(output_buffer.data[output_buffer.read_ptr]);
-
 
204
        output_buffer.read_ptr =
-
 
205
            ((output_buffer.read_ptr) + 1) % OUTPUT_BUFFER_SIZE;
-
 
206
    }
-
 
207
 
113
    uint64_t c = 50;
208
    uint64_t c;
114
 
209
 
115
    if (__hypercall_fast_ret1(0, 0, 0, 0, 0, CONS_GETCHAR, &c) == EOK) {
210
    if (__hypercall_fast_ret1(0, 0, 0, 0, 0, CONS_GETCHAR, &c) == EOK) {
-
 
211
        ipl_t ipl = interrupts_disable();
-
 
212
        spinlock_lock(&niagara_irq.lock);
-
 
213
 
-
 
214
        if (niagara_irq.notif_cfg.notify &&
-
 
215
                niagara_irq.notif_cfg.answerbox) {
-
 
216
            /*
-
 
217
             * remember the character, uspace will pick it
-
 
218
             * up using pseudocode
-
 
219
             */
-
 
220
            read_char = (char) c;
-
 
221
            ipc_irq_send_notif(&niagara_irq);
-
 
222
            spinlock_unlock(&niagara_irq.lock);
-
 
223
            interrupts_restore(ipl);
-
 
224
            return;
-
 
225
        } else {
-
 
226
            spinlock_unlock(&niagara_irq.lock);
-
 
227
            interrupts_restore(ipl);   
-
 
228
 
116
        chardev_push_character(&niagara_io, c);
229
            chardev_push_character(&niagara_io, c);
117
        if (c == '\r')
230
            if (c == '\r')
118
            chardev_push_character(&niagara_io, '\n');
231
                chardev_push_character(&niagara_io, '\n');
-
 
232
        }
119
    }
233
    }
120
 
234
 
121
}
235
}
122
 
236
 
123
/**
237
/**
Line 126... Line 240...
126
 */
240
 */
127
void niagara_init(void)
241
void niagara_init(void)
128
{
242
{
129
    kbd_type = KBD_SUN4V;
243
    kbd_type = KBD_SUN4V;
130
 
244
 
-
 
245
    devno_t devno = device_assign_devno();
-
 
246
    irq_initialize(&niagara_irq);
-
 
247
    niagara_irq.devno = devno;
-
 
248
    niagara_irq.inr = FICTIONAL_INR;
-
 
249
    niagara_irq.claim = niagara_claim;
-
 
250
    niagara_irq.handler = niagara_irq_handler;
-
 
251
    irq_register(&niagara_irq);
-
 
252
   
-
 
253
    sysinfo_set_item_val("kbd", NULL, true);
-
 
254
    sysinfo_set_item_val("kbd.type", NULL, KBD_SUN4V);
-
 
255
    sysinfo_set_item_val("kbd.devno", NULL, devno);
-
 
256
    sysinfo_set_item_val("kbd.inr", NULL, FICTIONAL_INR);
-
 
257
    sysinfo_set_item_val("fb.kind", NULL, 5);
-
 
258
 
-
 
259
    /*
-
 
260
     * Set sysinfos and pareas so that the userspace counterpart of the
-
 
261
     * niagara fb driver can communicate with kernel using a shared buffer.
-
 
262
     */
-
 
263
    output_buffer.read_ptr = 0;
-
 
264
    output_buffer.write_ptr = 0;
-
 
265
    sysinfo_set_item_val("niagara.outbuf.address", NULL,
-
 
266
        KA2PA(&output_buffer));
-
 
267
    sysinfo_set_item_val("niagara.outbuf.size", NULL,
-
 
268
        PAGE_SIZE);
-
 
269
    sysinfo_set_item_val("niagara.outbuf.datasize", NULL,
-
 
270
        OUTPUT_BUFFER_SIZE);
-
 
271
    static parea_t outbuf_parea;
-
 
272
    outbuf_parea.pbase = (uintptr_t) (KA2PA(&output_buffer));
-
 
273
    outbuf_parea.vbase = (uintptr_t) (&output_buffer);
-
 
274
    outbuf_parea.frames = 1;
-
 
275
    outbuf_parea.cacheable = false;
-
 
276
    ddi_parea_register(&outbuf_parea);
-
 
277
 
131
    chardev_initialize("niagara_io", &niagara_io, &niagara_ops);
278
    chardev_initialize("niagara_io", &niagara_io, &niagara_ops);
132
    stdin = &niagara_io;
279
    stdin = &niagara_io;
133
    stdout = &niagara_io;
280
    stdout = &niagara_io;
134
}
281
}
135
 
282