/branches/dd/kernel/genarch/include/kbrd/kbrd.h |
---|
37,9 → 37,23 |
#define KERN_KBD_H_ |
#include <console/chardev.h> |
#include <proc/thread.h> |
#include <synch/spinlock.h> |
extern void kbrd_init(indev_t *devin); |
typedef struct { |
thread_t *thread; |
indev_t *sink; |
indev_t raw; |
SPINLOCK_DECLARE(keylock); /**< keylock protects keyflags and lockflags. */ |
volatile unsigned int keyflags; /**< Tracking of multiple keypresses. */ |
volatile unsigned int lockflags; /**< Tracking of multiple keys lockings. */ |
} kbrd_instance_t; |
extern kbrd_instance_t *kbrd_init(void); |
extern indev_t *kbrd_wire(kbrd_instance_t *, indev_t *); |
#endif |
/** @} |
/branches/dd/kernel/genarch/include/drivers/ns16550/ns16550.h |
---|
62,12 → 62,13 |
/** Structure representing the ns16550 device. */ |
typedef struct { |
irq_t irq; |
ns16550_t *ns16550; |
irq_t irq; |
indev_t kbrdin; |
indev_t *kbrdin; |
} ns16550_instance_t; |
extern indev_t *ns16550_init(ns16550_t *, inr_t, cir_t, void *); |
extern ns16550_instance_t *ns16550_init(ns16550_t *, inr_t, cir_t, void *); |
extern void ns16550_wire(ns16550_instance_t *, indev_t *); |
#endif |
/branches/dd/kernel/genarch/include/drivers/dsrln/dsrlnin.h |
---|
49,10 → 49,11 |
typedef struct { |
irq_t irq; |
dsrlnin_t *dsrlnin; |
indev_t kbrdin; |
indev_t *srlnin; |
} dsrlnin_instance_t; |
extern indev_t *dsrlnin_init(dsrlnin_t *, inr_t); |
extern dsrlnin_instance_t *dsrlnin_init(dsrlnin_t *, inr_t); |
extern void dsrlnin_wire(dsrlnin_instance_t *, indev_t *); |
#endif |
/branches/dd/kernel/genarch/include/drivers/i8042/i8042.h |
---|
49,10 → 49,11 |
typedef struct { |
irq_t irq; |
i8042_t *i8042; |
indev_t kbrdin; |
indev_t *kbrdin; |
} i8042_instance_t; |
extern indev_t *i8042_init(i8042_t *, inr_t); |
extern i8042_instance_t *i8042_init(i8042_t *, inr_t); |
extern void i8042_wire(i8042_instance_t *, indev_t *); |
extern void i8042_cpu_reset(i8042_t *); |
#endif |
/branches/dd/kernel/genarch/include/drivers/z8530/z8530.h |
---|
116,10 → 116,11 |
typedef struct { |
irq_t irq; |
z8530_t *z8530; |
indev_t kbrdin; |
indev_t *kbrdin; |
} z8530_instance_t; |
extern indev_t *z8530_init(z8530_t *, inr_t, cir_t, void *); |
extern z8530_instance_t *z8530_init(z8530_t *, inr_t, cir_t, void *); |
extern void z8530_wire(z8530_instance_t *, indev_t *); |
#endif |
/branches/dd/kernel/genarch/include/drivers/via-cuda/cuda.h |
---|
0,0 → 1,57 |
/* |
* Copyright (c) 2006 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_CUDA_H_ |
#define KERN_CUDA_H_ |
#include <ddi/irq.h> |
#include <arch/types.h> |
#include <console/chardev.h> |
typedef struct { |
} cuda_t; |
typedef struct { |
irq_t irq; |
cuda_t *cuda; |
indev_t *kbrdin; |
} cuda_instance_t; |
extern cuda_instance_t *cuda_init(cuda_t *, inr_t, cir_t, void *); |
extern void cuda_wire(cuda_instance_t *, indev_t *); |
#endif |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/genarch/include/srln/srln.h |
---|
37,9 → 37,18 |
#define KERN_SRLN_H_ |
#include <console/chardev.h> |
#include <proc/thread.h> |
extern void srln_init(indev_t *devin); |
typedef struct { |
thread_t *thread; |
indev_t *sink; |
indev_t raw; |
} srln_instance_t; |
extern srln_instance_t *srln_init(void); |
extern indev_t *srln_wire(srln_instance_t *, indev_t *); |
#endif |
/** @} |
/branches/dd/kernel/genarch/Makefile.inc |
---|
93,6 → 93,11 |
genarch/src/drivers/z8530/z8530.c |
endif |
ifeq ($(CONFIG_VIA_CUDA),y) |
GENARCH_SOURCES += \ |
genarch/src/drivers/via-cuda/cuda.c |
endif |
ifeq ($(CONFIG_PC_KBD),y) |
GENARCH_SOURCES += \ |
genarch/src/kbrd/kbrd.c \ |
/branches/dd/kernel/genarch/src/kbrd/kbrd.c |
---|
59,39 → 59,35 |
#define PRESSED_CAPSLOCK (1 << 1) |
#define LOCKED_CAPSLOCK (1 << 0) |
static indev_t kbrdout; |
indev_operations_t kbrdout_ops = { |
static indev_operations_t kbrd_raw_ops = { |
.poll = NULL |
}; |
SPINLOCK_INITIALIZE(keylock); /**< keylock protects keyflags and lockflags. */ |
static volatile int keyflags; /**< Tracking of multiple keypresses. */ |
static volatile int lockflags; /**< Tracking of multiple keys lockings. */ |
/** Process release of key. |
* |
* @param sc Scancode of the key being released. |
*/ |
static void key_released(wchar_t sc) |
static void key_released(kbrd_instance_t *instance, wchar_t sc) |
{ |
spinlock_lock(&keylock); |
spinlock_lock(&instance->keylock); |
switch (sc) { |
case SC_LSHIFT: |
case SC_RSHIFT: |
keyflags &= ~PRESSED_SHIFT; |
instance->keyflags &= ~PRESSED_SHIFT; |
break; |
case SC_CAPSLOCK: |
keyflags &= ~PRESSED_CAPSLOCK; |
if (lockflags & LOCKED_CAPSLOCK) |
lockflags &= ~LOCKED_CAPSLOCK; |
instance->keyflags &= ~PRESSED_CAPSLOCK; |
if (instance->lockflags & LOCKED_CAPSLOCK) |
instance->lockflags &= ~LOCKED_CAPSLOCK; |
else |
lockflags |= LOCKED_CAPSLOCK; |
instance->lockflags |= LOCKED_CAPSLOCK; |
break; |
default: |
break; |
} |
spinlock_unlock(&keylock); |
spinlock_unlock(&instance->keylock); |
} |
/** Process keypress. |
98,69 → 94,94 |
* |
* @param sc Scancode of the key being pressed. |
*/ |
static void key_pressed(wchar_t sc) |
static void key_pressed(kbrd_instance_t *instance, wchar_t sc) |
{ |
bool letter; |
bool shift; |
bool capslock; |
spinlock_lock(&keylock); |
spinlock_lock(&instance->keylock); |
switch (sc) { |
case SC_LSHIFT: |
case SC_RSHIFT: |
keyflags |= PRESSED_SHIFT; |
instance->keyflags |= PRESSED_SHIFT; |
break; |
case SC_CAPSLOCK: |
keyflags |= PRESSED_CAPSLOCK; |
instance->keyflags |= PRESSED_CAPSLOCK; |
break; |
case SC_SCAN_ESCAPE: |
break; |
default: |
letter = islower(sc_primary_map[sc]); |
shift = keyflags & PRESSED_SHIFT; |
capslock = (keyflags & PRESSED_CAPSLOCK) || |
(lockflags & LOCKED_CAPSLOCK); |
shift = instance->keyflags & PRESSED_SHIFT; |
capslock = (instance->keyflags & PRESSED_CAPSLOCK) || |
(instance->lockflags & LOCKED_CAPSLOCK); |
if ((letter) && (capslock)) |
shift = !shift; |
if (shift) |
indev_push_character(stdin, sc_secondary_map[sc]); |
indev_push_character(instance->sink, sc_secondary_map[sc]); |
else |
indev_push_character(stdin, sc_primary_map[sc]); |
indev_push_character(instance->sink, sc_primary_map[sc]); |
break; |
} |
spinlock_unlock(&keylock); |
spinlock_unlock(&instance->keylock); |
} |
static void kkbrd(void *arg) |
{ |
indev_t *in = (indev_t *) arg; |
kbrd_instance_t *instance = (kbrd_instance_t *) arg; |
while (true) { |
wchar_t sc = _getc(in); |
wchar_t sc = indev_pop_character(&instance->raw); |
if (sc == IGNORE_CODE) |
continue; |
if (sc & KEY_RELEASE) |
key_released((sc ^ KEY_RELEASE) & 0x7f); |
key_released(instance, (sc ^ KEY_RELEASE) & 0x7f); |
else |
key_pressed(sc & 0x7f); |
key_pressed(instance, sc & 0x7f); |
} |
} |
void kbrd_init(indev_t *devin) |
kbrd_instance_t *kbrd_init(void) |
{ |
indev_initialize("kbrd", &kbrdout, &kbrdout_ops); |
thread_t *thread |
= thread_create(kkbrd, devin, TASK, 0, "kkbrd", false); |
kbrd_instance_t *instance |
= malloc(sizeof(kbrd_instance_t), FRAME_ATOMIC); |
if (instance) { |
instance->thread |
= thread_create(kkbrd, (void *) instance, TASK, 0, "kkbrd", false); |
if (!instance->thread) { |
free(instance); |
return NULL; |
} |
instance->sink = NULL; |
indev_initialize("kbrd", &instance->raw, &kbrd_raw_ops); |
spinlock_initialize(&instance->keylock, "instance_keylock"); |
instance->keyflags = 0; |
instance->lockflags = 0; |
} |
if (thread) { |
stdin = &kbrdout; |
thread_ready(thread); |
} |
return instance; |
} |
indev_t *kbrd_wire(kbrd_instance_t *instance, indev_t *sink) |
{ |
ASSERT(instance); |
ASSERT(sink); |
instance->sink = sink; |
thread_ready(instance->thread); |
return &instance->raw; |
} |
/** @} |
*/ |
/branches/dd/kernel/genarch/src/drivers/ns16550/ns16550.c |
---|
43,10 → 43,6 |
#define LSR_DATA_READY 0x01 |
static indev_operations_t kbrdin_ops = { |
.poll = NULL |
}; |
static irq_ownership_t ns16550_claim(irq_t *irq) |
{ |
ns16550_instance_t *instance = irq->instance; |
64,11 → 60,18 |
ns16550_t *dev = instance->ns16550; |
if (pio_read_8(&dev->lsr) & LSR_DATA_READY) { |
uint8_t x = pio_read_8(&dev->rbr); |
indev_push_character(&instance->kbrdin, x); |
uint8_t data = pio_read_8(&dev->rbr); |
indev_push_character(instance->kbrdin, data); |
} |
} |
/**< Clear input buffer. */ |
static void ns16550_clear_buffer(ns16550_t *dev) |
{ |
while ((pio_read_8(&dev->lsr) & LSR_DATA_READY)) |
(void) pio_read_8(&dev->rbr); |
} |
/** Initialize ns16550. |
* |
* @param dev Addrress of the beginning of the device in I/O space. |
77,38 → 80,43 |
* @param cir Clear interrupt function. |
* @param cir_arg First argument to cir. |
* |
* @return Keyboard device pointer or NULL on failure. |
* @return Keyboard instance or NULL on failure. |
* |
*/ |
indev_t *ns16550_init(ns16550_t *dev, inr_t inr, cir_t cir, void *cir_arg) |
ns16550_instance_t *ns16550_init(ns16550_t *dev, inr_t inr, cir_t cir, void *cir_arg) |
{ |
ns16550_instance_t *instance |
= malloc(sizeof(ns16550_instance_t), FRAME_ATOMIC); |
if (!instance) |
return NULL; |
if (instance) { |
instance->ns16550 = dev; |
instance->kbrdin = NULL; |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
instance->irq.claim = ns16550_claim; |
instance->irq.handler = ns16550_irq_handler; |
instance->irq.instance = instance; |
instance->irq.cir = cir; |
instance->irq.cir_arg = cir_arg; |
} |
indev_initialize("ns16550", &instance->kbrdin, &kbrdin_ops); |
return instance; |
} |
void ns16550_wire(ns16550_instance_t *instance, indev_t *kbrdin) |
{ |
ASSERT(instance); |
ASSERT(kbrdin); |
instance->ns16550 = dev; |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
instance->irq.claim = ns16550_claim; |
instance->irq.handler = ns16550_irq_handler; |
instance->irq.instance = instance; |
instance->irq.cir = cir; |
instance->irq.cir_arg = cir_arg; |
instance->kbrdin = kbrdin; |
irq_register(&instance->irq); |
while ((pio_read_8(&dev->lsr) & LSR_DATA_READY)) |
(void) pio_read_8(&dev->rbr); |
ns16550_clear_buffer(instance->ns16550); |
/* Enable interrupts */ |
pio_write_8(&dev->ier, IER_ERBFI); |
pio_write_8(&dev->mcr, MCR_OUT2); |
return &instance->kbrdin; |
pio_write_8(&instance->ns16550->ier, IER_ERBFI); |
pio_write_8(&instance->ns16550->mcr, MCR_OUT2); |
} |
/** @} |
/branches/dd/kernel/genarch/src/drivers/dsrln/dsrlnin.c |
---|
40,10 → 40,6 |
#include <arch/asm.h> |
#include <ddi/device.h> |
static indev_operations_t kbrdin_ops = { |
.poll = NULL |
}; |
static irq_ownership_t dsrlnin_claim(irq_t *irq) |
{ |
return IRQ_ACCEPT; |
54,29 → 50,35 |
dsrlnin_instance_t *instance = irq->instance; |
dsrlnin_t *dev = instance->dsrlnin; |
indev_push_character(&instance->kbrdin, pio_read_8(&dev->data)); |
indev_push_character(instance->srlnin, pio_read_8(&dev->data)); |
} |
indev_t *dsrlnin_init(dsrlnin_t *dev, inr_t inr) |
dsrlnin_instance_t *dsrlnin_init(dsrlnin_t *dev, inr_t inr) |
{ |
dsrlnin_instance_t *instance |
= malloc(sizeof(dsrlnin_instance_t), FRAME_ATOMIC); |
if (!instance) |
return NULL; |
if (instance) { |
instance->dsrlnin = dev; |
instance->srlnin = NULL; |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
instance->irq.claim = dsrlnin_claim; |
instance->irq.handler = dsrlnin_irq_handler; |
instance->irq.instance = instance; |
} |
indev_initialize("dsrlnin", &instance->kbrdin, &kbrdin_ops); |
return instance; |
} |
void dsrlnin_wire(dsrlnin_instance_t *instance, indev_t *srlnin) |
{ |
ASSERT(instance); |
ASSERT(srlnin); |
instance->dsrlnin = dev; |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
instance->irq.claim = dsrlnin_claim; |
instance->irq.handler = dsrlnin_irq_handler; |
instance->irq.instance = instance; |
instance->srlnin = srlnin; |
irq_register(&instance->irq); |
return &instance->kbrdin; |
} |
/** @} |
/branches/dd/kernel/genarch/src/drivers/i8042/i8042.c |
---|
44,10 → 44,6 |
#include <mm/slab.h> |
#include <ddi/device.h> |
static indev_operations_t kbrdin_ops = { |
.poll = NULL |
}; |
#define i8042_SET_COMMAND 0x60 |
#define i8042_COMMAND 0x69 |
#define i8042_CPU_RESET 0xfe |
74,35 → 70,46 |
if (((status = pio_read_8(&dev->status)) & i8042_BUFFER_FULL_MASK)) { |
uint8_t data = pio_read_8(&dev->data); |
indev_push_character(&instance->kbrdin, data); |
indev_push_character(instance->kbrdin, data); |
} |
} |
/**< Clear input buffer. */ |
static void i8042_clear_buffer(i8042_t *dev) |
{ |
while (pio_read_8(&dev->status) & i8042_BUFFER_FULL_MASK) |
(void) pio_read_8(&dev->data); |
} |
/** Initialize i8042. */ |
indev_t *i8042_init(i8042_t *dev, inr_t inr) |
i8042_instance_t *i8042_init(i8042_t *dev, inr_t inr) |
{ |
i8042_instance_t *instance |
= malloc(sizeof(i8042_instance_t), FRAME_ATOMIC); |
if (!instance) |
return NULL; |
if (instance) { |
instance->i8042 = dev; |
instance->kbrdin = NULL; |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
instance->irq.claim = i8042_claim; |
instance->irq.handler = i8042_irq_handler; |
instance->irq.instance = instance; |
} |
indev_initialize("i8042", &instance->kbrdin, &kbrdin_ops); |
return instance; |
} |
void i8042_wire(i8042_instance_t *instance, indev_t *kbrdin) |
{ |
ASSERT(instance); |
ASSERT(kbrdin); |
instance->i8042 = dev; |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
instance->irq.claim = i8042_claim; |
instance->irq.handler = i8042_irq_handler; |
instance->irq.instance = instance; |
instance->kbrdin = kbrdin; |
irq_register(&instance->irq); |
/* Clear input buffer */ |
while (pio_read_8(&dev->status) & i8042_BUFFER_FULL_MASK) |
(void) pio_read_8(&dev->data); |
return &instance->kbrdin; |
i8042_clear_buffer(instance->i8042); |
} |
/* Reset CPU by pulsing pin 0 */ |
110,9 → 117,7 |
{ |
interrupts_disable(); |
/* Clear input buffer */ |
while (pio_read_8(&dev->status) & i8042_BUFFER_FULL_MASK) |
(void) pio_read_8(&dev->data); |
i8042_clear_buffer(dev); |
/* Reset CPU */ |
pio_write_8(&dev->status, i8042_CPU_RESET); |
/branches/dd/kernel/genarch/src/drivers/z8530/z8530.c |
---|
41,10 → 41,6 |
#include <mm/slab.h> |
#include <ddi/device.h> |
static indev_operations_t kbrdin_ops = { |
.poll = NULL |
}; |
static inline void z8530_write(ioport8_t *ctl, uint8_t reg, uint8_t val) |
{ |
/* |
82,51 → 78,58 |
z8530_t *dev = instance->z8530; |
if (z8530_read(&dev->ctl_a, RR0) & RR0_RCA) { |
uint8_t x = z8530_read(&dev->ctl_a, RR8); |
indev_push_character(&instance->kbrdin, x); |
uint8_t data = z8530_read(&dev->ctl_a, RR8); |
indev_push_character(instance->kbrdin, data); |
} |
} |
/** Initialize z8530. */ |
indev_t *z8530_init(z8530_t *dev, inr_t inr, cir_t cir, void *cir_arg) |
z8530_instance_t *z8530_init(z8530_t *dev, inr_t inr, cir_t cir, void *cir_arg) |
{ |
z8530_instance_t *instance |
= malloc(sizeof(z8530_instance_t), FRAME_ATOMIC); |
if (!instance) |
return false; |
if (instance) { |
instance->z8530 = dev; |
instance->kbrdin = NULL; |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
instance->irq.claim = z8530_claim; |
instance->irq.handler = z8530_irq_handler; |
instance->irq.instance = instance; |
instance->irq.cir = cir; |
instance->irq.cir_arg = cir_arg; |
} |
indev_initialize("z8530", &instance->kbrdin, &kbrdin_ops); |
return instance; |
} |
void z8530_wire(z8530_instance_t *instance, indev_t *kbrdin) |
{ |
ASSERT(instance); |
ASSERT(kbrdin); |
instance->z8530 = dev; |
instance->kbrdin = kbrdin; |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
instance->irq.claim = z8530_claim; |
instance->irq.handler = z8530_irq_handler; |
instance->irq.instance = instance; |
instance->irq.cir = cir; |
instance->irq.cir_arg = cir_arg; |
irq_register(&instance->irq); |
(void) z8530_read(&dev->ctl_a, RR8); |
(void) z8530_read(&instance->z8530->ctl_a, RR8); |
/* |
* Clear any pending TX interrupts or we never manage |
* to set FHC UART interrupt state to idle. |
*/ |
z8530_write(&dev->ctl_a, WR0, WR0_TX_IP_RST); |
z8530_write(&instance->z8530->ctl_a, WR0, WR0_TX_IP_RST); |
/* interrupt on all characters */ |
z8530_write(&dev->ctl_a, WR1, WR1_IARCSC); |
z8530_write(&instance->z8530->ctl_a, WR1, WR1_IARCSC); |
/* 8 bits per character and enable receiver */ |
z8530_write(&dev->ctl_a, WR3, WR3_RX8BITSCH | WR3_RX_ENABLE); |
z8530_write(&instance->z8530->ctl_a, WR3, WR3_RX8BITSCH | WR3_RX_ENABLE); |
/* Master Interrupt Enable. */ |
z8530_write(&dev->ctl_a, WR9, WR9_MIE); |
return &instance->kbrdin; |
z8530_write(&instance->z8530->ctl_a, WR9, WR9_MIE); |
} |
/** @} |
/branches/dd/kernel/genarch/src/drivers/via-cuda/cuda.c |
---|
0,0 → 1,78 |
/* |
* Copyright (c) 2006 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** @file |
*/ |
#include <genarch/drivers/via-cuda/cuda.h> |
#include <console/chardev.h> |
#include <ddi/irq.h> |
#include <arch/asm.h> |
#include <mm/slab.h> |
#include <ddi/device.h> |
static irq_ownership_t cuda_claim(irq_t *irq) |
{ |
return IRQ_DECLINE; |
} |
static void cuda_irq_handler(irq_t *irq) |
{ |
} |
cuda_instance_t *cuda_init(cuda_t *dev, inr_t inr, cir_t cir, void *cir_arg) |
{ |
cuda_instance_t *instance |
= malloc(sizeof(cuda_instance_t), FRAME_ATOMIC); |
if (instance) { |
instance->cuda = dev; |
instance->kbrdin = NULL; |
irq_initialize(&instance->irq); |
instance->irq.devno = device_assign_devno(); |
instance->irq.inr = inr; |
instance->irq.claim = cuda_claim; |
instance->irq.handler = cuda_irq_handler; |
instance->irq.instance = instance; |
instance->irq.cir = cir; |
instance->irq.cir_arg = cir_arg; |
} |
return instance; |
} |
void cuda_wire(cuda_instance_t *instance, indev_t *kbrdin) |
{ |
} |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/genarch/src/drivers/ega/ega.c |
---|
426,45 → 426,56 |
/* |
* This function takes care of scrolling. |
*/ |
static void ega_check_cursor(void) |
static void ega_check_cursor(bool silent) |
{ |
if (ega_cursor < EGA_SCREEN) |
return; |
memmove((void *) videoram, (void *) (videoram + EGA_COLS * 2), |
(EGA_SCREEN - EGA_COLS) * 2); |
memmove((void *) backbuf, (void *) (backbuf + EGA_COLS * 2), |
(EGA_SCREEN - EGA_COLS) * 2); |
memsetw(videoram + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR); |
memsetw(backbuf + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR); |
if (!silent) { |
memmove((void *) videoram, (void *) (videoram + EGA_COLS * 2), |
(EGA_SCREEN - EGA_COLS) * 2); |
memsetw(videoram + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR); |
} |
ega_cursor = ega_cursor - EGA_COLS; |
} |
static void ega_show_cursor(void) |
static void ega_show_cursor(bool silent) |
{ |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0a); |
uint8_t stat = pio_read_8(ega_base + EGA_DATA_REG); |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0a); |
pio_write_8(ega_base + EGA_DATA_REG, stat & (~(1 << 5))); |
if (!silent) { |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0a); |
uint8_t stat = pio_read_8(ega_base + EGA_DATA_REG); |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0a); |
pio_write_8(ega_base + EGA_DATA_REG, stat & (~(1 << 5))); |
} |
} |
static void ega_move_cursor(void) |
static void ega_move_cursor(bool silent) |
{ |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0e); |
pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) ((ega_cursor >> 8) & 0xff)); |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0f); |
pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) (ega_cursor & 0xff)); |
if (!silent) { |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0e); |
pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) ((ega_cursor >> 8) & 0xff)); |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0f); |
pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) (ega_cursor & 0xff)); |
} |
} |
static void ega_sync_cursor(void) |
static void ega_sync_cursor(bool silent) |
{ |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0e); |
uint8_t hi = pio_read_8(ega_base + EGA_DATA_REG); |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0f); |
uint8_t lo = pio_read_8(ega_base + EGA_DATA_REG); |
if (!silent) { |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0e); |
uint8_t hi = pio_read_8(ega_base + EGA_DATA_REG); |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0f); |
uint8_t lo = pio_read_8(ega_base + EGA_DATA_REG); |
ega_cursor = (hi << 8) | lo; |
} else |
ega_cursor = 0; |
ega_cursor = (hi << 8) | lo; |
if (ega_cursor >= EGA_SCREEN) |
ega_cursor = 0; |
471,12 → 482,14 |
if ((ega_cursor % EGA_COLS) != 0) |
ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS; |
memsetw(videoram + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR); |
memsetw(backbuf + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR); |
ega_check_cursor(); |
ega_move_cursor(); |
ega_show_cursor(); |
if (!silent) |
memsetw(videoram + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR); |
ega_check_cursor(silent); |
ega_move_cursor(silent); |
ega_show_cursor(silent); |
} |
static void ega_display_char(wchar_t ch, bool silent) |
525,11 → 538,9 |
ega_cursor++; |
break; |
} |
ega_check_cursor(); |
ega_check_cursor(silent); |
ega_move_cursor(silent); |
if (!silent) |
ega_move_cursor(); |
spinlock_unlock(&egalock); |
interrupts_restore(ipl); |
} |
552,7 → 563,7 |
/* Synchronize the back buffer and cursor position. */ |
memcpy(backbuf, videoram, EGA_VRAM_SIZE); |
ega_sync_cursor(); |
ega_sync_cursor(silent); |
outdev_initialize("ega", &ega_console, &ega_ops); |
stdout = &ega_console; |
568,8 → 579,8 |
void ega_redraw(void) |
{ |
memcpy(videoram, backbuf, EGA_VRAM_SIZE); |
ega_move_cursor(); |
ega_show_cursor(); |
ega_move_cursor(silent); |
ega_show_cursor(silent); |
} |
/** @} |
/branches/dd/kernel/genarch/src/srln/srln.c |
---|
41,20 → 41,18 |
#include <arch.h> |
#include <string.h> |
static indev_t srlnout; |
indev_operations_t srlnout_ops = { |
static indev_operations_t srln_raw_ops = { |
.poll = NULL |
}; |
static void ksrln(void *arg) |
{ |
indev_t *in = (indev_t *) arg; |
srln_instance_t *instance = (srln_instance_t *) arg; |
bool cr = false; |
uint32_t escape = 0; |
while (true) { |
wchar_t ch = _getc(in); |
wchar_t ch = indev_pop_character(&instance->raw); |
/* ANSI escape sequence processing */ |
if (escape != 0) { |
122,21 → 120,40 |
if (ch == 0x7f) |
ch = '\b'; |
indev_push_character(stdin, ch); |
indev_push_character(instance->sink, ch); |
} |
} |
void srln_init(indev_t *devin) |
srln_instance_t *srln_init(void) |
{ |
indev_initialize("srln", &srlnout, &srlnout_ops); |
thread_t *thread |
= thread_create(ksrln, devin, TASK, 0, "ksrln", false); |
srln_instance_t *instance |
= malloc(sizeof(srln_instance_t), FRAME_ATOMIC); |
if (instance) { |
instance->thread |
= thread_create(ksrln, (void *) instance, TASK, 0, "ksrln", false); |
if (!instance->thread) { |
free(instance); |
return NULL; |
} |
instance->sink = NULL; |
indev_initialize("srln", &instance->raw, &srln_raw_ops); |
} |
if (thread) { |
stdin = &srlnout; |
thread_ready(thread); |
} |
return instance; |
} |
indev_t *srln_wire(srln_instance_t *instance, indev_t *sink) |
{ |
ASSERT(instance); |
ASSERT(sink); |
instance->sink = sink; |
thread_ready(instance->thread); |
return &instance->raw; |
} |
/** @} |
*/ |
/branches/dd/kernel/generic/include/byteorder.h |
---|
36,6 → 36,7 |
#define KERN_BYTEORDER_H_ |
#include <arch/byteorder.h> |
#include <arch/types.h> |
#if !(defined(ARCH_IS_BIG_ENDIAN) ^ defined(ARCH_IS_LITTLE_ENDIAN)) |
#error The architecture must be either big-endian or little-endian. |
/branches/dd/kernel/generic/include/console/chardev.h |
---|
89,10 → 89,13 |
extern void indev_initialize(char *name, indev_t *indev, |
indev_operations_t *op); |
extern void indev_push_character(indev_t *indev, wchar_t ch); |
extern wchar_t indev_pop_character(indev_t *indev); |
extern void outdev_initialize(char *name, outdev_t *outdev, |
outdev_operations_t *op); |
extern bool check_poll(indev_t *indev); |
#endif /* KERN_CHARDEV_H_ */ |
/** @} |
/branches/dd/kernel/generic/include/console/console.h |
---|
40,17 → 40,15 |
extern indev_t *stdin; |
extern outdev_t *stdout; |
extern bool silent; |
extern indev_t *stdin_wire(void); |
extern void console_init(void); |
extern void klog_init(void); |
extern void klog_update(void); |
extern bool check_poll(indev_t *indev); |
extern wchar_t getc(indev_t *indev); |
extern wchar_t _getc(indev_t *indev); |
extern count_t gets(indev_t *indev, char *buf, size_t buflen); |
extern unative_t sys_klog(int fd, const void *buf, size_t size); |
/branches/dd/kernel/generic/include/ipc/ipc.h |
---|
111,6 → 111,25 |
/* System-specific methods - only through special syscalls |
* These methods have special behaviour |
*/ |
/** Clone connection. |
* |
* The calling task clones one of its phones for the callee. |
* |
* - ARG1 - The caller sets ARG1 to the phone of the cloned connection. |
* - The callee gets the new phone from ARG1. |
* - on answer, the callee acknowledges the new connection by sending EOK back |
* or the kernel closes it |
*/ |
#define IPC_M_CONNECTION_CLONE 1 |
/** Protocol for CONNECT - ME |
* |
* Through this call, the recipient learns about the new cloned connection. |
* |
* - ARG5 - the kernel sets ARG5 to contain the hash of the used phone |
* - on asnwer, the callee acknowledges the new connection by sending EOK back |
* or the kernel closes it |
*/ |
#define IPC_M_CONNECT_ME 2 |
/** Protocol for CONNECT - TO - ME |
* |
* Calling process asks the callee to create a callback connection, |
127,7 → 146,7 |
* - the allocated phoneid is passed to userspace |
* (on the receiving side) as ARG5 of the call. |
*/ |
#define IPC_M_CONNECT_TO_ME 1 |
#define IPC_M_CONNECT_TO_ME 3 |
/** Protocol for CONNECT - ME - TO |
* |
* Calling process asks the callee to create for him a new connection. |
145,11 → 164,11 |
* - recepient may forward message. |
* |
*/ |
#define IPC_M_CONNECT_ME_TO 2 |
#define IPC_M_CONNECT_ME_TO 4 |
/** This message is sent to answerbox when the phone |
* is hung up |
*/ |
#define IPC_M_PHONE_HUNGUP 3 |
#define IPC_M_PHONE_HUNGUP 5 |
/** Send as_area over IPC. |
* - ARG1 - source as_area base address |
159,7 → 178,7 |
* on answer, the recipient must set: |
* - ARG1 - dst as_area base adress |
*/ |
#define IPC_M_SHARE_OUT 4 |
#define IPC_M_SHARE_OUT 6 |
/** Receive as_area over IPC. |
* - ARG1 - destination as_area base address |
171,7 → 190,7 |
* - ARG1 - source as_area base address |
* - ARG2 - flags that will be used for sharing |
*/ |
#define IPC_M_SHARE_IN 5 |
#define IPC_M_SHARE_IN 7 |
/** Send data to another address space over IPC. |
* - ARG1 - source address space virtual address |
182,7 → 201,7 |
* - ARG1 - final destination address space virtual address |
* - ARG2 - final size of data to be copied |
*/ |
#define IPC_M_DATA_WRITE 6 |
#define IPC_M_DATA_WRITE 8 |
/** Receive data from another address space over IPC. |
* - ARG1 - destination virtual address in the source address space |
193,13 → 212,13 |
* - ARG1 - source virtual address in the destination address space |
* - ARG2 - final size of data to be copied |
*/ |
#define IPC_M_DATA_READ 7 |
#define IPC_M_DATA_READ 9 |
/** Debug the recipient. |
* - ARG1 - specifies the debug method (from udebug_method_t) |
* - other arguments are specific to the debug method |
*/ |
#define IPC_M_DEBUG_ALL 8 |
#define IPC_M_DEBUG_ALL 10 |
/* Well-known methods */ |
#define IPC_M_LAST_SYSTEM 511 |
/branches/dd/kernel/generic/include/ipc/ipcrsc.h |
---|
35,8 → 35,11 |
#ifndef KERN_IPCRSC_H_ |
#define KERN_IPCRSC_H_ |
#include <proc/task.h> |
#include <ipc/ipc.h> |
extern call_t * get_call(unative_t callid); |
extern int phone_alloc(void); |
extern int phone_alloc(task_t *t); |
extern void phone_connect(int phoneid, answerbox_t *box); |
extern void phone_dealloc(int phoneid); |
/branches/dd/kernel/generic/src/main/kinit.c |
---|
218,19 → 218,11 |
} |
/* |
* Run user tasks with small delays |
* to avoid intermixed klog output. |
* |
* TODO: This certainly does not guarantee |
* anything, it just works in most of the |
* cases. Some better way how to achieve |
* nice klog output should be found. |
* Run user tasks. |
*/ |
for (i = 0; i < init.cnt; i++) { |
if (programs[i].task != NULL) { |
if (programs[i].task != NULL) |
program_ready(&programs[i]); |
thread_usleep(10000); |
} |
} |
#ifdef CONFIG_KCONSOLE |
/branches/dd/kernel/generic/src/main/main.c |
---|
250,10 → 250,10 |
count_t i; |
for (i = 0; i < init.cnt; i++) |
LOG("init[%" PRIc "].addr=%#" PRIp ", init[%" PRIc |
"].size=%#" PRIs "\n", i, init.tasks[i].addr, i, |
"].size=%#" PRIs, i, init.tasks[i].addr, i, |
init.tasks[i].size); |
} else |
printf("No init binaries found\n"); |
printf("No init binaries found.\n"); |
LOG_EXEC(ipc_init()); |
LOG_EXEC(event_init()); |
/branches/dd/kernel/generic/src/interrupt/interrupt.c |
---|
145,7 → 145,7 |
if (((i + 1) % 20) == 0) { |
printf(" -- Press any key to continue -- "); |
spinlock_unlock(&exctbl_lock); |
_getc(stdin); |
indev_pop_character(stdin); |
spinlock_lock(&exctbl_lock); |
printf("\n"); |
} |
/branches/dd/kernel/generic/src/console/console.c |
---|
44,7 → 44,6 |
#include <ipc/event.h> |
#include <ipc/irq.h> |
#include <arch.h> |
#include <func.h> |
#include <print.h> |
#include <putchar.h> |
#include <atomic.h> |
70,9 → 69,6 |
/** Number of stored kernel log characters for uspace */ |
static size_t klog_uspace = 0; |
/** Silence output */ |
bool silent = false; |
/** Kernel log spinlock */ |
SPINLOCK_INITIALIZE(klog_lock); |
79,10 → 75,28 |
/** Physical memory area used for klog buffer */ |
static parea_t klog_parea; |
static indev_operations_t stdin_ops = { |
.poll = NULL |
}; |
/** Silence output */ |
bool silent = false; |
/** Standard input and output character devices */ |
indev_t *stdin = NULL; |
outdev_t *stdout = NULL; |
indev_t *stdin_wire(void) |
{ |
if (stdin == NULL) { |
stdin = malloc(sizeof(indev_t), FRAME_ATOMIC); |
if (stdin != NULL) |
indev_initialize("stdin", stdin, &stdin_ops); |
} |
return stdin; |
} |
/** Initialize kernel logging facility |
* |
* The shared area contains kernel cyclic buffer. Userspace application may |
110,8 → 124,14 |
void grab_console(void) |
{ |
bool prev = silent; |
silent = false; |
arch_grab_console(); |
/* Force the console to print the prompt */ |
if ((stdin) && (prev)) |
indev_push_character(stdin, '\n'); |
} |
void release_console(void) |
138,55 → 158,6 |
return true; |
} |
bool check_poll(indev_t *indev) |
{ |
if (indev == NULL) |
return false; |
if (indev->op == NULL) |
return false; |
return (indev->op->poll != NULL); |
} |
/** Get character from input character device. Do not echo character. |
* |
* @param indev Input character device. |
* @return Character read. |
* |
*/ |
wchar_t _getc(indev_t *indev) |
{ |
if (atomic_get(&haltstate)) { |
/* If we are here, we are hopefully on the processor that |
* issued the 'halt' command, so proceed to read the character |
* directly from input |
*/ |
if (check_poll(indev)) |
return indev->op->poll(indev); |
/* No other way of interacting with user */ |
interrupts_disable(); |
if (CPU) |
printf("cpu%u: ", CPU->id); |
else |
printf("cpu: "); |
printf("halted (no polling input)\n"); |
cpu_halt(); |
} |
waitq_sleep(&indev->wq); |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&indev->lock); |
wchar_t ch = indev->buffer[(indev->index - indev->counter) % INDEV_BUFLEN]; |
indev->counter--; |
spinlock_unlock(&indev->lock); |
interrupts_restore(ipl); |
return ch; |
} |
/** Get string from input character device. |
* |
* Read characters from input character device until first occurrence |
206,7 → 177,7 |
buf[offset] = 0; |
wchar_t ch; |
while ((ch = _getc(indev)) != '\n') { |
while ((ch = indev_pop_character(indev)) != '\n') { |
if (ch == '\b') { |
if (count > 0) { |
/* Space, backspace, space */ |
232,7 → 203,7 |
/** Get character from input device & echo it to screen */ |
wchar_t getc(indev_t *indev) |
{ |
wchar_t ch = _getc(indev); |
wchar_t ch = indev_pop_character(indev); |
putchar(ch); |
return ch; |
} |
/branches/dd/kernel/generic/src/console/cmd.c |
---|
956,6 → 956,7 |
release_console(); |
event_notify_0(EVENT_KCONSOLE); |
indev_pop_character(stdin); |
return 1; |
} |
/branches/dd/kernel/generic/src/console/chardev.c |
---|
35,6 → 35,9 |
#include <console/chardev.h> |
#include <synch/waitq.h> |
#include <synch/spinlock.h> |
#include <print.h> |
#include <func.h> |
#include <arch.h> |
/** Initialize input character device. |
* |
79,6 → 82,46 |
spinlock_unlock(&indev->lock); |
} |
/** Pop character from input character device. |
* |
* @param indev Input character device. |
* |
* @return Character read. |
* |
*/ |
wchar_t indev_pop_character(indev_t *indev) |
{ |
if (atomic_get(&haltstate)) { |
/* If we are here, we are hopefully on the processor that |
* issued the 'halt' command, so proceed to read the character |
* directly from input |
*/ |
if (check_poll(indev)) |
return indev->op->poll(indev); |
/* No other way of interacting with user */ |
interrupts_disable(); |
if (CPU) |
printf("cpu%u: ", CPU->id); |
else |
printf("cpu: "); |
printf("halted (no polling input)\n"); |
cpu_halt(); |
} |
waitq_sleep(&indev->wq); |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&indev->lock); |
wchar_t ch = indev->buffer[(indev->index - indev->counter) % INDEV_BUFLEN]; |
indev->counter--; |
spinlock_unlock(&indev->lock); |
interrupts_restore(ipl); |
return ch; |
} |
/** Initialize output character device. |
* |
* @param outdev Output character device. |
93,5 → 136,16 |
outdev->op = op; |
} |
bool check_poll(indev_t *indev) |
{ |
if (indev == NULL) |
return false; |
if (indev->op == NULL) |
return false; |
return (indev->op->poll != NULL); |
} |
/** @} |
*/ |
/branches/dd/kernel/generic/src/console/kconsole.c |
---|
245,7 → 245,7 |
current[0] = 0; |
while (true) { |
wchar_t ch = _getc(indev); |
wchar_t ch = indev_pop_character(indev); |
if (ch == '\n') { |
/* Enter */ |
582,7 → 582,7 |
case ARG_TYPE_STRING: |
buf = (char *) cmd->argv[i].buffer; |
str_ncpy(buf, cmd->argv[i].len, cmdline + start, |
(end - start) + 1); |
end - start); |
break; |
case ARG_TYPE_INT: |
if (!parse_int_arg(cmdline + start, end - start, |
653,7 → 653,7 |
printf("%s", msg); |
if (kcon) |
_getc(stdin); |
indev_pop_character(stdin); |
else |
printf("Type \"exit\" to leave the console.\n"); |
/branches/dd/kernel/generic/src/proc/program.c |
---|
133,7 → 133,7 |
/* Register image as the program loader */ |
ASSERT(program_loader == NULL); |
program_loader = image_addr; |
printf("Registered program loader at 0x%" PRIp "\n", |
LOG("Registered program loader at 0x%" PRIp "\n", |
image_addr); |
return EOK; |
} |
/branches/dd/kernel/generic/src/lib/string.c |
---|
641,10 → 641,12 |
{ |
wchar_t acc; |
size_t off = 0; |
size_t last = 0; |
while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) { |
if (acc == ch) |
return (str + off); |
return (str + last); |
last = off; |
} |
return NULL; |
/branches/dd/kernel/generic/src/mm/slab.c |
---|
936,7 → 936,7 |
void *malloc(unsigned int size, int flags) |
{ |
ASSERT(_slab_initialized); |
ASSERT(size && size <= (1 << SLAB_MAX_MALLOC_W)); |
ASSERT(size <= (1 << SLAB_MAX_MALLOC_W)); |
if (size < (1 << SLAB_MIN_MALLOC_W)) |
size = (1 << SLAB_MIN_MALLOC_W); |
/branches/dd/kernel/generic/src/syscall/syscall.c |
---|
59,9 → 59,19 |
unative_t a4, unative_t a5, unative_t a6, unative_t id) |
{ |
unative_t rc; |
#ifdef CONFIG_UDEBUG |
bool debug; |
/* |
* Early check for undebugged tasks. We do not lock anything as this |
* test need not be precise in either way. |
*/ |
debug = THREAD->udebug.active; |
#ifdef CONFIG_UDEBUG |
udebug_syscall_event(a1, a2, a3, a4, a5, a6, id, 0, false); |
if (debug) { |
udebug_syscall_event(a1, a2, a3, a4, a5, a6, id, 0, false); |
} |
#endif |
if (id < SYSCALL_END) { |
76,14 → 86,17 |
thread_exit(); |
#ifdef CONFIG_UDEBUG |
udebug_syscall_event(a1, a2, a3, a4, a5, a6, id, rc, true); |
if (debug) { |
udebug_syscall_event(a1, a2, a3, a4, a5, a6, id, rc, true); |
/* |
* Stopping point needed for tasks that only invoke non-blocking |
* system calls. |
*/ |
udebug_stoppable_begin(); |
udebug_stoppable_end(); |
/* |
* Stopping point needed for tasks that only invoke |
* non-blocking system calls. Not needed if the task |
* is not being debugged (it cannot block here). |
*/ |
udebug_stoppable_begin(); |
udebug_stoppable_end(); |
} |
#endif |
return rc; |
/branches/dd/kernel/generic/src/ipc/ipcrsc.c |
---|
160,27 → 160,29 |
return result; |
} |
/** Allocate new phone slot in the current TASK structure. |
/** Allocate new phone slot in the specified task. |
* |
* @param t Task for which to allocate a new phone. |
* |
* @return New phone handle or -1 if the phone handle limit is |
* exceeded. |
*/ |
int phone_alloc(void) |
int phone_alloc(task_t *t) |
{ |
int i; |
spinlock_lock(&TASK->lock); |
spinlock_lock(&t->lock); |
for (i = 0; i < IPC_MAX_PHONES; i++) { |
if (TASK->phones[i].state == IPC_PHONE_HUNGUP && |
atomic_get(&TASK->phones[i].active_calls) == 0) |
TASK->phones[i].state = IPC_PHONE_FREE; |
if (t->phones[i].state == IPC_PHONE_HUNGUP && |
atomic_get(&t->phones[i].active_calls) == 0) |
t->phones[i].state = IPC_PHONE_FREE; |
if (TASK->phones[i].state == IPC_PHONE_FREE) { |
TASK->phones[i].state = IPC_PHONE_CONNECTING; |
if (t->phones[i].state == IPC_PHONE_FREE) { |
t->phones[i].state = IPC_PHONE_CONNECTING; |
break; |
} |
} |
spinlock_unlock(&TASK->lock); |
spinlock_unlock(&t->lock); |
if (i == IPC_MAX_PHONES) |
return -1; |
/branches/dd/kernel/generic/src/ipc/kbox.c |
---|
84,10 → 84,10 |
interrupts_restore(ipl); |
if (have_kb_thread) { |
LOG("join kb.thread..\n"); |
LOG("Join kb.thread."); |
thread_join(TASK->kb.thread); |
thread_detach(TASK->kb.thread); |
LOG("join done\n"); |
LOG("...join done."); |
TASK->kb.thread = NULL; |
} |
108,12 → 108,10 |
{ |
ipl_t ipl; |
LOG("kbox_proc_phone_hungup()\n"); |
/* Was it our debugger, who hung up? */ |
if (call->sender == TASK->udebug.debugger) { |
/* Terminate debugging session (if any). */ |
LOG("kbox: terminate debug session\n"); |
LOG("Terminate debugging session."); |
ipl = interrupts_disable(); |
spinlock_lock(&TASK->lock); |
udebug_task_cleanup(TASK); |
120,10 → 118,10 |
spinlock_unlock(&TASK->lock); |
interrupts_restore(ipl); |
} else { |
LOG("kbox: was not debugger\n"); |
LOG("Was not debugger."); |
} |
LOG("kbox: continue with hangup message\n"); |
LOG("Continue with hangup message."); |
IPC_SET_RETVAL(call->data, 0); |
ipc_answer(&TASK->kb.box, call); |
145,7 → 143,7 |
} |
mutex_unlock(&TASK->kb.cleanup_lock); |
LOG("phone list is empty\n"); |
LOG("Phone list is empty."); |
*last = true; |
} else { |
*last = false; |
169,7 → 167,7 |
bool done; |
(void)arg; |
LOG("kbox_thread_proc()\n"); |
LOG("Starting."); |
done = false; |
while (!done) { |
201,7 → 199,7 |
} |
} |
LOG("kbox: finished\n"); |
LOG("Exiting."); |
} |
250,7 → 248,7 |
return EINVAL; |
} |
newphid = phone_alloc(); |
newphid = phone_alloc(TASK); |
if (newphid < 0) { |
mutex_unlock(&ta->kb.cleanup_lock); |
return ELIMIT; |
/branches/dd/kernel/generic/src/ipc/sysipc.c |
---|
93,6 → 93,8 |
static inline int method_is_forwardable(unative_t method) |
{ |
switch (method) { |
case IPC_M_CONNECTION_CLONE: |
case IPC_M_CONNECT_ME: |
case IPC_M_PHONE_HUNGUP: |
/* This message is meant only for the original recipient. */ |
return 0; |
140,6 → 142,8 |
static inline int answer_need_old(call_t *call) |
{ |
switch (IPC_GET_METHOD(call->data)) { |
case IPC_M_CONNECTION_CLONE: |
case IPC_M_CONNECT_ME: |
case IPC_M_CONNECT_TO_ME: |
case IPC_M_CONNECT_ME_TO: |
case IPC_M_SHARE_OUT: |
182,9 → 186,48 |
if (!olddata) |
return 0; |
if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) { |
if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECTION_CLONE) { |
phoneid = IPC_GET_ARG1(*olddata); |
phone_t *phone = &TASK->phones[phoneid]; |
if (IPC_GET_RETVAL(answer->data) != EOK) { |
/* |
* The recipient of the cloned phone rejected the offer. |
* In this case, the connection was established at the |
* request time and therefore we need to slam the phone. |
* We don't merely hangup as that would result in |
* sending IPC_M_HUNGUP to the third party on the |
* other side of the cloned phone. |
*/ |
mutex_lock(&phone->lock); |
if (phone->state == IPC_PHONE_CONNECTED) { |
spinlock_lock(&phone->callee->lock); |
list_remove(&phone->link); |
phone->state = IPC_PHONE_SLAMMED; |
spinlock_unlock(&phone->callee->lock); |
} |
mutex_unlock(&phone->lock); |
} |
} else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME) { |
phone_t *phone = (phone_t *)IPC_GET_ARG5(*olddata); |
if (IPC_GET_RETVAL(answer->data) != EOK) { |
/* |
* The other party on the cloned phoned rejected our |
* request for connection on the protocol level. |
* We need to break the connection without sending |
* IPC_M_HUNGUP back. |
*/ |
mutex_lock(&phone->lock); |
if (phone->state == IPC_PHONE_CONNECTED) { |
spinlock_lock(&phone->callee->lock); |
list_remove(&phone->link); |
phone->state = IPC_PHONE_SLAMMED; |
spinlock_unlock(&phone->callee->lock); |
} |
mutex_unlock(&phone->lock); |
} |
} else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) { |
phoneid = IPC_GET_ARG5(*olddata); |
if (IPC_GET_RETVAL(answer->data)) { |
if (IPC_GET_RETVAL(answer->data) != EOK) { |
/* The connection was not accepted */ |
phone_dealloc(phoneid); |
} else { |
196,7 → 239,7 |
} |
} else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME_TO) { |
/* If the users accepted call, connect */ |
if (!IPC_GET_RETVAL(answer->data)) { |
if (IPC_GET_RETVAL(answer->data) == EOK) { |
ipc_phone_connect((phone_t *) IPC_GET_ARG5(*olddata), |
&TASK->answerbox); |
} |
308,8 → 351,48 |
int rc; |
switch (IPC_GET_METHOD(call->data)) { |
case IPC_M_CONNECTION_CLONE: { |
phone_t *cloned_phone; |
GET_CHECK_PHONE(cloned_phone, IPC_GET_ARG1(call->data), |
return ENOENT); |
if (cloned_phone < phone) { |
mutex_lock(&cloned_phone->lock); |
mutex_lock(&phone->lock); |
} else { |
mutex_lock(&phone->lock); |
mutex_lock(&cloned_phone->lock); |
} |
if ((cloned_phone->state != IPC_PHONE_CONNECTED) || |
phone->state != IPC_PHONE_CONNECTED) { |
mutex_unlock(&cloned_phone->lock); |
mutex_unlock(&phone->lock); |
return EINVAL; |
} |
/* |
* We can be pretty sure now that both tasks exist and we are |
* connected to them. As we continue to hold the phone locks, |
* we are effectively preventing them from finishing their |
* potential cleanup. |
*/ |
newphid = phone_alloc(phone->callee->task); |
if (newphid < 0) { |
mutex_unlock(&cloned_phone->lock); |
mutex_unlock(&phone->lock); |
return ELIMIT; |
} |
ipc_phone_connect(&phone->callee->task->phones[newphid], |
cloned_phone->callee); |
mutex_unlock(&cloned_phone->lock); |
mutex_unlock(&phone->lock); |
/* Set the new phone for the callee. */ |
IPC_SET_ARG1(call->data, newphid); |
break; |
} |
case IPC_M_CONNECT_ME: |
IPC_SET_ARG5(call->data, (unative_t) phone); |
break; |
case IPC_M_CONNECT_ME_TO: |
newphid = phone_alloc(); |
newphid = phone_alloc(TASK); |
if (newphid < 0) |
return ELIMIT; |
/* Set arg5 for server */ |
332,7 → 415,7 |
src = IPC_GET_ARG1(call->data); |
size = IPC_GET_ARG2(call->data); |
if ((size <= 0) || (size > DATA_XFER_LIMIT)) |
if (size > DATA_XFER_LIMIT) |
return ELIMIT; |
call->buffer = (uint8_t *) malloc(size, 0); |
399,7 → 482,7 |
int phoneid; |
if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) { |
phoneid = phone_alloc(); |
phoneid = phone_alloc(TASK); |
if (phoneid < 0) { /* Failed to allocate phone */ |
IPC_SET_RETVAL(call->data, ELIMIT); |
ipc_answer(box, call); |
/branches/dd/kernel/generic/src/ipc/ipc.c |
---|
328,12 → 328,10 |
list_remove(&phone->link); |
spinlock_unlock(&box->lock); |
if (phone->state != IPC_PHONE_SLAMMED) { |
call = ipc_call_alloc(0); |
IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); |
call->flags |= IPC_CALL_DISCARD_ANSWER; |
_ipc_call(phone, box, call); |
} |
call = ipc_call_alloc(0); |
IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); |
call->flags |= IPC_CALL_DISCARD_ANSWER; |
_ipc_call(phone, box, call); |
} |
phone->state = IPC_PHONE_HUNGUP; |
/branches/dd/kernel/generic/src/udebug/udebug.c |
---|
98,27 → 98,6 |
waitq_sleep_finish(wq, rc, ipl); |
} |
/** Do a preliminary check that a debugging session is in progress. |
* |
* This only requires the THREAD->udebug.lock mutex (and not TASK->udebug.lock |
* mutex). For an undebugged task, this will never block (while there could be |
* collisions by different threads on the TASK mutex), thus improving SMP |
* perormance for undebugged tasks. |
* |
* @return True if the thread was in a debugging session when the function |
* checked, false otherwise. |
*/ |
static bool udebug_thread_precheck(void) |
{ |
bool res; |
mutex_lock(&THREAD->udebug.lock); |
res = THREAD->udebug.active; |
mutex_unlock(&THREAD->udebug.lock); |
return res; |
} |
/** Start of stoppable section. |
* |
* A stoppable section is a section of code where if the thread can be stoped. In other words, |
137,11 → 116,6 |
ASSERT(THREAD); |
ASSERT(TASK); |
/* Early check for undebugged tasks */ |
if (!udebug_thread_precheck()) { |
return; |
} |
mutex_lock(&TASK->udebug.lock); |
nsc = --TASK->udebug.not_stoppable_count; |
202,11 → 176,6 |
*/ |
void udebug_stoppable_end(void) |
{ |
/* Early check for undebugged tasks */ |
if (!udebug_thread_precheck()) { |
return; |
} |
restart: |
mutex_lock(&TASK->udebug.lock); |
mutex_lock(&THREAD->udebug.lock); |
255,11 → 224,6 |
etype = end_variant ? UDEBUG_EVENT_SYSCALL_E : UDEBUG_EVENT_SYSCALL_B; |
/* Early check for undebugged tasks */ |
if (!udebug_thread_precheck()) { |
return; |
} |
mutex_lock(&TASK->udebug.lock); |
mutex_lock(&THREAD->udebug.lock); |
271,7 → 235,7 |
return; |
} |
//printf("udebug_syscall_event\n"); |
/* Fill in the GO response. */ |
call = THREAD->udebug.go_call; |
THREAD->udebug.go_call = NULL; |
279,7 → 243,6 |
IPC_SET_ARG1(call->data, etype); |
IPC_SET_ARG2(call->data, id); |
IPC_SET_ARG3(call->data, rc); |
//printf("udebug_syscall_event/ipc_answer\n"); |
THREAD->udebug.syscall_args[0] = a1; |
THREAD->udebug.syscall_args[1] = a2; |
329,21 → 292,19 |
thread_attach(t, ta); |
LOG("udebug_thread_b_event\n"); |
LOG("- check state\n"); |
LOG("Check state"); |
/* Must only generate events when in debugging session */ |
if (THREAD->udebug.active != true) { |
LOG("- udebug.active: %s, udebug.go: %s\n", |
THREAD->udebug.active ? "yes(+)" : "no(-)", |
THREAD->udebug.go ? "yes(-)" : "no(+)"); |
LOG("udebug.active: %s, udebug.go: %s", |
THREAD->udebug.active ? "Yes(+)" : "No", |
THREAD->udebug.go ? "Yes(-)" : "No"); |
mutex_unlock(&THREAD->udebug.lock); |
mutex_unlock(&TASK->udebug.lock); |
return; |
} |
LOG("- trigger event\n"); |
LOG("Trigger event"); |
call = THREAD->udebug.go_call; |
THREAD->udebug.go_call = NULL; |
IPC_SET_RETVAL(call->data, 0); |
363,7 → 324,7 |
mutex_unlock(&THREAD->udebug.lock); |
mutex_unlock(&TASK->udebug.lock); |
LOG("- sleep\n"); |
LOG("Wait for Go"); |
udebug_wait_for_go(&THREAD->udebug.go_wq); |
} |
379,21 → 340,19 |
mutex_lock(&TASK->udebug.lock); |
mutex_lock(&THREAD->udebug.lock); |
LOG("udebug_thread_e_event\n"); |
LOG("- check state\n"); |
LOG("Check state"); |
/* Must only generate events when in debugging session. */ |
if (THREAD->udebug.active != true) { |
/* printf("- udebug.active: %s, udebug.go: %s\n", |
THREAD->udebug.active ? "yes(+)" : "no(-)", |
THREAD->udebug.go ? "yes(-)" : "no(+)");*/ |
LOG("udebug.active: %s, udebug.go: %s", |
THREAD->udebug.active ? "Yes" : "No", |
THREAD->udebug.go ? "Yes" : "No"); |
mutex_unlock(&THREAD->udebug.lock); |
mutex_unlock(&TASK->udebug.lock); |
return; |
} |
LOG("- trigger event\n"); |
LOG("Trigger event"); |
call = THREAD->udebug.go_call; |
THREAD->udebug.go_call = NULL; |
IPC_SET_RETVAL(call->data, 0); |
432,15 → 391,13 |
int flags; |
ipl_t ipl; |
LOG("udebug_task_cleanup()\n"); |
LOG("task %" PRIu64 "\n", ta->taskid); |
if (ta->udebug.dt_state != UDEBUG_TS_BEGINNING && |
ta->udebug.dt_state != UDEBUG_TS_ACTIVE) { |
LOG("udebug_task_cleanup(): task not being debugged\n"); |
return EINVAL; |
} |
LOG("Task %" PRIu64, ta->taskid); |
/* Finish debugging of all userspace threads */ |
for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
t = list_get_instance(cur, thread_t, th_link); |
470,7 → 427,7 |
t->udebug.go = false; |
/* Answer GO call */ |
LOG("answer GO call with EVENT_FINISHED\n"); |
LOG("Answer GO call with EVENT_FINISHED."); |
IPC_SET_RETVAL(t->udebug.go_call->data, 0); |
IPC_SET_ARG1(t->udebug.go_call->data, |
UDEBUG_EVENT_FINISHED); |
/branches/dd/kernel/generic/src/udebug/udebug_ops.c |
---|
181,15 → 181,11 |
thread_t *t; |
link_t *cur; |
LOG("udebug_begin()\n"); |
LOG("Debugging task %llu", TASK->taskid); |
mutex_lock(&TASK->udebug.lock); |
LOG("debugging task %llu\n", TASK->taskid); |
if (TASK->udebug.dt_state != UDEBUG_TS_INACTIVE) { |
mutex_unlock(&TASK->udebug.lock); |
LOG("udebug_begin(): busy error\n"); |
return EBUSY; |
} |
217,10 → 213,6 |
} |
mutex_unlock(&TASK->udebug.lock); |
LOG("udebug_begin() done (%s)\n", |
reply ? "reply" : "stoppability wait"); |
return reply; |
} |
233,13 → 225,10 |
{ |
int rc; |
LOG("udebug_end()\n"); |
LOG("Task %" PRIu64, TASK->taskid); |
mutex_lock(&TASK->udebug.lock); |
LOG("task %" PRIu64 "\n", TASK->taskid); |
rc = udebug_task_cleanup(TASK); |
mutex_unlock(&TASK->udebug.lock); |
return rc; |
254,19 → 243,16 |
*/ |
int udebug_set_evmask(udebug_evmask_t mask) |
{ |
LOG("udebug_set_mask()\n"); |
LOG("mask = 0x%x", mask); |
mutex_lock(&TASK->udebug.lock); |
if (TASK->udebug.dt_state != UDEBUG_TS_ACTIVE) { |
mutex_unlock(&TASK->udebug.lock); |
LOG("udebug_set_mask(): not active debuging session\n"); |
return EINVAL; |
} |
TASK->udebug.evmask = mask; |
mutex_unlock(&TASK->udebug.lock); |
return 0; |
317,7 → 303,7 |
{ |
int rc; |
LOG("udebug_stop()\n"); |
LOG("udebug_stop()"); |
/* |
* On success, this will lock t->udebug.lock. Note that this makes sure |
340,7 → 326,6 |
/* |
* Answer GO call. |
*/ |
LOG("udebug_stop - answering go call\n"); |
/* Make sure nobody takes this call away from us. */ |
call = t->udebug.go_call; |
348,7 → 333,6 |
IPC_SET_RETVAL(call->data, 0); |
IPC_SET_ARG1(call->data, UDEBUG_EVENT_STOP); |
LOG("udebug_stop/ipc_answer\n"); |
THREAD->udebug.cur_event = UDEBUG_EVENT_STOP; |
358,7 → 342,6 |
ipc_answer(&TASK->answerbox, call); |
mutex_unlock(&TASK->udebug.lock); |
LOG("udebog_stop/done\n"); |
return 0; |
} |
392,7 → 375,7 |
int flags; |
size_t max_ids; |
LOG("udebug_thread_read()\n"); |
LOG("udebug_thread_read()"); |
/* Allocate a buffer to hold thread IDs */ |
id_buffer = malloc(buf_size, 0); |
/branches/dd/kernel/arch/sparc64/include/atomic.h |
---|
123,7 → 123,7 |
"ldx %0, %2\n" |
"brz %2, 0b\n" |
"nop\n" |
"ba 1b\n" |
"ba %xcc, 1b\n" |
"nop\n" |
"2:\n" |
: "+m" (*((uint64_t *) x)), "+r" (tmp1), "+r" (tmp2) : "r" (0) |
/branches/dd/kernel/arch/sparc64/include/trap/trap_table.h |
---|
100,7 → 100,7 |
.macro PREEMPTIBLE_HANDLER f |
sethi %hi(\f), %g1 |
b preemptible_handler |
ba %xcc, preemptible_handler |
or %g1, %lo(\f), %g1 |
.endm |
/branches/dd/kernel/arch/sparc64/include/drivers/sgcn.h |
---|
37,6 → 37,7 |
#include <arch/types.h> |
#include <console/chardev.h> |
#include <proc/thread.h> |
/* number of bytes in the TOC magic, including the NULL-terminator */ |
#define TOC_MAGIC_BYTES 8 |
116,11 → 117,17 |
uint32_t out_wrptr; |
} __attribute__ ((packed)) sgcn_buffer_header_t; |
void sgcn_grab(void); |
void sgcn_release(void); |
indev_t *sgcnin_init(void); |
void sgcnout_init(void); |
typedef struct { |
thread_t *thread; |
indev_t *srlnin; |
} sgcn_instance_t; |
extern void sgcn_grab(void); |
extern void sgcn_release(void); |
extern sgcn_instance_t *sgcnin_init(void); |
extern void sgcnin_wire(sgcn_instance_t *, indev_t *); |
extern void sgcnout_init(void); |
#endif |
/** @} |
/branches/dd/kernel/arch/sparc64/include/drivers/kbd.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup sparc64 |
/** @addtogroup sparc64 |
* @{ |
*/ |
/** @file |
38,15 → 38,6 |
#include <arch/types.h> |
#include <genarch/ofw/ofw_tree.h> |
typedef enum { |
KBD_UNKNOWN, |
KBD_Z8530, |
KBD_NS16550, |
KBD_SGCN |
} kbd_type_t; |
extern kbd_type_t kbd_type; |
extern void kbd_init(ofw_tree_node_t *node); |
#endif |
/branches/dd/kernel/arch/sparc64/src/asm.S |
---|
225,12 → 225,12 |
.global memsetb |
memsetb: |
b _memsetb |
ba %xcc, _memsetb |
nop |
.global memsetw |
memsetw: |
b _memsetw |
ba %xcc, _memsetw |
nop |
/branches/dd/kernel/arch/sparc64/src/console.c |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup sparc64 |
/** @addtogroup sparc64 |
* @{ |
*/ |
/** @file |
92,10 → 92,15 |
static void serengeti_init(void) |
{ |
#ifdef CONFIG_SGCN_KBD |
indev_t *kbrdin; |
kbrdin = sgcnin_init(); |
if (kbrdin) |
srln_init(kbrdin); |
sgcn_instance_t *sgcn_instance = sgcnin_init(); |
if (sgcn_instance) { |
srln_instance_t *srln_instance = srln_init(); |
if (srln_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *srln = srln_wire(srln_instance, sink); |
sgcnin_wire(sgcn_instance, srln); |
} |
} |
#endif |
#ifdef CONFIG_SGCN_PRN |
sgcnout_init(); |
135,15 → 140,9 |
scr_redraw(); |
#endif |
switch (kbd_type) { |
#ifdef CONFIG_SGCN_KBD |
case KBD_SGCN: |
sgcn_grab(); |
break; |
sgcn_grab(); |
#endif |
default: |
break; |
} |
} |
/** Return console to userspace |
151,15 → 150,9 |
*/ |
void arch_release_console(void) |
{ |
switch (kbd_type) { |
#ifdef CONFIG_SGCN_KBD |
case KBD_SGCN: |
sgcn_release(); |
break; |
sgcn_release(); |
#endif |
default: |
break; |
} |
} |
/** @} |
/branches/dd/kernel/arch/sparc64/src/trap/trap_table.S |
---|
341,7 → 341,7 |
.org trap_table + (TT_TRAP_INSTRUCTION_0+\cur)*ENTRY_SIZE |
.global trap_instruction_\cur\()_tl0 |
trap_instruction_\cur\()_tl0: |
ba trap_instruction_handler |
ba %xcc, trap_instruction_handler |
mov \cur, %g2 |
.endr |
480,7 → 480,7 |
cmp %g3, 1 |
be %xcc, 1f |
nop |
0: ba 0b ! this is for debugging, if we ever get here |
0: ba %xcc, 0b ! this is for debugging, if we ever get here |
nop ! it will be easy to find |
1: |
545,7 → 545,7 |
flush %l0 |
.if NOT(\is_syscall) |
ba 1f |
ba %xcc, 1f |
nop |
0: |
save %sp, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp |
774,7 → 774,7 |
and %g3, NWINDOWS - 1, %g3 |
wrpr %g3, 0, %cwp ! switch to the preceeding window |
ba 0b |
ba %xcc, 0b |
inc %g4 |
0: |
/branches/dd/kernel/arch/sparc64/src/mm/tlb.c |
---|
497,38 → 497,7 |
dtlb_sfsr_write(0); |
} |
#if defined (US3) |
/** Invalidates given TLB entry if and only if it is non-locked or global. |
* |
* @param tlb TLB number (one of TLB_DSMALL, TLB_DBIG_0, TLB_DBIG_1, |
* TLB_ISMALL, TLB_IBIG). |
* @param entry Entry index within the given TLB. |
*/ |
static void tlb_invalidate_entry(int tlb, index_t entry) |
{ |
tlb_data_t d; |
tlb_tag_read_reg_t t; |
if (tlb == TLB_DSMALL || tlb == TLB_DBIG_0 || tlb == TLB_DBIG_1) { |
d.value = dtlb_data_access_read(tlb, entry); |
if (!d.l || d.g) { |
t.value = dtlb_tag_read_read(tlb, entry); |
d.v = false; |
dtlb_tag_access_write(t.value); |
dtlb_data_access_write(tlb, entry, d.value); |
} |
} else if (tlb == TLB_ISMALL || tlb == TLB_IBIG) { |
d.value = itlb_data_access_read(tlb, entry); |
if (!d.l || d.g) { |
t.value = itlb_tag_read_read(tlb, entry); |
d.v = false; |
itlb_tag_access_write(t.value); |
itlb_data_access_write(tlb, entry, d.value); |
} |
} |
} |
#endif |
#if defined (US) |
/** Invalidate all unlocked ITLB and DTLB entries. */ |
void tlb_invalidate_all(void) |
{ |
543,7 → 512,6 |
* be safe to invalidate them as late as now. |
*/ |
#if defined (US) |
tlb_data_t d; |
tlb_tag_read_reg_t t; |
567,22 → 535,19 |
} |
} |
} |
#elif defined (US3) |
for (i = 0; i < tlb_ismall_size(); i++) |
tlb_invalidate_entry(TLB_ISMALL, i); |
for (i = 0; i < tlb_ibig_size(); i++) |
tlb_invalidate_entry(TLB_IBIG, i); |
for (i = 0; i < tlb_dsmall_size(); i++) |
tlb_invalidate_entry(TLB_DSMALL, i); |
for (i = 0; i < tlb_dbig_size(); i++) |
tlb_invalidate_entry(TLB_DBIG_0, i); |
for (i = 0; i < tlb_dbig_size(); i++) |
tlb_invalidate_entry(TLB_DBIG_1, i); |
/** Invalidate all unlocked ITLB and DTLB entries. */ |
void tlb_invalidate_all(void) |
{ |
itlb_demap(TLB_DEMAP_ALL, 0, 0); |
dtlb_demap(TLB_DEMAP_ALL, 0, 0); |
} |
#endif |
} |
/** Invalidate all ITLB and DTLB entries that belong to specified ASID |
* (Context). |
* |
/branches/dd/kernel/arch/sparc64/src/dummy.s |
---|
42,5 → 42,5 |
.global cpu_halt |
cpu_halt: |
b cpu_halt |
ba %xcc, cpu_halt |
nop |
/branches/dd/kernel/arch/sparc64/src/drivers/kbd.c |
---|
54,100 → 54,140 |
#include <print.h> |
#include <sysinfo/sysinfo.h> |
kbd_type_t kbd_type = KBD_UNKNOWN; |
#ifdef CONFIG_SUN_KBD |
/** Initialize keyboard. |
* |
* Traverse OpenFirmware device tree in order to find necessary |
* info about the keyboard device. |
* |
* @param node Keyboard device node. |
*/ |
void kbd_init(ofw_tree_node_t *node) |
#ifdef CONFIG_Z8530 |
static bool kbd_z8530_init(ofw_tree_node_t *node) |
{ |
size_t offset; |
uintptr_t aligned_addr; |
ofw_tree_property_t *prop; |
const char *name; |
const char *name = ofw_tree_node_name(node); |
if (str_cmp(name, "zs") != 0) |
return false; |
/* |
* Read 'interrupts' property. |
*/ |
ofw_tree_property_t *prop = ofw_tree_getprop(node, "interrupts"); |
if ((!prop) || (!prop->value)) { |
printf("z8530: Unable to find interrupts property\n"); |
return false; |
} |
uint32_t interrupts = *((uint32_t *) prop->value); |
/* |
* Read 'reg' property. |
*/ |
prop = ofw_tree_getprop(node, "reg"); |
if ((!prop) || (!prop->value)) { |
printf("z8530: Unable to find reg property\n"); |
return false; |
} |
size_t size = ((ofw_fhc_reg_t *) prop->value)->size; |
uintptr_t pa; |
if (!ofw_fhc_apply_ranges(node->parent, |
((ofw_fhc_reg_t *) prop->value), &pa)) { |
printf("z8530: Failed to determine address\n"); |
return false; |
} |
inr_t inr; |
cir_t cir; |
void *cir_arg; |
if (!ofw_fhc_map_interrupt(node->parent, |
((ofw_fhc_reg_t *) prop->value), interrupts, &inr, &cir, |
&cir_arg)) { |
printf("z8530: Failed to determine interrupt\n"); |
return false; |
} |
#ifdef CONFIG_NS16550 |
ns16550_t *ns16550; |
#endif |
#ifdef CONFIG_Z8530 |
z8530_t *z8530; |
#endif |
/* |
* We need to pass aligned address to hw_map(). |
* However, the physical keyboard address can |
* be pretty much unaligned, depending on the |
* underlying controller. |
*/ |
uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE); |
size_t offset = pa - aligned_addr; |
name = ofw_tree_node_name(node); |
z8530_t *z8530 = (z8530_t *) |
(hw_map(aligned_addr, offset + size) + offset); |
z8530_instance_t *z8530_instance = z8530_init(z8530, inr, cir, cir_arg); |
if (z8530_instance) { |
kbrd_instance_t *kbrd_instance = kbrd_init(); |
if (kbrd_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *kbrd = kbrd_wire(kbrd_instance, sink); |
z8530_wire(z8530_instance, kbrd); |
} |
} |
/* |
* Determine keyboard serial controller type. |
* This is the necessary evil until the userspace drivers are |
* entirely self-sufficient. |
*/ |
if (str_cmp(name, "zs") == 0) |
kbd_type = KBD_Z8530; |
else if (str_cmp(name, "su") == 0) |
kbd_type = KBD_NS16550; |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.inr", NULL, inr); |
sysinfo_set_item_val("kbd.address.kernel", NULL, |
(uintptr_t) z8530); |
sysinfo_set_item_val("kbd.address.physical", NULL, pa); |
sysinfo_set_item_val("kbd.type.z8530", NULL, true); |
if (kbd_type == KBD_UNKNOWN) { |
printf("Unknown keyboard device.\n"); |
return; |
} |
return true; |
} |
#endif /* CONFIG_Z8530 */ |
#ifdef CONFIG_NS16550 |
static bool kbd_ns16550_init(ofw_tree_node_t *node) |
{ |
const char *name = ofw_tree_node_name(node); |
if (str_cmp(name, "su") != 0) |
return false; |
/* |
* Read 'interrupts' property. |
*/ |
uint32_t interrupts; |
prop = ofw_tree_getprop(node, "interrupts"); |
if ((!prop) || (!prop->value)) |
panic("Cannot find 'interrupt' property."); |
interrupts = *((uint32_t *) prop->value); |
ofw_tree_property_t *prop = ofw_tree_getprop(node, "interrupts"); |
if ((!prop) || (!prop->value)) { |
printf("ns16550: Unable to find interrupts property\n"); |
return false; |
} |
uint32_t interrupts = *((uint32_t *) prop->value); |
/* |
* Read 'reg' property. |
*/ |
prop = ofw_tree_getprop(node, "reg"); |
if ((!prop) || (!prop->value)) |
panic("Cannot find 'reg' property."); |
if ((!prop) || (!prop->value)) { |
printf("ns16550: Unable to find reg property\n"); |
return false; |
} |
size_t size = ((ofw_ebus_reg_t *) prop->value)->size; |
uintptr_t pa; |
size_t size; |
if (!ofw_ebus_apply_ranges(node->parent, |
((ofw_ebus_reg_t *) prop->value), &pa)) { |
printf("ns16550: Failed to determine address\n"); |
return false; |
} |
inr_t inr; |
switch (kbd_type) { |
case KBD_Z8530: |
size = ((ofw_fhc_reg_t *) prop->value)->size; |
if (!ofw_fhc_apply_ranges(node->parent, |
((ofw_fhc_reg_t *) prop->value), &pa)) { |
printf("Failed to determine keyboard address.\n"); |
return; |
} |
if (!ofw_fhc_map_interrupt(node->parent, |
((ofw_fhc_reg_t *) prop->value), interrupts, &inr, &cir, |
&cir_arg)) { |
printf("Failed to determine keyboard interrupt.\n"); |
return; |
} |
break; |
case KBD_NS16550: |
size = ((ofw_ebus_reg_t *) prop->value)->size; |
if (!ofw_ebus_apply_ranges(node->parent, |
((ofw_ebus_reg_t *) prop->value), &pa)) { |
printf("Failed to determine keyboard address.\n"); |
return; |
} |
if (!ofw_ebus_map_interrupt(node->parent, |
((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir, |
&cir_arg)) { |
printf("Failed to determine keyboard interrupt.\n"); |
return; |
}; |
break; |
default: |
panic("Unexpected keyboard type."); |
cir_t cir; |
void *cir_arg; |
if (!ofw_ebus_map_interrupt(node->parent, |
((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir, |
&cir_arg)) { |
printf("ns16550: Failed to determine interrupt\n"); |
return false; |
} |
/* |
156,59 → 196,58 |
* be pretty much unaligned, depending on the |
* underlying controller. |
*/ |
aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE); |
offset = pa - aligned_addr; |
uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE); |
size_t offset = pa - aligned_addr; |
switch (kbd_type) { |
ns16550_t *ns16550 = (ns16550_t *) |
(hw_map(aligned_addr, offset + size) + offset); |
ns16550_instance_t *ns16550_instance = ns16550_init(ns16550, inr, cir, cir_arg); |
if (ns16550_instance) { |
kbrd_instance_t *kbrd_instance = kbrd_init(); |
if (kbrd_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *kbrd = kbrd_wire(kbrd_instance, sink); |
ns16550_wire(ns16550_instance, kbrd); |
} |
} |
/* |
* This is the necessary evil until the userspace drivers are |
* entirely self-sufficient. |
*/ |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.inr", NULL, inr); |
sysinfo_set_item_val("kbd.address.kernel", NULL, |
(uintptr_t) ns16550); |
sysinfo_set_item_val("kbd.address.physical", NULL, pa); |
sysinfo_set_item_val("kbd.type.ns16550", NULL, true); |
return true; |
} |
#endif /* CONFIG_NS16550 */ |
/** Initialize keyboard. |
* |
* Traverse OpenFirmware device tree in order to find necessary |
* info about the keyboard device. |
* |
* @param node Keyboard device node. |
* |
*/ |
void kbd_init(ofw_tree_node_t *node) |
{ |
#ifdef CONFIG_Z8530 |
case KBD_Z8530: |
z8530 = (z8530_t *) |
(hw_map(aligned_addr, offset + size) + offset); |
indev_t *kbrdin_z8530 = z8530_init(z8530, inr, cir, cir_arg); |
if (kbrdin_z8530) |
kbrd_init(kbrdin_z8530); |
/* |
* This is the necessary evil until the userspace drivers are |
* entirely self-sufficient. |
*/ |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.type", NULL, KBD_Z8530); |
sysinfo_set_item_val("kbd.inr", NULL, inr); |
sysinfo_set_item_val("kbd.address.kernel", NULL, |
(uintptr_t) z8530); |
sysinfo_set_item_val("kbd.address.physical", NULL, pa); |
break; |
kbd_z8530_init(node); |
#endif |
#ifdef CONFIG_NS16550 |
case KBD_NS16550: |
ns16550 = (ns16550_t *) |
(hw_map(aligned_addr, offset + size) + offset); |
indev_t *kbrdin_ns16550 = ns16550_init(ns16550, inr, cir, cir_arg); |
if (kbrdin_ns16550) |
kbrd_init(kbrdin_ns16550); |
/* |
* This is the necessary evil until the userspace driver is |
* entirely self-sufficient. |
*/ |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550); |
sysinfo_set_item_val("kbd.inr", NULL, inr); |
sysinfo_set_item_val("kbd.address.kernel", NULL, |
(uintptr_t) ns16550); |
sysinfo_set_item_val("kbd.address.physical", NULL, pa); |
break; |
kbd_ns16550_init(node); |
#endif |
default: |
printf("Kernel is not compiled with the necessary keyboard " |
"driver this machine requires.\n"); |
} |
} |
#endif |
#endif /* CONFIG_SUN_KBD */ |
/** @} |
*/ |
/branches/dd/kernel/arch/sparc64/src/drivers/sgcn.c |
---|
101,9 → 101,6 |
/** Returns a pointer to the console buffer header. */ |
#define SGCN_BUFFER_HEADER (SGCN_BUFFER(sgcn_buffer_header_t, 0)) |
/** defined in drivers/kbd.c */ |
extern kbd_type_t kbd_type; |
/** starting address of SRAM, will be set by the init_sram_begin function */ |
static uintptr_t sram_begin; |
137,12 → 134,6 |
.write = sgcn_putchar |
}; |
/** SGCN input device operations */ |
static indev_operations_t sgcnin_ops = { |
.poll = NULL |
}; |
static indev_t sgcnin; /**< SGCN input device. */ |
static outdev_t sgcnout; /**< SGCN output device. */ |
/** |
288,7 → 279,7 |
*/ |
void sgcn_grab(void) |
{ |
kbd_disabled = true; |
kbd_disabled = false; |
} |
/** |
304,7 → 295,7 |
* there are some unread characters in the input queue. If so, it picks them up |
* and sends them to the upper layers of HelenOS. |
*/ |
static void sgcn_poll() |
static void sgcn_poll(sgcn_instance_t *instance) |
{ |
uint32_t begin = SGCN_BUFFER_HEADER->in_begin; |
uint32_t end = SGCN_BUFFER_HEADER->in_end; |
322,13 → 313,12 |
volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr); |
while (*in_rdptr_ptr != *in_wrptr_ptr) { |
buf_ptr = (volatile char *) |
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr); |
char c = *buf_ptr; |
*in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin; |
indev_push_character(&sgcnin, c); |
indev_push_character(instance->srlnin, c); |
} |
spinlock_unlock(&sgcn_input_lock); |
337,11 → 327,10 |
/** |
* Polling thread function. |
*/ |
static void kkbdpoll(void *arg) { |
static void ksgcnpoll(void *instance) { |
while (1) { |
if (!silent) { |
sgcn_poll(); |
} |
if (!silent) |
sgcn_poll(instance); |
thread_usleep(POLL_INTERVAL); |
} |
} |
349,23 → 338,36 |
/** |
* A public function which initializes input from the Serengeti console. |
*/ |
indev_t *sgcnin_init(void) |
sgcn_instance_t *sgcnin_init(void) |
{ |
sgcn_buffer_begin_init(); |
sgcn_instance_t *instance = |
malloc(sizeof(sgcn_instance_t), FRAME_ATOMIC); |
if (instance) { |
instance->srlnin = NULL; |
instance->thread = thread_create(ksgcnpoll, instance, TASK, 0, |
"ksgcnpoll", true); |
if (!instance->thread) { |
free(instance); |
return NULL; |
} |
} |
return instance; |
} |
kbd_type = KBD_SGCN; |
void sgcnin_wire(sgcn_instance_t *instance, indev_t *srlnin) |
{ |
ASSERT(instance); |
ASSERT(srlnin); |
instance->srlnin = srlnin; |
thread_ready(instance->thread); |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.type", NULL, KBD_SGCN); |
thread_t *t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true); |
if (!t) |
panic("Cannot create kkbdpoll."); |
thread_ready(t); |
indev_initialize("sgcnin", &sgcnin, &sgcnin_ops); |
return &sgcnin; |
} |
/** |
/branches/dd/kernel/arch/sparc64/src/start.S |
---|
294,7 → 294,7 |
/* Not reached. */ |
0: |
ba 0b |
ba %xcc, 0b |
nop |
352,7 → 352,7 |
#endif |
0: |
ba 0b |
ba %xcc, 0b |
nop |
/branches/dd/kernel/arch/ia64/include/ski/ski.h |
---|
File deleted |
/branches/dd/kernel/arch/ia64/include/arch.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia64 |
/** @addtogroup ia64 |
* @{ |
*/ |
/** @file |
37,7 → 37,7 |
#define LOADED_PROG_STACK_PAGES_NO 2 |
#include <arch/ski/ski.h> |
#include <arch/drivers/ski.h> |
extern void arch_pre_main(void); |
/branches/dd/kernel/arch/ia64/include/drivers/ski.h |
---|
0,0 → 1,56 |
/* |
* Copyright (c) 2005 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia64 |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_ia64_SKI_H_ |
#define KERN_ia64_SKI_H_ |
#include <console/chardev.h> |
#include <proc/thread.h> |
typedef struct { |
thread_t *thread; |
indev_t *srlnin; |
} ski_instance_t; |
extern void skiout_init(void); |
extern ski_instance_t *skiin_init(void); |
extern void skiin_wire(ski_instance_t *, indev_t *); |
extern void ski_kbd_grab(void); |
extern void ski_kbd_release(void); |
#endif |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/arch/ia64/Makefile.inc |
---|
64,8 → 64,7 |
arch/$(KARCH)/src/drivers/it.c |
ifeq ($(MACHINE),ski) |
ARCH_SOURCES += arch/$(KARCH)/src/ski/ski.c |
DEFS += -DSKI |
ARCH_SOURCES += arch/$(KARCH)/src/drivers/ski.c |
BFD = binary |
endif |
/branches/dd/kernel/arch/ia64/src/ski/ski.c |
---|
File deleted |
/branches/dd/kernel/arch/ia64/src/smp/smp.c |
---|
33,7 → 33,7 |
*/ |
#include <arch.h> |
#include <arch/ski/ski.h> |
#include <arch/drivers/ski.h> |
#include <arch/drivers/it.h> |
#include <arch/interrupt.h> |
#include <arch/barrier.h> |
/branches/dd/kernel/arch/ia64/src/ia64.c |
---|
33,7 → 33,7 |
*/ |
#include <arch.h> |
#include <arch/ski/ski.h> |
#include <arch/drivers/ski.h> |
#include <arch/drivers/it.h> |
#include <arch/interrupt.h> |
#include <arch/barrier.h> |
148,11 → 148,17 |
void arch_post_smp_init(void) |
{ |
#ifdef SKI |
indev_t *in; |
in = skiin_init(); |
if (in) |
srln_init(in); |
#ifdef MACHINE_ski |
ski_instance_t *ski_instance = skiin_init(); |
if (ski_instance) { |
srln_instance_t *srln_instance = srln_init(); |
if (srln_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *srln = srln_wire(srln_instance, sink); |
skiin_wire(ski_instance, srln); |
} |
} |
skiout_init(); |
#endif |
161,10 → 167,16 |
#endif |
#ifdef CONFIG_NS16550 |
indev_t *kbrdin_ns16550 |
ns16550_instance_t *ns16550_instance |
= ns16550_init((ns16550_t *) NS16550_BASE, NS16550_IRQ, NULL, NULL); |
if (kbrdin_ns16550) |
srln_init(kbrdin_ns16550); |
if (ns16550_instance) { |
srln_instance_t *srln_instance = srln_init(); |
if (srln_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *srln = srln_wire(srln_instance, sink); |
ns16550_wire(ns16550_instance, srln); |
} |
} |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.inr", NULL, NS16550_IRQ); |
176,9 → 188,15 |
#endif |
#ifdef CONFIG_I8042 |
indev_t *kbrdin_i8042 = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD); |
if (kbrdin_i8042) |
kbrd_init(kbrdin_i8042); |
i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD); |
if (i8042_instance) { |
kbrd_instance_t *kbrd_instance = kbrd_init(); |
if (kbrd_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *kbrd = kbrd_wire(kbrd_instance, sink); |
i8042_wire(i8042_instance, kbrd); |
} |
} |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.inr", NULL, IRQ_KBD); |
238,7 → 256,7 |
*/ |
void arch_grab_console(void) |
{ |
#ifdef SKI |
#ifdef MACHINE_ski |
ski_kbd_grab(); |
#endif |
} |
248,7 → 266,7 |
*/ |
void arch_release_console(void) |
{ |
#ifdef SKI |
#ifdef MACHINE_ski |
ski_kbd_release(); |
#endif |
} |
/branches/dd/kernel/arch/ia64/src/drivers/ski.c |
---|
0,0 → 1,246 |
/* |
* Copyright (c) 2005 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia64 |
* @{ |
*/ |
/** @file |
*/ |
#include <arch/drivers/ski.h> |
#include <console/console.h> |
#include <console/chardev.h> |
#include <sysinfo/sysinfo.h> |
#include <arch/types.h> |
#include <proc/thread.h> |
#include <synch/spinlock.h> |
#include <arch/asm.h> |
#include <arch/drivers/kbd.h> |
#include <string.h> |
#include <arch.h> |
enum { |
/** Interval between polling in microseconds */ |
POLL_INTERVAL = 10000, /* 0.01 s */ |
/** Max. number of characters to pull out at a time */ |
POLL_LIMIT = 30, |
SKI_INIT_CONSOLE = 20, |
SKI_GETCHAR = 21, |
SKI_PUTCHAR = 31 |
}; |
static void ski_putchar(outdev_t *, const wchar_t, bool); |
static outdev_operations_t skiout_ops = { |
.write = ski_putchar |
}; |
static outdev_t skiout; /**< Ski output device. */ |
static bool initialized = false; |
static bool kbd_disabled = false; |
/** Initialize debug console |
* |
* Issue SSC (Simulator System Call) to |
* to open debug console. |
* |
*/ |
static void ski_init(void) |
{ |
if (initialized) |
return; |
asm volatile ( |
"mov r15 = %0\n" |
"break 0x80000\n" |
: |
: "i" (SKI_INIT_CONSOLE) |
: "r15", "r8" |
); |
initialized = true; |
} |
static void ski_do_putchar(const wchar_t ch) |
{ |
asm volatile ( |
"mov r15 = %[cmd]\n" |
"mov r32 = %[ch]\n" /* r32 is in0 */ |
"break 0x80000\n" /* modifies r8 */ |
: |
: [cmd] "i" (SKI_PUTCHAR), [ch] "r" (ch) |
: "r15", "in0", "r8" |
); |
} |
/** Display character on debug console |
* |
* Use SSC (Simulator System Call) to |
* display character on debug console. |
* |
* @param dev Character device. |
* @param ch Character to be printed. |
* @param silent Whether the output should be silenced. |
* |
*/ |
static void ski_putchar(outdev_t *dev, const wchar_t ch, bool silent) |
{ |
if (!silent) { |
if (ascii_check(ch)) { |
if (ch == '\n') |
ski_do_putchar('\r'); |
ski_do_putchar(ch); |
} else |
ski_do_putchar(U_SPECIAL); |
} |
} |
void skiout_init(void) |
{ |
ski_init(); |
outdev_initialize("skiout", &skiout, &skiout_ops); |
stdout = &skiout; |
sysinfo_set_item_val("fb", NULL, false); |
} |
/** Ask debug console if a key was pressed. |
* |
* Use SSC (Simulator System Call) to |
* get character from debug console. |
* |
* This call is non-blocking. |
* |
* @return ASCII code of pressed key or 0 if no key pressed. |
* |
*/ |
static wchar_t ski_getchar(void) |
{ |
uint64_t ch; |
asm volatile ( |
"mov r15 = %1\n" |
"break 0x80000;;\n" /* modifies r8 */ |
"mov %0 = r8;;\n" |
: "=r" (ch) |
: "i" (SKI_GETCHAR) |
: "r15", "r8" |
); |
return (wchar_t) ch; |
} |
/** Ask keyboard if a key was pressed. |
* |
* If so, it will repeat and pull up to POLL_LIMIT characters. |
*/ |
static void poll_keyboard(ski_instance_t *instance) |
{ |
wchar_t ch; |
int count; |
if (kbd_disabled) |
return; |
count = POLL_LIMIT; |
while (count > 0) { |
ch = ski_getchar(); |
if (ch == '\0') |
break; |
indev_push_character(instance->srlnin, ch); |
--count; |
} |
} |
/** Kernel thread for polling keyboard. */ |
static void kskipoll(void *arg) |
{ |
ski_instance_t *instance = (ski_instance_t *) arg; |
while (true) { |
if (!silent) |
poll_keyboard(instance); |
thread_usleep(POLL_INTERVAL); |
} |
} |
ski_instance_t *skiin_init(void) |
{ |
ski_init(); |
ski_instance_t *instance = |
malloc(sizeof(ski_instance_t), FRAME_ATOMIC); |
if (instance) { |
instance->thread = thread_create(kskipoll, instance, TASK, 0, |
"kskipoll", true); |
if (!instance->thread) { |
free(instance); |
return NULL; |
} |
instance->srlnin = NULL; |
} |
return instance; |
} |
void skiin_wire(ski_instance_t *instance, indev_t *srlnin) |
{ |
ASSERT(instance); |
ASSERT(srlnin); |
instance->srlnin = srlnin; |
thread_ready(instance->thread); |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.type", NULL, KBD_SKI); |
} |
void ski_kbd_grab(void) |
{ |
kbd_disabled = false; |
} |
void ski_kbd_release(void) |
{ |
kbd_disabled = true; |
} |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/kernel/arch/arm32/include/console.h |
---|
File deleted |
/branches/dd/kernel/arch/arm32/Makefile.inc |
---|
51,7 → 51,6 |
arch/$(KARCH)/src/cpu/cpu.c \ |
arch/$(KARCH)/src/ddi/ddi.c \ |
arch/$(KARCH)/src/interrupt.c \ |
arch/$(KARCH)/src/console.c \ |
arch/$(KARCH)/src/exception.c \ |
arch/$(KARCH)/src/userspace.c \ |
arch/$(KARCH)/src/mm/as.c \ |
/branches/dd/kernel/arch/arm32/src/console.c |
---|
File deleted |
/branches/dd/kernel/arch/arm32/src/arm32.c |
---|
35,7 → 35,6 |
#include <arch.h> |
#include <config.h> |
#include <arch/console.h> |
#include <genarch/fb/fb.h> |
#include <genarch/fb/visuals.h> |
#include <genarch/drivers/dsrln/dsrlnin.h> |
42,6 → 41,7 |
#include <genarch/drivers/dsrln/dsrlnout.h> |
#include <genarch/srln/srln.h> |
#include <sysinfo/sysinfo.h> |
#include <console/console.h> |
#include <ddi/irq.h> |
#include <arch/drivers/gxemul.h> |
#include <print.h> |
129,11 → 129,18 |
#ifdef CONFIG_ARM_KBD |
/* |
* Initialize the GXemul keyboard port. Then initialize the serial line |
* module and connect it to the GXemul keyboard. Enable keyboard interrupts. |
* module and connect it to the GXemul keyboard. |
*/ |
indev_t *kbrdin = dsrlnin_init((dsrlnin_t *) gxemul_kbd, GXEMUL_KBD_IRQ); |
if (kbrdin) |
srln_init(kbrdin); |
dsrlnin_instance_t *dsrlnin_instance |
= dsrlnin_init((dsrlnin_t *) gxemul_kbd, GXEMUL_KBD_IRQ); |
if (dsrlnin_instance) { |
srln_instance_t *srln_instance = srln_init(); |
if (srln_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *srln = srln_wire(srln_instance, sink); |
dsrlnin_wire(dsrlnin_instance, srln); |
} |
} |
/* |
* This is the necessary evil until the userspace driver is entirely |
201,5 → 208,18 |
return addr; |
} |
/** Acquire console back for kernel. */ |
void arch_grab_console(void) |
{ |
#ifdef CONFIG_FB |
fb_redraw(); |
#endif |
} |
/** Return console to userspace. */ |
void arch_release_console(void) |
{ |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/ppc32/include/drivers/cuda.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc32/include/drivers/pic.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ppc32 |
/** @addtogroup ppc32 |
* @{ |
*/ |
/** @file |
36,6 → 36,7 |
#define KERN_ppc32_PIC_H_ |
#include <arch/types.h> |
#include <ddi/irq.h> |
#define PIC_PENDING_LOW 8 |
#define PIC_PENDING_HIGH 4 |
44,11 → 45,11 |
#define PIC_ACK_LOW 10 |
#define PIC_ACK_HIGH 6 |
void pic_init(uintptr_t base, size_t size); |
void pic_enable_interrupt(int intnum); |
void pic_disable_interrupt(int intnum); |
void pic_ack_interrupt(int intnum); |
int pic_get_pending(void); |
extern void pic_init(uintptr_t base, size_t size, cir_t *cir, void **cir_arg); |
extern void pic_enable_interrupt(inr_t intnum); |
extern void pic_disable_interrupt(inr_t intnum); |
extern void pic_ack_interrupt(void *arg, inr_t intnum); |
extern int pic_get_pending(void); |
#endif |
/branches/dd/kernel/arch/ppc32/Makefile.inc |
---|
54,7 → 54,6 |
arch/$(KARCH)/src/cpu/cpu.c \ |
arch/$(KARCH)/src/proc/scheduler.c \ |
arch/$(KARCH)/src/ddi/ddi.c \ |
arch/$(KARCH)/src/drivers/cuda.c \ |
arch/$(KARCH)/src/mm/as.c \ |
arch/$(KARCH)/src/mm/frame.c \ |
arch/$(KARCH)/src/mm/page.c \ |
/branches/dd/kernel/arch/ppc32/src/ppc32.c |
---|
35,7 → 35,7 |
#include <config.h> |
#include <arch.h> |
#include <arch/boot/boot.h> |
#include <arch/drivers/cuda.h> |
#include <genarch/drivers/via-cuda/cuda.h> |
#include <arch/interrupt.h> |
#include <genarch/fb/fb.h> |
#include <genarch/fb/visuals.h> |
44,10 → 44,12 |
#include <console/console.h> |
#include <ddi/irq.h> |
#include <arch/drivers/pic.h> |
#include <align.h> |
#include <macros.h> |
#include <string.h> |
#define IRQ_COUNT 64 |
#define IRQ_CUDA 10 |
bootinfo_t bootinfo; |
117,10 → 119,27 |
if (bootinfo.macio.addr) { |
/* Initialize PIC */ |
pic_init(bootinfo.macio.addr, PAGE_SIZE); |
cir_t cir; |
void *cir_arg; |
pic_init(bootinfo.macio.addr, PAGE_SIZE, &cir, &cir_arg); |
#ifdef CONFIG_VIA_CUDA |
uintptr_t pa = bootinfo.macio.addr + 0x16000; |
uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE); |
size_t offset = pa - aligned_addr; |
size_t size = 2 * PAGE_SIZE; |
cuda_t *cuda = (cuda_t *) |
(hw_map(aligned_addr, offset + size) + offset); |
/* Initialize I/O controller */ |
cuda_init(bootinfo.macio.addr + 0x16000, 2 * PAGE_SIZE); |
cuda_instance_t *cuda_instance = |
cuda_init(cuda, IRQ_CUDA, cir, cir_arg); |
if (cuda_instance) { |
indev_t *sink = stdin_wire(); |
cuda_wire(cuda_instance, sink); |
} |
#endif |
} |
/* Merge all zones to 1 big zone */ |
186,5 → 205,11 |
return addr; |
} |
void arch_reboot(void) |
{ |
// TODO |
while (1); |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/ppc32/src/dummy.s |
---|
30,6 → 30,7 |
.global asm_delay_loop |
.global sys_tls_set |
.global cpu_halt |
sys_tls_set: |
b sys_tls_set |
36,3 → 37,6 |
asm_delay_loop: |
blr |
cpu_halt: |
b cpu_halt |
/branches/dd/kernel/arch/ppc32/src/interrupt.c |
---|
60,7 → 60,6 |
int inum; |
while ((inum = pic_get_pending()) != -1) { |
bool ack = false; |
irq_t *irq = irq_dispatch_and_lock(inum); |
if (irq) { |
/* |
69,11 → 68,17 |
if (irq->preack) { |
/* Acknowledge the interrupt before processing */ |
pic_ack_interrupt(inum); |
ack = true; |
if (irq->cir) |
irq->cir(irq->cir_arg, irq->inr); |
} |
irq->handler(irq); |
if (!irq->preack) { |
if (irq->cir) |
irq->cir(irq->cir_arg, irq->inr); |
} |
spinlock_unlock(&irq->lock); |
} else { |
/* |
83,9 → 88,6 |
printf("cpu%u: spurious interrupt (inum=%d)\n", CPU->id, inum); |
#endif |
} |
if (!ack) |
pic_ack_interrupt(inum); |
} |
} |
/branches/dd/kernel/arch/ppc32/src/drivers/cuda.c |
---|
File deleted |
/branches/dd/kernel/arch/ppc32/src/drivers/pic.c |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ppc32 |
/** @addtogroup ppc32 |
* @{ |
*/ |
/** @file |
40,12 → 40,14 |
static volatile uint32_t *pic = NULL; |
void pic_init(uintptr_t base, size_t size) |
void pic_init(uintptr_t base, size_t size, cir_t *cir, void **cir_arg) |
{ |
pic = (uint32_t *) hw_map(base, size); |
*cir = pic_ack_interrupt; |
*cir_arg = NULL; |
} |
void pic_enable_interrupt(int intnum) |
void pic_enable_interrupt(inr_t intnum) |
{ |
if (pic) { |
if (intnum < 32) |
56,7 → 58,7 |
} |
void pic_disable_interrupt(int intnum) |
void pic_disable_interrupt(inr_t intnum) |
{ |
if (pic) { |
if (intnum < 32) |
66,7 → 68,7 |
} |
} |
void pic_ack_interrupt(int intnum) |
void pic_ack_interrupt(void *arg, inr_t intnum) |
{ |
if (pic) { |
if (intnum < 32) |
/branches/dd/kernel/arch/amd64/include/atomic.h |
---|
115,9 → 115,7 |
preemption_disable(); |
asm volatile ( |
"0:\n" |
#ifdef CONFIG_HT |
"pause\n" |
#endif |
"mov %[count], %[tmp]\n" |
"testq %[tmp], %[tmp]\n" |
"jnz 0b\n" /* lightweight looping on locked spinlock */ |
/branches/dd/kernel/arch/amd64/src/amd64.c |
---|
197,10 → 197,15 |
* Initialize the i8042 controller. Then initialize the keyboard |
* module and connect it to i8042. Enable keyboard interrupts. |
*/ |
indev_t *kbrdin = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD); |
if (kbrdin) { |
kbrd_init(kbrdin); |
trap_virtual_enable_irqs(1 << IRQ_KBD); |
i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD); |
if (i8042_instance) { |
kbrd_instance_t *kbrd_instance = kbrd_init(); |
if (kbrd_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *kbrd = kbrd_wire(kbrd_instance, sink); |
i8042_wire(i8042_instance, kbrd); |
trap_virtual_enable_irqs(1 << IRQ_KBD); |
} |
} |
/* |
/branches/dd/kernel/arch/mips32/include/console.h |
---|
File deleted |
/branches/dd/kernel/arch/mips32/include/elf.h |
---|
35,9 → 35,11 |
#ifndef KERN_mips32_ELF_H_ |
#define KERN_mips32_ELF_H_ |
#include <byteorder.h> |
#define ELF_MACHINE EM_MIPS |
#ifdef BIG_ENDIAN |
#ifdef ARCH_IS_BIG_ENDIAN |
# define ELF_DATA_ENCODING ELFDATA2MSB |
#else |
# define ELF_DATA_ENCODING ELFDATA2LSB |
/branches/dd/kernel/arch/mips32/Makefile.inc |
---|
60,7 → 60,6 |
arch/$(KARCH)/src/context.S \ |
arch/$(KARCH)/src/panic.S \ |
arch/$(KARCH)/src/mips32.c \ |
arch/$(KARCH)/src/console.c \ |
arch/$(KARCH)/src/asm.S \ |
arch/$(KARCH)/src/exception.c \ |
arch/$(KARCH)/src/interrupt.c \ |
/branches/dd/kernel/arch/mips32/src/console.c |
---|
File deleted |
/branches/dd/kernel/arch/mips32/src/mips32.c |
---|
36,16 → 36,14 |
#include <arch/cp0.h> |
#include <arch/exception.h> |
#include <mm/as.h> |
#include <userspace.h> |
#include <arch/console.h> |
#include <memstr.h> |
#include <proc/thread.h> |
#include <proc/uarg.h> |
#include <print.h> |
#include <console/console.h> |
#include <syscall/syscall.h> |
#include <sysinfo/sysinfo.h> |
#include <arch/interrupt.h> |
#include <console/chardev.h> |
#include <arch/barrier.h> |
59,7 → 57,6 |
#include <config.h> |
#include <string.h> |
#include <arch/drivers/msim.h> |
#include <arch/asm/regname.h> |
/* Size of the code jumping to the exception handler code |
169,10 → 166,16 |
* Initialize the msim/GXemul keyboard port. Then initialize the serial line |
* module and connect it to the msim/GXemul keyboard. Enable keyboard interrupts. |
*/ |
indev_t *kbrdin = dsrlnin_init((dsrlnin_t *) MSIM_KBD_ADDRESS, MSIM_KBD_IRQ); |
if (kbrdin) { |
srln_init(kbrdin); |
cp0_unmask_int(MSIM_KBD_IRQ); |
dsrlnin_instance_t *dsrlnin_instance |
= dsrlnin_init((dsrlnin_t *) MSIM_KBD_ADDRESS, MSIM_KBD_IRQ); |
if (dsrlnin_instance) { |
srln_instance_t *srln_instance = srln_init(); |
if (srln_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *srln = srln_wire(srln_instance, sink); |
dsrlnin_wire(dsrlnin_instance, srln); |
cp0_unmask_int(MSIM_KBD_IRQ); |
} |
} |
/* |
248,5 → 251,19 |
return addr; |
} |
void arch_grab_console(void) |
{ |
#ifdef CONFIG_FB |
fb_redraw(); |
#endif |
} |
/** Return console to userspace |
* |
*/ |
void arch_release_console(void) |
{ |
} |
/** @} |
*/ |
/branches/dd/kernel/arch/ia32/include/atomic.h |
---|
114,9 → 114,7 |
preemption_disable(); |
asm volatile ( |
"0:\n" |
#ifdef CONFIG_HT |
"pause\n" /* Pentium 4's HT love this instruction */ |
#endif |
"mov %[count], %[tmp]\n" |
"testl %[tmp], %[tmp]\n" |
"jnz 0b\n" /* lightweight looping on locked spinlock */ |
/branches/dd/kernel/arch/ia32/src/ia32.c |
---|
80,7 → 80,7 |
void arch_pre_main(uint32_t signature, const multiboot_info_t *mi) |
{ |
/* Parse multiboot information obtained from the bootloader. */ |
multiboot_info_parse(signature, mi); |
multiboot_info_parse(signature, mi); |
#ifdef CONFIG_SMP |
/* Copy AP bootstrap routines below 1 MB. */ |
155,10 → 155,15 |
* Initialize the i8042 controller. Then initialize the keyboard |
* module and connect it to i8042. Enable keyboard interrupts. |
*/ |
indev_t *kbrdin = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD); |
if (kbrdin) { |
kbrd_init(kbrdin); |
trap_virtual_enable_irqs(1 << IRQ_KBD); |
i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD); |
if (i8042_instance) { |
kbrd_instance_t *kbrd_instance = kbrd_init(); |
if (kbrd_instance) { |
indev_t *sink = stdin_wire(); |
indev_t *kbrd = kbrd_wire(kbrd_instance, sink); |
i8042_wire(i8042_instance, kbrd); |
trap_virtual_enable_irqs(1 << IRQ_KBD); |
} |
} |
/* |
/branches/dd/kernel/arch/ia32/src/atomic.S |
---|
42,9 → 42,7 |
movl 12(%esp),%ebx |
0: |
#ifdef CONFIG_HT |
pause # Pentium 4's with HT love this instruction |
#endif |
movl (%ebx),%eax |
testl %eax,%eax |
jnz 0b # lightweight looping while it is locked |
/branches/dd/tools/mkfat.py |
---|
138,7 → 138,7 |
char name[8] /* file name */ |
char ext[3] /* file extension */ |
uint8_t attr /* file attributes */ |
padding[1] /* reserved for NT */ |
uint8_t lcase /* file name case (NT extension) */ |
uint8_t ctime_fine /* create time (fine resolution) */ |
uint16_t ctime /* create time */ |
uint16_t cdate /* create date */ |
217,6 → 217,7 |
else: |
dir_entry.attr = 0x20 |
dir_entry.lcase = 0x18 |
dir_entry.ctime_fine = 0 # FIXME |
dir_entry.ctime = 0 # FIXME |
dir_entry.cdate = 0 # FIXME |
/branches/dd/uspace/app/bdsh/cmds/modules/mv/mv.c |
---|
0,0 → 1,70 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <errno.h> |
#include "config.h" |
#include "util.h" |
#include "errors.h" |
#include "entry.h" |
#include "mv.h" |
#include "cmds.h" |
static const char *cmdname = "mv"; |
/* Dispays help for mv in various levels */ |
void help_cmd_mv(unsigned int level) |
{ |
printf("'%s' renames files\n", cmdname); |
return; |
} |
/* Main entry point for mv, accepts an array of arguments */ |
int cmd_mv(char **argv) |
{ |
unsigned int argc; |
int rc; |
argc = cli_count_args(argv); |
if (argc != 3) { |
printf("%s: invalid number of arguments.\n", |
cmdname); |
return CMD_FAILURE; |
} |
rc = rename(argv[1], argv[2]); |
if (rc != EOK) { |
printf("Unable to rename %s to %s (rc=%d)\n", |
argv[1], argv[2], rc); |
return CMD_FAILURE; |
} |
return CMD_SUCCESS; |
} |
/branches/dd/uspace/app/bdsh/cmds/modules/mv/mv_def.h |
---|
0,0 → 1,14 |
{ |
"mv", |
"The mv command", |
&cmd_mv, |
&help_cmd_mv, |
}, |
{ |
"ren", |
NULL, |
&cmd_mv, |
&help_cmd_mv, |
}, |
/branches/dd/uspace/app/bdsh/cmds/modules/mv/entry.h |
---|
0,0 → 1,9 |
#ifndef MV_ENTRY_H |
#define MV_ENTRY_H |
/* Entry points for the mv command */ |
extern int cmd_mv(char **); |
extern void help_cmd_mv(unsigned int); |
#endif /* MV_ENTRY_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/mv/mv.h |
---|
0,0 → 1,8 |
#ifndef MV_H |
#define MV_H |
/* Prototypes for the mv command, excluding entry points */ |
#endif /* MV_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/bdd/bdd.h |
---|
0,0 → 1,8 |
#ifndef BDD_H |
#define BDD_H |
/* Prototypes for the bdd command, excluding entry points */ |
#endif /* BDD_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/bdd/entry.h |
---|
0,0 → 1,9 |
#ifndef BDD_ENTRY_H |
#define BDD_ENTRY_H |
/* Entry points for the bdd command */ |
extern int cmd_bdd(char **); |
extern void help_cmd_bdd(unsigned int); |
#endif /* BDD_ENTRY_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/bdd/bdd.c |
---|
0,0 → 1,153 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include "config.h" |
#include "util.h" |
#include "errors.h" |
#include "entry.h" |
#include "bdd.h" |
#include "cmds.h" |
#include <libblock.h> |
#include <devmap.h> |
#include <errno.h> |
#define BLOCK_SIZE 512 |
#define BPR 16 |
static const char *cmdname = "bdd"; |
/* Dispays help for bdd in various levels */ |
void help_cmd_bdd(unsigned int level) |
{ |
static char helpfmt[] = |
"Usage: %s <device> [<block_number> [<bytes>]]\n"; |
if (level == HELP_SHORT) { |
printf("'%s' dump block device contents.\n", cmdname); |
} else { |
help_cmd_bdd(HELP_SHORT); |
printf(helpfmt, cmdname); |
} |
return; |
} |
/* Main entry point for bdd, accepts an array of arguments */ |
int cmd_bdd(char **argv) |
{ |
unsigned int argc; |
unsigned int i, j; |
dev_handle_t handle; |
block_t *block; |
uint8_t *blk; |
size_t size, bytes, rows; |
int rc; |
bn_t boff; |
uint8_t b; |
/* Count the arguments */ |
for (argc = 0; argv[argc] != NULL; argc ++); |
if (argc < 2 || argc > 4) { |
printf("%s - incorrect number of arguments.\n", cmdname); |
return CMD_FAILURE; |
} |
if (argc >= 3) |
boff = strtol(argv[2], NULL, 0); |
else |
boff = 0; |
if (argc >= 4) |
size = strtol(argv[3], NULL, 0); |
else |
size = 256; |
rc = devmap_device_get_handle(argv[1], &handle, 0); |
if (rc != EOK) { |
printf("Error: could not resolve device `%s'.\n", argv[1]); |
return CMD_FAILURE; |
} |
rc = block_init(handle, BLOCK_SIZE); |
if (rc != EOK) { |
printf("Error: could not init libblock.\n"); |
return CMD_FAILURE; |
} |
rc = block_cache_init(handle, BLOCK_SIZE, 2); |
if (rc != EOK) { |
printf("Error: could not init block cache.\n"); |
return CMD_FAILURE; |
} |
while (size > 0) { |
block = block_get(handle, boff, 0); |
blk = (uint8_t *) block->data; |
bytes = (size < BLOCK_SIZE) ? size : BLOCK_SIZE; |
rows = (bytes + BPR - 1) / BPR; |
for (j = 0; j < rows; j++) { |
for (i = 0; i < BPR; i++) { |
if (j * BPR + i < bytes) |
printf("%02x ", blk[j * BPR + i]); |
else |
printf(" "); |
} |
putchar('\t'); |
for (i = 0; i < BPR; i++) { |
if (j * BPR + i < bytes) { |
b = blk[j * BPR + i]; |
if (b >= 32 && b < 127) |
putchar(b); |
else |
putchar(' '); |
} else { |
putchar(' '); |
} |
} |
putchar('\n'); |
} |
block_put(block); |
if (size > rows * BPR) |
size -= rows * BPR; |
else |
size = 0; |
boff += rows * BPR; |
} |
block_fini(handle); |
return CMD_SUCCESS; |
} |
/branches/dd/uspace/app/bdsh/cmds/modules/bdd/bdd_def.h |
---|
0,0 → 1,7 |
{ |
"bdd", |
"Dump block device contents", |
&cmd_bdd, |
&help_cmd_bdd, |
}, |
/branches/dd/uspace/app/bdsh/cmds/modules/modules.h |
---|
20,6 → 20,7 |
#include "help/entry.h" |
#include "mkdir/entry.h" |
#include "rm/entry.h" |
#include "bdd/entry.h" |
#include "cat/entry.h" |
#include "touch/entry.h" |
#include "ls/entry.h" |
26,6 → 27,8 |
#include "pwd/entry.h" |
#include "sleep/entry.h" |
#include "cp/entry.h" |
#include "mv/entry.h" |
#include "mount/entry.h" |
#include "kcon/entry.h" |
/* Each .def function fills the module_t struct with the individual name, entry |
36,6 → 39,7 |
#include "help/help_def.h" |
#include "mkdir/mkdir_def.h" |
#include "rm/rm_def.h" |
#include "bdd/bdd_def.h" |
#include "cat/cat_def.h" |
#include "touch/touch_def.h" |
#include "ls/ls_def.h" |
42,7 → 46,10 |
#include "pwd/pwd_def.h" |
#include "sleep/sleep_def.h" |
#include "cp/cp_def.h" |
#include "mv/mv_def.h" |
#include "mount/mount_def.h" |
#include "kcon/kcon_def.h" |
{NULL, NULL, NULL, NULL} |
}; |
/branches/dd/uspace/app/bdsh/cmds/modules/mount/mount.c |
---|
0,0 → 1,82 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <vfs/vfs.h> |
#include <errno.h> |
#include "config.h" |
#include "util.h" |
#include "errors.h" |
#include "entry.h" |
#include "mount.h" |
#include "cmds.h" |
static const char *cmdname = "mount"; |
/* Dispays help for mount in various levels */ |
void help_cmd_mount(unsigned int level) |
{ |
static char helpfmt[] = |
"Usage: %s <fstype> <mp> <dev> [<moptions>]\n"; |
if (level == HELP_SHORT) { |
printf("'%s' mounts a file system.\n", cmdname); |
} else { |
help_cmd_mount(HELP_SHORT); |
printf(helpfmt, cmdname); |
} |
return; |
} |
/* Main entry point for mount, accepts an array of arguments */ |
int cmd_mount(char **argv) |
{ |
unsigned int argc; |
char *mopts = ""; |
int rc; |
argc = cli_count_args(argv); |
if ((argc < 4) || (argc > 5)) { |
printf("%s: invalid number of arguments.\n", |
cmdname); |
return CMD_FAILURE; |
} |
if (argc == 5) |
mopts = argv[4]; |
rc = mount(argv[1], argv[2], argv[3], mopts, 0); |
if (rc != EOK) { |
printf("Unable to mount %s filesystem to %s on %s (rc=%d)\n", |
argv[1], argv[2], argv[3], rc); |
return CMD_FAILURE; |
} |
return CMD_SUCCESS; |
} |
/branches/dd/uspace/app/bdsh/cmds/modules/mount/mount_def.h |
---|
0,0 → 1,7 |
{ |
"mount", |
"The mount command", |
&cmd_mount, |
&help_cmd_mount, |
}, |
/branches/dd/uspace/app/bdsh/cmds/modules/mount/entry.h |
---|
0,0 → 1,9 |
#ifndef MOUNT_ENTRY_H |
#define MOUNT_ENTRY_H |
/* Entry points for the mount command */ |
extern int cmd_mount(char **); |
extern void help_cmd_mount(unsigned int); |
#endif /* MOUNT_ENTRY_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/mount/mount.h |
---|
0,0 → 1,8 |
#ifndef MOUNT_H |
#define MOUNT_H |
/* Prototypes for the mount command, excluding entry points */ |
#endif /* MOUNT_H */ |
/branches/dd/uspace/app/bdsh/cmds/modules/cat/cat.c |
---|
87,7 → 87,8 |
off_t total = 0; |
char *buff = NULL; |
if (-1 == (fd = open(fname, O_RDONLY))) { |
fd = open(fname, O_RDONLY); |
if (fd < 0) { |
printf("Unable to open %s\n", fname); |
return 1; |
} |
/branches/dd/uspace/app/bdsh/cmds/modules/module_aliases.h |
---|
12,6 → 12,7 |
* the entry point being reached. */ |
char *mod_aliases[] = { |
"ren", "mv", |
NULL, NULL |
}; |
/branches/dd/uspace/app/bdsh/Makefile |
---|
33,12 → 33,13 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
LIBBLOCK_PREFIX = ../../lib/libblock |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../../srv/kbd/include |
CFLAGS += -I../../srv/kbd/include -I$(LIBBLOCK_PREFIX) |
LIBS = $(LIBC_PREFIX)/libc.a |
LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBC_PREFIX)/libc.a |
DEFS += -DRELEASE=$(RELEASE) |
PROGRAM = bdsh |
51,6 → 52,7 |
cmds/modules/help/ \ |
cmds/modules/mkdir/ \ |
cmds/modules/rm/ \ |
cmds/modules/bdd/ \ |
cmds/modules/cat/ \ |
cmds/modules/touch/ \ |
cmds/modules/ls/ \ |
57,6 → 59,8 |
cmds/modules/pwd/ \ |
cmds/modules/sleep/ \ |
cmds/modules/cp/ \ |
cmds/modules/mv/ \ |
cmds/modules/mount/ \ |
cmds/modules/kcon/ \ |
cmds/builtins/ \ |
cmds/builtins/exit/\ |
66,6 → 70,7 |
cmds/modules/help/help.c \ |
cmds/modules/mkdir/mkdir.c \ |
cmds/modules/rm/rm.c \ |
cmds/modules/bdd/bdd.c \ |
cmds/modules/cat/cat.c \ |
cmds/modules/touch/touch.c \ |
cmds/modules/ls/ls.c \ |
72,6 → 77,8 |
cmds/modules/pwd/pwd.c \ |
cmds/modules/sleep/sleep.c \ |
cmds/modules/cp/cp.c \ |
cmds/modules/mv/mv.c \ |
cmds/modules/mount/mount.c \ |
cmds/modules/kcon/kcon.c \ |
cmds/builtins/exit/exit.c \ |
cmds/builtins/cd/cd.c \ |
/branches/dd/uspace/app/init/init.c |
---|
45,6 → 45,7 |
#include <malloc.h> |
#include <macros.h> |
#include <console.h> |
#include <string.h> |
#include "init.h" |
#include "version.h" |
51,9 → 52,13 |
static bool mount_fs(const char *fstype) |
{ |
int rc = -1; |
char *opts = ""; |
if (str_cmp(fstype, "tmpfs") == 0) |
opts = "restore"; |
while (rc < 0) { |
rc = mount(fstype, "/", "initrd", IPC_FLAG_BLOCKING); |
rc = mount(fstype, "/", "initrd", opts, IPC_FLAG_BLOCKING); |
switch (rc) { |
case EOK: |
74,6 → 79,32 |
return true; |
} |
static bool mount_devfs(void) |
{ |
int rc = -1; |
while (rc < 0) { |
rc = mount("devfs", "/dev", "null", "", IPC_FLAG_BLOCKING); |
switch (rc) { |
case EOK: |
printf(NAME ": Device filesystem mounted\n"); |
break; |
case EBUSY: |
printf(NAME ": Device filesystem already mounted\n"); |
break; |
case ELIMIT: |
printf(NAME ": Unable to mount device filesystem\n"); |
return false; |
case ENOENT: |
printf(NAME ": Unknown filesystem type (devfs)\n"); |
return false; |
} |
} |
return true; |
} |
static void spawn(char *fname) |
{ |
char *argv[2]; |
83,12 → 114,8 |
argv[0] = fname; |
argv[1] = NULL; |
if (task_spawn(fname, argv)) { |
/* Add reasonable delay to avoid intermixed klog output. */ |
usleep(10000); |
} else { |
if (!task_spawn(fname, argv)) |
printf(NAME ": Error spawning %s\n", fname); |
} |
} |
int main(int argc, char *argv[]) |
100,6 → 127,13 |
return -1; |
} |
spawn("/srv/devfs"); |
if (!mount_devfs()) { |
return(NAME ": Exiting\n"); |
return -2; |
} |
spawn("/srv/fb"); |
spawn("/srv/kbd"); |
spawn("/srv/console"); |
/branches/dd/uspace/app/init/Makefile |
---|
69,7 → 69,7 |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/app/tester/tester.c |
---|
56,6 → 56,7 |
#include "ipc/send_sync.def" |
#include "ipc/answer.def" |
#include "ipc/hangup.def" |
#include "ipc/ping_pong.def" |
#include "devmap/devmap1.def" |
#include "loop/loop1.def" |
#include "vfs/vfs1.def" |
/branches/dd/uspace/app/tester/ipc/ping_pong.c |
---|
0,0 → 1,68 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <console.h> |
#include <sys/time.h> |
#include "../tester.h" |
#define DURATION_SECS 10 |
#define COUNT_GRANULARITY 100 |
char * test_ping_pong(bool quiet) |
{ |
int i; |
int w, h; |
struct timeval start, now; |
long count; |
printf("Pinging console server for %d seconds...\n", DURATION_SECS); |
if (gettimeofday(&start, NULL) != 0) |
return "Failed getting the time."; |
count = 0; |
while (true) { |
if (gettimeofday(&now, NULL) != 0) |
return "Failed getting the time."; |
if (tv_sub(&now, &start) >= DURATION_SECS * 1000000L) |
break; |
for (i = 0; i < COUNT_GRANULARITY; i++) |
console_get_size(&w, &h); |
count += COUNT_GRANULARITY; |
} |
printf("Completed %ld round trips in %d seconds, %ld RT/s.\n", count, |
DURATION_SECS, count / DURATION_SECS); |
return NULL; |
} |
/branches/dd/uspace/app/tester/ipc/ping_pong.def |
---|
0,0 → 1,6 |
{ |
"ping_pong", |
"IPC ping-pong benchmark", |
&test_ping_pong, |
true |
}, |
/branches/dd/uspace/app/tester/devmap/devmap1.c |
---|
32,7 → 32,7 |
#include <ipc/services.h> |
#include <async.h> |
#include <errno.h> |
#include <ipc/devmap.h> |
#include <devmap.h> |
#include "../tester.h" |
#include <time.h> |
84,22 → 84,14 |
handle = (int)arg; |
device_phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, |
DEVMAP_CONNECT_TO_DEVICE, handle); |
device_phone = devmap_device_connect(handle, 0); |
if (device_phone < 0) { |
printf("Failed to connect to devmap as client (handle = %u).\n", |
printf("Failed to connect to device (handle = %u).\n", |
handle); |
return -1; |
} |
/* |
* device_phone = (int) IPC_GET_ARG5(answer); |
*/ |
printf("Connected to device.\n"); |
ipc_call_sync_1_0(device_phone, 1024, 1025); |
/* |
* ipc_hangup(device_phone); |
*/ |
ipc_hangup(device_phone); |
return EOK; |
121,126 → 113,6 |
return EOK; |
} |
/** |
* |
*/ |
static int driver_register(char *name) |
{ |
ipcarg_t retval; |
aid_t req; |
ipc_call_t answer; |
int phone; |
ipcarg_t callback_phonehash; |
phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0); |
if (phone < 0) { |
printf("Failed to connect to device mapper\n"); |
return -1; |
} |
req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer); |
retval = ipc_data_write_start(phone, (char *)name, str_size(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
return -1; |
} |
async_set_client_connection(driver_client_connection); |
ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash); |
/* |
if (NULL == async_new_connection(callback_phonehash, 0, NULL, |
driver_client_connection)) { |
printf("Failed to create new fibril.\n"); |
async_wait_for(req, NULL); |
return -1; |
} |
*/ |
async_wait_for(req, &retval); |
printf("Driver '%s' registered.\n", name); |
return phone; |
} |
static int device_get_handle(int driver_phone, char *name, int *handle) |
{ |
ipcarg_t retval; |
aid_t req; |
ipc_call_t answer; |
req = async_send_2(driver_phone, DEVMAP_DEVICE_GET_HANDLE, 0, 0, |
&answer); |
retval = ipc_data_write_start(driver_phone, name, str_size(name) + 1); |
if (retval != EOK) { |
printf("Failed to send device name '%s'.\n", name); |
async_wait_for(req, NULL); |
return retval; |
} |
async_wait_for(req, &retval); |
if (NULL != handle) { |
*handle = -1; |
} |
if (EOK == retval) { |
if (NULL != handle) { |
*handle = (int) IPC_GET_ARG1(answer); |
} |
printf("Device '%s' has handle %u.\n", name, |
(int) IPC_GET_ARG1(answer)); |
} else { |
printf("Failed to get handle for device '%s'.\n", name); |
} |
return retval; |
} |
/** Register new device. |
* @param driver_phone |
* @param name Device name. |
* @param handle Output variable. Handle to the created instance of device. |
*/ |
static int device_register(int driver_phone, char *name, int *handle) |
{ |
ipcarg_t retval; |
aid_t req; |
ipc_call_t answer; |
req = async_send_2(driver_phone, DEVMAP_DEVICE_REGISTER, 0, 0, &answer); |
retval = ipc_data_write_start(driver_phone, (char *)name, |
str_size(name) + 1); |
if (retval != EOK) { |
printf("Failed to send device name '%s'.\n", name); |
async_wait_for(req, NULL); |
return retval; |
} |
async_wait_for(req, &retval); |
if (NULL != handle) { |
*handle = -1; |
} |
if (EOK == retval) { |
if (NULL != handle) { |
*handle = (int) IPC_GET_ARG1(answer); |
} |
printf("Device registered with handle %u.\n", |
(int) IPC_GET_ARG1(answer)); |
} |
return retval; |
} |
/** Test DevMap from the driver's point of view. |
* |
* |
247,64 → 119,71 |
*/ |
char * test_devmap1(bool quiet) |
{ |
int driver_phone; |
int dev1_handle; |
int dev2_handle; |
int dev3_handle; |
int handle; |
const char *retval = NULL; |
/* Register new driver */ |
driver_phone = driver_register("TestDriver"); |
if (driver_phone < 0) { |
return "Error: Cannot register driver.\n"; |
int rc = devmap_driver_register("TestDriver", driver_client_connection); |
if (rc < 0) { |
retval = "Error: Cannot register driver.\n"; |
goto out; |
} |
/* Register new device dev1*/ |
if (EOK != device_register(driver_phone, TEST_DEVICE1, &dev1_handle)) { |
ipc_hangup(driver_phone); |
return "Error: cannot register device.\n"; |
/* Register new device dev1. */ |
dev_handle_t dev1_handle; |
rc = devmap_device_register(TEST_DEVICE1, &dev1_handle); |
if (rc != EOK) { |
retval = "Error: cannot register device.\n"; |
goto out; |
} |
/* Get handle for dev2 (Should fail unless device is already |
* registered by someone else) |
/* |
* Get handle for dev2 (Should fail unless device is already registered |
* by someone else). |
*/ |
if (EOK == device_get_handle(driver_phone, TEST_DEVICE2, &handle)) { |
ipc_hangup(driver_phone); |
return "Error: got handle for dev2 before it was registered.\n"; |
dev_handle_t handle; |
rc = devmap_device_get_handle(TEST_DEVICE2, &handle, 0); |
if (rc == EOK) { |
retval = "Error: got handle for dev2 before it was registered.\n"; |
goto out; |
} |
/* Register new device dev2*/ |
if (EOK != device_register(driver_phone, TEST_DEVICE2, &dev2_handle)) { |
ipc_hangup(driver_phone); |
return "Error: cannot register device dev2.\n"; |
/* Register new device dev2. */ |
dev_handle_t dev2_handle; |
rc = devmap_device_register(TEST_DEVICE2, &dev2_handle); |
if (rc != EOK) { |
retval = "Error: cannot register device dev2.\n"; |
goto out; |
} |
/* Register again device dev1 */ |
if (EOK == device_register(driver_phone, TEST_DEVICE1, &dev3_handle)) { |
return "Error: dev1 registered twice.\n"; |
/* Register device dev1 again. */ |
dev_handle_t dev3_handle; |
rc = devmap_device_register(TEST_DEVICE1, &dev3_handle); |
if (rc == EOK) { |
retval = "Error: dev1 registered twice.\n"; |
goto out; |
} |
/* Get handle for dev1*/ |
if (EOK != device_get_handle(driver_phone, TEST_DEVICE1, &handle)) { |
ipc_hangup(driver_phone); |
return "Error: cannot get handle for 'DEVMAP_DEVICE1'.\n"; |
/* Get handle for dev1. */ |
rc = devmap_device_get_handle(TEST_DEVICE1, &handle, 0); |
if (rc != EOK) { |
retval = "Error: cannot get handle for 'DEVMAP_DEVICE1'.\n"; |
goto out; |
} |
if (handle != dev1_handle) { |
ipc_hangup(driver_phone); |
return "Error: cannot get handle for 'DEVMAP_DEVICE1'.\n"; |
retval = "Error: cannot get handle for 'DEVMAP_DEVICE1'.\n"; |
goto out; |
} |
if (EOK != device_client(dev1_handle)) { |
ipc_hangup(driver_phone); |
return "Error: failed client test for 'DEVMAP_DEVICE1'.\n"; |
if (device_client(dev1_handle) != EOK) { |
retval = "Error: failed client test for 'DEVMAP_DEVICE1'.\n"; |
goto out; |
} |
/* TODO: */ |
ipc_hangup(driver_phone); |
out: |
devmap_hangup_phone(DEVMAP_DRIVER); |
devmap_hangup_phone(DEVMAP_CLIENT); |
return NULL; |
} |
/branches/dd/uspace/app/tester/tester.h |
---|
69,6 → 69,7 |
extern char * test_send_sync(bool quiet); |
extern char * test_answer(bool quiet); |
extern char * test_hangup(bool quiet); |
extern char * test_ping_pong(bool quiet); |
extern char * test_devmap1(bool quiet); |
extern char * test_loop1(bool quiet); |
extern char * test_vfs1(bool quiet); |
/branches/dd/uspace/app/tester/Makefile |
---|
54,6 → 54,7 |
ipc/send_sync.c \ |
ipc/answer.c \ |
ipc/hangup.c \ |
ipc/ping_pong.c \ |
loop/loop1.c \ |
devmap/devmap1.c \ |
console/console1.c \ |
81,7 → 82,7 |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/app/tester/vfs/vfs1.c |
---|
45,7 → 45,7 |
{ |
int rc; |
rc = mount("tmpfs", "/", "nulldev0", 0); |
rc = mount("tmpfs", "/", "nulldev0", "", 0); |
switch (rc) { |
case EOK: |
if (!quiet) |
/branches/dd/uspace/app/tetris/input.c |
---|
115,7 → 115,7 |
if (!lastchar) { |
again: |
if (!getchar_inprog) { |
cons_phone = console_phone_get(true); |
cons_phone = console_open(true); |
getchar_inprog = async_send_2(cons_phone, |
CONSOLE_GETKEY, 0, 0, &charcall); |
} |
/branches/dd/uspace/app/tetris/Makefile |
---|
27,7 → 27,7 |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/app/klog/Makefile |
---|
64,7 → 64,7 |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/app/trace/trace.c |
---|
666,6 → 666,8 |
arg_def[0] = V_CHAR; |
o = oper_new("putchar", 1, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_PUTCHAR, o); |
o = oper_new("write", 0, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_WRITE, o); |
o = oper_new("clear", 0, arg_def, V_VOID, 0, resp_def); |
proto_add_oper(p, CONSOLE_CLEAR, o); |
/branches/dd/uspace/lib/libfs/libfs.c |
---|
1,5 → 1,5 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
122,6 → 122,85 |
return IPC_GET_RETVAL(answer); |
} |
void fs_node_initialize(fs_node_t *fn) |
{ |
memset(fn, 0, sizeof(fs_node_t)); |
} |
void libfs_mount(libfs_ops_t *ops, ipc_callid_t rid, ipc_call_t *request) |
{ |
dev_handle_t mp_dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); |
fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*request); |
fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*request); |
dev_handle_t mr_dev_handle = (dev_handle_t) IPC_GET_ARG4(*request); |
int res; |
ipcarg_t rc; |
ipc_call_t call; |
ipc_callid_t callid; |
/* accept the phone */ |
callid = async_get_call(&call); |
int mountee_phone = (int)IPC_GET_ARG1(call); |
if ((IPC_GET_METHOD(call) != IPC_M_CONNECTION_CLONE) || |
mountee_phone < 0) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
ipc_answer_0(callid, EOK); /* acknowledge the mountee_phone */ |
res = ipc_data_write_receive(&callid, NULL); |
if (!res) { |
ipc_hangup(mountee_phone); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
fs_node_t *fn = ops->node_get(mp_dev_handle, mp_fs_index); |
if (!fn) { |
ipc_hangup(mountee_phone); |
ipc_answer_0(callid, ENOENT); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
if (fn->mp_data.mp_active) { |
ipc_hangup(mountee_phone); |
ops->node_put(fn); |
ipc_answer_0(callid, EBUSY); |
ipc_answer_0(rid, EBUSY); |
return; |
} |
rc = async_req_0_0(mountee_phone, IPC_M_CONNECT_ME); |
if (rc != 0) { |
ipc_hangup(mountee_phone); |
ops->node_put(fn); |
ipc_answer_0(callid, rc); |
ipc_answer_0(rid, rc); |
return; |
} |
ipc_call_t answer; |
aid_t msg = async_send_1(mountee_phone, VFS_MOUNTED, mr_dev_handle, |
&answer); |
ipc_forward_fast(callid, mountee_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); |
async_wait_for(msg, &rc); |
if (rc == EOK) { |
fn->mp_data.mp_active = true; |
fn->mp_data.fs_handle = mr_fs_handle; |
fn->mp_data.dev_handle = mr_dev_handle; |
fn->mp_data.phone = mountee_phone; |
} |
/* |
* Do not release the FS node so that it stays in memory. |
*/ |
ipc_answer_0(rid, rc); |
} |
/** Lookup VFS triplet by name in the file system name space. |
* |
* The path passed in the PLB must be in the canonical file system path format |
137,8 → 216,9 |
void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, |
ipc_call_t *request) |
{ |
unsigned next = IPC_GET_ARG1(*request); |
unsigned first = IPC_GET_ARG1(*request); |
unsigned last = IPC_GET_ARG2(*request); |
unsigned next = first; |
dev_handle_t dev_handle = IPC_GET_ARG3(*request); |
int lflag = IPC_GET_ARG4(*request); |
fs_index_t index = IPC_GET_ARG5(*request); /* when L_LINK specified */ |
148,10 → 228,18 |
if (last < next) |
last += PLB_SIZE; |
void *par = NULL; |
void *cur = ops->root_get(dev_handle); |
void *tmp = NULL; |
fs_node_t *par = NULL; |
fs_node_t *cur = ops->root_get(dev_handle); |
fs_node_t *tmp = NULL; |
if (cur->mp_data.mp_active) { |
ipc_forward_slow(rid, cur->mp_data.phone, VFS_LOOKUP, |
next, last, cur->mp_data.dev_handle, lflag, index, |
IPC_FF_ROUTE_FROM_ME); |
ops->node_put(cur); |
return; |
} |
if (ops->plb_get_char(next) == '/') |
next++; /* eat slash */ |
174,6 → 262,21 |
/* match the component */ |
tmp = ops->match(cur, component); |
if (tmp && tmp->mp_data.mp_active) { |
if (next > last) |
next = last = first; |
else |
next--; |
ipc_forward_slow(rid, tmp->mp_data.phone, VFS_LOOKUP, |
next, last, tmp->mp_data.dev_handle, lflag, index, |
IPC_FF_ROUTE_FROM_ME); |
ops->node_put(cur); |
ops->node_put(tmp); |
if (par) |
ops->node_put(par); |
return; |
} |
/* handle miss: match amongst siblings */ |
if (!tmp) { |
189,39 → 292,33 |
ipc_answer_0(rid, ENOTDIR); |
goto out; |
} |
void *nodep; |
fs_node_t *fn; |
if (lflag & L_CREATE) |
nodep = ops->create(dev_handle, lflag); |
fn = ops->create(dev_handle, lflag); |
else |
nodep = ops->node_get(dev_handle, |
fn = ops->node_get(dev_handle, |
index); |
if (nodep) { |
if (fn) { |
int rc; |
rc = ops->link(cur, nodep, component); |
rc = ops->link(cur, fn, component); |
if (rc != EOK) { |
if (lflag & L_CREATE) { |
(void)ops->destroy( |
nodep); |
(void)ops->destroy(fn); |
} |
ipc_answer_0(rid, rc); |
} else { |
ipc_answer_5(rid, EOK, |
fs_handle, dev_handle, |
ops->index_get(nodep), |
ops->size_get(nodep), |
ops->lnkcnt_get(nodep)); |
ops->node_put(nodep); |
ops->index_get(fn), |
ops->size_get(fn), |
ops->lnkcnt_get(fn)); |
ops->node_put(fn); |
} |
} else { |
ipc_answer_0(rid, ENOSPC); |
} |
goto out; |
} else if (lflag & L_PARENT) { |
/* return parent */ |
ipc_answer_5(rid, EOK, fs_handle, dev_handle, |
ops->index_get(cur), ops->size_get(cur), |
ops->lnkcnt_get(cur)); |
} |
ipc_answer_0(rid, ENOENT); |
goto out; |
263,26 → 360,26 |
assert(len); |
component[len] = '\0'; |
void *nodep; |
fs_node_t *fn; |
if (lflag & L_CREATE) |
nodep = ops->create(dev_handle, lflag); |
fn = ops->create(dev_handle, lflag); |
else |
nodep = ops->node_get(dev_handle, index); |
if (nodep) { |
fn = ops->node_get(dev_handle, index); |
if (fn) { |
int rc; |
rc = ops->link(cur, nodep, component); |
rc = ops->link(cur, fn, component); |
if (rc != EOK) { |
if (lflag & L_CREATE) |
(void)ops->destroy(nodep); |
(void)ops->destroy(fn); |
ipc_answer_0(rid, rc); |
} else { |
ipc_answer_5(rid, EOK, |
fs_handle, dev_handle, |
ops->index_get(nodep), |
ops->size_get(nodep), |
ops->lnkcnt_get(nodep)); |
ops->node_put(nodep); |
ops->index_get(fn), |
ops->size_get(fn), |
ops->lnkcnt_get(fn)); |
ops->node_put(fn); |
} |
} else { |
ipc_answer_0(rid, ENOSPC); |
294,18 → 391,9 |
} |
/* handle hit */ |
if (lflag & L_PARENT) { |
ops->node_put(cur); |
cur = par; |
par = NULL; |
if (!cur) { |
ipc_answer_0(rid, ENOENT); |
goto out; |
} |
} |
if (lflag & L_UNLINK) { |
unsigned old_lnkcnt = ops->lnkcnt_get(cur); |
int res = ops->unlink(par, cur); |
int res = ops->unlink(par, cur, component); |
ipc_answer_5(rid, (ipcarg_t)res, fs_handle, dev_handle, |
ops->index_get(cur), ops->size_get(cur), old_lnkcnt); |
goto out; |
/branches/dd/uspace/lib/libfs/libfs.h |
---|
1,5 → 1,5 |
/* |
* Copyright (c) 2007 Jakub Jermar |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
42,21 → 42,33 |
#include <async.h> |
typedef struct { |
void * (* match)(void *, const char *); |
void * (* node_get)(dev_handle_t, fs_index_t); |
void (* node_put)(void *); |
void * (* create)(dev_handle_t, int); |
int (* destroy)(void *); |
int (* link)(void *, void *, const char *); |
int (* unlink)(void *, void *); |
fs_index_t (* index_get)(void *); |
size_t (* size_get)(void *); |
unsigned (* lnkcnt_get)(void *); |
bool (* has_children)(void *); |
void *(* root_get)(dev_handle_t); |
bool mp_active; |
int phone; |
fs_handle_t fs_handle; |
dev_handle_t dev_handle; |
} mp_data_t; |
typedef struct { |
mp_data_t mp_data; /**< Mount point info. */ |
void *data; /**< Data of the file system implementation. */ |
} fs_node_t; |
typedef struct { |
fs_node_t * (* match)(fs_node_t *, const char *); |
fs_node_t * (* node_get)(dev_handle_t, fs_index_t); |
void (* node_put)(fs_node_t *); |
fs_node_t * (* create)(dev_handle_t, int); |
int (* destroy)(fs_node_t *); |
int (* link)(fs_node_t *, fs_node_t *, const char *); |
int (* unlink)(fs_node_t *, fs_node_t *, const char *); |
fs_index_t (* index_get)(fs_node_t *); |
size_t (* size_get)(fs_node_t *); |
unsigned (* lnkcnt_get)(fs_node_t *); |
bool (* has_children)(fs_node_t *); |
fs_node_t *(* root_get)(dev_handle_t); |
char (* plb_get_char)(unsigned pos); |
bool (* is_directory)(void *); |
bool (* is_file)(void *); |
bool (* is_directory)(fs_node_t *); |
bool (* is_file)(fs_node_t *); |
} libfs_ops_t; |
typedef struct { |
67,6 → 79,9 |
extern int fs_register(int, fs_reg_t *, vfs_info_t *, async_client_conn_t); |
extern void fs_node_initialize(fs_node_t *); |
extern void libfs_mount(libfs_ops_t *, ipc_callid_t, ipc_call_t *); |
extern void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *); |
#endif |
/branches/dd/uspace/lib/libblock/libblock.c |
---|
37,8 → 37,8 |
#include "libblock.h" |
#include "../../srv/vfs/vfs.h" |
#include "../../srv/rd/rd.h" |
#include <ipc/devmap.h> |
#include <ipc/bd.h> |
#include <ipc/services.h> |
#include <errno.h> |
#include <sys/mman.h> |
146,9 → 146,8 |
if (!com_area) { |
return ENOMEM; |
} |
dev_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, |
DEVMAP_CONNECT_TO_DEVICE, dev_handle); |
dev_phone = devmap_device_connect(dev_handle, IPC_FLAG_BLOCKING); |
if (dev_phone < 0) { |
munmap(com_area, com_size); |
return dev_phone; |
477,7 → 476,7 |
if (*bufpos == *buflen) { |
/* Refill the communication buffer with a new block. */ |
ipcarg_t retval; |
int rc = async_req_2_1(devcon->dev_phone, RD_READ_BLOCK, |
int rc = async_req_2_1(devcon->dev_phone, BD_READ_BLOCK, |
*pos / block_size, block_size, &retval); |
if ((rc != EOK) || (retval != EOK)) |
return (rc != EOK ? rc : retval); |
/branches/dd/uspace/lib/libc/include/console.h |
---|
27,7 → 27,7 |
*/ |
/** @addtogroup libc |
* @{ |
* @{ |
*/ |
/** @file |
*/ |
40,19 → 40,16 |
#include <sys/types.h> |
#include <bool.h> |
extern void console_open(bool); |
extern int console_open(bool); |
extern void console_close(void); |
extern int console_phone_get(bool); |
extern void console_wait(void); |
extern void console_clear(void); |
extern void console_goto(int, int); |
extern void console_putchar(wchar_t); |
extern ssize_t console_write(const char *buf, size_t nbyte); |
extern void console_putstr(const char *s); |
extern ssize_t console_write(const char *, size_t); |
extern void console_putstr(const char *); |
extern void console_flush(void); |
extern void console_flush_optional(void); |
extern int console_get_size(int *, int *); |
extern void console_set_style(int); |
63,6 → 60,6 |
extern void console_kcon_enable(void); |
#endif |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/include/string.h |
---|
42,10 → 42,10 |
#define U_SPECIAL '?' |
#define U_BOM 0xfeff |
/**< No size limit constant */ |
/** No size limit constant */ |
#define STR_NO_LIMIT ((size_t) -1) |
/**< Maximum size of a string containing @c length characters */ |
/** Maximum size of a string containing @c length characters */ |
#define STR_BOUNDS(length) ((length) << 2) |
extern wchar_t str_decode(const char *str, size_t *offset, size_t sz); |
/branches/dd/uspace/lib/libc/include/vfs/vfs.h |
---|
39,8 → 39,8 |
extern char *absolutize(const char *, size_t *); |
extern int mount(const char *, const char *, const char *, |
const unsigned int flags); |
extern int mount(const char *, const char *, const char *, const char *, |
unsigned int flags); |
#endif |
/branches/dd/uspace/lib/libc/include/async.h |
---|
98,22 → 98,22 |
/* Wrappers for simple communication */ |
#define async_msg_0(phone, method) \ |
ipc_call_async_0((phone), (method), NULL, NULL, !in_interrupt_handler()) |
ipc_call_async_0((phone), (method), NULL, NULL, true) |
#define async_msg_1(phone, method, arg1) \ |
ipc_call_async_1((phone), (method), (arg1), NULL, NULL, \ |
!in_interrupt_handler()) |
true) |
#define async_msg_2(phone, method, arg1, arg2) \ |
ipc_call_async_2((phone), (method), (arg1), (arg2), NULL, NULL, \ |
!in_interrupt_handler()) |
true) |
#define async_msg_3(phone, method, arg1, arg2, arg3) \ |
ipc_call_async_3((phone), (method), (arg1), (arg2), (arg3), NULL, NULL, \ |
!in_interrupt_handler()) |
true) |
#define async_msg_4(phone, method, arg1, arg2, arg3, arg4) \ |
ipc_call_async_4((phone), (method), (arg1), (arg2), (arg3), (arg4), NULL, \ |
NULL, !in_interrupt_handler()) |
NULL, true) |
#define async_msg_5(phone, method, arg1, arg2, arg3, arg4, arg5) \ |
ipc_call_async_5((phone), (method), (arg1), (arg2), (arg3), (arg4), \ |
(arg5), NULL, NULL, !in_interrupt_handler()) |
(arg5), NULL, NULL, true) |
/* |
* User-friendly wrappers for async_req_fast() and async_req_slow(). The macros |
253,8 → 253,6 |
fibril_dec_sercount(); |
} |
extern bool in_interrupt_handler(void); |
extern atomic_t async_futex; |
#endif |
/branches/dd/uspace/lib/libc/include/libadt/list.h |
---|
37,26 → 37,20 |
#include <unistd.h> |
#ifndef true |
# define true 1 |
#endif |
#ifndef false |
# define false 0 |
#endif |
typedef struct link link_t; |
/** Doubly linked list head and link type. */ |
struct link { |
link_t *prev; /**< Pointer to the previous item in the list. */ |
link_t *next; /**< Pointer to the next item in the list. */ |
}; |
typedef struct link { |
struct link *prev; /**< Pointer to the previous item in the list. */ |
struct link *next; /**< Pointer to the next item in the list. */ |
} link_t; |
/** Declare and initialize statically allocated list. |
* |
* @param name Name of the new statically allocated list. |
*/ |
#define LIST_INITIALIZE(name) link_t name = { .prev = &name, .next = &name } |
#define LIST_INITIALIZE(name) link_t name = { \ |
.prev = &name, \ |
.next = &name \ |
} |
/** Initialize doubly-linked circular list link |
* |
145,7 → 139,7 |
*/ |
static inline int list_empty(link_t *head) |
{ |
return head->next == head ? true : false; |
return ((head->next == head) ? 1 : 0); |
} |
161,11 → 155,11 |
*/ |
static inline void headless_list_split_or_concat(link_t *part1, link_t *part2) |
{ |
link_t *hlp; |
part1->prev->next = part2; |
part2->prev->next = part1; |
hlp = part1->prev; |
part2->prev->next = part1; |
link_t *hlp = part1->prev; |
part1->prev = part2->prev; |
part2->prev = hlp; |
} |
195,10 → 189,11 |
headless_list_split_or_concat(part1, part2); |
} |
#define list_get_instance(link,type,member) (type *)(((char *)(link))-((char *)&(((type *)NULL)->member))) |
#define list_get_instance(link, type, member) ((type *) (((void *)(link)) - ((void *) &(((type *) NULL)->member)))) |
extern int list_member(const link_t *link, const link_t *head); |
extern void list_concat(link_t *head1, link_t *head2); |
extern unsigned int list_count(const link_t *link); |
#endif |
/branches/dd/uspace/lib/libc/include/devmap.h |
---|
0,0 → 1,56 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_DEVMAP_H_ |
#define LIBC_DEVMAP_H_ |
#include <ipc/devmap.h> |
#include <async.h> |
extern int devmap_get_phone(devmap_interface_t, unsigned int); |
extern void devmap_hangup_phone(devmap_interface_t iface); |
extern int devmap_driver_register(const char *, async_client_conn_t); |
extern int devmap_device_register(const char *, dev_handle_t *); |
extern int devmap_device_get_handle(const char *, dev_handle_t *, unsigned int); |
extern int devmap_device_connect(dev_handle_t, unsigned int); |
extern ipcarg_t devmap_device_get_count(void); |
extern ipcarg_t devmap_device_get_devices(ipcarg_t, dev_desc_t *); |
#endif |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/include/io/stream.h |
---|
37,15 → 37,12 |
#include <libarch/types.h> |
#define EMFILE -17 |
#define EMFILE -17 |
extern ssize_t read_stdin(void *, size_t); |
extern int klog_puts(const char *); |
extern void klog_update(void); |
extern ssize_t read_stdin(void *, size_t); |
extern ssize_t write_stdout(const void *, size_t); |
extern ssize_t write_stderr(const void *, size_t); |
extern int flush_stdout(void); |
#endif |
/** @} |
/branches/dd/uspace/lib/libc/include/ipc/devmap.h |
---|
33,11 → 33,14 |
#ifndef DEVMAP_DEVMAP_H_ |
#define DEVMAP_DEVMAP_H_ |
#include <atomic.h> |
#include <ipc/ipc.h> |
#include <libadt/list.h> |
#define DEVMAP_NAME_MAXLEN 512 |
#define DEVMAP_NAME_MAXLEN 255 |
typedef ipcarg_t dev_handle_t; |
typedef enum { |
DEVMAP_DRIVER_REGISTER = IPC_FIRST_USER_METHOD, |
DEVMAP_DRIVER_UNREGISTER, |
44,56 → 47,30 |
DEVMAP_DEVICE_REGISTER, |
DEVMAP_DEVICE_UNREGISTER, |
DEVMAP_DEVICE_GET_NAME, |
DEVMAP_DEVICE_GET_HANDLE |
DEVMAP_DEVICE_GET_HANDLE, |
DEVMAP_DEVICE_GET_COUNT, |
DEVMAP_DEVICE_GET_DEVICES |
} devmap_request_t; |
/** Representation of device driver. |
* Each driver is responsible for a set of devices. |
*/ |
typedef struct { |
/** Pointers to previous and next drivers in linked list */ |
link_t drivers; |
/** Pointer to the linked list of devices controlled by |
* this driver */ |
link_t devices; |
/** Phone asociated with this driver */ |
ipcarg_t phone; |
/** Device driver name */ |
char *name; |
/** Futex for list of devices owned by this driver */ |
atomic_t devices_futex; |
} devmap_driver_t; |
/** Info about registered device |
/** Interface provided by devmap. |
* |
*/ |
typedef struct { |
/** Pointer to the previous and next device in the list of all devices */ |
link_t devices; |
/** Pointer to the previous and next device in the list of devices |
owned by one driver */ |
link_t driver_devices; |
/** Unique device identifier */ |
int handle; |
/** Device name */ |
char *name; |
/** Device driver handling this device */ |
devmap_driver_t *driver; |
} devmap_device_t; |
/** Interface provided by devmap. |
* Every process that connects to devmap must ask one of following |
* interfaces otherwise connection will be refused. |
* |
*/ |
typedef enum { |
/** Connect as device driver */ |
DEVMAP_DRIVER = 1, |
/** Connect as client */ |
/** Connect as device driver */ |
DEVMAP_DRIVER = 1, |
/** Connect as client */ |
DEVMAP_CLIENT, |
/** Create new connection to instance of device that |
* is specified by second argument of call. */ |
/** Create new connection to instance of device that |
is specified by second argument of call. */ |
DEVMAP_CONNECT_TO_DEVICE |
} devmap_interface_t; |
typedef struct { |
dev_handle_t handle; |
char name[DEVMAP_NAME_MAXLEN + 1]; |
} dev_desc_t; |
#endif |
/branches/dd/uspace/lib/libc/include/ipc/bd.h |
---|
0,0 → 1,48 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libcipc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_IPC_BD_H_ |
#define LIBC_IPC_BD_H_ |
#include <ipc/ipc.h> |
typedef enum { |
BD_READ_BLOCK = IPC_FIRST_USER_METHOD, |
BD_WRITE_BLOCK |
} bd_request_t; |
#endif |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/include/ipc/fb.h |
---|
66,7 → 66,9 |
FB_ANIM_CHGVP, |
FB_ANIM_START, |
FB_ANIM_STOP, |
FB_POINTER_MOVE |
FB_POINTER_MOVE, |
FB_SCREEN_YIELD, |
FB_SCREEN_RECLAIM |
} fb_request_t; |
#endif |
/branches/dd/uspace/lib/libc/generic/ddi.c |
---|
130,7 → 130,7 |
phys = ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE); |
offset = pio_addr - phys; |
pages = ALIGN_UP(offset + size, PAGE_SIZE) >> PAGE_WIDTH; |
virt = as_get_mappable_page(pages); |
virt = as_get_mappable_page(pages << PAGE_WIDTH); |
*use_addr = virt + offset; |
return physmem_map(phys, virt, pages, AS_AREA_READ | AS_AREA_WRITE); |
} |
/branches/dd/uspace/lib/libc/generic/kbd.c |
---|
42,7 → 42,7 |
int kbd_get_event(kbd_event_t *ev) |
{ |
int cons_phone = console_phone_get(true); |
int cons_phone = console_open(true); |
ipcarg_t r0, r1, r2, r3; |
int rc; |
/branches/dd/uspace/lib/libc/generic/console.c |
---|
32,8 → 32,9 |
* @{ |
*/ |
/** @file |
*/ |
*/ |
#include <libc.h> |
#include <async.h> |
#include <io/stream.h> |
#include <ipc/console.h> |
45,7 → 46,7 |
static int console_phone = -1; |
/** Size of cbuffer. */ |
#define CBUFFER_SIZE 256 |
#define CBUFFER_SIZE 256 |
/** Buffer for writing characters to the console. */ |
static char cbuffer[CBUFFER_SIZE]; |
56,92 → 57,56 |
/** Pointer to first available field in cbuffer. */ |
static char *cbp = cbuffer; |
static ssize_t cons_write(const char *buf, size_t nbyte); |
static void cons_putchar(wchar_t c); |
static void cbuffer_flush(void); |
static void cbuffer_drain(void); |
static inline void cbuffer_putc(int c); |
void console_open(bool blocking) |
/** Write one character to the console via IPC. */ |
static void cons_putchar(wchar_t c) |
{ |
if (console_phone < 0) { |
int phone; |
if (blocking) { |
phone = ipc_connect_me_to_blocking(PHONE_NS, |
SERVICE_CONSOLE, 0, 0); |
} else { |
phone = ipc_connect_me_to(PHONE_NS, SERVICE_CONSOLE, 0, |
0); |
} |
if (phone >= 0) |
console_phone = phone; |
} |
console_wait(); |
async_msg_1(console_phone, CONSOLE_PUTCHAR, c); |
} |
void console_close(void) |
/** Write characters to the console via IPC or to klog */ |
static ssize_t cons_write(const char *buf, size_t size) |
{ |
console_open(false); |
if (console_phone >= 0) { |
if (ipc_hangup(console_phone) == 0) { |
console_phone = -1; |
async_serialize_start(); |
ipc_call_t answer; |
aid_t req = async_send_0(console_phone, CONSOLE_WRITE, &answer); |
ipcarg_t rc = ipc_data_write_start(console_phone, (void *) buf, size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
return (ssize_t) rc; |
} |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
if (rc == EOK) |
return (ssize_t) IPC_GET_ARG1(answer); |
else |
return -1; |
} else |
return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, size); |
} |
int console_phone_get(bool blocking) |
{ |
if (console_phone < 0) |
console_open(blocking); |
return console_phone; |
} |
void console_wait(void) |
{ |
while (console_phone < 0) |
console_open(true); |
} |
void console_clear(void) |
{ |
int cons_phone = console_phone_get(true); |
cbuffer_drain(); |
async_msg_0(cons_phone, CONSOLE_CLEAR); |
} |
void console_goto(int row, int col) |
{ |
int cons_phone = console_phone_get(true); |
cbuffer_flush(); |
async_msg_2(cons_phone, CONSOLE_GOTO, row, col); |
} |
void console_putchar(wchar_t c) |
{ |
// cbuffer_putc(c); |
cbuffer_flush(); |
cons_putchar(c); |
} |
/** Write all data from output buffer to the console. */ |
static void cbuffer_flush(void) |
{ |
int rc; |
int len; |
len = cbp - cbuffer; |
size_t len = cbp - cbuffer; |
while (len > 0) { |
rc = cons_write(cbuffer, cbp - cbuffer); |
ssize_t rc = cons_write(cbuffer, cbp - cbuffer); |
if (rc < 0) |
return; |
len -= rc; |
} |
cbp = cbuffer; |
} |
152,151 → 117,158 |
} |
/** Write one character to the output buffer. */ |
static inline void cbuffer_putc(int c) |
static inline void cbuffer_putc(char c) |
{ |
if (cbp == cbuffer_end) |
cbuffer_flush(); |
*cbp++ = c; |
if (c == '\n') |
cbuffer_flush(); |
} |
/** Write one character to the console via IPC. */ |
static void cons_putchar(wchar_t c) |
int console_open(bool blocking) |
{ |
int cons_phone = console_phone_get(true); |
async_msg_1(cons_phone, CONSOLE_PUTCHAR, c); |
} |
/** Write characters to the console via IPC. */ |
static ssize_t cons_write(const char *buf, size_t nbyte) |
{ |
int cons_phone = console_phone_get(true); |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
async_serialize_start(); |
if (console_phone < 0) { |
int phone; |
if (blocking) |
phone = ipc_connect_me_to_blocking(PHONE_NS, |
SERVICE_CONSOLE, 0, 0); |
else |
phone = ipc_connect_me_to(PHONE_NS, |
SERVICE_CONSOLE, 0, 0); |
if (phone >= 0) |
console_phone = phone; |
} |
req = async_send_0(cons_phone, CONSOLE_WRITE, &answer); |
rc = ipc_data_write_start(cons_phone, (void *) buf, nbyte); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
return (ssize_t) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
if (rc == EOK) |
return (ssize_t) IPC_GET_ARG1(answer); |
else |
return -1; |
return console_phone; |
} |
/** Write characters to the console. */ |
ssize_t console_write(const char *buf, size_t nbyte) |
void console_close(void) |
{ |
size_t left; |
left = nbyte; |
while (left > 0) { |
cbuffer_putc(*buf++); |
--left; |
if (console_phone >= 0) { |
if (ipc_hangup(console_phone) == 0) |
console_phone = -1; |
} |
return nbyte; |
} |
/** Write a NULL-terminated string to the console. */ |
void console_putstr(const char *s) |
void console_wait(void) |
{ |
size_t len; |
ssize_t rc; |
len = str_size(s); |
while (len > 0) { |
rc = console_write(s, len); |
if (rc < 0) |
return; /* Error */ |
s += rc; |
len -= rc; |
} |
while (console_phone < 0) |
console_open(true); |
} |
/** Flush all output to the console. */ |
void console_flush(void) |
void console_clear(void) |
{ |
int cons_phone = console_phone_get(false); |
cbuffer_flush(); |
async_msg_0(cons_phone, CONSOLE_FLUSH); |
console_wait(); |
cbuffer_drain(); |
async_msg_0(console_phone, CONSOLE_CLEAR); |
} |
void console_flush_optional(void) |
{ |
if (console_phone >= 0) |
console_flush(); |
} |
int console_get_size(int *rows, int *cols) |
{ |
int cons_phone = console_phone_get(true); |
ipcarg_t r, c; |
int rc; |
rc = async_req_0_2(cons_phone, CONSOLE_GETSIZE, &r, &c); |
console_wait(); |
ipcarg_t r; |
ipcarg_t c; |
int rc = async_req_0_2(console_phone, CONSOLE_GETSIZE, &r, &c); |
*rows = (int) r; |
*cols = (int) c; |
return rc; |
} |
void console_set_style(int style) |
{ |
int cons_phone = console_phone_get(true); |
console_wait(); |
cbuffer_flush(); |
async_msg_1(cons_phone, CONSOLE_SET_STYLE, style); |
async_msg_1(console_phone, CONSOLE_SET_STYLE, style); |
} |
void console_set_color(int fg_color, int bg_color, int flags) |
{ |
int cons_phone = console_phone_get(true); |
console_wait(); |
cbuffer_flush(); |
async_msg_3(cons_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags); |
async_msg_3(console_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags); |
} |
void console_set_rgb_color(int fg_color, int bg_color) |
{ |
int cons_phone = console_phone_get(true); |
console_wait(); |
cbuffer_flush(); |
async_msg_2(cons_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color); |
async_msg_2(console_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color); |
} |
void console_cursor_visibility(int show) |
{ |
int cons_phone = console_phone_get(true); |
console_wait(); |
cbuffer_flush(); |
async_msg_1(cons_phone, CONSOLE_CURSOR_VISIBILITY, show != 0); |
async_msg_1(console_phone, CONSOLE_CURSOR_VISIBILITY, show != 0); |
} |
void console_kcon_enable(void) |
{ |
int cons_phone = console_phone_get(true); |
console_wait(); |
cbuffer_flush(); |
async_msg_0(console_phone, CONSOLE_KCON_ENABLE); |
} |
void console_goto(int row, int col) |
{ |
console_wait(); |
cbuffer_flush(); |
async_msg_0(cons_phone, CONSOLE_KCON_ENABLE); |
async_msg_2(console_phone, CONSOLE_GOTO, row, col); |
} |
void console_putchar(wchar_t c) |
{ |
console_wait(); |
cbuffer_flush(); |
cons_putchar(c); |
} |
/** Write characters to the console. */ |
ssize_t console_write(const char *buf, size_t size) |
{ |
size_t left = size; |
while (left > 0) { |
cbuffer_putc(*buf++); |
left--; |
} |
return size; |
} |
/** Write a NULL-terminated string to the console. */ |
void console_putstr(const char *str) |
{ |
size_t left = str_size(str); |
while (left > 0) { |
ssize_t rc = console_write(str, left); |
if (rc < 0) { |
/* Error */ |
return; |
} |
str += rc; |
left -= rc; |
} |
} |
/** Flush all output to the console or klog. */ |
void console_flush(void) |
{ |
cbuffer_flush(); |
if (console_phone >= 0) |
async_msg_0(console_phone, CONSOLE_FLUSH); |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/string.c |
---|
593,10 → 593,12 |
{ |
wchar_t acc; |
size_t off = 0; |
size_t last = 0; |
while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) { |
if (acc == ch) |
return (str + off); |
return (str + last); |
last = off; |
} |
return NULL; |
613,14 → 615,15 |
{ |
wchar_t acc; |
size_t off = 0; |
char *res; |
res = NULL; |
size_t last = 0; |
char *res = NULL; |
while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) { |
if (acc == ch) |
res = (str + off); |
res = (str + last); |
last = off; |
} |
return res; |
} |
/branches/dd/uspace/lib/libc/generic/libc.c |
---|
84,7 → 84,7 |
} |
main(argc, argv); |
console_flush_optional(); |
console_flush(); |
} |
void __exit(void) |
/branches/dd/uspace/lib/libc/generic/ipc.c |
---|
704,7 → 704,7 |
IPC_SET_ARG4(data, arg4); |
IPC_SET_ARG5(data, arg5); |
return __SYSCALL3(SYS_IPC_FORWARD_SLOW, callid, (sysarg_t) &data, mode); |
return __SYSCALL4(SYS_IPC_FORWARD_SLOW, callid, phoneid, (sysarg_t) &data, mode); |
} |
/** Wrapper for making IPC_M_SHARE_IN calls. |
/branches/dd/uspace/lib/libc/generic/devmap.c |
---|
0,0 → 1,244 |
/* |
* Copyright (c) 2007 Josef Cejka |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <string.h> |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <ipc/devmap.h> |
#include <devmap.h> |
#include <async.h> |
#include <errno.h> |
static int devmap_phone_driver = -1; |
static int devmap_phone_client = -1; |
/** Get phone to device mapper task. */ |
int devmap_get_phone(devmap_interface_t iface, unsigned int flags) |
{ |
switch (iface) { |
case DEVMAP_DRIVER: |
if (devmap_phone_driver >= 0) |
return devmap_phone_driver; |
if (flags & IPC_FLAG_BLOCKING) |
devmap_phone_driver = ipc_connect_me_to_blocking(PHONE_NS, |
SERVICE_DEVMAP, DEVMAP_DRIVER, 0); |
else |
devmap_phone_driver = ipc_connect_me_to(PHONE_NS, |
SERVICE_DEVMAP, DEVMAP_DRIVER, 0); |
return devmap_phone_driver; |
case DEVMAP_CLIENT: |
if (devmap_phone_client >= 0) |
return devmap_phone_client; |
if (flags & IPC_FLAG_BLOCKING) |
devmap_phone_client = ipc_connect_me_to_blocking(PHONE_NS, |
SERVICE_DEVMAP, DEVMAP_CLIENT, 0); |
else |
devmap_phone_client = ipc_connect_me_to(PHONE_NS, |
SERVICE_DEVMAP, DEVMAP_CLIENT, 0); |
return devmap_phone_client; |
default: |
return -1; |
} |
} |
void devmap_hangup_phone(devmap_interface_t iface) |
{ |
switch (iface) { |
case DEVMAP_DRIVER: |
if (devmap_phone_driver >= 0) { |
ipc_hangup(devmap_phone_driver); |
devmap_phone_driver = -1; |
} |
break; |
case DEVMAP_CLIENT: |
if (devmap_phone_client >= 0) { |
ipc_hangup(devmap_phone_client); |
devmap_phone_client = -1; |
} |
break; |
default: |
break; |
} |
} |
/** Register new driver with devmap. */ |
int devmap_driver_register(const char *name, async_client_conn_t conn) |
{ |
int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING); |
if (phone < 0) |
return phone; |
ipc_call_t answer; |
aid_t req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer); |
ipcarg_t retval = ipc_data_write_start(phone, name, str_size(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
return -1; |
} |
async_set_client_connection(conn); |
ipcarg_t callback_phonehash; |
ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash); |
async_wait_for(req, &retval); |
return retval; |
} |
/** Register new device. |
* |
* @param name Device name. |
* @param handle Output: Handle to the created instance of device. |
* |
*/ |
int devmap_device_register(const char *name, dev_handle_t *handle) |
{ |
int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING); |
if (phone < 0) |
return phone; |
ipc_call_t answer; |
aid_t req = async_send_2(phone, DEVMAP_DEVICE_REGISTER, 0, 0, |
&answer); |
ipcarg_t retval = ipc_data_write_start(phone, name, str_size(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
return retval; |
} |
async_wait_for(req, &retval); |
if (retval != EOK) { |
if (handle != NULL) |
*handle = -1; |
return retval; |
} |
if (handle != NULL) |
*handle = (dev_handle_t) IPC_GET_ARG1(answer); |
return retval; |
} |
int devmap_device_get_handle(const char *name, dev_handle_t *handle, unsigned int flags) |
{ |
int phone = devmap_get_phone(DEVMAP_CLIENT, flags); |
if (phone < 0) |
return phone; |
ipc_call_t answer; |
aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0, |
&answer); |
ipcarg_t retval = ipc_data_write_start(phone, name, str_size(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
return retval; |
} |
async_wait_for(req, &retval); |
if (retval != EOK) { |
if (handle != NULL) |
*handle = -1; |
return retval; |
} |
if (handle != NULL) |
*handle = (dev_handle_t) IPC_GET_ARG1(answer); |
return retval; |
} |
int devmap_device_connect(dev_handle_t handle, unsigned int flags) |
{ |
int phone; |
if (flags & IPC_FLAG_BLOCKING) { |
phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, |
DEVMAP_CONNECT_TO_DEVICE, handle); |
} else { |
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, |
DEVMAP_CONNECT_TO_DEVICE, handle); |
} |
return phone; |
} |
ipcarg_t devmap_device_get_count(void) |
{ |
int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING); |
if (phone < 0) |
return 0; |
ipcarg_t count; |
int retval = ipc_call_sync_0_1(phone, DEVMAP_DEVICE_GET_COUNT, &count); |
if (retval != EOK) |
return 0; |
return count; |
} |
ipcarg_t devmap_device_get_devices(ipcarg_t count, dev_desc_t *data) |
{ |
int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING); |
if (phone < 0) |
return 0; |
ipc_call_t answer; |
aid_t req = async_send_0(phone, DEVMAP_DEVICE_GET_DEVICES, &answer); |
ipcarg_t retval = ipc_data_read_start(phone, data, count * sizeof(dev_desc_t)); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
return 0; |
} |
async_wait_for(req, &retval); |
if (retval != EOK) |
return 0; |
return IPC_GET_ARG1(answer); |
} |
/branches/dd/uspace/lib/libc/generic/async.c |
---|
30,64 → 30,65 |
* @{ |
*/ |
/** @file |
*/ |
*/ |
/** |
* Asynchronous library |
* |
* The aim of this library is facilitating writing programs utilizing the |
* asynchronous nature of HelenOS IPC, yet using a normal way of programming. |
* The aim of this library is to provide a facility for writing programs which |
* utilize the asynchronous nature of HelenOS IPC, yet using a normal way of |
* programming. |
* |
* You should be able to write very simple multithreaded programs, the async |
* framework will automatically take care of most synchronization problems. |
* |
* Default semantics: |
* - async_send_*(): send asynchronously. If the kernel refuses to send |
* more messages, [ try to get responses from kernel, if |
* nothing found, might try synchronous ] |
* - async_send_*(): Send asynchronously. If the kernel refuses to send |
* more messages, [ try to get responses from kernel, if |
* nothing found, might try synchronous ] |
* |
* Example of use (pseudo C): |
* |
* |
* 1) Multithreaded client application |
* |
* fibril_create(fibril1, ...); |
* fibril_create(fibril2, ...); |
* ... |
* |
* int fibril1(void *arg) |
* { |
* conn = ipc_connect_me_to(); |
* c1 = async_send(conn); |
* c2 = async_send(conn); |
* async_wait_for(c1); |
* async_wait_for(c2); |
* ... |
* } |
* fibril_create(fibril1, ...); |
* fibril_create(fibril2, ...); |
* ... |
* |
* int fibril1(void *arg) |
* { |
* conn = ipc_connect_me_to(); |
* c1 = async_send(conn); |
* c2 = async_send(conn); |
* async_wait_for(c1); |
* async_wait_for(c2); |
* ... |
* } |
* |
* |
* 2) Multithreaded server application |
* main() |
* { |
* async_manager(); |
* } |
* |
* |
* my_client_connection(icallid, *icall) |
* { |
* if (want_refuse) { |
* ipc_answer_0(icallid, ELIMIT); |
* return; |
* } |
* ipc_answer_0(icallid, EOK); |
* main() |
* { |
* async_manager(); |
* } |
* |
* callid = async_get_call(&call); |
* handle_call(callid, call); |
* ipc_answer_2(callid, 1, 2, 3); |
* my_client_connection(icallid, *icall) |
* { |
* if (want_refuse) { |
* ipc_answer_0(icallid, ELIMIT); |
* return; |
* } |
* ipc_answer_0(icallid, EOK); |
* |
* callid = async_get_call(&call); |
* .... |
* } |
* callid = async_get_call(&call); |
* handle_call(callid, call); |
* ipc_answer_2(callid, 1, 2, 3); |
* |
* callid = async_get_call(&call); |
* ... |
* } |
* |
*/ |
#include <futex.h> |
104,24 → 105,26 |
#include <bool.h> |
atomic_t async_futex = FUTEX_INITIALIZER; |
static hash_table_t conn_hash_table; |
static LIST_INITIALIZE(timeout_list); |
/** Structures of this type represent a waiting fibril. */ |
typedef struct { |
/** Expiration time. */ |
struct timeval expires; |
struct timeval expires; |
/** If true, this struct is in the timeout list. */ |
int inlist; |
bool inlist; |
/** Timeout list link. */ |
link_t link; |
/** Identification of and link to the waiting fibril. */ |
fid_t fid; |
/** If true, this fibril is currently active. */ |
int active; |
bool active; |
/** If true, we have timed out. */ |
int timedout; |
bool timedout; |
} awaiter_t; |
typedef struct { |
128,10 → 131,11 |
awaiter_t wdata; |
/** If reply was received. */ |
int done; |
bool done; |
/** Pointer to where the answer data is stored. */ |
ipc_call_t *dataptr; |
ipc_call_t *dataptr; |
ipcarg_t retval; |
} amsg_t; |
147,24 → 151,24 |
typedef struct { |
awaiter_t wdata; |
/** Hash table link. */ |
link_t link; |
/** Incoming phone hash. */ |
ipcarg_t in_phone_hash; |
ipcarg_t in_phone_hash; |
/** Messages that should be delivered to this fibril. */ |
link_t msg_queue; |
link_t msg_queue; |
/** Identification of the opening call. */ |
ipc_callid_t callid; |
/** Call data of the opening call. */ |
ipc_call_t call; |
/** Identification of the closing call. */ |
ipc_callid_t close_callid; |
/** Fibril function that will be used to handle the connection. */ |
void (*cfibril)(ipc_callid_t, ipc_call_t *); |
} connection_t; |
172,12 → 176,6 |
/** Identifier of the incoming connection handled by the current fibril. */ |
__thread connection_t *FIBRIL_connection; |
/** |
* If true, it is forbidden to use async_req functions and all preemption is |
* disabled. |
*/ |
__thread int _in_interrupt_handler; |
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call); |
static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call); |
185,6 → 183,7 |
* Pointer to a fibril function that will be used to handle connections. |
*/ |
static async_client_conn_t client_connection = default_client_connection; |
/** |
* Pointer to a fibril function that will be used to handle interrupt |
* notifications. |
191,46 → 190,39 |
*/ |
static async_client_conn_t interrupt_received = default_interrupt_received; |
/* |
* Getter for _in_interrupt_handler. We need to export the value of this thread |
* local variable to other modules, but the binutils 2.18 linkers die on an |
* attempt to export this symbol in the header file. For now, consider this as a |
* workaround. |
*/ |
bool in_interrupt_handler(void) |
{ |
return _in_interrupt_handler; |
} |
#define CONN_HASH_TABLE_CHAINS 32 |
static hash_table_t conn_hash_table; |
static LIST_INITIALIZE(timeout_list); |
#define CONN_HASH_TABLE_CHAINS 32 |
/** Compute hash into the connection hash table based on the source phone hash. |
* |
* @param key Pointer to source phone hash. |
* @param key Pointer to source phone hash. |
* |
* @return Index into the connection hash table. |
* @return Index into the connection hash table. |
* |
*/ |
static hash_index_t conn_hash(unsigned long *key) |
{ |
assert(key); |
return ((*key) >> 4) % CONN_HASH_TABLE_CHAINS; |
return (((*key) >> 4) % CONN_HASH_TABLE_CHAINS); |
} |
/** Compare hash table item with a key. |
* |
* @param key Array containing the source phone hash as the only item. |
* @param keys Expected 1 but ignored. |
* @param item Connection hash table item. |
* @param key Array containing the source phone hash as the only item. |
* @param keys Expected 1 but ignored. |
* @param item Connection hash table item. |
* |
* @return True on match, false otherwise. |
* @return True on match, false otherwise. |
* |
*/ |
static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item) |
{ |
connection_t *hs; |
hs = hash_table_get_instance(item, connection_t, link); |
return key[0] == hs->in_phone_hash; |
connection_t *hs = hash_table_get_instance(item, connection_t, link); |
return (key[0] == hs->in_phone_hash); |
} |
/** Connection hash table removal callback function. |
238,7 → 230,8 |
* This function is called whenever a connection is removed from the connection |
* hash table. |
* |
* @param item Connection hash table item being removed. |
* @param item Connection hash table item being removed. |
* |
*/ |
static void conn_remove(link_t *item) |
{ |
255,23 → 248,24 |
/** Sort in current fibril's timeout request. |
* |
* @param wd Wait data of the current fibril. |
* @param wd Wait data of the current fibril. |
* |
*/ |
static void insert_timeout(awaiter_t *wd) |
{ |
link_t *tmp; |
awaiter_t *cur; |
wd->timedout = 0; |
wd->inlist = 1; |
tmp = timeout_list.next; |
wd->timedout = false; |
wd->inlist = true; |
link_t *tmp = timeout_list.next; |
while (tmp != &timeout_list) { |
cur = list_get_instance(tmp, awaiter_t, link); |
awaiter_t *cur = list_get_instance(tmp, awaiter_t, link); |
if (tv_gteq(&cur->expires, &wd->expires)) |
break; |
tmp = tmp->next; |
} |
list_append(&wd->link, tmp); |
} |
281,93 → 275,146 |
* its message queue. If the fibril was not active, it is activated and all |
* timeouts are unregistered. |
* |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* |
* @return Zero if the call doesn't match any connection. |
* One if the call was passed to the respective connection |
* fibril. |
* @return False if the call doesn't match any connection. |
* True if the call was passed to the respective connection fibril. |
* |
*/ |
static int route_call(ipc_callid_t callid, ipc_call_t *call) |
static bool route_call(ipc_callid_t callid, ipc_call_t *call) |
{ |
connection_t *conn; |
msg_t *msg; |
link_t *hlp; |
unsigned long key; |
futex_down(&async_futex); |
key = call->in_phone_hash; |
hlp = hash_table_find(&conn_hash_table, &key); |
unsigned long key = call->in_phone_hash; |
link_t *hlp = hash_table_find(&conn_hash_table, &key); |
if (!hlp) { |
futex_up(&async_futex); |
return 0; |
return false; |
} |
conn = hash_table_get_instance(hlp, connection_t, link); |
msg = malloc(sizeof(*msg)); |
connection_t *conn = hash_table_get_instance(hlp, connection_t, link); |
msg_t *msg = malloc(sizeof(*msg)); |
if (!msg) { |
futex_up(&async_futex); |
return false; |
} |
msg->callid = callid; |
msg->call = *call; |
list_append(&msg->link, &conn->msg_queue); |
if (IPC_GET_METHOD(*call) == IPC_M_PHONE_HUNGUP) |
conn->close_callid = callid; |
/* If the connection fibril is waiting for an event, activate it */ |
if (!conn->wdata.active) { |
/* If in timeout list, remove it */ |
if (conn->wdata.inlist) { |
conn->wdata.inlist = 0; |
conn->wdata.inlist = false; |
list_remove(&conn->wdata.link); |
} |
conn->wdata.active = 1; |
conn->wdata.active = true; |
fibril_add_ready(conn->wdata.fid); |
} |
futex_up(&async_futex); |
return true; |
} |
return 1; |
/** Notification fibril. |
* |
* When a notification arrives, a fibril with this implementing function is |
* created. It calls interrupt_received() and does the final cleanup. |
* |
* @param arg Message structure pointer. |
* |
* @return Always zero. |
* |
*/ |
static int notification_fibril(void *arg) |
{ |
msg_t *msg = (msg_t *) arg; |
interrupt_received(msg->callid, &msg->call); |
free(msg); |
return 0; |
} |
/** Process interrupt notification. |
* |
* A new fibril is created which would process the notification. |
* |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* |
* @return False if an error occured. |
* True if the call was passed to the notification fibril. |
* |
*/ |
static bool process_notification(ipc_callid_t callid, ipc_call_t *call) |
{ |
futex_down(&async_futex); |
msg_t *msg = malloc(sizeof(*msg)); |
if (!msg) { |
futex_up(&async_futex); |
return false; |
} |
msg->callid = callid; |
msg->call = *call; |
fid_t fid = fibril_create(notification_fibril, msg); |
fibril_add_ready(fid); |
futex_up(&async_futex); |
return true; |
} |
/** Return new incoming message for the current (fibril-local) connection. |
* |
* @param call Storage where the incoming call data will be stored. |
* @param usecs Timeout in microseconds. Zero denotes no timeout. |
* @param call Storage where the incoming call data will be stored. |
* @param usecs Timeout in microseconds. Zero denotes no timeout. |
* |
* @return If no timeout was specified, then a hash of the |
* incoming call is returned. If a timeout is specified, |
* then a hash of the incoming call is returned unless |
* the timeout expires prior to receiving a message. In |
* that case zero is returned. |
* @return If no timeout was specified, then a hash of the |
* incoming call is returned. If a timeout is specified, |
* then a hash of the incoming call is returned unless |
* the timeout expires prior to receiving a message. In |
* that case zero is returned. |
* |
*/ |
ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs) |
{ |
msg_t *msg; |
ipc_callid_t callid; |
connection_t *conn; |
assert(FIBRIL_connection); |
assert(FIBRIL_connection); |
/* GCC 4.1.0 coughs on FIBRIL_connection-> dereference, |
/* Why doing this? |
* GCC 4.1.0 coughs on FIBRIL_connection-> dereference. |
* GCC 4.1.1 happilly puts the rdhwr instruction in delay slot. |
* I would never expect to find so many errors in |
* a compiler *($&$(*&$ |
* I would never expect to find so many errors in |
* a compiler. |
*/ |
conn = FIBRIL_connection; |
connection_t *conn = FIBRIL_connection; |
futex_down(&async_futex); |
if (usecs) { |
gettimeofday(&conn->wdata.expires, NULL); |
tv_add(&conn->wdata.expires, usecs); |
} else { |
conn->wdata.inlist = 0; |
} |
} else |
conn->wdata.inlist = false; |
/* If nothing in queue, wait until something arrives */ |
while (list_empty(&conn->msg_queue)) { |
if (usecs) |
insert_timeout(&conn->wdata); |
conn->wdata.active = 0; |
conn->wdata.active = false; |
/* |
* Note: the current fibril will be rescheduled either due to a |
* timeout or due to an arriving message destined to it. In the |
375,13 → 422,14 |
* case, route_call() will perform the wakeup. |
*/ |
fibril_switch(FIBRIL_TO_MANAGER); |
/* |
* Futex is up after getting back from async_manager get it |
* again. |
* Futex is up after getting back from async_manager. |
* Get it again. |
*/ |
futex_down(&async_futex); |
if (usecs && conn->wdata.timedout && |
list_empty(&conn->msg_queue)) { |
if ((usecs) && (conn->wdata.timedout) |
&& (list_empty(&conn->msg_queue))) { |
/* If we timed out -> exit */ |
futex_up(&async_futex); |
return 0; |
388,9 → 436,10 |
} |
} |
msg = list_get_instance(conn->msg_queue.next, msg_t, link); |
msg_t *msg = list_get_instance(conn->msg_queue.next, msg_t, link); |
list_remove(&msg->link); |
callid = msg->callid; |
ipc_callid_t callid = msg->callid; |
*call = msg->call; |
free(msg); |
402,8 → 451,9 |
* |
* This function is defined as a weak symbol - to be redefined in user code. |
* |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* |
*/ |
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call) |
{ |
412,8 → 462,11 |
/** Default fibril function that gets called to handle interrupt notifications. |
* |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* This function is defined as a weak symbol - to be redefined in user code. |
* |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* |
*/ |
static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call) |
{ |
424,17 → 477,17 |
* When a new connection arrives, a fibril with this implementing function is |
* created. It calls client_connection() and does the final cleanup. |
* |
* @param arg Connection structure pointer. |
* @param arg Connection structure pointer. |
* |
* @return Always zero. |
* @return Always zero. |
* |
*/ |
static int connection_fibril(void *arg) |
static int connection_fibril(void *arg) |
{ |
unsigned long key; |
msg_t *msg; |
int close_answered = 0; |
/* Setup fibril-local connection pointer */ |
/* |
* Setup fibril-local connection pointer and call client_connection(). |
* |
*/ |
FIBRIL_connection = (connection_t *) arg; |
FIBRIL_connection->cfibril(FIBRIL_connection->callid, |
&FIBRIL_connection->call); |
441,20 → 494,20 |
/* Remove myself from the connection hash table */ |
futex_down(&async_futex); |
key = FIBRIL_connection->in_phone_hash; |
unsigned long key = FIBRIL_connection->in_phone_hash; |
hash_table_remove(&conn_hash_table, &key, 1); |
futex_up(&async_futex); |
/* Answer all remaining messages with EHANGUP */ |
while (!list_empty(&FIBRIL_connection->msg_queue)) { |
msg = list_get_instance(FIBRIL_connection->msg_queue.next, |
msg_t, link); |
msg_t *msg |
= list_get_instance(FIBRIL_connection->msg_queue.next, msg_t, link); |
list_remove(&msg->link); |
if (msg->callid == FIBRIL_connection->close_callid) |
close_answered = 1; |
ipc_answer_0(msg->callid, EHANGUP); |
free(msg); |
} |
if (FIBRIL_connection->close_callid) |
ipc_answer_0(FIBRIL_connection->close_callid, EOK); |
463,43 → 516,45 |
/** Create a new fibril for a new connection. |
* |
* Creates new fibril for connection, fills in connection structures and inserts |
* Create new fibril for connection, fill in connection structures and inserts |
* it into the hash table, so that later we can easily do routing of messages to |
* particular fibrils. |
* |
* @param in_phone_hash Identification of the incoming connection. |
* @param callid Hash of the opening IPC_M_CONNECT_ME_TO call. |
* If callid is zero, the connection was opened by |
* accepting the IPC_M_CONNECT_TO_ME call and this function |
* is called directly by the server. |
* @param call Call data of the opening call. |
* @param cfibril Fibril function that should be called upon opening the |
* connection. |
* @param in_phone_hash Identification of the incoming connection. |
* @param callid Hash of the opening IPC_M_CONNECT_ME_TO call. |
* If callid is zero, the connection was opened by |
* accepting the IPC_M_CONNECT_TO_ME call and this function |
* is called directly by the server. |
* @param call Call data of the opening call. |
* @param cfibril Fibril function that should be called upon opening the |
* connection. |
* |
* @return New fibril id or NULL on failure. |
* @return New fibril id or NULL on failure. |
* |
*/ |
fid_t async_new_connection(ipcarg_t in_phone_hash, ipc_callid_t callid, |
ipc_call_t *call, void (*cfibril)(ipc_callid_t, ipc_call_t *)) |
{ |
connection_t *conn; |
unsigned long key; |
conn = malloc(sizeof(*conn)); |
connection_t *conn = malloc(sizeof(*conn)); |
if (!conn) { |
if (callid) |
ipc_answer_0(callid, ENOMEM); |
return NULL; |
} |
conn->in_phone_hash = in_phone_hash; |
list_initialize(&conn->msg_queue); |
conn->callid = callid; |
conn->close_callid = 0; |
conn->close_callid = false; |
if (call) |
conn->call = *call; |
conn->wdata.active = 1; /* We will activate the fibril ASAP */ |
/* We will activate the fibril ASAP */ |
conn->wdata.active = true; |
conn->cfibril = cfibril; |
conn->wdata.fid = fibril_create(connection_fibril, conn); |
conn->wdata.fid = fibril_create(connection_fibril, conn); |
if (!conn->wdata.fid) { |
free(conn); |
if (callid) |
508,7 → 563,8 |
} |
/* Add connection to the connection hash table */ |
key = conn->in_phone_hash; |
ipcarg_t key = conn->in_phone_hash; |
futex_down(&async_futex); |
hash_table_insert(&conn_hash_table, &key, &conn->link); |
futex_up(&async_futex); |
523,8 → 579,8 |
* If the call has the IPC_M_CONNECT_ME_TO method, a new connection is created. |
* Otherwise the call is routed to its connection fibril. |
* |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* |
*/ |
static void handle_call(ipc_callid_t callid, ipc_call_t *call) |
531,13 → 587,12 |
{ |
/* Unrouted call - do some default behaviour */ |
if ((callid & IPC_CALLID_NOTIFICATION)) { |
_in_interrupt_handler = 1; |
(*interrupt_received)(callid, call); |
_in_interrupt_handler = 0; |
process_notification(callid, call); |
return; |
} |
switch (IPC_GET_METHOD(*call)) { |
case IPC_M_CONNECT_ME: |
case IPC_M_CONNECT_ME_TO: |
/* Open new connection with fibril etc. */ |
async_new_connection(IPC_GET_ARG5(*call), callid, call, |
557,47 → 612,44 |
static void handle_expired_timeouts(void) |
{ |
struct timeval tv; |
awaiter_t *waiter; |
link_t *cur; |
gettimeofday(&tv, NULL); |
futex_down(&async_futex); |
cur = timeout_list.next; |
link_t *cur = timeout_list.next; |
while (cur != &timeout_list) { |
waiter = list_get_instance(cur, awaiter_t, link); |
awaiter_t *waiter = list_get_instance(cur, awaiter_t, link); |
if (tv_gt(&waiter->expires, &tv)) |
break; |
cur = cur->next; |
list_remove(&waiter->link); |
waiter->inlist = 0; |
waiter->timedout = 1; |
waiter->inlist = false; |
waiter->timedout = true; |
/* |
* Redundant condition? |
* The fibril should not be active when it gets here. |
* Redundant condition? |
* The fibril should not be active when it gets here. |
*/ |
if (!waiter->active) { |
waiter->active = 1; |
waiter->active = true; |
fibril_add_ready(waiter->fid); |
} |
} |
futex_up(&async_futex); |
} |
/** Endless loop dispatching incoming calls and answers. |
* |
* @return Never returns. |
* @return Never returns. |
* |
*/ |
static int async_manager_worker(void) |
{ |
ipc_call_t call; |
ipc_callid_t callid; |
int timeout; |
awaiter_t *waiter; |
struct timeval tv; |
while (1) { |
while (true) { |
if (fibril_switch(FIBRIL_FROM_MANAGER)) { |
futex_up(&async_futex); |
/* |
606,11 → 658,17 |
*/ |
continue; |
} |
futex_down(&async_futex); |
suseconds_t timeout; |
if (!list_empty(&timeout_list)) { |
waiter = list_get_instance(timeout_list.next, awaiter_t, |
link); |
awaiter_t *waiter |
= list_get_instance(timeout_list.next, awaiter_t, link); |
struct timeval tv; |
gettimeofday(&tv, NULL); |
if (tv_gteq(&tv, &waiter->expires)) { |
futex_up(&async_futex); |
handle_expired_timeouts(); |
619,19 → 677,21 |
timeout = tv_sub(&waiter->expires, &tv); |
} else |
timeout = SYNCH_NO_TIMEOUT; |
futex_up(&async_futex); |
callid = ipc_wait_cycle(&call, timeout, SYNCH_FLAGS_NONE); |
ipc_call_t call; |
ipc_callid_t callid |
= ipc_wait_cycle(&call, timeout, SYNCH_FLAGS_NONE); |
if (!callid) { |
handle_expired_timeouts(); |
continue; |
} |
if (callid & IPC_CALLID_ANSWERED) { |
if (callid & IPC_CALLID_ANSWERED) |
continue; |
} |
handle_call(callid, &call); |
} |
639,16 → 699,17 |
} |
/** Function to start async_manager as a standalone fibril. |
* |
* |
* When more kernel threads are used, one async manager should exist per thread. |
* |
* @param arg Unused. |
* @param arg Unused. |
* @return Never returns. |
* |
* @return Never returns. |
*/ |
static int async_manager_fibril(void *arg) |
{ |
futex_up(&async_futex); |
/* |
* async_futex is always locked when entering manager |
*/ |
660,9 → 721,7 |
/** Add one manager to manager list. */ |
void async_create_manager(void) |
{ |
fid_t fid; |
fid = fibril_create(async_manager_fibril, NULL); |
fid_t fid = fibril_create(async_manager_fibril, NULL); |
fibril_add_manager(fid); |
} |
674,7 → 733,7 |
/** Initialize the async framework. |
* |
* @return Zero on success or an error code. |
* @return Zero on success or an error code. |
*/ |
int _async_init(void) |
{ |
694,30 → 753,33 |
* |
* Notify the fibril which is waiting for this message that it has arrived. |
* |
* @param private Pointer to the asynchronous message record. |
* @param retval Value returned in the answer. |
* @param data Call data of the answer. |
* @param arg Pointer to the asynchronous message record. |
* @param retval Value returned in the answer. |
* @param data Call data of the answer. |
*/ |
static void reply_received(void *private, int retval, ipc_call_t *data) |
static void reply_received(void *arg, int retval, ipc_call_t *data) |
{ |
amsg_t *msg = (amsg_t *) private; |
amsg_t *msg = (amsg_t *) arg; |
msg->retval = retval; |
futex_down(&async_futex); |
/* Copy data after futex_down, just in case the call was detached */ |
if (msg->dataptr) |
*msg->dataptr = *data; |
*msg->dataptr = *data; |
write_barrier(); |
/* Remove message from timeout list */ |
if (msg->wdata.inlist) |
list_remove(&msg->wdata.link); |
msg->done = 1; |
msg->done = true; |
if (!msg->wdata.active) { |
msg->wdata.active = 1; |
msg->wdata.active = true; |
fibril_add_ready(msg->wdata.fid); |
} |
futex_up(&async_futex); |
} |
726,31 → 788,35 |
* The return value can be used as input for async_wait() to wait for |
* completion. |
* |
* @param phoneid Handle of the phone that will be used for the send. |
* @param method Service-defined method. |
* @param arg1 Service-defined payload argument. |
* @param arg2 Service-defined payload argument. |
* @param arg3 Service-defined payload argument. |
* @param arg4 Service-defined payload argument. |
* @param dataptr If non-NULL, storage where the reply data will be |
* stored. |
* @param phoneid Handle of the phone that will be used for the send. |
* @param method Service-defined method. |
* @param arg1 Service-defined payload argument. |
* @param arg2 Service-defined payload argument. |
* @param arg3 Service-defined payload argument. |
* @param arg4 Service-defined payload argument. |
* @param dataptr If non-NULL, storage where the reply data will be |
* stored. |
* |
* @return Hash of the sent message. |
* @return Hash of the sent message or 0 on error. |
* |
*/ |
aid_t async_send_fast(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr) |
{ |
amsg_t *msg; |
amsg_t *msg = malloc(sizeof(*msg)); |
msg = malloc(sizeof(*msg)); |
msg->done = 0; |
if (!msg) |
return 0; |
msg->done = false; |
msg->dataptr = dataptr; |
msg->wdata.inlist = false; |
/* We may sleep in the next method, but it will use its own mechanism */ |
msg->wdata.active = 1; |
msg->wdata.active = true; |
ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg, |
reply_received, !_in_interrupt_handler); |
reply_received, true); |
return (aid_t) msg; |
} |
760,33 → 826,37 |
* The return value can be used as input for async_wait() to wait for |
* completion. |
* |
* @param phoneid Handle of the phone that will be used for the send. |
* @param method Service-defined method. |
* @param arg1 Service-defined payload argument. |
* @param arg2 Service-defined payload argument. |
* @param arg3 Service-defined payload argument. |
* @param arg4 Service-defined payload argument. |
* @param arg5 Service-defined payload argument. |
* @param dataptr If non-NULL, storage where the reply data will be |
* stored. |
* @param phoneid Handle of the phone that will be used for the send. |
* @param method Service-defined method. |
* @param arg1 Service-defined payload argument. |
* @param arg2 Service-defined payload argument. |
* @param arg3 Service-defined payload argument. |
* @param arg4 Service-defined payload argument. |
* @param arg5 Service-defined payload argument. |
* @param dataptr If non-NULL, storage where the reply data will be |
* stored. |
* |
* @return Hash of the sent message. |
* @return Hash of the sent message or 0 on error. |
* |
*/ |
aid_t async_send_slow(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, |
ipc_call_t *dataptr) |
{ |
amsg_t *msg; |
amsg_t *msg = malloc(sizeof(*msg)); |
msg = malloc(sizeof(*msg)); |
msg->done = 0; |
if (!msg) |
return 0; |
msg->done = false; |
msg->dataptr = dataptr; |
msg->wdata.inlist = false; |
/* We may sleep in next method, but it will use its own mechanism */ |
msg->wdata.active = 1; |
msg->wdata.active = true; |
ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg, |
reply_received, !_in_interrupt_handler); |
reply_received, true); |
return (aid_t) msg; |
} |
793,74 → 863,82 |
/** Wait for a message sent by the async framework. |
* |
* @param amsgid Hash of the message to wait for. |
* @param retval Pointer to storage where the retval of the answer will |
* be stored. |
* @param amsgid Hash of the message to wait for. |
* @param retval Pointer to storage where the retval of the answer will |
* be stored. |
* |
*/ |
void async_wait_for(aid_t amsgid, ipcarg_t *retval) |
{ |
amsg_t *msg = (amsg_t *) amsgid; |
futex_down(&async_futex); |
if (msg->done) { |
futex_up(&async_futex); |
goto done; |
} |
msg->wdata.fid = fibril_get_id(); |
msg->wdata.active = 0; |
msg->wdata.inlist = 0; |
msg->wdata.active = false; |
msg->wdata.inlist = false; |
/* Leave the async_futex locked when entering this function */ |
fibril_switch(FIBRIL_TO_MANAGER); |
/* futex is up automatically after fibril_switch...*/ |
/* Futex is up automatically after fibril_switch */ |
done: |
if (retval) |
*retval = msg->retval; |
free(msg); |
} |
/** Wait for a message sent by the async framework, timeout variant. |
* |
* @param amsgid Hash of the message to wait for. |
* @param retval Pointer to storage where the retval of the answer will |
* be stored. |
* @param timeout Timeout in microseconds. |
* @param amsgid Hash of the message to wait for. |
* @param retval Pointer to storage where the retval of the answer will |
* be stored. |
* @param timeout Timeout in microseconds. |
* |
* @return Zero on success, ETIMEOUT if the timeout has expired. |
* @return Zero on success, ETIMEOUT if the timeout has expired. |
* |
*/ |
int async_wait_timeout(aid_t amsgid, ipcarg_t *retval, suseconds_t timeout) |
{ |
amsg_t *msg = (amsg_t *) amsgid; |
/* TODO: Let it go through the event read at least once */ |
if (timeout < 0) |
return ETIMEOUT; |
futex_down(&async_futex); |
if (msg->done) { |
futex_up(&async_futex); |
goto done; |
} |
gettimeofday(&msg->wdata.expires, NULL); |
tv_add(&msg->wdata.expires, timeout); |
msg->wdata.fid = fibril_get_id(); |
msg->wdata.active = 0; |
msg->wdata.active = false; |
insert_timeout(&msg->wdata); |
/* Leave the async_futex locked when entering this function */ |
fibril_switch(FIBRIL_TO_MANAGER); |
/* futex is up automatically after fibril_switch...*/ |
/* Futex is up automatically after fibril_switch */ |
if (!msg->done) |
return ETIMEOUT; |
done: |
if (retval) |
*retval = msg->retval; |
free(msg); |
return 0; |
} |
868,33 → 946,38 |
* |
* The current fibril is suspended but the thread continues to execute. |
* |
* @param timeout Duration of the wait in microseconds. |
* @param timeout Duration of the wait in microseconds. |
* |
*/ |
void async_usleep(suseconds_t timeout) |
{ |
amsg_t *msg; |
amsg_t *msg = malloc(sizeof(*msg)); |
msg = malloc(sizeof(*msg)); |
if (!msg) |
return; |
msg->wdata.fid = fibril_get_id(); |
msg->wdata.active = 0; |
msg->wdata.active = false; |
gettimeofday(&msg->wdata.expires, NULL); |
tv_add(&msg->wdata.expires, timeout); |
futex_down(&async_futex); |
insert_timeout(&msg->wdata); |
/* Leave the async_futex locked when entering this function */ |
fibril_switch(FIBRIL_TO_MANAGER); |
/* futex is up automatically after fibril_switch()...*/ |
/* Futex is up automatically after fibril_switch() */ |
free(msg); |
} |
/** Setter for client_connection function pointer. |
* |
* @param conn Function that will implement a new connection fibril. |
* @param conn Function that will implement a new connection fibril. |
* |
*/ |
void async_set_client_connection(async_client_conn_t conn) |
{ |
903,12 → 986,12 |
/** Setter for interrupt_received function pointer. |
* |
* @param conn Function that will implement a new interrupt |
* notification fibril. |
* @param intr Function that will implement a new interrupt |
* notification fibril. |
*/ |
void async_set_interrupt_received(async_client_conn_t conn) |
void async_set_interrupt_received(async_client_conn_t intr) |
{ |
interrupt_received = conn; |
interrupt_received = intr; |
} |
/** Pseudo-synchronous message sending - fast version. |
918,18 → 1001,20 |
* This function can only transfer 4 register payload arguments. For |
* transferring more arguments, see the slower async_req_slow(). |
* |
* @param phoneid Hash of the phone through which to make the call. |
* @param method Method of the call. |
* @param arg1 Service-defined payload argument. |
* @param arg2 Service-defined payload argument. |
* @param arg3 Service-defined payload argument. |
* @param arg4 Service-defined payload argument. |
* @param r1 If non-NULL, storage for the 1st reply argument. |
* @param r2 If non-NULL, storage for the 2nd reply argument. |
* @param r3 If non-NULL, storage for the 3rd reply argument. |
* @param r4 If non-NULL, storage for the 4th reply argument. |
* @param r5 If non-NULL, storage for the 5th reply argument. |
* @return Return code of the reply or a negative error code. |
* @param phoneid Hash of the phone through which to make the call. |
* @param method Method of the call. |
* @param arg1 Service-defined payload argument. |
* @param arg2 Service-defined payload argument. |
* @param arg3 Service-defined payload argument. |
* @param arg4 Service-defined payload argument. |
* @param r1 If non-NULL, storage for the 1st reply argument. |
* @param r2 If non-NULL, storage for the 2nd reply argument. |
* @param r3 If non-NULL, storage for the 3rd reply argument. |
* @param r4 If non-NULL, storage for the 4th reply argument. |
* @param r5 If non-NULL, storage for the 5th reply argument. |
* |
* @return Return code of the reply or a negative error code. |
* |
*/ |
ipcarg_t async_req_fast(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t *r1, ipcarg_t *r2, |
936,21 → 1021,27 |
ipcarg_t *r3, ipcarg_t *r4, ipcarg_t *r5) |
{ |
ipc_call_t result; |
ipcarg_t rc; |
aid_t eid = async_send_4(phoneid, method, arg1, arg2, arg3, arg4, |
&result); |
ipcarg_t rc; |
async_wait_for(eid, &rc); |
if (r1) |
if (r1) |
*r1 = IPC_GET_ARG1(result); |
if (r2) |
*r2 = IPC_GET_ARG2(result); |
if (r3) |
*r3 = IPC_GET_ARG3(result); |
if (r4) |
*r4 = IPC_GET_ARG4(result); |
if (r5) |
*r5 = IPC_GET_ARG5(result); |
return rc; |
} |
958,19 → 1049,21 |
* |
* Send message asynchronously and return only after the reply arrives. |
* |
* @param phoneid Hash of the phone through which to make the call. |
* @param method Method of the call. |
* @param arg1 Service-defined payload argument. |
* @param arg2 Service-defined payload argument. |
* @param arg3 Service-defined payload argument. |
* @param arg4 Service-defined payload argument. |
* @param arg5 Service-defined payload argument. |
* @param r1 If non-NULL, storage for the 1st reply argument. |
* @param r2 If non-NULL, storage for the 2nd reply argument. |
* @param r3 If non-NULL, storage for the 3rd reply argument. |
* @param r4 If non-NULL, storage for the 4th reply argument. |
* @param r5 If non-NULL, storage for the 5th reply argument. |
* @return Return code of the reply or a negative error code. |
* @param phoneid Hash of the phone through which to make the call. |
* @param method Method of the call. |
* @param arg1 Service-defined payload argument. |
* @param arg2 Service-defined payload argument. |
* @param arg3 Service-defined payload argument. |
* @param arg4 Service-defined payload argument. |
* @param arg5 Service-defined payload argument. |
* @param r1 If non-NULL, storage for the 1st reply argument. |
* @param r2 If non-NULL, storage for the 2nd reply argument. |
* @param r3 If non-NULL, storage for the 3rd reply argument. |
* @param r4 If non-NULL, storage for the 4th reply argument. |
* @param r5 If non-NULL, storage for the 5th reply argument. |
* |
* @return Return code of the reply or a negative error code. |
* |
*/ |
ipcarg_t async_req_slow(int phoneid, ipcarg_t method, ipcarg_t arg1, |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, ipcarg_t *r1, |
977,21 → 1070,27 |
ipcarg_t *r2, ipcarg_t *r3, ipcarg_t *r4, ipcarg_t *r5) |
{ |
ipc_call_t result; |
ipcarg_t rc; |
aid_t eid = async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, |
&result); |
ipcarg_t rc; |
async_wait_for(eid, &rc); |
if (r1) |
if (r1) |
*r1 = IPC_GET_ARG1(result); |
if (r2) |
*r2 = IPC_GET_ARG2(result); |
if (r3) |
*r3 = IPC_GET_ARG3(result); |
if (r4) |
*r4 = IPC_GET_ARG4(result); |
if (r5) |
*r5 = IPC_GET_ARG5(result); |
return rc; |
} |
/branches/dd/uspace/lib/libc/generic/vfs/vfs.c |
---|
48,7 → 48,7 |
#include <futex.h> |
#include <errno.h> |
#include <string.h> |
#include <ipc/devmap.h> |
#include <devmap.h> |
#include "../../../srv/vfs/vfs.h" |
int vfs_phone = -1; |
115,47 → 115,8 |
vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0); |
} |
static int device_get_handle(const char *name, dev_handle_t *handle, |
const unsigned int flags) |
{ |
int phone; |
if (flags & IPC_FLAG_BLOCKING) |
phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT, 0); |
else |
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT, 0); |
if (phone < 0) |
return phone; |
ipc_call_t answer; |
aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0, |
&answer); |
ipcarg_t retval = ipc_data_write_start(phone, name, str_size(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
ipc_hangup(phone); |
return retval; |
} |
async_wait_for(req, &retval); |
if (handle != NULL) |
*handle = -1; |
if (retval == EOK) { |
if (handle != NULL) |
*handle = (dev_handle_t) IPC_GET_ARG1(answer); |
} |
ipc_hangup(phone); |
return retval; |
} |
int mount(const char *fs_name, const char *mp, const char *dev, |
const unsigned int flags) |
const char *opts, unsigned int flags) |
{ |
int res; |
ipcarg_t rc; |
162,7 → 123,7 |
aid_t req; |
dev_handle_t dev_handle; |
res = device_get_handle(dev, &dev_handle, flags); |
res = devmap_device_get_handle(dev, &dev_handle, flags); |
if (res != EOK) |
return res; |
185,6 → 146,15 |
return (int) rc; |
} |
rc = ipc_data_write_start(vfs_phone, (void *) opts, str_size(opts)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(mpa); |
return (int) rc; |
} |
rc = ipc_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
193,6 → 163,16 |
free(mpa); |
return (int) rc; |
} |
/* Ask VFS whether it likes fs_name. */ |
rc = async_req_0_0(vfs_phone, IPC_M_PING); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(mpa); |
return (int) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
/branches/dd/uspace/lib/libc/generic/libadt/list.c |
---|
48,12 → 48,12 |
*/ |
int list_member(const link_t *link, const link_t *head) |
{ |
int found = false; |
int found = 0; |
link_t *hlp = head->next; |
while (hlp != head) { |
if (hlp == link) { |
found = true; |
found = 1; |
break; |
} |
hlp = hlp->next; |
77,13 → 77,36 |
{ |
if (list_empty(head2)) |
return; |
head2->next->prev = head1->prev; |
head2->prev->next = head1; |
head2->prev->next = head1; |
head1->prev->next = head2->next; |
head1->prev = head2->prev; |
list_initialize(head2); |
} |
/** Count list items |
* |
* Return the number of items in the list. |
* |
* @param link List to count. |
* |
* @return Number of items in the list. |
* |
*/ |
unsigned int list_count(const link_t *link) |
{ |
unsigned int count = 0; |
link_t *hlp = link->next; |
while (hlp != link) { |
count++; |
hlp = hlp->next; |
} |
return count; |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/io/io.c |
---|
38,6 → 38,7 |
#include <io/io.h> |
#include <string.h> |
#include <errno.h> |
#include <console.h> |
const static char nl = '\n'; |
49,8 → 50,9 |
return putnchars("(NULL)", 6); |
for (count = 0; str[count] != 0; count++); |
if (write_stdout((void *) str, count) == count) { |
if (write_stdout(&nl, 1) == 1) |
if (console_write((void *) str, count) == count) { |
if (console_write(&nl, 1) == 1) |
return 0; |
} |
64,7 → 66,7 |
*/ |
int putnchars(const char *buf, size_t count) |
{ |
if (write_stdout((void *) buf, count) == count) |
if (console_write((void *) buf, count) == count) |
return 0; |
return EOF; |
81,7 → 83,7 |
return putnchars("(NULL)", 6); |
for (count = 0; str[count] != 0; count++); |
if (write_stdout((void *) str, count) == count) |
if (console_write((void *) str, count) == count) |
return 0; |
return EOF; |
96,7 → 98,7 |
if (chr_encode(c, buf, &offs, STR_BOUNDS(1)) != EOK) |
return EOF; |
if (write_stdout((void *) buf, offs) == offs) |
if (console_write((void *) buf, offs) == offs) |
return c; |
return EOF; |
105,8 → 107,8 |
int getchar(void) |
{ |
unsigned char c; |
flush_stdout(); |
console_flush(); |
if (read_stdin((void *) &c, 1) == 1) |
return c; |
115,8 → 117,10 |
int fflush(FILE *f) |
{ |
/* Dummy implementation */ |
(void) f; |
return flush_stdout(); |
console_flush(); |
return 0; |
} |
/** @} |
/branches/dd/uspace/lib/libc/generic/io/vprintf.c |
---|
38,6 → 38,7 |
#include <io/printf_core.h> |
#include <futex.h> |
#include <async.h> |
#include <console.h> |
static atomic_t printf_futex = FUTEX_INITIALIZER; |
50,7 → 51,7 |
while (offset < size) { |
prev = offset; |
str_decode(str, &offset, size); |
write_stdout(str + prev, offset - prev); |
console_write(str + prev, offset - prev); |
chars++; |
} |
67,7 → 68,7 |
while (offset < size) { |
boff = 0; |
chr_encode(str[chars], buf, &boff, 4); |
write_stdout(buf, boff); |
console_write(buf, boff); |
chars++; |
offset += sizeof(wchar_t); |
} |
/branches/dd/uspace/lib/libc/generic/io/stream.c |
---|
49,62 → 49,34 |
#include <async.h> |
#include <sys/types.h> |
ssize_t write_stderr(const void *buf, size_t count) |
{ |
return count; |
} |
ssize_t read_stdin(void *buf, size_t count) |
{ |
int cons_phone = console_phone_get(false); |
int cons_phone = console_open(false); |
if (cons_phone >= 0) { |
kbd_event_t ev; |
int rc; |
size_t i = 0; |
while (i < count) { |
do { |
rc = kbd_get_event(&ev); |
if (rc < 0) return -1; |
} while (ev.c == 0 || ev.type == KE_RELEASE); |
((char *) buf)[i++] = ev.c; |
} |
return i; |
} else { |
} else |
return -1; |
} |
} |
ssize_t write_stdout(const void *buf, size_t count) |
/** Write a string to klog. */ |
int klog_puts(const char *str) |
{ |
int cons_phone = console_phone_get(false); |
int left, rc; |
if (cons_phone >= 0) { |
int i; |
left = count; |
while (left > 0) { |
rc = console_write(buf, left); |
if (rc < 0) |
break; |
buf += rc; |
left -= rc; |
} |
return count; |
} else |
return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, count); |
return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) str, str_size(str)); |
} |
int flush_stdout(void) |
{ |
console_flush(); |
return 0; |
} |
void klog_update(void) |
{ |
(void) __SYSCALL3(SYS_KLOG, 1, NULL, 0); |
/branches/dd/uspace/lib/libc/Makefile |
---|
47,6 → 47,7 |
generic/as.c \ |
generic/cap.c \ |
generic/console.c \ |
generic/devmap.c \ |
generic/event.c \ |
generic/mem.c \ |
generic/string.c \ |
/branches/dd/uspace/srv/fhc/Makefile |
---|
64,7 → 64,7 |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/kbd/include/kbd.h |
---|
38,6 → 38,7 |
#define KBD_KBD_H_ |
#include <key_buffer.h> |
#include <ipc/ipc.h> |
#define KBD_EVENT 1024 |
#define KBD_MS_LEFT 1025 |
45,6 → 46,11 |
#define KBD_MS_MIDDLE 1027 |
#define KBD_MS_MOVE 1028 |
typedef enum { |
KBD_YIELD = IPC_FIRST_USER_METHOD, |
KBD_RECLAIM |
} kbd_request_t; |
extern int cir_service; |
extern int cir_phone; |
/branches/dd/uspace/srv/kbd/include/kbd_port.h |
---|
38,6 → 38,8 |
#define KBD_PORT_H_ |
extern int kbd_port_init(void); |
extern void kbd_port_yield(void); |
extern void kbd_port_reclaim(void); |
#endif |
/branches/dd/uspace/srv/kbd/port/gxemul.c |
---|
69,6 → 69,14 |
return 0; |
} |
void kbd_port_yield(void) |
{ |
} |
void kbd_port_reclaim(void) |
{ |
} |
/** Process data sent when a key is pressed. |
* |
* @param keybuffer Buffer of pressed keys. |
/branches/dd/uspace/srv/kbd/port/ns16550.c |
---|
106,6 → 106,14 |
return pio_enable((void *) ns16550_physical, 8, &vaddr); |
} |
void ns16550_port_yield(void) |
{ |
} |
void ns16550_port_reclaim(void) |
{ |
} |
static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call) |
{ |
int scan_code = IPC_GET_ARG2(*call); |
/branches/dd/uspace/srv/kbd/port/msim.c |
---|
69,22 → 69,17 |
return 0; |
} |
void kbd_port_yield(void) |
{ |
} |
void kbd_port_reclaim(void) |
{ |
} |
static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call) |
{ |
int scan_code = IPC_GET_ARG2(*call); |
// static int esc_count=0; |
// if (scan_code == 0x1b) { |
// esc_count++; |
// if (esc_count == 3) |
// __SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE); |
// } else { |
// esc_count=0; |
// } |
// if (fb_fb) |
// return kbd_arch_process_fb(keybuffer, scan_code); |
kbd_push_scancode(scan_code); |
} |
/branches/dd/uspace/srv/kbd/port/sun.c |
---|
39,13 → 39,6 |
#include <sun.h> |
#include <sysinfo.h> |
typedef enum { |
KBD_UNKNOWN, |
KBD_Z8530, |
KBD_NS16550, |
KBD_SGCN |
} kbd_type_t; |
/** Sun keyboard virtual port driver. |
* |
* This is a virtual port driver which can use |
56,13 → 49,26 |
*/ |
int kbd_port_init(void) |
{ |
if (sysinfo_value("kbd.type") == KBD_Z8530) |
return z8530_port_init(); |
else if (sysinfo_value("kbd.type") == KBD_NS16550) |
return ns16550_port_init(); |
if (sysinfo_value("kbd.type.z8530")) { |
if (z8530_port_init() == 0) |
return 0; |
} |
if (sysinfo_value("kbd.type.ns16550")) { |
if (ns16550_port_init() == 0) |
return 0; |
} |
return -1; |
} |
void kbd_port_yield(void) |
{ |
} |
void kbd_port_reclaim(void) |
{ |
} |
/** @} |
*/ |
/branches/dd/uspace/srv/kbd/port/i8042.c |
---|
151,6 → 151,14 |
return 0; |
} |
void kbd_port_yield(void) |
{ |
} |
void kbd_port_reclaim(void) |
{ |
} |
static void i8042_irq_handler(ipc_callid_t iid, ipc_call_t *call) |
{ |
int status = IPC_GET_ARG1(*call); |
/branches/dd/uspace/srv/kbd/port/ski.c |
---|
42,6 → 42,7 |
#include <kbd_port.h> |
#include <sys/types.h> |
#include <thread.h> |
#include <bool.h> |
#define SKI_GETCHAR 21 |
50,6 → 51,8 |
static void *ski_thread_impl(void *arg); |
static int32_t ski_getchar(void); |
static volatile bool polling_disabled = false; |
/** Initialize Ski port driver. */ |
int kbd_port_init(void) |
{ |
64,6 → 67,16 |
return 0; |
} |
void kbd_port_yield(void) |
{ |
polling_disabled = true; |
} |
void kbd_port_reclaim(void) |
{ |
polling_disabled = false; |
} |
/** Thread to poll Ski for keypresses. */ |
static void *ski_thread_impl(void *arg) |
{ |
71,7 → 84,7 |
(void) arg; |
while (1) { |
while (1) { |
while (polling_disabled == false) { |
c = ski_getchar(); |
if (c == 0) |
break; |
/branches/dd/uspace/srv/kbd/port/z8530.c |
---|
95,6 → 95,14 |
return 0; |
} |
void z8530_port_yield(void) |
{ |
} |
void z8530_port_reclaim(void) |
{ |
} |
static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call) |
{ |
int scan_code = IPC_GET_ARG2(*call); |
/branches/dd/uspace/srv/kbd/port/sgcn.c |
---|
42,6 → 42,7 |
#include <sysinfo.h> |
#include <stdio.h> |
#include <thread.h> |
#include <bool.h> |
#define POLL_INTERVAL 10000 |
92,6 → 93,7 |
/* polling thread */ |
static void *sgcn_thread_impl(void *arg); |
static volatile bool polling_disabled = false; |
/** |
* Initializes the SGCN driver. |
120,6 → 122,16 |
return 0; |
} |
void kbd_port_yield(void) |
{ |
polling_disabled = true; |
} |
void kbd_port_reclaim(void) |
{ |
polling_disabled = false; |
} |
/** |
* Handler of the "key pressed" event. Reads codes of all the pressed keys from |
* the buffer. |
154,11 → 166,11 |
(void) arg; |
while (1) { |
sgcn_key_pressed(); |
if (polling_disabled == false) |
sgcn_key_pressed(); |
usleep(POLL_INTERVAL); |
} |
} |
/** @} |
*/ |
/branches/dd/uspace/srv/kbd/port/dummy.c |
---|
42,5 → 42,13 |
return 0; |
} |
void kbd_port_yield(void) |
{ |
} |
void kbd_port_reclaim(void) |
{ |
} |
/** @} |
*/ |
/branches/dd/uspace/srv/kbd/generic/kbd.c |
---|
193,6 → 193,14 |
phone2cons = IPC_GET_ARG5(call); |
retval = 0; |
break; |
case KBD_YIELD: |
kbd_port_yield(); |
retval = 0; |
break; |
case KBD_RECLAIM: |
kbd_port_reclaim(); |
retval = 0; |
break; |
default: |
retval = EINVAL; |
} |
/branches/dd/uspace/srv/kbd/Makefile |
---|
112,8 → 112,15 |
ifeq ($(MACHINE), bgxemul) |
GENARCH_SOURCES += \ |
port/gxemul.c \ |
ctl/stty.c |
port/gxemul.c |
ifeq ($(CONFIG_FB), y) |
GENARCH_SOURCES += \ |
ctl/gxe_fb.c |
else |
GENARCH_SOURCES += \ |
ctl/stty.c |
endif |
endif |
ifeq ($(UARCH), ppc32) |
160,7 → 167,7 |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/kbd/layout/cz.c |
---|
54,19 → 54,6 |
}; |
static wchar_t map_lcase[] = { |
[KC_2] = L'ě', |
[KC_3] = L'š', |
[KC_4] = L'č', |
[KC_5] = L'ř', |
[KC_6] = L'ž', |
[KC_7] = L'ý', |
[KC_8] = L'á', |
[KC_9] = L'í', |
[KC_0] = L'é', |
[KC_LBRACKET] = L'ú', |
[KC_SEMICOLON] = L'ů', |
[KC_Q] = 'q', |
[KC_W] = 'w', |
[KC_E] = 'e', |
98,19 → 85,6 |
}; |
static wchar_t map_ucase[] = { |
[KC_2] = L'Ě', |
[KC_3] = L'Š', |
[KC_4] = L'Č', |
[KC_5] = L'Ř', |
[KC_6] = L'Ž', |
[KC_7] = L'Ý', |
[KC_8] = L'Á', |
[KC_9] = L'Í', |
[KC_0] = L'É', |
[KC_LBRACKET] = L'Ú', |
[KC_SEMICOLON] = L'Ů', |
[KC_Q] = 'Q', |
[KC_W] = 'W', |
[KC_E] = 'E', |
183,6 → 157,36 |
[KC_SLASH] = '_', |
}; |
static wchar_t map_ns_nocaps[] = { |
[KC_2] = L'ě', |
[KC_3] = L'š', |
[KC_4] = L'č', |
[KC_5] = L'ř', |
[KC_6] = L'ž', |
[KC_7] = L'ý', |
[KC_8] = L'á', |
[KC_9] = L'í', |
[KC_0] = L'é', |
[KC_LBRACKET] = L'ú', |
[KC_SEMICOLON] = L'ů' |
}; |
static wchar_t map_ns_caps[] = { |
[KC_2] = L'Ě', |
[KC_3] = L'Š', |
[KC_4] = L'Č', |
[KC_5] = L'Ř', |
[KC_6] = L'Ž', |
[KC_7] = L'Ý', |
[KC_8] = L'Á', |
[KC_9] = L'Í', |
[KC_0] = L'É', |
[KC_LBRACKET] = L'Ú', |
[KC_SEMICOLON] = L'Ů' |
}; |
static wchar_t map_neutral[] = { |
[KC_BACKSPACE] = '\b', |
[KC_TAB] = '\t', |
325,6 → 329,16 |
if (c != 0) |
return c; |
if ((ev->mods & KM_SHIFT) == 0) { |
if ((ev->mods & KM_CAPS_LOCK) != 0) |
c = translate(ev->key, map_ns_caps, sizeof(map_ns_caps) / sizeof(wchar_t)); |
else |
c = translate(ev->key, map_ns_nocaps, sizeof(map_ns_nocaps) / sizeof(wchar_t)); |
if (c != 0) |
return c; |
} |
if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0)) |
c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t)); |
else |
/branches/dd/uspace/srv/ns/Makefile |
---|
63,7 → 63,7 |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/console/console.c |
---|
64,6 → 64,9 |
int active_console = 0; |
int prev_console = 0; |
/** Phone to the keyboard driver. */ |
static int kbd_phone; |
/** Information about framebuffer */ |
struct { |
int phone; /**< Framebuffer phone */ |
141,6 → 144,26 |
async_msg_2(fb_info.phone, FB_CURSOR_GOTO, row, col); |
} |
static void screen_yield(void) |
{ |
ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_YIELD); |
} |
static void screen_reclaim(void) |
{ |
ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_RECLAIM); |
} |
static void kbd_yield(void) |
{ |
ipc_call_sync_0_0(kbd_phone, KBD_YIELD); |
} |
static void kbd_reclaim(void) |
{ |
ipc_call_sync_0_0(kbd_phone, KBD_RECLAIM); |
} |
static void set_style(int style) |
{ |
async_msg_1(fb_info.phone, FB_SET_STYLE, style); |
330,7 → 353,10 |
async_serialize_start(); |
curs_hide_sync(); |
gcons_in_kernel(); |
screen_yield(); |
kbd_yield(); |
async_serialize_end(); |
if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) { |
prev_console = active_console; |
342,8 → 368,11 |
if (newcons != KERNEL_CONSOLE) { |
async_serialize_start(); |
if (active_console == KERNEL_CONSOLE) |
if (active_console == KERNEL_CONSOLE) { |
screen_reclaim(); |
kbd_reclaim(); |
gcons_redraw_console(); |
} |
active_console = newcons; |
gcons_change_console(newcons); |
474,6 → 503,7 |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
if (size > CWRITE_BUF_SIZE) |
481,6 → 511,8 |
(void) ipc_data_write_finalize(callid, cwrite_buf, size); |
async_serialize_start(); |
off = 0; |
while (off < size) { |
ch = str_decode(cwrite_buf, &off, size); |
487,6 → 519,8 |
write_char(consnum, ch); |
} |
async_serialize_end(); |
gcons_notify_char(consnum); |
ipc_answer_1(rid, EOK, size); |
} |
512,6 → 546,8 |
gcons_notify_connect(consnum); |
conn->client_phone = IPC_GET_ARG5(*icall); |
screenbuffer_clear(&conn->screenbuffer); |
if (consnum == active_console) |
clrscr(); |
/* Accept the connection */ |
ipc_answer_0(iid, EOK); |
544,7 → 580,9 |
gcons_notify_char(consnum); |
break; |
case CONSOLE_WRITE: |
async_serialize_end(); |
cons_write(consnum, callid, &call); |
async_serialize_start(); |
continue; |
case CONSOLE_CLEAR: |
/* Send message to fb */ |
649,7 → 687,6 |
printf(NAME ": HelenOS Console service\n"); |
ipcarg_t phonehash; |
int kbd_phone; |
size_t ib_size; |
int i; |
/branches/dd/uspace/srv/console/Makefile |
---|
78,7 → 78,7 |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/rd/rd.h |
---|
File deleted |
/branches/dd/uspace/srv/rd/rd.c |
---|
52,8 → 52,8 |
#include <async.h> |
#include <futex.h> |
#include <stdio.h> |
#include <ipc/devmap.h> |
#include "rd.h" |
#include <devmap.h> |
#include <ipc/bd.h> |
#define NAME "rd" |
112,7 → 112,7 |
return; |
} |
while (1) { |
while (true) { |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
122,7 → 122,7 |
*/ |
ipc_answer_0(callid, EOK); |
return; |
case RD_READ_BLOCK: |
case BD_READ_BLOCK: |
offset = IPC_GET_ARG1(call); |
block_size = IPC_GET_ARG2(call); |
if (block_size > maxblock_size) { |
144,7 → 144,7 |
futex_up(&rd_futex); |
retval = EOK; |
break; |
case RD_WRITE_BLOCK: |
case BD_WRITE_BLOCK: |
offset = IPC_GET_ARG1(call); |
block_size = IPC_GET_ARG2(call); |
if (block_size > maxblock_size) { |
180,66 → 180,6 |
} |
} |
static int driver_register(char *name) |
{ |
ipcarg_t retval; |
aid_t req; |
ipc_call_t answer; |
int phone; |
ipcarg_t callback_phonehash; |
phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0); |
if (phone < 0) { |
printf(NAME ": Failed to connect to device mapper\n"); |
return -1; |
} |
req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer); |
retval = ipc_data_write_start(phone, (char *) name, str_size(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
return -1; |
} |
async_set_client_connection(rd_connection); |
ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash); |
async_wait_for(req, &retval); |
return phone; |
} |
static int device_register(int driver_phone, char *name, int *handle) |
{ |
ipcarg_t retval; |
aid_t req; |
ipc_call_t answer; |
req = async_send_2(driver_phone, DEVMAP_DEVICE_REGISTER, 0, 0, &answer); |
retval = ipc_data_write_start(driver_phone, (char *) name, |
str_size(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
return retval; |
} |
async_wait_for(req, &retval); |
if (handle != NULL) |
*handle = -1; |
if (EOK == retval) { |
if (NULL != handle) |
*handle = (int) IPC_GET_ARG1(answer); |
} |
return retval; |
} |
/** Prepare the ramdisk image for operation. */ |
static bool rd_init(void) |
{ |
264,15 → 204,15 |
printf(NAME ": Found RAM disk at %p, %d bytes\n", rd_ph_addr, rd_size); |
int driver_phone = driver_register(NAME); |
if (driver_phone < 0) { |
printf(NAME ": Unable to register driver\n"); |
int rc = devmap_driver_register(NAME, rd_connection); |
if (rc < 0) { |
printf(NAME ": Unable to register driver (%d)\n", rc); |
return false; |
} |
int dev_handle; |
if (EOK != device_register(driver_phone, "initrd", &dev_handle)) { |
ipc_hangup(driver_phone); |
dev_handle_t dev_handle; |
if (devmap_device_register("initrd", &dev_handle) != EOK) { |
devmap_hangup_phone(DEVMAP_DRIVER); |
printf(NAME ": Unable to register device\n"); |
return false; |
} |
296,4 → 236,4 |
/** |
* @} |
*/ |
*/ |
/branches/dd/uspace/srv/rd/Makefile |
---|
64,7 → 64,7 |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/bd/gxe_bd/gxe_bd.c |
---|
0,0 → 1,272 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup bd |
* @{ |
*/ |
/** |
* @file |
* @brief GXemul disk driver |
*/ |
#include <stdio.h> |
#include <libarch/ddi.h> |
#include <ddi.h> |
#include <ipc/ipc.h> |
#include <ipc/bd.h> |
#include <async.h> |
#include <as.h> |
#include <futex.h> |
#include <devmap.h> |
#include <sys/types.h> |
#include <errno.h> |
#define NAME "gxe_bd" |
enum { |
CTL_READ_START = 0, |
CTL_WRITE_START = 1, |
}; |
enum { |
STATUS_FAILURE = 0 |
}; |
typedef struct { |
uint32_t offset_lo; |
uint32_t pad0; |
uint32_t offset_hi; |
uint32_t pad1; |
uint32_t disk_id; |
uint32_t pad2[3]; |
uint32_t control; |
uint32_t pad3[3]; |
uint32_t status; |
/* FIXME: Need to fix pio_enable() to support >= page_size areas. |
uint32_t pad4[3]; |
uint32_t pad5[0x3fc0]; |
uint8_t buffer[512];*/ |
} gxe_bd_t; |
typedef struct { |
uint8_t buffer[512]; |
} gxe_buf_t; |
static size_t maxblock_size = 512; |
static uintptr_t dev_physical = 0x13000000; |
static gxe_bd_t *dev; |
static gxe_buf_t *devbuf; |
static uint32_t disk_id = 0; |
static atomic_t dev_futex = FUTEX_INITIALIZER; |
static int gxe_bd_init(void); |
static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall); |
static int gxe_bd_read_block(uint64_t offset, size_t block_size, void *buf); |
static int gxe_bd_write_block(uint64_t offset, size_t block_size, |
const void *buf); |
int main(int argc, char **argv) |
{ |
printf(NAME ": GXemul disk driver\n"); |
if (gxe_bd_init() != EOK) |
return -1; |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* Not reached */ |
return 0; |
} |
static int gxe_bd_init(void) |
{ |
dev_handle_t dev_handle; |
void *vaddr; |
int rc; |
rc = devmap_driver_register(NAME, gxe_bd_connection); |
if (rc < 0) { |
printf(NAME ": Unable to register driver.\n"); |
return rc; |
} |
rc = pio_enable((void *) dev_physical, sizeof(gxe_bd_t), &vaddr); |
if (rc != EOK) { |
printf(NAME ": Could not initialize device I/O space.\n"); |
return rc; |
} |
dev = vaddr; |
rc = pio_enable((void *) dev_physical + 0x4000, sizeof(gxe_buf_t), &vaddr); |
if (rc != EOK) { |
printf(NAME ": Could not initialize device I/O space.\n"); |
return rc; |
} |
devbuf = vaddr; |
rc = devmap_device_register("disk0", &dev_handle); |
if (rc != EOK) { |
devmap_hangup_phone(DEVMAP_DRIVER); |
printf(NAME ": Unable to register device.\n"); |
return rc; |
} |
return EOK; |
} |
static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
void *fs_va = NULL; |
ipc_callid_t callid; |
ipc_call_t call; |
int flags; |
int retval; |
off_t offset; |
size_t block_size; |
/* Answer the IPC_M_CONNECT_ME_TO call. */ |
ipc_answer_0(iid, EOK); |
if (!ipc_share_out_receive(&callid, &maxblock_size, &flags)) { |
ipc_answer_0(callid, EHANGUP); |
return; |
} |
maxblock_size = 512; |
fs_va = as_get_mappable_page(maxblock_size); |
if (fs_va == NULL) { |
ipc_answer_0(callid, EHANGUP); |
return; |
} |
(void) ipc_share_out_finalize(callid, fs_va); |
while (1) { |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
/* The other side has hung up. */ |
ipc_answer_0(callid, EOK); |
return; |
case BD_READ_BLOCK: |
offset = IPC_GET_ARG1(call); |
block_size = IPC_GET_ARG2(call); |
retval = gxe_bd_read_block(offset, block_size, fs_va); |
break; |
case BD_WRITE_BLOCK: |
offset = IPC_GET_ARG1(call); |
block_size = IPC_GET_ARG2(call); |
retval = gxe_bd_write_block(offset, block_size, fs_va); |
break; |
default: |
retval = EINVAL; |
break; |
} |
ipc_answer_0(callid, retval); |
} |
} |
static int gxe_bd_read_block(uint64_t offset, size_t block_size, void *buf) |
{ |
uint32_t status; |
size_t i; |
uint32_t w; |
if (block_size != maxblock_size) { |
printf("Failed: bs = %d, mbs = %d\n", block_size, |
maxblock_size); |
return EINVAL; |
} |
futex_down(&dev_futex); |
pio_write_32(&dev->offset_lo, (uint32_t) offset); |
pio_write_32(&dev->offset_hi, offset >> 32); |
pio_write_32(&dev->disk_id, disk_id); |
pio_write_32(&dev->control, CTL_READ_START); |
status = pio_read_32(&dev->status); |
if (status == STATUS_FAILURE) { |
return EIO; |
} |
for (i = 0; i < maxblock_size; i++) { |
((uint8_t *) buf)[i] = w = |
pio_read_8(&devbuf->buffer[i]); |
} |
futex_up(&dev_futex); |
return EOK; |
} |
static int gxe_bd_write_block(uint64_t offset, size_t block_size, |
const void *buf) |
{ |
uint32_t status; |
size_t i; |
uint32_t w; |
if (block_size != maxblock_size) { |
printf("Failed: bs = %d, mbs = %d\n", block_size, |
maxblock_size); |
return EINVAL; |
} |
for (i = 0; i < maxblock_size; i++) { |
pio_write_8(&devbuf->buffer[i], ((const uint8_t *) buf)[i]); |
} |
futex_down(&dev_futex); |
pio_write_32(&dev->offset_lo, (uint32_t) offset); |
pio_write_32(&dev->offset_hi, offset >> 32); |
pio_write_32(&dev->disk_id, disk_id); |
pio_write_32(&dev->control, CTL_WRITE_START); |
status = pio_read_32(&dev->status); |
if (status == STATUS_FAILURE) { |
return EIO; |
} |
futex_up(&dev_futex); |
return EOK; |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/bd/gxe_bd/Makefile |
---|
0,0 → 1,76 |
# |
# Copyright (c) 2006 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
## Setup toolchain |
# |
LIBC_PREFIX = ../../../lib/libc |
SOFTINT_PREFIX = ../../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
## Sources |
# |
OUTPUT = gxe_bd |
SOURCES = \ |
gxe_bd.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
/branches/dd/uspace/srv/loader/main.c |
---|
231,7 → 231,7 |
int rc; |
rc = elf_load_file(pathname, 0, &prog_info); |
if (rc < 0) { |
if (rc != EE_OK) { |
DPRINTF("Failed to load executable '%s'.\n", pathname); |
ipc_answer_0(rid, EINVAL); |
return 1; |
250,7 → 250,7 |
} |
rc = elf_load_file(prog_info.interp, 0, &interp_info); |
if (rc < 0) { |
if (rc != EE_OK) { |
DPRINTF("Failed to load interpreter '%s.'\n", |
prog_info.interp); |
ipc_answer_0(rid, EINVAL); |
/branches/dd/uspace/srv/fb/serial_console.c |
---|
274,9 → 274,6 |
serial_goto(y, x); |
for (i = 0; i < w; i++) { |
unsigned int col = x + i; |
unsigned int row = y + j; |
field = &data[j * w + i]; |
a1 = &field->attrs; |
304,12 → 301,9 |
wchar_t c; |
int col, row, w, h; |
int fgcolor; |
int bgcolor; |
int flags; |
int style; |
int i; |
attrs_t cur_attr; |
if (client_connected) { |
ipc_answer_0(iid, ELIMIT); |
318,6 → 312,9 |
client_connected = 1; |
ipc_answer_0(iid, EOK); |
cur_attr.t = at_style; |
cur_attr.a.s.style = STYLE_NORMAL; |
/* Clear the terminal, set scrolling region |
to 0 - height rows. */ |
388,23 → 385,28 |
retval = 0; |
break; |
case FB_SET_STYLE: |
style = IPC_GET_ARG1(call); |
serial_set_style(style); |
cur_attr.t = at_style; |
cur_attr.a.s.style = IPC_GET_ARG1(call); |
cur_attr.a.i.bg_color = IPC_GET_ARG2(call); |
serial_set_attrs(&cur_attr); |
retval = 0; |
break; |
case FB_SET_COLOR: |
fgcolor = IPC_GET_ARG1(call); |
bgcolor = IPC_GET_ARG2(call); |
flags = IPC_GET_ARG3(call); |
cur_attr.t = at_idx; |
cur_attr.a.i.fg_color = IPC_GET_ARG1(call); |
cur_attr.a.i.bg_color = IPC_GET_ARG2(call); |
cur_attr.a.i.flags = IPC_GET_ARG3(call); |
serial_set_attrs(&cur_attr); |
serial_set_idx(fgcolor, bgcolor, flags); |
retval = 0; |
break; |
case FB_SET_RGB_COLOR: |
fgcolor = IPC_GET_ARG1(call); |
bgcolor = IPC_GET_ARG2(call); |
cur_attr.t = at_rgb; |
cur_attr.a.i.fg_color = IPC_GET_ARG1(call); |
cur_attr.a.i.bg_color = IPC_GET_ARG2(call); |
serial_set_attrs(&cur_attr); |
serial_set_rgb(fgcolor, bgcolor); |
retval = 0; |
break; |
case FB_SCROLL: |
424,6 → 426,18 |
serial_cursor_disable(); |
retval = 0; |
break; |
case FB_SCREEN_YIELD: |
serial_sgr(SGR_RESET); |
serial_puts("\033[2J"); |
serial_goto(0, 0); |
serial_cursor_enable(); |
retval = 0; |
break; |
case FB_SCREEN_RECLAIM: |
serial_clrscr(); |
serial_set_attrs(&cur_attr); |
retval = 0; |
break; |
default: |
retval = ENOENT; |
} |
/branches/dd/uspace/srv/fb/fb.c |
---|
30,7 → 30,7 |
/** |
* @defgroup fb Graphical framebuffer |
* @brief HelenOS graphical framebuffer. |
* @brief HelenOS graphical framebuffer. |
* @ingroup fbs |
* @{ |
*/ |
68,7 → 68,7 |
#define DEFAULT_BGCOLOR 0xf0f0f0 |
#define DEFAULT_FGCOLOR 0x000000 |
#define GLYPH_UNAVAIL '?' |
#define GLYPH_UNAVAIL '?' |
#define MAX_ANIM_LEN 8 |
#define MAX_ANIMATIONS 4 |
78,6 → 78,9 |
/** Function to render a pixel from a RGB value. */ |
typedef void (*rgb_conv_t)(void *, uint32_t); |
/** Function to render a bit mask. */ |
typedef void (*mask_conv_t)(void *, bool); |
/** Function to draw a glyph. */ |
typedef void (*dg_t)(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color); |
93,11 → 96,12 |
unsigned int pixelbytes; |
unsigned int glyphbytes; |
/** Pre-rendered mask for rendering glyphs. Specific for the visual. */ |
uint8_t *glyphs; |
rgb_conv_t rgb_conv; |
mask_conv_t mask_conv; |
} screen; |
/** Backbuffer character cell. */ |
121,12 → 125,12 |
/* |
* Style and glyphs for text printing |
*/ |
/** Current attributes. */ |
attr_rgb_t attr; |
uint8_t *bgpixel; |
/** |
* Glyph drawing function for this viewport. Different viewports |
* might use different drawing functions depending on whether their |
170,23 → 174,23 |
static bool client_connected = false; /**< Allow only 1 connection */ |
static uint32_t color_table[16] = { |
[COLOR_BLACK] = 0x000000, |
[COLOR_BLUE] = 0x0000f0, |
[COLOR_GREEN] = 0x00f000, |
[COLOR_CYAN] = 0x00f0f0, |
[COLOR_RED] = 0xf00000, |
[COLOR_MAGENTA] = 0xf000f0, |
[COLOR_YELLOW] = 0xf0f000, |
[COLOR_WHITE] = 0xf0f0f0, |
[8 + COLOR_BLACK] = 0x000000, |
[8 + COLOR_BLUE] = 0x0000ff, |
[8 + COLOR_GREEN] = 0x00ff00, |
[8 + COLOR_CYAN] = 0x00ffff, |
[8 + COLOR_RED] = 0xff0000, |
[8 + COLOR_MAGENTA] = 0xff00ff, |
[8 + COLOR_YELLOW] = 0xffff00, |
[8 + COLOR_WHITE] = 0xffffff, |
[COLOR_BLACK] = 0x000000, |
[COLOR_BLUE] = 0x0000f0, |
[COLOR_GREEN] = 0x00f000, |
[COLOR_CYAN] = 0x00f0f0, |
[COLOR_RED] = 0xf00000, |
[COLOR_MAGENTA] = 0xf000f0, |
[COLOR_YELLOW] = 0xf0f000, |
[COLOR_WHITE] = 0xf0f0f0, |
[8 + COLOR_BLACK] = 0x000000, |
[8 + COLOR_BLUE] = 0x0000ff, |
[8 + COLOR_GREEN] = 0x00ff00, |
[8 + COLOR_CYAN] = 0x00ffff, |
[8 + COLOR_RED] = 0xff0000, |
[8 + COLOR_MAGENTA] = 0xff00ff, |
[8 + COLOR_YELLOW] = 0xffff00, |
[8 + COLOR_WHITE] = 0xffffff, |
}; |
static int rgb_from_attr(attr_rgb_t *rgb, const attrs_t *a); |
226,10 → 230,15 |
*/ |
static void rgb_0888(void *dst, uint32_t rgb) |
{ |
*((uint32_t *) dst) = rgb & 0xffffff; |
*((uint32_t *) dst) = rgb & 0x00ffffff; |
} |
static void mask_0888(void *dst, bool mask) |
{ |
*((uint32_t *) dst) = (mask ? 0x00ffffff : 0); |
} |
/** ABGR 8:8:8:8 conversion |
* |
*/ |
250,7 → 259,20 |
((uint8_t *) dst)[2] = RED(rgb, 8); |
} |
static void mask_888(void *dst, bool mask) |
{ |
if (mask) { |
((uint8_t *) dst)[0] = 0xff; |
((uint8_t *) dst)[1] = 0xff; |
((uint8_t *) dst)[2] = 0xff; |
} else { |
((uint8_t *) dst)[0] = 0; |
((uint8_t *) dst)[1] = 0; |
((uint8_t *) dst)[2] = 0; |
} |
} |
/** BGR 8:8:8 conversion |
* |
*/ |
271,7 → 293,12 |
= (RED(rgb, 5) << 10) | (GREEN(rgb, 5) << 5) | BLUE(rgb, 5); |
} |
static void mask_555(void *dst, bool mask) |
{ |
*((uint16_t *) dst) = (mask ? 0x7fff : 0); |
} |
/** RGB 5:6:5 conversion |
* |
*/ |
281,7 → 308,12 |
= (RED(rgb, 5) << 11) | (GREEN(rgb, 6) << 5) | BLUE(rgb, 5); |
} |
static void mask_565(void *dst, bool mask) |
{ |
*((uint16_t *) dst) = (mask ? 0xffff : 0); |
} |
/** RGB 3:2:3 |
* |
*/ |
291,34 → 323,44 |
= ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3)); |
} |
static void mask_323(void *dst, bool mask) |
{ |
*((uint8_t *) dst) = (mask ? 0xff : 0); |
} |
/** Draw a filled rectangle. |
* |
* @note Need real implementation that does not access VRAM twice. |
* |
*/ |
static void draw_filled_rect(unsigned int x0, unsigned int y0, unsigned int x1, |
unsigned int y1, uint32_t color) |
{ |
unsigned int x, y; |
unsigned int x; |
unsigned int y; |
unsigned int copy_bytes; |
uint8_t *sp, *dp; |
uint8_t *sp; |
uint8_t *dp; |
uint8_t cbuf[4]; |
if (y0 >= y1 || x0 >= x1) return; |
if ((y0 >= y1) || (x0 >= x1)) |
return; |
screen.rgb_conv(cbuf, color); |
sp = &screen.fb_addr[FB_POS(x0, y0)]; |
dp = sp; |
/* Draw the first line. */ |
for (x = x0; x < x1; x++) { |
memcpy(dp, cbuf, screen.pixelbytes); |
dp += screen.pixelbytes; |
} |
dp = sp + screen.scanline; |
copy_bytes = (x1 - x0) * screen.pixelbytes; |
/* Draw the remaining lines by copying. */ |
for (y = y0 + 1; y < y1; y++) { |
memcpy(dp, sp, copy_bytes); |
333,14 → 375,15 |
*/ |
static void vport_redraw(viewport_t *vport) |
{ |
unsigned int row, col; |
unsigned int row; |
unsigned int col; |
for (row = 0; row < vport->rows; row++) { |
for (col = 0; col < vport->cols; col++) { |
draw_vp_glyph(vport, false, col, row); |
} |
} |
if (COL2X(vport->cols) < vport->width) { |
draw_filled_rect( |
vport->x + COL2X(vport->cols), vport->y, |
347,7 → 390,7 |
vport->x + vport->width, vport->y + vport->height, |
vport->attr.bg_color); |
} |
if (ROW2Y(vport->rows) < vport->height) { |
draw_filled_rect( |
vport->x, vport->y + ROW2Y(vport->rows), |
359,8 → 402,8 |
static void backbuf_clear(bb_cell_t *backbuf, size_t len, uint32_t fg_color, |
uint32_t bg_color) |
{ |
unsigned i; |
size_t i; |
for (i = 0; i < len; i++) { |
backbuf[i].glyph = 0; |
backbuf[i].fg_color = fg_color; |
388,17 → 431,20 |
*/ |
static void vport_scroll(viewport_t *vport, int lines) |
{ |
unsigned int row, col; |
unsigned int x, y; |
unsigned int row; |
unsigned int col; |
unsigned int x; |
unsigned int y; |
uint32_t glyph; |
uint32_t fg_color; |
uint32_t bg_color; |
bb_cell_t *bbp, *xbp; |
bb_cell_t *bbp; |
bb_cell_t *xbp; |
/* |
* Redraw. |
*/ |
y = vport->y; |
for (row = 0; row < vport->rows; row++) { |
x = vport->x; |
406,14 → 452,14 |
if ((row + lines >= 0) && (row + lines < vport->rows)) { |
xbp = &vport->backbuf[BB_POS(vport, col, row + lines)]; |
bbp = &vport->backbuf[BB_POS(vport, col, row)]; |
glyph = xbp->glyph; |
fg_color = xbp->fg_color; |
bg_color = xbp->bg_color; |
if (bbp->glyph == glyph && |
bbp->fg_color == xbp->fg_color && |
bbp->bg_color == xbp->bg_color) { |
if ((bbp->glyph == glyph) |
&& (bbp->fg_color == xbp->fg_color) |
&& (bbp->bg_color == xbp->bg_color)) { |
x += FONT_WIDTH; |
continue; |
} |
422,7 → 468,7 |
fg_color = vport->attr.fg_color; |
bg_color = vport->attr.bg_color; |
} |
(*vport->dglyph)(x, y, false, screen.glyphs, glyph, |
fg_color, bg_color); |
x += FONT_WIDTH; |
429,11 → 475,11 |
} |
y += FONT_SCANLINES; |
} |
/* |
* Scroll backbuffer. |
*/ |
if (lines > 0) { |
memmove(vport->backbuf, vport->backbuf + vport->cols * lines, |
vport->cols * (vport->rows - lines) * sizeof(bb_cell_t)); |
451,31 → 497,29 |
* |
* Convert glyphs from device independent font |
* description to current visual representation. |
* |
*/ |
static void render_glyphs(void) |
{ |
unsigned int glyph; |
for (glyph = 0; glyph < FONT_GLYPHS; glyph++) { |
unsigned int y; |
for (y = 0; y < FONT_SCANLINES; y++) { |
unsigned int x; |
for (x = 0; x < FONT_WIDTH; x++) { |
screen.rgb_conv(&screen.glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes], |
(fb_font[glyph][y] & (1 << (7 - x))) |
? 0xffffff : 0x000000); |
screen.rgb_conv(&screen.glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes], |
(fb_font[glyph][y] & (1 << (7 - x))) |
? 0x000000 : 0xffffff); |
screen.mask_conv(&screen.glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes], |
(fb_font[glyph][y] & (1 << (7 - x))) ? true : false); |
screen.mask_conv(&screen.glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes], |
(fb_font[glyph][y] & (1 << (7 - x))) ? false : true); |
} |
} |
} |
} |
/** Create new viewport |
* |
* @param x Origin of the viewport (x). |
495,6 → 539,7 |
if (!viewports[i].initialized) |
break; |
} |
if (i == MAX_VIEWPORTS) |
return ELIMIT; |
512,7 → 557,7 |
free(backbuf); |
return ENOMEM; |
} |
backbuf_clear(backbuf, cols * rows, DEFAULT_FGCOLOR, DEFAULT_BGCOLOR); |
memset(bgpixel, 0, screen.pixelbytes); |
528,24 → 573,23 |
viewports[i].attr.fg_color = DEFAULT_FGCOLOR; |
viewports[i].bgpixel = bgpixel; |
/* |
* Conditions necessary to select aligned version: |
* Conditions necessary to select aligned version: |
* - word size is divisible by pixelbytes |
* - cell scanline size is divisible by word size |
* - cell scanlines are word-aligned |
* |
* - word size is divisible by pixelbytes |
* - cell scanline size is divisible by word size |
* - cell scanlines are word-aligned |
*/ |
if ((word_size % screen.pixelbytes) == 0 && |
(FONT_WIDTH * screen.pixelbytes) % word_size == 0 && |
(x * screen.pixelbytes) % word_size == 0 && |
screen.scanline % word_size == 0) { |
if (((word_size % screen.pixelbytes) == 0) |
&& ((FONT_WIDTH * screen.pixelbytes) % word_size == 0) |
&& ((x * screen.pixelbytes) % word_size == 0) |
&& (screen.scanline % word_size == 0)) { |
viewports[i].dglyph = draw_glyph_aligned; |
} else { |
viewports[i].dglyph = draw_glyph_fallback; |
} |
viewports[i].cur_col = 0; |
viewports[i].cur_row = 0; |
viewports[i].cursor_active = false; |
574,45 → 618,53 |
static bool screen_init(void *addr, unsigned int xres, unsigned int yres, |
unsigned int scan, unsigned int visual) |
{ |
unsigned int glyphsize; |
uint8_t *glyphs; |
switch (visual) { |
case VISUAL_INDIRECT_8: |
screen.rgb_conv = rgb_323; |
screen.mask_conv = mask_323; |
screen.pixelbytes = 1; |
break; |
case VISUAL_RGB_5_5_5: |
screen.rgb_conv = rgb_555; |
screen.mask_conv = mask_555; |
screen.pixelbytes = 2; |
break; |
case VISUAL_RGB_5_6_5: |
screen.rgb_conv = rgb_565; |
screen.mask_conv = mask_565; |
screen.pixelbytes = 2; |
break; |
case VISUAL_RGB_8_8_8: |
screen.rgb_conv = rgb_888; |
screen.mask_conv = mask_888; |
screen.pixelbytes = 3; |
break; |
case VISUAL_BGR_8_8_8: |
screen.rgb_conv = bgr_888; |
screen.mask_conv = mask_888; |
screen.pixelbytes = 3; |
break; |
case VISUAL_RGB_8_8_8_0: |
screen.rgb_conv = rgb_888; |
screen.mask_conv = mask_888; |
screen.pixelbytes = 4; |
break; |
case VISUAL_RGB_0_8_8_8: |
screen.rgb_conv = rgb_0888; |
screen.mask_conv = mask_0888; |
screen.pixelbytes = 4; |
break; |
case VISUAL_BGR_0_8_8_8: |
screen.rgb_conv = bgr_0888; |
screen.mask_conv = mask_0888; |
screen.pixelbytes = 4; |
break; |
default: |
return false; |
} |
screen.fb_addr = (unsigned char *) addr; |
screen.xres = xres; |
screen.yres = yres; |
620,15 → 672,15 |
screen.glyphscanline = FONT_WIDTH * screen.pixelbytes; |
screen.glyphbytes = screen.glyphscanline * FONT_SCANLINES; |
glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes; |
glyphs = (uint8_t *) malloc(glyphsize); |
size_t glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes; |
uint8_t *glyphs = (uint8_t *) malloc(glyphsize); |
if (!glyphs) |
return false; |
memset(glyphs, 0, glyphsize); |
screen.glyphs = glyphs; |
render_glyphs(); |
/* Create first viewport */ |
651,46 → 703,47 |
* making it very fast. Most notably this version is not applicable at 24 bits |
* per pixel. |
* |
* @param x x coordinate of top-left corner on screen. |
* @param y y coordinate of top-left corner on screen. |
* @param cursor Draw glyph with cursor |
* @param glyphs Pointer to font bitmap. |
* @param glyph Code of the glyph to draw. |
* @param fg_color Foreground color. |
* @param bg_color Backgroudn color. |
* @param x x coordinate of top-left corner on screen. |
* @param y y coordinate of top-left corner on screen. |
* @param cursor Draw glyph with cursor |
* @param glyphs Pointer to font bitmap. |
* @param glyph Code of the glyph to draw. |
* @param fg_color Foreground color. |
* @param bg_color Backgroudn color. |
* |
*/ |
static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color) |
{ |
unsigned int i, yd; |
unsigned long fg_buf, bg_buf; |
unsigned long *maskp, *dp; |
unsigned int i; |
unsigned int yd; |
unsigned long fg_buf; |
unsigned long bg_buf; |
unsigned long mask; |
unsigned int ww, d_add; |
/* |
* Prepare a pair of words, one filled with foreground-color |
* pattern and the other filled with background-color pattern. |
*/ |
for (i = 0; i < sizeof(unsigned long) / screen.pixelbytes; i++) { |
screen.rgb_conv(&((uint8_t *)&fg_buf)[i * screen.pixelbytes], |
screen.rgb_conv(&((uint8_t *) &fg_buf)[i * screen.pixelbytes], |
fg_color); |
screen.rgb_conv(&((uint8_t *)&bg_buf)[i * screen.pixelbytes], |
screen.rgb_conv(&((uint8_t *) &bg_buf)[i * screen.pixelbytes], |
bg_color); |
} |
/* Pointer to the current position in the mask. */ |
maskp = (unsigned long *) &glyphs[GLYPH_POS(glyph, 0, cursor)]; |
unsigned long *maskp = (unsigned long *) &glyphs[GLYPH_POS(glyph, 0, cursor)]; |
/* Pointer to the current position on the screen. */ |
dp = (unsigned long *) &screen.fb_addr[FB_POS(x, y)]; |
unsigned long *dp = (unsigned long *) &screen.fb_addr[FB_POS(x, y)]; |
/* Width of the character cell in words. */ |
ww = FONT_WIDTH * screen.pixelbytes / sizeof(unsigned long); |
unsigned int ww = FONT_WIDTH * screen.pixelbytes / sizeof(unsigned long); |
/* Offset to add when moving to another screen scanline. */ |
d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
unsigned int d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
for (yd = 0; yd < FONT_SCANLINES; yd++) { |
/* |
* Now process the cell scanline, combining foreground |
700,7 → 753,7 |
mask = *maskp++; |
*dp++ = (fg_buf & mask) | (bg_buf & ~mask); |
} |
/* Move to the beginning of the next scanline of the cell. */ |
dp = (unsigned long *) ((uint8_t *) dp + d_add); |
} |
711,23 → 764,26 |
* This version does not make use of the pre-rendered mask, it uses |
* the font bitmap directly. It works always, but it is slower. |
* |
* @param x x coordinate of top-left corner on screen. |
* @param y y coordinate of top-left corner on screen. |
* @param cursor Draw glyph with cursor |
* @param glyphs Pointer to font bitmap. |
* @param glyph Code of the glyph to draw. |
* @param fg_color Foreground color. |
* @param bg_color Backgroudn color. |
* @param x x coordinate of top-left corner on screen. |
* @param y y coordinate of top-left corner on screen. |
* @param cursor Draw glyph with cursor |
* @param glyphs Pointer to font bitmap. |
* @param glyph Code of the glyph to draw. |
* @param fg_color Foreground color. |
* @param bg_color Backgroudn color. |
* |
*/ |
void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color) |
{ |
unsigned int i, j, yd; |
uint8_t fg_buf[4], bg_buf[4]; |
uint8_t *dp, *sp; |
unsigned int d_add; |
unsigned int i; |
unsigned int j; |
unsigned int yd; |
uint8_t fg_buf[4]; |
uint8_t bg_buf[4]; |
uint8_t *sp; |
uint8_t b; |
/* Pre-render 1x the foreground and background color pixels. */ |
if (cursor) { |
screen.rgb_conv(fg_buf, bg_color); |
736,26 → 792,26 |
screen.rgb_conv(fg_buf, fg_color); |
screen.rgb_conv(bg_buf, bg_color); |
} |
/* Pointer to the current position on the screen. */ |
dp = (uint8_t *) &screen.fb_addr[FB_POS(x, y)]; |
uint8_t *dp = (uint8_t *) &screen.fb_addr[FB_POS(x, y)]; |
/* Offset to add when moving to another screen scanline. */ |
d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
unsigned int d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
for (yd = 0; yd < FONT_SCANLINES; yd++) { |
/* Byte containing bits of the glyph scanline. */ |
b = fb_font[glyph][yd]; |
for (i = 0; i < FONT_WIDTH; i++) { |
/* Choose color based on the current bit. */ |
sp = (b & 0x80) ? fg_buf : bg_buf; |
/* Copy the pixel. */ |
for (j = 0; j < screen.pixelbytes; j++) { |
*dp++ = *sp++; |
} |
/* Move to the next bit. */ |
b = b << 1; |
} |
765,7 → 821,7 |
} |
} |
/** Draw glyph at specified position in viewport. |
/** Draw glyph at specified position in viewport. |
* |
* @param vport Viewport identification |
* @param cursor Draw glyph with cursor |
778,15 → 834,11 |
{ |
unsigned int x = vport->x + COL2X(col); |
unsigned int y = vport->y + ROW2Y(row); |
uint32_t glyph; |
uint32_t fg_color; |
uint32_t bg_color; |
glyph = vport->backbuf[BB_POS(vport, col, row)].glyph; |
fg_color = vport->backbuf[BB_POS(vport, col, row)].fg_color; |
bg_color = vport->backbuf[BB_POS(vport, col, row)].bg_color; |
uint32_t glyph = vport->backbuf[BB_POS(vport, col, row)].glyph; |
uint32_t fg_color = vport->backbuf[BB_POS(vport, col, row)].fg_color; |
uint32_t bg_color = vport->backbuf[BB_POS(vport, col, row)].bg_color; |
(*vport->dglyph)(x, y, cursor, screen.glyphs, glyph, |
fg_color, bg_color); |
} |
839,17 → 891,17 |
static void draw_char(viewport_t *vport, wchar_t c, unsigned int col, unsigned int row) |
{ |
bb_cell_t *bbp; |
/* Do not hide cursor if we are going to overwrite it */ |
if ((vport->cursor_active) && (vport->cursor_shown) && |
((vport->cur_col != col) || (vport->cur_row != row))) |
cursor_hide(vport); |
bbp = &vport->backbuf[BB_POS(vport, col, row)]; |
bbp->glyph = fb_font_glyph(c); |
bbp->fg_color = vport->attr.fg_color; |
bbp->bg_color = vport->attr.bg_color; |
draw_vp_glyph(vport, false, col, row); |
vport->cur_col = col; |
870,33 → 922,35 |
* |
* @param vport Viewport id |
* @param data Text data. |
* @param x Leftmost column of the area. |
* @param y Topmost row of the area. |
* @param w Number of rows. |
* @param h Number of columns. |
* @param x Leftmost column of the area. |
* @param y Topmost row of the area. |
* @param w Number of rows. |
* @param h Number of columns. |
* |
*/ |
static void draw_text_data(viewport_t *vport, keyfield_t *data, unsigned int x, |
unsigned int y, unsigned int w, unsigned int h) |
{ |
unsigned int i, j; |
unsigned int i; |
unsigned int j; |
bb_cell_t *bbp; |
attrs_t *a; |
attr_rgb_t rgb; |
for (j = 0; j < h; j++) { |
for (i = 0; i < w; i++) { |
unsigned int col = x + i; |
unsigned int row = y + j; |
bbp = &vport->backbuf[BB_POS(vport, col, row)]; |
a = &data[j * w + i].attrs; |
rgb_from_attr(&rgb, a); |
bbp->glyph = fb_font_glyph(data[j * w + i].character); |
bbp->fg_color = rgb.fg_color; |
bbp->bg_color = rgb.bg_color; |
draw_vp_glyph(vport, false, col, row); |
} |
} |
1192,7 → 1246,7 |
counts = (counts + 1) % 8; |
if (counts) |
return; |
for (i = 0; i < MAX_ANIMATIONS; i++) { |
if ((!animations[i].animlen) || (!animations[i].initialized) || |
(!animations[i].enabled)) |
1659,6 → 1713,10 |
mouse_move(IPC_GET_ARG1(call), IPC_GET_ARG2(call)); |
retval = EOK; |
break; |
case FB_SCREEN_YIELD: |
case FB_SCREEN_RECLAIM: |
retval = EOK; |
break; |
default: |
retval = ENOENT; |
} |
/branches/dd/uspace/srv/fb/ega.c |
---|
391,7 → 391,10 |
} |
retval = 0; |
break; |
case FB_SCREEN_YIELD: |
case FB_SCREEN_RECLAIM: |
retval = EOK; |
break; |
default: |
retval = EINVAL; |
} |
/branches/dd/uspace/srv/fb/Makefile |
---|
34,10 → 34,8 |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../libipc/include |
LIBS = $(LIBC_PREFIX)/libc.a |
LIBS = $(LIBC_PREFIX)/libc.a |
## Sources |
# |
105,7 → 103,7 |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/fs/devfs/devfs.c |
---|
0,0 → 1,127 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
/** |
* @file devfs.c |
* @brief Devices file system. |
* |
* Every device registered to device mapper is represented as a file in this |
* file system. |
*/ |
#include <stdio.h> |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <async.h> |
#include <errno.h> |
#include <libfs.h> |
#include "devfs.h" |
#include "devfs_ops.h" |
#define NAME "devfs" |
static vfs_info_t devfs_vfs_info = { |
.name = "devfs", |
}; |
fs_reg_t devfs_reg; |
static void devfs_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
if (iid) |
ipc_answer_0(iid, EOK); |
while (true) { |
ipc_call_t call; |
ipc_callid_t callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case VFS_MOUNTED: |
devfs_mounted(callid, &call); |
break; |
case VFS_MOUNT: |
devfs_mount(callid, &call); |
break; |
case VFS_LOOKUP: |
devfs_lookup(callid, &call); |
break; |
case VFS_READ: |
devfs_read(callid, &call); |
break; |
case VFS_WRITE: |
devfs_write(callid, &call); |
break; |
case VFS_TRUNCATE: |
devfs_truncate(callid, &call); |
break; |
case VFS_DESTROY: |
devfs_destroy(callid, &call); |
break; |
default: |
ipc_answer_0(callid, ENOTSUP); |
break; |
} |
} |
} |
int main(int argc, char *argv[]) |
{ |
printf(NAME ": HelenOS Device Filesystem\n"); |
if (!devfs_init()) { |
printf(NAME ": failed to initialize devfs\n"); |
return -1; |
} |
int vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0); |
if (vfs_phone < EOK) { |
printf(NAME ": Unable to connect to VFS\n"); |
return -1; |
} |
int rc = fs_register(vfs_phone, &devfs_reg, &devfs_vfs_info, |
devfs_connection); |
if (rc != EOK) { |
printf(NAME ": Failed to register file system (%d)\n", rc); |
return rc; |
} |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* Not reached */ |
return 0; |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/fs/devfs/devfs_ops.c |
---|
0,0 → 1,242 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
/** |
* @file devfs_ops.c |
* @brief Implementation of VFS operations for the devfs file system server. |
*/ |
#include <ipc/ipc.h> |
#include <bool.h> |
#include <errno.h> |
#include <malloc.h> |
#include <string.h> |
#include <libfs.h> |
#include "devfs.h" |
#include "devfs_ops.h" |
#define PLB_GET_CHAR(pos) (devfs_reg.plb_ro[pos % PLB_SIZE]) |
bool devfs_init(void) |
{ |
if (devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING) < 0) |
return false; |
return true; |
} |
void devfs_mounted(ipc_callid_t rid, ipc_call_t *request) |
{ |
/* Accept the mount options */ |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
char *opts = malloc(size + 1); |
if (!opts) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
ipcarg_t retval = ipc_data_write_finalize(callid, opts, size); |
if (retval != EOK) { |
ipc_answer_0(rid, retval); |
free(opts); |
return; |
} |
free(opts); |
ipc_answer_3(rid, EOK, 0, 0, 0); |
} |
void devfs_mount(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_answer_0(rid, ENOTSUP); |
} |
void devfs_lookup(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipcarg_t first = IPC_GET_ARG1(*request); |
ipcarg_t last = IPC_GET_ARG2(*request); |
dev_handle_t dev_handle = IPC_GET_ARG3(*request); |
ipcarg_t lflag = IPC_GET_ARG4(*request); |
fs_index_t index = IPC_GET_ARG5(*request); |
/* Hierarchy is flat, no altroot is supported */ |
if (index != 0) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
/* This is a read-only filesystem */ |
if ((lflag & L_CREATE) || (lflag & L_LINK) || (lflag & L_UNLINK)) { |
ipc_answer_0(rid, ENOTSUP); |
return; |
} |
/* Eat slash */ |
if (PLB_GET_CHAR(first) == '/') { |
first++; |
first %= PLB_SIZE; |
} |
if (first >= last) { |
/* Root entry */ |
if (lflag & L_DIRECTORY) |
ipc_answer_5(rid, EOK, devfs_reg.fs_handle, dev_handle, 0, 0, 0); |
else |
ipc_answer_0(rid, ENOENT); |
} else { |
if (lflag & L_FILE) { |
count_t len; |
if (last >= first) |
len = last - first + 1; |
else |
len = first + PLB_SIZE - last + 1; |
char *name = (char *) malloc(len + 1); |
if (name == NULL) { |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
count_t i; |
for (i = 0; i < len; i++) |
name[i] = PLB_GET_CHAR(first + i); |
name[len] = 0; |
dev_handle_t handle; |
if (devmap_device_get_handle(name, &handle, 0) != EOK) { |
free(name); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
free(name); |
ipc_answer_5(rid, EOK, devfs_reg.fs_handle, dev_handle, handle, 0, 1); |
} else |
ipc_answer_0(rid, ENOENT); |
} |
} |
void devfs_read(ipc_callid_t rid, ipc_call_t *request) |
{ |
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); |
off_t pos = (off_t) IPC_GET_ARG3(*request); |
if (index != 0) { |
ipc_answer_1(rid, ENOENT, 0); |
return; |
} |
/* |
* Receive the read request. |
*/ |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_read_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
size_t bytes = 0; |
if (index != 0) { |
(void) ipc_data_read_finalize(callid, NULL, bytes); |
} else { |
count_t count = devmap_device_get_count(); |
dev_desc_t *desc = malloc(count * sizeof(dev_desc_t)); |
if (desc == NULL) { |
ipc_answer_0(callid, ENOENT); |
ipc_answer_1(rid, ENOENT, 0); |
return; |
} |
count_t max = devmap_device_get_devices(count, desc); |
if (pos < max) { |
ipc_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1); |
} else { |
ipc_answer_0(callid, ENOENT); |
ipc_answer_1(rid, ENOENT, 0); |
return; |
} |
free(desc); |
bytes = 1; |
} |
ipc_answer_1(rid, EOK, bytes); |
} |
void devfs_write(ipc_callid_t rid, ipc_call_t *request) |
{ |
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); |
off_t pos = (off_t) IPC_GET_ARG3(*request); |
/* |
* Receive the write request. |
*/ |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
// TODO |
ipc_answer_0(callid, ENOENT); |
ipc_answer_2(rid, ENOENT, 0, 0); |
} |
void devfs_truncate(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_answer_0(rid, ENOTSUP); |
} |
void devfs_destroy(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_answer_0(rid, ENOTSUP); |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/fs/devfs/Makefile |
---|
0,0 → 1,82 |
# |
# Copyright (c) 2005 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
## Setup toolchain |
# |
LIBC_PREFIX = ../../../lib/libc |
LIBFS_PREFIX = ../../../lib/libfs |
SOFTINT_PREFIX = ../../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I $(LIBFS_PREFIX) |
LIBS = \ |
$(LIBFS_PREFIX)/libfs.a \ |
$(LIBC_PREFIX)/libc.a |
## Sources |
# |
OUTPUT = devfs |
SOURCES = \ |
devfs.c \ |
devfs_ops.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) $(OUTPUT).disasm |
-include Makefile.depend |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS) |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
/branches/dd/uspace/srv/fs/devfs/devfs.h |
---|
0,0 → 1,44 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
#ifndef DEVFS_DEVFS_H_ |
#define DEVFS_DEVFS_H_ |
#include <libfs.h> |
extern fs_reg_t devfs_reg; |
#endif |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/fs/devfs/devfs_ops.h |
---|
0,0 → 1,53 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup fs |
* @{ |
*/ |
#ifndef DEVFS_DEVFS_OPS_H_ |
#define DEVFS_DEVFS_OPS_H_ |
#include <ipc/ipc.h> |
#include <bool.h> |
extern bool devfs_init(void); |
extern void devfs_mounted(ipc_callid_t, ipc_call_t *); |
extern void devfs_mount(ipc_callid_t, ipc_call_t *); |
extern void devfs_lookup(ipc_callid_t, ipc_call_t *); |
extern void devfs_read(ipc_callid_t, ipc_call_t *); |
extern void devfs_write(ipc_callid_t, ipc_call_t *); |
extern void devfs_truncate(ipc_callid_t, ipc_call_t *); |
extern void devfs_destroy(ipc_callid_t, ipc_call_t *); |
#endif |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/fs/tmpfs/tmpfs.h |
---|
44,6 → 44,9 |
#define dprintf(...) printf(__VA_ARGS__) |
#endif |
#define TMPFS_NODE(node) ((node) ? (tmpfs_node_t *)(node)->data : NULL) |
#define FS_NODE(node) ((node) ? (node)->bp : NULL) |
typedef enum { |
TMPFS_NONE, |
TMPFS_FILE, |
50,22 → 53,33 |
TMPFS_DIRECTORY |
} tmpfs_dentry_type_t; |
/* forward declaration */ |
struct tmpfs_node; |
typedef struct tmpfs_dentry { |
link_t link; /**< Linkage for the list of siblings. */ |
struct tmpfs_node *node;/**< Back pointer to TMPFS node. */ |
char *name; /**< Name of dentry. */ |
} tmpfs_dentry_t; |
typedef struct tmpfs_node { |
fs_node_t *bp; /**< Back pointer to the FS node. */ |
fs_index_t index; /**< TMPFS node index. */ |
link_t dh_link; /**< Dentries hash table link. */ |
struct tmpfs_dentry *sibling; |
struct tmpfs_dentry *child; |
hash_table_t names; /**< All names linking to this TMPFS node. */ |
dev_handle_t dev_handle;/**< Device handle. */ |
link_t nh_link; /**< Nodes hash table link. */ |
tmpfs_dentry_type_t type; |
unsigned lnkcnt; /**< Link count. */ |
size_t size; /**< File size if type is TMPFS_FILE. */ |
void *data; /**< File content's if type is TMPFS_FILE. */ |
} tmpfs_dentry_t; |
link_t cs_head; /**< Head of child's siblings list. */ |
} tmpfs_node_t; |
extern fs_reg_t tmpfs_reg; |
extern libfs_ops_t tmpfs_libfs_ops; |
extern bool tmpfs_init(void); |
extern void tmpfs_mounted(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_mount(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_lookup(ipc_callid_t, ipc_call_t *); |
/branches/dd/uspace/srv/fs/tmpfs/tmpfs_dump.c |
---|
55,7 → 55,7 |
static bool |
tmpfs_restore_recursion(int dev, off_t *bufpos, size_t *buflen, off_t *pos, |
tmpfs_dentry_t *parent) |
fs_node_t *pfn) |
{ |
struct rdentry entry; |
libfs_ops_t *ops = &tmpfs_libfs_ops; |
63,7 → 63,8 |
do { |
char *fname; |
tmpfs_dentry_t *node; |
fs_node_t *fn; |
tmpfs_node_t *nodep; |
uint32_t size; |
if (block_read(dev, bufpos, buflen, pos, &entry, sizeof(entry), |
80,8 → 81,8 |
if (fname == NULL) |
return false; |
node = (tmpfs_dentry_t *) ops->create(dev, L_FILE); |
if (node == NULL) { |
fn = ops->create(dev, L_FILE); |
if (fn == NULL) { |
free(fname); |
return false; |
} |
88,15 → 89,15 |
if (block_read(dev, bufpos, buflen, pos, fname, |
entry.len, TMPFS_BLOCK_SIZE) != EOK) { |
ops->destroy((void *) node); |
ops->destroy(fn); |
free(fname); |
return false; |
} |
fname[entry.len] = 0; |
rc = ops->link((void *) parent, (void *) node, fname); |
rc = ops->link(pfn, fn, fname); |
if (rc != EOK) { |
ops->destroy((void *) node); |
ops->destroy(fn); |
free(fname); |
return false; |
} |
108,12 → 109,13 |
size = uint32_t_le2host(size); |
node->data = malloc(size); |
if (node->data == NULL) |
nodep = TMPFS_NODE(fn); |
nodep->data = malloc(size); |
if (nodep->data == NULL) |
return false; |
node->size = size; |
if (block_read(dev, bufpos, buflen, pos, node->data, |
nodep->size = size; |
if (block_read(dev, bufpos, buflen, pos, nodep->data, |
size, TMPFS_BLOCK_SIZE) != EOK) |
return false; |
123,8 → 125,8 |
if (fname == NULL) |
return false; |
node = (tmpfs_dentry_t *) ops->create(dev, L_DIRECTORY); |
if (node == NULL) { |
fn = ops->create(dev, L_DIRECTORY); |
if (fn == NULL) { |
free(fname); |
return false; |
} |
131,15 → 133,15 |
if (block_read(dev, bufpos, buflen, pos, fname, |
entry.len, TMPFS_BLOCK_SIZE) != EOK) { |
ops->destroy((void *) node); |
ops->destroy(fn); |
free(fname); |
return false; |
} |
fname[entry.len] = 0; |
rc = ops->link((void *) parent, (void *) node, fname); |
rc = ops->link(pfn, fn, fname); |
if (rc != EOK) { |
ops->destroy((void *) node); |
ops->destroy(fn); |
free(fname); |
return false; |
} |
146,7 → 148,7 |
free(fname); |
if (!tmpfs_restore_recursion(dev, bufpos, buflen, pos, |
node)) |
fn)) |
return false; |
break; |
/branches/dd/uspace/srv/fs/tmpfs/tmpfs.c |
---|
127,7 → 127,12 |
int main(int argc, char **argv) |
{ |
printf(NAME ": HelenOS TMPFS file system server\n"); |
if (!tmpfs_init()) { |
printf(NAME ": failed to initialize TMPFS\n"); |
return -1; |
} |
int vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0); |
if (vfs_phone < EOK) { |
printf(NAME ": Unable to connect to VFS\n"); |
140,7 → 145,7 |
printf(NAME ": Failed to register file system (%d)\n", rc); |
return rc; |
} |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
/* not reached */ |
/branches/dd/uspace/srv/fs/tmpfs/tmpfs_ops.c |
---|
54,55 → 54,50 |
#define min(a, b) ((a) < (b) ? (a) : (b)) |
#define max(a, b) ((a) > (b) ? (a) : (b)) |
#define DENTRIES_BUCKETS 256 |
#define NODES_BUCKETS 256 |
#define NAMES_BUCKETS 4 |
/** All root nodes have index 0. */ |
#define TMPFS_SOME_ROOT 0 |
/** Global counter for assigning node indices. Shared by all instances. */ |
fs_index_t tmpfs_next_index = 1; |
/* |
* For now, we don't distinguish between different dev_handles/instances. All |
* requests resolve to the only instance, rooted in the following variable. |
*/ |
static tmpfs_dentry_t *root; |
#define TMPFS_DEV 0 /**< Dummy device handle for TMPFS */ |
/* |
* Implementation of the libfs interface. |
*/ |
/* Forward declarations of static functions. */ |
static void *tmpfs_match(void *, const char *); |
static void *tmpfs_node_get(dev_handle_t, fs_index_t); |
static void tmpfs_node_put(void *); |
static void *tmpfs_create_node(dev_handle_t, int); |
static int tmpfs_link_node(void *, void *, const char *); |
static int tmpfs_unlink_node(void *, void *); |
static int tmpfs_destroy_node(void *); |
static fs_node_t *tmpfs_match(fs_node_t *, const char *); |
static fs_node_t *tmpfs_node_get(dev_handle_t, fs_index_t); |
static void tmpfs_node_put(fs_node_t *); |
static fs_node_t *tmpfs_create_node(dev_handle_t, int); |
static int tmpfs_link_node(fs_node_t *, fs_node_t *, const char *); |
static int tmpfs_unlink_node(fs_node_t *, fs_node_t *, const char *); |
static int tmpfs_destroy_node(fs_node_t *); |
/* Implementation of helper functions. */ |
static fs_index_t tmpfs_index_get(void *nodep) |
static fs_index_t tmpfs_index_get(fs_node_t *fn) |
{ |
return ((tmpfs_dentry_t *) nodep)->index; |
return TMPFS_NODE(fn)->index; |
} |
static size_t tmpfs_size_get(void *nodep) |
static size_t tmpfs_size_get(fs_node_t *fn) |
{ |
return ((tmpfs_dentry_t *) nodep)->size; |
return TMPFS_NODE(fn)->size; |
} |
static unsigned tmpfs_lnkcnt_get(void *nodep) |
static unsigned tmpfs_lnkcnt_get(fs_node_t *fn) |
{ |
return ((tmpfs_dentry_t *) nodep)->lnkcnt; |
return TMPFS_NODE(fn)->lnkcnt; |
} |
static bool tmpfs_has_children(void *nodep) |
static bool tmpfs_has_children(fs_node_t *fn) |
{ |
return ((tmpfs_dentry_t *) nodep)->child != NULL; |
return !list_empty(&TMPFS_NODE(fn)->cs_head); |
} |
static void *tmpfs_root_get(dev_handle_t dev_handle) |
static fs_node_t *tmpfs_root_get(dev_handle_t dev_handle) |
{ |
return root; |
return tmpfs_node_get(dev_handle, TMPFS_SOME_ROOT); |
} |
static char tmpfs_plb_get_char(unsigned pos) |
110,14 → 105,14 |
return tmpfs_reg.plb_ro[pos % PLB_SIZE]; |
} |
static bool tmpfs_is_directory(void *nodep) |
static bool tmpfs_is_directory(fs_node_t *fn) |
{ |
return ((tmpfs_dentry_t *) nodep)->type == TMPFS_DIRECTORY; |
return TMPFS_NODE(fn)->type == TMPFS_DIRECTORY; |
} |
static bool tmpfs_is_file(void *nodep) |
static bool tmpfs_is_file(fs_node_t *fn) |
{ |
return ((tmpfs_dentry_t *) nodep)->type == TMPFS_FILE; |
return TMPFS_NODE(fn)->type == TMPFS_FILE; |
} |
/** libfs operations */ |
139,259 → 134,231 |
.is_file = tmpfs_is_file |
}; |
/** Hash table of all directory entries. */ |
hash_table_t dentries; |
/** Hash table of all TMPFS nodes. */ |
hash_table_t nodes; |
/* Implementation of hash table interface for the dentries hash table. */ |
static hash_index_t dentries_hash(unsigned long *key) |
{ |
return *key % DENTRIES_BUCKETS; |
} |
#define NODES_KEY_INDEX 0 |
#define NODES_KEY_DEV 1 |
static int dentries_compare(unsigned long *key, hash_count_t keys, |
link_t *item) |
/* Implementation of hash table interface for the nodes hash table. */ |
static hash_index_t nodes_hash(unsigned long key[]) |
{ |
tmpfs_dentry_t *dentry = hash_table_get_instance(item, tmpfs_dentry_t, |
dh_link); |
return dentry->index == *key; |
return key[NODES_KEY_INDEX] % NODES_BUCKETS; |
} |
static void dentries_remove_callback(link_t *item) |
static int nodes_compare(unsigned long key[], hash_count_t keys, link_t *item) |
{ |
tmpfs_node_t *nodep = hash_table_get_instance(item, tmpfs_node_t, |
nh_link); |
return (nodep->index == key[NODES_KEY_INDEX] && |
nodep->dev_handle == key[NODES_KEY_DEV]); |
} |
/** TMPFS dentries hash table operations. */ |
hash_table_operations_t dentries_ops = { |
.hash = dentries_hash, |
.compare = dentries_compare, |
.remove_callback = dentries_remove_callback |
}; |
fs_index_t tmpfs_next_index = 1; |
typedef struct { |
char *name; |
tmpfs_dentry_t *parent; |
link_t link; |
} tmpfs_name_t; |
/* Implementation of hash table interface for the names hash table. */ |
static hash_index_t names_hash(unsigned long *key) |
static void nodes_remove_callback(link_t *item) |
{ |
tmpfs_dentry_t *dentry = (tmpfs_dentry_t *) *key; |
return dentry->index % NAMES_BUCKETS; |
} |
static int names_compare(unsigned long *key, hash_count_t keys, link_t *item) |
{ |
tmpfs_dentry_t *dentry = (tmpfs_dentry_t *) *key; |
tmpfs_name_t *namep = hash_table_get_instance(item, tmpfs_name_t, |
link); |
return dentry == namep->parent; |
} |
static void names_remove_callback(link_t *item) |
{ |
tmpfs_name_t *namep = hash_table_get_instance(item, tmpfs_name_t, |
link); |
free(namep->name); |
free(namep); |
} |
/** TMPFS node names hash table operations. */ |
static hash_table_operations_t names_ops = { |
.hash = names_hash, |
.compare = names_compare, |
.remove_callback = names_remove_callback |
/** TMPFS nodes hash table operations. */ |
hash_table_operations_t nodes_ops = { |
.hash = nodes_hash, |
.compare = nodes_compare, |
.remove_callback = nodes_remove_callback |
}; |
static void tmpfs_name_initialize(tmpfs_name_t *namep) |
static void tmpfs_node_initialize(tmpfs_node_t *nodep) |
{ |
namep->name = NULL; |
namep->parent = NULL; |
link_initialize(&namep->link); |
nodep->bp = NULL; |
nodep->index = 0; |
nodep->dev_handle = 0; |
nodep->type = TMPFS_NONE; |
nodep->lnkcnt = 0; |
nodep->size = 0; |
nodep->data = NULL; |
link_initialize(&nodep->nh_link); |
list_initialize(&nodep->cs_head); |
} |
static bool tmpfs_dentry_initialize(tmpfs_dentry_t *dentry) |
static void tmpfs_dentry_initialize(tmpfs_dentry_t *dentryp) |
{ |
dentry->index = 0; |
dentry->sibling = NULL; |
dentry->child = NULL; |
dentry->type = TMPFS_NONE; |
dentry->lnkcnt = 0; |
dentry->size = 0; |
dentry->data = NULL; |
link_initialize(&dentry->dh_link); |
return (bool)hash_table_create(&dentry->names, NAMES_BUCKETS, 1, |
&names_ops); |
link_initialize(&dentryp->link); |
dentryp->name = NULL; |
dentryp->node = NULL; |
} |
static bool tmpfs_init(void) |
bool tmpfs_init(void) |
{ |
if (!hash_table_create(&dentries, DENTRIES_BUCKETS, 1, &dentries_ops)) |
if (!hash_table_create(&nodes, NODES_BUCKETS, 2, &nodes_ops)) |
return false; |
root = (tmpfs_dentry_t *) tmpfs_create_node(TMPFS_DEV, L_DIRECTORY); |
if (!root) { |
hash_table_destroy(&dentries); |
return false; |
} |
root->lnkcnt = 0; /* FS root is not linked */ |
return true; |
} |
/** Compare one component of path to a directory entry. |
* |
* @param parentp Pointer to node from which we descended. |
* @param childp Pointer to node to compare the path component with. |
* @param component Array of characters holding component name. |
* |
* @return True on match, false otherwise. |
*/ |
static bool |
tmpfs_match_one(tmpfs_dentry_t *parentp, tmpfs_dentry_t *childp, |
const char *component) |
static bool tmpfs_instance_init(dev_handle_t dev_handle) |
{ |
unsigned long key = (unsigned long) parentp; |
link_t *hlp = hash_table_find(&childp->names, &key); |
assert(hlp); |
tmpfs_name_t *namep = hash_table_get_instance(hlp, tmpfs_name_t, link); |
return !str_cmp(namep->name, component); |
fs_node_t *rfn; |
rfn = tmpfs_create_node(dev_handle, L_DIRECTORY); |
if (!rfn) |
return false; |
TMPFS_NODE(rfn)->lnkcnt = 0; /* FS root is not linked */ |
return true; |
} |
void *tmpfs_match(void *prnt, const char *component) |
fs_node_t *tmpfs_match(fs_node_t *pfn, const char *component) |
{ |
tmpfs_dentry_t *parentp = (tmpfs_dentry_t *) prnt; |
tmpfs_dentry_t *childp = parentp->child; |
tmpfs_node_t *parentp = TMPFS_NODE(pfn); |
link_t *lnk; |
while (childp && !tmpfs_match_one(parentp, childp, component)) |
childp = childp->sibling; |
for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head; |
lnk = lnk->next) { |
tmpfs_dentry_t *dentryp = list_get_instance(lnk, tmpfs_dentry_t, |
link); |
if (!str_cmp(dentryp->name, component)) |
return FS_NODE(dentryp->node); |
} |
return (void *) childp; |
return NULL; |
} |
void * |
tmpfs_node_get(dev_handle_t dev_handle, fs_index_t index) |
fs_node_t *tmpfs_node_get(dev_handle_t dev_handle, fs_index_t index) |
{ |
unsigned long key = index; |
link_t *lnk = hash_table_find(&dentries, &key); |
unsigned long key[] = { |
[NODES_KEY_INDEX] = index, |
[NODES_KEY_DEV] = dev_handle |
}; |
link_t *lnk = hash_table_find(&nodes, key); |
if (!lnk) |
return NULL; |
return hash_table_get_instance(lnk, tmpfs_dentry_t, dh_link); |
return FS_NODE(hash_table_get_instance(lnk, tmpfs_node_t, nh_link)); |
} |
void tmpfs_node_put(void *node) |
void tmpfs_node_put(fs_node_t *fn) |
{ |
/* nothing to do */ |
} |
void *tmpfs_create_node(dev_handle_t dev_handle, int lflag) |
fs_node_t *tmpfs_create_node(dev_handle_t dev_handle, int lflag) |
{ |
assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY)); |
tmpfs_dentry_t *node = malloc(sizeof(tmpfs_dentry_t)); |
if (!node) |
tmpfs_node_t *nodep = malloc(sizeof(tmpfs_node_t)); |
if (!nodep) |
return NULL; |
if (!tmpfs_dentry_initialize(node)) { |
free(node); |
tmpfs_node_initialize(nodep); |
nodep->bp = malloc(sizeof(fs_node_t)); |
if (!nodep->bp) { |
free(nodep); |
return NULL; |
} |
node->index = tmpfs_next_index++; |
fs_node_initialize(nodep->bp); |
nodep->bp->data = nodep; /* link the FS and TMPFS nodes */ |
if (!tmpfs_root_get(dev_handle)) |
nodep->index = TMPFS_SOME_ROOT; |
else |
nodep->index = tmpfs_next_index++; |
nodep->dev_handle = dev_handle; |
if (lflag & L_DIRECTORY) |
node->type = TMPFS_DIRECTORY; |
nodep->type = TMPFS_DIRECTORY; |
else |
node->type = TMPFS_FILE; |
nodep->type = TMPFS_FILE; |
/* Insert the new node into the dentry hash table. */ |
unsigned long key = node->index; |
hash_table_insert(&dentries, &key, &node->dh_link); |
return (void *) node; |
/* Insert the new node into the nodes hash table. */ |
unsigned long key[] = { |
[NODES_KEY_INDEX] = nodep->index, |
[NODES_KEY_DEV] = nodep->dev_handle |
}; |
hash_table_insert(&nodes, key, &nodep->nh_link); |
return FS_NODE(nodep); |
} |
int tmpfs_link_node(void *prnt, void *chld, const char *nm) |
int tmpfs_link_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm) |
{ |
tmpfs_dentry_t *parentp = (tmpfs_dentry_t *) prnt; |
tmpfs_dentry_t *childp = (tmpfs_dentry_t *) chld; |
tmpfs_node_t *parentp = TMPFS_NODE(pfn); |
tmpfs_node_t *childp = TMPFS_NODE(cfn); |
tmpfs_dentry_t *dentryp; |
link_t *lnk; |
assert(parentp->type == TMPFS_DIRECTORY); |
tmpfs_name_t *namep = malloc(sizeof(tmpfs_name_t)); |
if (!namep) |
/* Check for duplicit entries. */ |
for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head; |
lnk = lnk->next) { |
dentryp = list_get_instance(lnk, tmpfs_dentry_t, link); |
if (!str_cmp(dentryp->name, nm)) |
return EEXIST; |
} |
/* Allocate and initialize the dentry. */ |
dentryp = malloc(sizeof(tmpfs_dentry_t)); |
if (!dentryp) |
return ENOMEM; |
tmpfs_name_initialize(namep); |
tmpfs_dentry_initialize(dentryp); |
/* Populate and link the new dentry. */ |
size_t size = str_size(nm); |
namep->name = malloc(size + 1); |
if (!namep->name) { |
free(namep); |
dentryp->name = malloc(size + 1); |
if (!dentryp->name) { |
free(dentryp); |
return ENOMEM; |
} |
str_cpy(namep->name, size + 1, nm); |
namep->parent = parentp; |
str_cpy(dentryp->name, size + 1, nm); |
dentryp->node = childp; |
childp->lnkcnt++; |
list_append(&dentryp->link, &parentp->cs_head); |
unsigned long key = (unsigned long) parentp; |
hash_table_insert(&childp->names, &key, &namep->link); |
/* Insert the new node into the namespace. */ |
if (parentp->child) { |
tmpfs_dentry_t *tmp = parentp->child; |
while (tmp->sibling) |
tmp = tmp->sibling; |
tmp->sibling = childp; |
} else { |
parentp->child = childp; |
} |
return EOK; |
} |
int tmpfs_unlink_node(void *prnt, void *chld) |
int tmpfs_unlink_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm) |
{ |
tmpfs_dentry_t *parentp = (tmpfs_dentry_t *)prnt; |
tmpfs_dentry_t *childp = (tmpfs_dentry_t *)chld; |
tmpfs_node_t *parentp = TMPFS_NODE(pfn); |
tmpfs_node_t *childp = NULL; |
tmpfs_dentry_t *dentryp; |
link_t *lnk; |
if (!parentp) |
return EBUSY; |
for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head; |
lnk = lnk->next) { |
dentryp = list_get_instance(lnk, tmpfs_dentry_t, link); |
if (!str_cmp(dentryp->name, nm)) { |
childp = dentryp->node; |
assert(FS_NODE(childp) == cfn); |
break; |
} |
} |
if (childp->child) |
if (!childp) |
return ENOENT; |
if ((childp->lnkcnt == 1) && !list_empty(&childp->cs_head)) |
return ENOTEMPTY; |
if (parentp->child == childp) { |
parentp->child = childp->sibling; |
} else { |
/* TODO: consider doubly linked list for organizing siblings. */ |
tmpfs_dentry_t *tmp = parentp->child; |
while (tmp->sibling != childp) |
tmp = tmp->sibling; |
tmp->sibling = childp->sibling; |
} |
childp->sibling = NULL; |
unsigned long key = (unsigned long) parentp; |
hash_table_remove(&childp->names, &key, 1); |
list_remove(&dentryp->link); |
free(dentryp); |
childp->lnkcnt--; |
return EOK; |
} |
int tmpfs_destroy_node(void *nodep) |
int tmpfs_destroy_node(fs_node_t *fn) |
{ |
tmpfs_dentry_t *dentry = (tmpfs_dentry_t *) nodep; |
tmpfs_node_t *nodep = TMPFS_NODE(fn); |
assert(!dentry->lnkcnt); |
assert(!dentry->child); |
assert(!dentry->sibling); |
assert(!nodep->lnkcnt); |
assert(list_empty(&nodep->cs_head)); |
unsigned long key = dentry->index; |
hash_table_remove(&dentries, &key, 1); |
unsigned long key[] = { |
[NODES_KEY_INDEX] = nodep->index, |
[NODES_KEY_DEV] = nodep->dev_handle |
}; |
hash_table_remove(&nodes, key, 2); |
hash_table_destroy(&dentry->names); |
if (dentry->type == TMPFS_FILE) |
free(dentry->data); |
free(dentry); |
if (nodep->type == TMPFS_FILE) |
free(nodep->data); |
free(nodep->bp); |
free(nodep); |
return EOK; |
} |
399,20 → 366,44 |
{ |
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); |
/* Initialize TMPFS. */ |
if (!root && !tmpfs_init()) { |
/* accept the mount options */ |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
char *opts = malloc(size + 1); |
if (!opts) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
ipcarg_t retval = ipc_data_write_finalize(callid, opts, size); |
if (retval != EOK) { |
ipc_answer_0(rid, retval); |
free(opts); |
return; |
} |
opts[size] = '\0'; |
if (dev_handle >= 0) { |
/* Initialize TMPFS instance. */ |
if (!tmpfs_instance_init(dev_handle)) { |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
tmpfs_node_t *rootp = TMPFS_NODE(tmpfs_root_get(dev_handle)); |
if (str_cmp(opts, "restore") == 0) { |
if (tmpfs_restore(dev_handle)) |
ipc_answer_3(rid, EOK, root->index, root->size, |
root->lnkcnt); |
ipc_answer_3(rid, EOK, rootp->index, rootp->size, |
rootp->lnkcnt); |
else |
ipc_answer_0(rid, ELIMIT); |
} else { |
ipc_answer_3(rid, EOK, root->index, root->size, root->lnkcnt); |
ipc_answer_3(rid, EOK, rootp->index, rootp->size, |
rootp->lnkcnt); |
} |
} |
438,17 → 429,20 |
off_t pos = (off_t)IPC_GET_ARG3(*request); |
/* |
* Lookup the respective dentry. |
* Lookup the respective TMPFS node. |
*/ |
link_t *hlp; |
unsigned long key = index; |
hlp = hash_table_find(&dentries, &key); |
unsigned long key[] = { |
[NODES_KEY_INDEX] = index, |
[NODES_KEY_DEV] = dev_handle, |
}; |
hlp = hash_table_find(&nodes, key); |
if (!hlp) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
tmpfs_dentry_t *dentry = hash_table_get_instance(hlp, tmpfs_dentry_t, |
dh_link); |
tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t, |
nh_link); |
/* |
* Receive the read request. |
462,15 → 456,16 |
} |
size_t bytes; |
if (dentry->type == TMPFS_FILE) { |
bytes = max(0, min(dentry->size - pos, size)); |
(void) ipc_data_read_finalize(callid, dentry->data + pos, |
if (nodep->type == TMPFS_FILE) { |
bytes = max(0, min(nodep->size - pos, size)); |
(void) ipc_data_read_finalize(callid, nodep->data + pos, |
bytes); |
} else { |
tmpfs_dentry_t *dentryp; |
link_t *lnk; |
int i; |
tmpfs_dentry_t *cur; |
assert(dentry->type == TMPFS_DIRECTORY); |
assert(nodep->type == TMPFS_DIRECTORY); |
/* |
* Yes, we really use O(n) algorithm here. |
477,24 → 472,21 |
* If it bothers someone, it could be fixed by introducing a |
* hash table. |
*/ |
for (i = 0, cur = dentry->child; i < pos && cur; i++, |
cur = cur->sibling) |
for (i = 0, lnk = nodep->cs_head.next; |
i < pos && lnk != &nodep->cs_head; |
i++, lnk = lnk->next) |
; |
if (!cur) { |
if (lnk == &nodep->cs_head) { |
ipc_answer_0(callid, ENOENT); |
ipc_answer_1(rid, ENOENT, 0); |
return; |
} |
unsigned long key = (unsigned long) dentry; |
link_t *hlp = hash_table_find(&cur->names, &key); |
assert(hlp); |
tmpfs_name_t *namep = hash_table_get_instance(hlp, tmpfs_name_t, |
link); |
dentryp = list_get_instance(lnk, tmpfs_dentry_t, link); |
(void) ipc_data_read_finalize(callid, namep->name, |
str_size(namep->name) + 1); |
(void) ipc_data_read_finalize(callid, dentryp->name, |
str_size(dentryp->name) + 1); |
bytes = 1; |
} |
511,17 → 503,20 |
off_t pos = (off_t)IPC_GET_ARG3(*request); |
/* |
* Lookup the respective dentry. |
* Lookup the respective TMPFS node. |
*/ |
link_t *hlp; |
unsigned long key = index; |
hlp = hash_table_find(&dentries, &key); |
unsigned long key[] = { |
[NODES_KEY_INDEX] = index, |
[NODES_KEY_DEV] = dev_handle |
}; |
hlp = hash_table_find(&nodes, key); |
if (!hlp) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
tmpfs_dentry_t *dentry = hash_table_get_instance(hlp, tmpfs_dentry_t, |
dh_link); |
tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t, |
nh_link); |
/* |
* Receive the write request. |
537,13 → 532,13 |
/* |
* Check whether the file needs to grow. |
*/ |
if (pos + size <= dentry->size) { |
if (pos + size <= nodep->size) { |
/* The file size is not changing. */ |
(void) ipc_data_write_finalize(callid, dentry->data + pos, size); |
ipc_answer_2(rid, EOK, size, dentry->size); |
(void) ipc_data_write_finalize(callid, nodep->data + pos, size); |
ipc_answer_2(rid, EOK, size, nodep->size); |
return; |
} |
size_t delta = (pos + size) - dentry->size; |
size_t delta = (pos + size) - nodep->size; |
/* |
* At this point, we are deliberately extremely straightforward and |
* simply realloc the contents of the file on every write that grows the |
551,18 → 546,18 |
* our heap allocator can save us and just grow the block whenever |
* possible. |
*/ |
void *newdata = realloc(dentry->data, dentry->size + delta); |
void *newdata = realloc(nodep->data, nodep->size + delta); |
if (!newdata) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_2(rid, EOK, 0, dentry->size); |
ipc_answer_2(rid, EOK, 0, nodep->size); |
return; |
} |
/* Clear any newly allocated memory in order to emulate gaps. */ |
memset(newdata + dentry->size, 0, delta); |
dentry->size += delta; |
dentry->data = newdata; |
(void) ipc_data_write_finalize(callid, dentry->data + pos, size); |
ipc_answer_2(rid, EOK, size, dentry->size); |
memset(newdata + nodep->size, 0, delta); |
nodep->size += delta; |
nodep->data = newdata; |
(void) ipc_data_write_finalize(callid, nodep->data + pos, size); |
ipc_answer_2(rid, EOK, size, nodep->size); |
} |
void tmpfs_truncate(ipc_callid_t rid, ipc_call_t *request) |
572,34 → 567,37 |
size_t size = (off_t)IPC_GET_ARG3(*request); |
/* |
* Lookup the respective dentry. |
* Lookup the respective TMPFS node. |
*/ |
link_t *hlp; |
unsigned long key = index; |
hlp = hash_table_find(&dentries, &key); |
unsigned long key[] = { |
[NODES_KEY_INDEX] = index, |
[NODES_KEY_DEV] = dev_handle |
}; |
hlp = hash_table_find(&nodes, key); |
if (!hlp) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
tmpfs_dentry_t *dentry = hash_table_get_instance(hlp, tmpfs_dentry_t, |
dh_link); |
tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t, |
nh_link); |
if (size == dentry->size) { |
if (size == nodep->size) { |
ipc_answer_0(rid, EOK); |
return; |
} |
void *newdata = realloc(dentry->data, size); |
void *newdata = realloc(nodep->data, size); |
if (!newdata) { |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
if (size > dentry->size) { |
size_t delta = size - dentry->size; |
memset(newdata + dentry->size, 0, delta); |
if (size > nodep->size) { |
size_t delta = size - nodep->size; |
memset(newdata + nodep->size, 0, delta); |
} |
dentry->size = size; |
dentry->data = newdata; |
nodep->size = size; |
nodep->data = newdata; |
ipc_answer_0(rid, EOK); |
} |
610,15 → 608,18 |
int rc; |
link_t *hlp; |
unsigned long key = index; |
hlp = hash_table_find(&dentries, &key); |
unsigned long key[] = { |
[NODES_KEY_INDEX] = index, |
[NODES_KEY_DEV] = dev_handle |
}; |
hlp = hash_table_find(&nodes, key); |
if (!hlp) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
tmpfs_dentry_t *dentry = hash_table_get_instance(hlp, tmpfs_dentry_t, |
dh_link); |
rc = tmpfs_destroy_node(dentry); |
tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t, |
nh_link); |
rc = tmpfs_destroy_node(FS_NODE(nodep)); |
ipc_answer_0(rid, rc); |
} |
/branches/dd/uspace/srv/fs/tmpfs/Makefile |
---|
72,7 → 72,7 |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/fs/fat/fat.h |
---|
178,6 → 178,9 |
/** FAT in-core node. */ |
typedef struct fat_node { |
/** Back pointer to the FS node. */ |
fs_node_t *bp; |
futex_t lock; |
fat_node_type_t type; |
fat_idx_t *idx; |
/branches/dd/uspace/srv/fs/fat/fat_dentry.c |
---|
114,37 → 114,51 |
void fat_dentry_name_get(const fat_dentry_t *d, char *buf) |
{ |
int i; |
unsigned int i; |
for (i = 0; i < FAT_NAME_LEN; i++) { |
if (d->name[i] == FAT_PAD) |
break; |
if (d->name[i] == FAT_DENTRY_E5_ESC) |
*buf++ = 0xe5; |
else |
*buf++ = d->name[i]; |
else { |
if (d->lcase & FAT_LCASE_LOWER_NAME) |
*buf++ = tolower(d->name[i]); |
else |
*buf++ = d->name[i]; |
} |
} |
if (d->ext[0] != FAT_PAD) |
*buf++ = '.'; |
for (i = 0; i < FAT_EXT_LEN; i++) { |
if (d->ext[i] == FAT_PAD) { |
*buf = '\0'; |
return; |
} |
if (d->ext[i] == FAT_DENTRY_E5_ESC) |
*buf++ = 0xe5; |
else |
*buf++ = d->ext[i]; |
else { |
if (d->lcase & FAT_LCASE_LOWER_EXT) |
*buf++ = tolower(d->ext[i]); |
else |
*buf++ = d->ext[i]; |
} |
} |
*buf = '\0'; |
} |
void fat_dentry_name_set(fat_dentry_t *d, const char *name) |
{ |
int i; |
unsigned int i; |
const char fake_ext[] = " "; |
bool lower_name = true; |
bool lower_ext = true; |
for (i = 0; i < FAT_NAME_LEN; i++) { |
switch ((uint8_t) *name) { |
case 0xe5: |
156,12 → 170,19 |
d->name[i] = FAT_PAD; |
break; |
default: |
if (isalpha(*name)) { |
if (!islower(*name)) |
lower_name = false; |
} |
d->name[i] = toupper(*name++); |
break; |
} |
} |
if (*name++ != '.') |
name = fake_ext; |
for (i = 0; i < FAT_EXT_LEN; i++) { |
switch ((uint8_t) *name) { |
case 0xe5: |
172,10 → 193,25 |
d->ext[i] = FAT_PAD; |
break; |
default: |
if (isalpha(*name)) { |
if (!islower(*name)) |
lower_ext = false; |
} |
d->ext[i] = toupper(*name++); |
break; |
} |
} |
if (lower_name) |
d->lcase |= FAT_LCASE_LOWER_NAME; |
else |
d->lcase &= ~FAT_LCASE_LOWER_NAME; |
if (lower_ext) |
d->lcase |= FAT_LCASE_LOWER_EXT; |
else |
d->lcase &= ~FAT_LCASE_LOWER_EXT; |
} |
fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d) |
/branches/dd/uspace/srv/fs/fat/fat_dentry.h |
---|
47,6 → 47,9 |
#define FAT_ATTR_VOLLABEL (1 << 3) |
#define FAT_ATTR_SUBDIR (1 << 4) |
#define FAT_LCASE_LOWER_NAME 0x08 |
#define FAT_LCASE_LOWER_EXT 0x10 |
#define FAT_PAD ' ' |
#define FAT_DENTRY_UNUSED 0x00 |
65,7 → 68,7 |
uint8_t name[8]; |
uint8_t ext[3]; |
uint8_t attr; |
uint8_t reserved; |
uint8_t lcase; |
uint8_t ctime_fine; |
uint16_t ctime; |
uint16_t cdate; |
/branches/dd/uspace/srv/fs/fat/fat_ops.c |
---|
55,6 → 55,9 |
#include <sys/mman.h> |
#include <align.h> |
#define FAT_NODE(node) ((node) ? (fat_node_t *) (node)->data : NULL) |
#define FS_NODE(node) ((node) ? (node)->bp : NULL) |
/** Futex protecting the list of cached free FAT nodes. */ |
static futex_t ffn_futex = FUTEX_INITIALIZER; |
64,6 → 67,7 |
static void fat_node_initialize(fat_node_t *node) |
{ |
futex_initialize(&node->lock, 1); |
node->bp = NULL; |
node->idx = NULL; |
node->type = 0; |
link_initialize(&node->ffn_link); |
108,6 → 112,7 |
static fat_node_t *fat_node_get_new(void) |
{ |
fs_node_t *fn; |
fat_node_t *nodep; |
futex_down(&ffn_futex); |
129,15 → 134,24 |
idxp_tmp->nodep = NULL; |
futex_up(&nodep->lock); |
futex_up(&idxp_tmp->lock); |
fn = FS_NODE(nodep); |
} else { |
skip_cache: |
/* Try to allocate a new node structure. */ |
futex_up(&ffn_futex); |
fn = (fs_node_t *)malloc(sizeof(fs_node_t)); |
if (!fn) |
return NULL; |
nodep = (fat_node_t *)malloc(sizeof(fat_node_t)); |
if (!nodep) |
if (!nodep) { |
free(fn); |
return NULL; |
} |
} |
fat_node_initialize(nodep); |
fs_node_initialize(fn); |
fn->data = nodep; |
nodep->bp = fn; |
return nodep; |
} |
146,7 → 160,7 |
* |
* @param idxp Locked index structure. |
*/ |
static void *fat_node_get_core(fat_idx_t *idxp) |
static fat_node_t *fat_node_get_core(fat_idx_t *idxp) |
{ |
block_t *b; |
fat_bs_t *bs; |
223,21 → 237,21 |
/* |
* Forward declarations of FAT libfs operations. |
*/ |
static void *fat_node_get(dev_handle_t, fs_index_t); |
static void fat_node_put(void *); |
static void *fat_create_node(dev_handle_t, int); |
static int fat_destroy_node(void *); |
static int fat_link(void *, void *, const char *); |
static int fat_unlink(void *, void *); |
static void *fat_match(void *, const char *); |
static fs_index_t fat_index_get(void *); |
static size_t fat_size_get(void *); |
static unsigned fat_lnkcnt_get(void *); |
static bool fat_has_children(void *); |
static void *fat_root_get(dev_handle_t); |
static fs_node_t *fat_node_get(dev_handle_t, fs_index_t); |
static void fat_node_put(fs_node_t *); |
static fs_node_t *fat_create_node(dev_handle_t, int); |
static int fat_destroy_node(fs_node_t *); |
static int fat_link(fs_node_t *, fs_node_t *, const char *); |
static int fat_unlink(fs_node_t *, fs_node_t *, const char *); |
static fs_node_t *fat_match(fs_node_t *, const char *); |
static fs_index_t fat_index_get(fs_node_t *); |
static size_t fat_size_get(fs_node_t *); |
static unsigned fat_lnkcnt_get(fs_node_t *); |
static bool fat_has_children(fs_node_t *); |
static fs_node_t *fat_root_get(dev_handle_t); |
static char fat_plb_get_char(unsigned); |
static bool fat_is_directory(void *); |
static bool fat_is_file(void *node); |
static bool fat_is_directory(fs_node_t *); |
static bool fat_is_file(fs_node_t *node); |
/* |
* FAT libfs operations. |
244,9 → 258,9 |
*/ |
/** Instantiate a FAT in-core node. */ |
void *fat_node_get(dev_handle_t dev_handle, fs_index_t index) |
fs_node_t *fat_node_get(dev_handle_t dev_handle, fs_index_t index) |
{ |
void *node; |
fat_node_t *nodep; |
fat_idx_t *idxp; |
idxp = fat_idx_get_by_index(dev_handle, index); |
253,14 → 267,14 |
if (!idxp) |
return NULL; |
/* idxp->lock held */ |
node = fat_node_get_core(idxp); |
nodep = fat_node_get_core(idxp); |
futex_up(&idxp->lock); |
return node; |
return FS_NODE(nodep); |
} |
void fat_node_put(void *node) |
void fat_node_put(fs_node_t *fn) |
{ |
fat_node_t *nodep = (fat_node_t *)node; |
fat_node_t *nodep = FAT_NODE(fn); |
bool destroy = false; |
futex_down(&nodep->lock); |
280,11 → 294,13 |
} |
} |
futex_up(&nodep->lock); |
if (destroy) |
free(node); |
if (destroy) { |
free(nodep->bp); |
free(nodep); |
} |
} |
void *fat_create_node(dev_handle_t dev_handle, int flags) |
fs_node_t *fat_create_node(dev_handle_t dev_handle, int flags) |
{ |
fat_idx_t *idxp; |
fat_node_t *nodep; |
310,7 → 326,7 |
idxp = fat_idx_get_new(dev_handle); |
if (!idxp) { |
fat_free_clusters(bs, dev_handle, mcl); |
fat_node_put(nodep); |
fat_node_put(FS_NODE(nodep)); |
return NULL; |
} |
/* idxp->lock held */ |
345,12 → 361,12 |
idxp->nodep = nodep; |
futex_up(&idxp->lock); |
return nodep; |
return FS_NODE(nodep); |
} |
int fat_destroy_node(void *node) |
int fat_destroy_node(fs_node_t *fn) |
{ |
fat_node_t *nodep = (fat_node_t *)node; |
fat_node_t *nodep = FAT_NODE(fn); |
fat_bs_t *bs; |
/* |
364,7 → 380,7 |
/* |
* The node may not have any children. |
*/ |
assert(fat_has_children(node) == false); |
assert(fat_has_children(fn) == false); |
bs = block_bb_get(nodep->idx->dev_handle); |
if (nodep->firstc != FAT_CLST_RES0) { |
374,14 → 390,15 |
} |
fat_idx_destroy(nodep->idx); |
free(nodep->bp); |
free(nodep); |
return EOK; |
} |
int fat_link(void *prnt, void *chld, const char *name) |
int fat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name) |
{ |
fat_node_t *parentp = (fat_node_t *)prnt; |
fat_node_t *childp = (fat_node_t *)chld; |
fat_node_t *parentp = FAT_NODE(pfn); |
fat_node_t *childp = FAT_NODE(cfn); |
fat_dentry_t *d; |
fat_bs_t *bs; |
block_t *b; |
527,15 → 544,21 |
return EOK; |
} |
int fat_unlink(void *prnt, void *chld) |
int fat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm) |
{ |
fat_node_t *parentp = (fat_node_t *)prnt; |
fat_node_t *childp = (fat_node_t *)chld; |
fat_node_t *parentp = FAT_NODE(pfn); |
fat_node_t *childp = FAT_NODE(cfn); |
fat_bs_t *bs; |
fat_dentry_t *d; |
uint16_t bps; |
block_t *b; |
if (!parentp) |
return EBUSY; |
if (fat_has_children(cfn)) |
return ENOTEMPTY; |
futex_down(&parentp->lock); |
futex_down(&childp->lock); |
assert(childp->lnkcnt == 1); |
567,10 → 590,10 |
return EOK; |
} |
void *fat_match(void *prnt, const char *component) |
fs_node_t *fat_match(fs_node_t *pfn, const char *component) |
{ |
fat_bs_t *bs; |
fat_node_t *parentp = (fat_node_t *)prnt; |
fat_node_t *parentp = FAT_NODE(pfn); |
char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; |
unsigned i, j; |
unsigned bps; /* bytes per sector */ |
603,7 → 626,7 |
} |
if (fat_dentry_namecmp(name, component) == 0) { |
/* hit */ |
void *node; |
fat_node_t *nodep; |
/* |
* Assume tree hierarchy for locking. We |
* already have the parent and now we are going |
622,10 → 645,10 |
block_put(b); |
return NULL; |
} |
node = fat_node_get_core(idx); |
nodep = fat_node_get_core(idx); |
futex_up(&idx->lock); |
block_put(b); |
return node; |
return FS_NODE(nodep); |
} |
} |
block_put(b); |
635,28 → 658,25 |
return NULL; |
} |
fs_index_t fat_index_get(void *node) |
fs_index_t fat_index_get(fs_node_t *fn) |
{ |
fat_node_t *fnodep = (fat_node_t *)node; |
if (!fnodep) |
return 0; |
return fnodep->idx->index; |
return FAT_NODE(fn)->idx->index; |
} |
size_t fat_size_get(void *node) |
size_t fat_size_get(fs_node_t *fn) |
{ |
return ((fat_node_t *)node)->size; |
return FAT_NODE(fn)->size; |
} |
unsigned fat_lnkcnt_get(void *node) |
unsigned fat_lnkcnt_get(fs_node_t *fn) |
{ |
return ((fat_node_t *)node)->lnkcnt; |
return FAT_NODE(fn)->lnkcnt; |
} |
bool fat_has_children(void *node) |
bool fat_has_children(fs_node_t *fn) |
{ |
fat_bs_t *bs; |
fat_node_t *nodep = (fat_node_t *)node; |
fat_node_t *nodep = FAT_NODE(fn); |
unsigned bps; |
unsigned dps; |
unsigned blocks; |
704,7 → 724,7 |
return false; |
} |
void *fat_root_get(dev_handle_t dev_handle) |
fs_node_t *fat_root_get(dev_handle_t dev_handle) |
{ |
return fat_node_get(dev_handle, 0); |
} |
714,14 → 734,14 |
return fat_reg.plb_ro[pos % PLB_SIZE]; |
} |
bool fat_is_directory(void *node) |
bool fat_is_directory(fs_node_t *fn) |
{ |
return ((fat_node_t *)node)->type == FAT_DIRECTORY; |
return FAT_NODE(fn)->type == FAT_DIRECTORY; |
} |
bool fat_is_file(void *node) |
bool fat_is_file(fs_node_t *fn) |
{ |
return ((fat_node_t *)node)->type == FAT_FILE; |
return FAT_NODE(fn)->type == FAT_FILE; |
} |
/** libfs operations */ |
755,6 → 775,28 |
uint16_t rde; |
int rc; |
/* accept the mount options */ |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
char *opts = malloc(size + 1); |
if (!opts) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
ipcarg_t retval = ipc_data_write_finalize(callid, opts, size); |
if (retval != EOK) { |
ipc_answer_0(rid, retval); |
free(opts); |
return; |
} |
opts[size] = '\0'; |
/* initialize libblock */ |
rc = block_init(dev_handle, BS_SIZE); |
if (rc != EOK) { |
799,8 → 841,17 |
} |
/* Initialize the root node. */ |
fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t)); |
if (!rfn) { |
block_fini(dev_handle); |
fat_idx_fini_by_dev_handle(dev_handle); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
fs_node_initialize(rfn); |
fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t)); |
if (!rootp) { |
free(rfn); |
block_fini(dev_handle); |
fat_idx_fini_by_dev_handle(dev_handle); |
ipc_answer_0(rid, ENOMEM); |
810,8 → 861,9 |
fat_idx_t *ridxp = fat_idx_get_by_pos(dev_handle, FAT_CLST_ROOTPAR, 0); |
if (!ridxp) { |
free(rfn); |
free(rootp); |
block_fini(dev_handle); |
free(rootp); |
fat_idx_fini_by_dev_handle(dev_handle); |
ipc_answer_0(rid, ENOMEM); |
return; |
826,6 → 878,8 |
rootp->size = rde * sizeof(fat_dentry_t); |
rootp->idx = ridxp; |
ridxp->nodep = rootp; |
rootp->bp = rfn; |
rfn->data = rootp; |
futex_up(&ridxp->lock); |
834,7 → 888,7 |
void fat_mount(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_answer_0(rid, ENOTSUP); |
libfs_mount(&fat_libfs_ops, rid, request); |
} |
void fat_lookup(ipc_callid_t rid, ipc_call_t *request) |
847,21 → 901,23 |
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); |
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); |
off_t pos = (off_t)IPC_GET_ARG3(*request); |
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index); |
fs_node_t *fn = fat_node_get(dev_handle, index); |
fat_node_t *nodep; |
fat_bs_t *bs; |
uint16_t bps; |
size_t bytes; |
block_t *b; |
if (!nodep) { |
if (!fn) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
nodep = FAT_NODE(fn); |
ipc_callid_t callid; |
size_t len; |
if (!ipc_data_read_receive(&callid, &len)) { |
fat_node_put(nodep); |
fat_node_put(fn); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
932,7 → 988,7 |
bnum++; |
} |
miss: |
fat_node_put(nodep); |
fat_node_put(fn); |
ipc_answer_0(callid, ENOENT); |
ipc_answer_1(rid, ENOENT, 0); |
return; |
941,7 → 997,7 |
bytes = (pos - spos) + 1; |
} |
fat_node_put(nodep); |
fat_node_put(fn); |
ipc_answer_1(rid, EOK, (ipcarg_t)bytes); |
} |
950,7 → 1006,8 |
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); |
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); |
off_t pos = (off_t)IPC_GET_ARG3(*request); |
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index); |
fs_node_t *fn = fat_node_get(dev_handle, index); |
fat_node_t *nodep; |
fat_bs_t *bs; |
size_t bytes; |
block_t *b; |
960,15 → 1017,16 |
off_t boundary; |
int flags = BLOCK_FLAGS_NONE; |
if (!nodep) { |
if (!fn) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
nodep = FAT_NODE(fn); |
ipc_callid_t callid; |
size_t len; |
if (!ipc_data_write_receive(&callid, &len)) { |
fat_node_put(nodep); |
fat_node_put(fn); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
1009,7 → 1067,7 |
nodep->dirty = true; /* need to sync node */ |
} |
ipc_answer_2(rid, EOK, bytes, nodep->size); |
fat_node_put(nodep); |
fat_node_put(fn); |
return; |
} else { |
/* |
1025,7 → 1083,7 |
status = fat_alloc_clusters(bs, dev_handle, nclsts, &mcl, &lcl); |
if (status != EOK) { |
/* could not allocate a chain of nclsts clusters */ |
fat_node_put(nodep); |
fat_node_put(fn); |
ipc_answer_0(callid, status); |
ipc_answer_0(rid, status); |
return; |
1046,7 → 1104,7 |
nodep->size = pos + bytes; |
nodep->dirty = true; /* need to sync node */ |
ipc_answer_2(rid, EOK, bytes, nodep->size); |
fat_node_put(nodep); |
fat_node_put(fn); |
return; |
} |
} |
1056,7 → 1114,8 |
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); |
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); |
size_t size = (off_t)IPC_GET_ARG3(*request); |
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index); |
fs_node_t *fn = fat_node_get(dev_handle, index); |
fat_node_t *nodep; |
fat_bs_t *bs; |
uint16_t bps; |
uint8_t spc; |
1063,10 → 1122,11 |
unsigned bpc; /* bytes per cluster */ |
int rc; |
if (!nodep) { |
if (!fn) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
nodep = FAT_NODE(fn); |
bs = block_bb_get(dev_handle); |
bps = uint16_t_le2host(bs->bps); |
1104,7 → 1164,7 |
nodep->dirty = true; /* need to sync node */ |
rc = EOK; |
} |
fat_node_put(nodep); |
fat_node_put(fn); |
ipc_answer_0(rid, rc); |
return; |
} |
1115,13 → 1175,13 |
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); |
int rc; |
fat_node_t *nodep = fat_node_get(dev_handle, index); |
if (!nodep) { |
fs_node_t *fn = fat_node_get(dev_handle, index); |
if (!fn) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
rc = fat_destroy_node(nodep); |
rc = fat_destroy_node(fn); |
ipc_answer_0(rid, rc); |
} |
/branches/dd/uspace/srv/fs/fat/Makefile |
---|
74,7 → 74,7 |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/obio/Makefile |
---|
64,7 → 64,7 |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/devmap/Makefile |
---|
34,10 → 34,8 |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../libipc/include |
LIBS = $(LIBC_PREFIX)/libc.a |
LIBS = $(LIBC_PREFIX)/libc.a |
## Sources |
# |
67,7 → 65,7 |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/devmap/devmap.c |
---|
48,6 → 48,41 |
#define NAME "devmap" |
/** Representation of device driver. |
* |
* Each driver is responsible for a set of devices. |
* |
*/ |
typedef struct { |
/** Pointers to previous and next drivers in linked list */ |
link_t drivers; |
/** Pointer to the linked list of devices controlled by this driver */ |
link_t devices; |
/** Phone asociated with this driver */ |
ipcarg_t phone; |
/** Device driver name */ |
char *name; |
/** Futex for list of devices owned by this driver */ |
atomic_t devices_futex; |
} devmap_driver_t; |
/** Info about registered device |
* |
*/ |
typedef struct { |
/** Pointer to the previous and next device in the list of all devices */ |
link_t devices; |
/** Pointer to the previous and next device in the list of devices |
owned by one driver */ |
link_t driver_devices; |
/** Unique device identifier */ |
dev_handle_t handle; |
/** Device name */ |
char *name; |
/** Device driver handling this device */ |
devmap_driver_t *driver; |
} devmap_device_t; |
/** Pending lookup structure. */ |
typedef struct { |
link_t link; |
70,11 → 105,10 |
static atomic_t drivers_list_futex = FUTEX_INITIALIZER; |
static atomic_t create_handle_futex = FUTEX_INITIALIZER; |
static int devmap_create_handle(void) |
static dev_handle_t last_handle = 0; |
static dev_handle_t devmap_create_handle(void) |
{ |
static int last_handle = 0; |
int handle; |
/* TODO: allow reusing old handles after their unregistration |
* and implement some version of LRU algorithm |
*/ |
81,27 → 115,12 |
/* FIXME: overflow */ |
futex_down(&create_handle_futex); |
last_handle += 1; |
handle = last_handle; |
last_handle++; |
futex_up(&create_handle_futex); |
return handle; |
return last_handle; |
} |
/** Initialize device mapper. |
* |
* |
*/ |
static int devmap_init() |
{ |
/* TODO: */ |
return EOK; |
} |
/** Find device with given name. |
* |
*/ |
129,7 → 148,7 |
* @todo: use hash table |
* |
*/ |
static devmap_device_t *devmap_device_find_handle(int handle) |
static devmap_device_t *devmap_device_find_handle(dev_handle_t handle) |
{ |
futex_down(&devices_list_futex); |
297,13 → 316,13 |
futex_down(&drivers_list_futex); |
ipc_hangup(driver->phone); |
if (driver->phone != 0) |
ipc_hangup(driver->phone); |
/* remove it from list of drivers */ |
/* Remove it from list of drivers */ |
list_remove(&(driver->drivers)); |
/* unregister all its devices */ |
/* Unregister all its devices */ |
futex_down(&devices_list_futex); |
futex_down(&(driver->devices_futex)); |
318,7 → 337,7 |
futex_up(&drivers_list_futex); |
/* free name and driver */ |
if (NULL != driver->name) |
if (driver->name != NULL) |
free(driver->name); |
free(driver); |
454,15 → 473,15 |
/* |
* Get handle from request |
*/ |
int handle = IPC_GET_ARG2(*call); |
dev_handle_t handle = IPC_GET_ARG2(*call); |
devmap_device_t *dev = devmap_device_find_handle(handle); |
if (NULL == dev) { |
if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) { |
ipc_answer_0(callid, ENOENT); |
return; |
} |
ipc_forward_fast(callid, dev->driver->phone, (ipcarg_t)(dev->handle), |
ipc_forward_fast(callid, dev->driver->phone, dev->handle, |
IPC_GET_ARG3(*call), 0, IPC_FF_NONE); |
} |
495,7 → 514,7 |
/* |
* Allocate buffer for device name. |
*/ |
char *name = (char *) malloc(size); |
char *name = (char *) malloc(size + 1); |
if (name == NULL) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(iid, EREFUSED); |
549,7 → 568,7 |
/** Find name of device identified by id and send it to caller. |
* |
*/ |
static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall) |
static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall) |
{ |
const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall)); |
579,6 → 598,99 |
/* TODO: send name in response */ |
} |
static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall) |
{ |
futex_down(&devices_list_futex); |
ipc_answer_1(iid, EOK, list_count(&devices_list)); |
futex_up(&devices_list_futex); |
} |
static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall) |
{ |
futex_down(&devices_list_futex); |
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_read_receive(&callid, &size)) { |
ipc_answer_0(callid, EREFUSED); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
if ((size % sizeof(dev_desc_t)) != 0) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
count_t count = size / sizeof(dev_desc_t); |
dev_desc_t *desc = (dev_desc_t *) malloc(size); |
if (desc == NULL) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(iid, EREFUSED); |
return; |
} |
count_t pos = 0; |
link_t *item = devices_list.next; |
while ((item != &devices_list) && (pos < count)) { |
devmap_device_t *device = list_get_instance(item, devmap_device_t, devices); |
desc[pos].handle = device->handle; |
str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name); |
pos++; |
item = item->next; |
} |
ipcarg_t retval = ipc_data_read_finalize(callid, desc, pos * sizeof(dev_desc_t)); |
if (retval != EOK) { |
ipc_answer_0(iid, EREFUSED); |
free(desc); |
return; |
} |
free(desc); |
futex_up(&devices_list_futex); |
ipc_answer_1(iid, EOK, pos); |
} |
/** Initialize device mapper. |
* |
* |
*/ |
static bool devmap_init() |
{ |
/* Create NULL device entry */ |
devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t)); |
if (device == NULL) |
return false; |
device->name = str_dup("null"); |
if (device->name == NULL) { |
free(device); |
return false; |
} |
list_initialize(&(device->devices)); |
list_initialize(&(device->driver_devices)); |
futex_down(&devices_list_futex); |
/* Get unique device handle */ |
device->handle = devmap_create_handle(); |
device->driver = NULL; |
/* Insert device into list of all devices */ |
list_append(&device->devices, &devices_list); |
futex_up(&devices_list_futex); |
return true; |
} |
/** Handle connection with device driver. |
* |
*/ |
621,7 → 733,7 |
devmap_get_handle(callid, &call); |
break; |
case DEVMAP_DEVICE_GET_NAME: |
devmap_get_handle(callid, &call); |
devmap_get_name(callid, &call); |
break; |
default: |
if (!(callid & IPC_CALLID_NOTIFICATION)) |
660,9 → 772,14 |
devmap_get_handle(callid, &call); |
break; |
case DEVMAP_DEVICE_GET_NAME: |
/* TODO */ |
devmap_get_name(callid, &call); |
break; |
case DEVMAP_DEVICE_GET_COUNT: |
devmap_get_count(callid, &call); |
break; |
case DEVMAP_DEVICE_GET_DEVICES: |
devmap_get_devices(callid, &call); |
break; |
default: |
if (!(callid & IPC_CALLID_NOTIFICATION)) |
ipc_answer_0(callid, ENOENT); |
700,7 → 817,7 |
{ |
printf(NAME ": HelenOS Device Mapper\n"); |
if (devmap_init() != 0) { |
if (!devmap_init()) { |
printf(NAME ": Error while initializing service\n"); |
return -1; |
} |
/branches/dd/uspace/srv/vfs/vfs.c |
---|
52,7 → 52,7 |
static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
bool keep_on_going = true; |
/* |
* The connection was opened via the IPC_CONNECT_ME_TO call. |
* This call needs to be answered. |
80,21 → 80,6 |
case IPC_M_PHONE_HUNGUP: |
keep_on_going = false; |
break; |
case IPC_M_CONNECT_ME_TO: |
/* |
* Connect the client file system to another one. |
*/ |
/* FIXME: |
* Prevent ordinary clients from connecting to file |
* system servers directly. This should be solved by |
* applying some security mechanisms. |
*/ |
fs_handle = IPC_GET_ARG1(call); |
phone = vfs_grab_phone(fs_handle); |
(void) ipc_forward_fast(callid, phone, 0, 0, 0, |
IPC_FF_NONE); |
vfs_release_phone(phone); |
break; |
case VFS_REGISTER: |
vfs_register(callid, &call); |
/* |
/branches/dd/uspace/srv/vfs/vfs_ops.c |
---|
60,6 → 60,7 |
link_t link; |
char *fs_name; /**< File system name */ |
char *mp; /**< Mount point */ |
char *opts; /**< Mount options. */ |
ipc_callid_t callid; /**< Call ID waiting for the mount */ |
ipc_callid_t rid; /**< Request ID */ |
dev_handle_t dev_handle; /**< Device handle */ |
80,13 → 81,22 |
}; |
static void vfs_mount_internal(ipc_callid_t rid, dev_handle_t dev_handle, |
fs_handle_t fs_handle, char *mp) |
fs_handle_t fs_handle, char *mp, char *opts) |
{ |
/* Resolve the path to the mountpoint. */ |
vfs_lookup_res_t mp_res; |
vfs_lookup_res_t mr_res; |
vfs_node_t *mp_node = NULL; |
int rc; |
vfs_node_t *mr_node; |
fs_index_t rindex; |
size_t rsize; |
unsigned rlnkcnt; |
ipcarg_t rc; |
int phone; |
aid_t msg; |
ipc_call_t answer; |
/* Resolve the path to the mountpoint. */ |
futex_down(&rootfs_futex); |
if (rootfs.fs_handle) { |
/* We already have the root FS. */ |
125,12 → 135,6 |
} else { |
/* We still don't have the root file system mounted. */ |
if (str_cmp(mp, "/") == 0) { |
vfs_lookup_res_t mr_res; |
vfs_node_t *mr_node; |
ipcarg_t rindex; |
ipcarg_t rsize; |
ipcarg_t rlnkcnt; |
/* |
* For this simple, but important case, |
* we are almost done. |
138,8 → 142,19 |
/* Tell the mountee that it is being mounted. */ |
phone = vfs_grab_phone(fs_handle); |
rc = async_req_1_3(phone, VFS_MOUNTED, |
(ipcarg_t) dev_handle, &rindex, &rsize, &rlnkcnt); |
msg = async_send_1(phone, VFS_MOUNTED, |
(ipcarg_t) dev_handle, &answer); |
/* send the mount options */ |
rc = ipc_data_write_start(phone, (void *)opts, |
str_size(opts)); |
if (rc != EOK) { |
async_wait_for(msg, NULL); |
vfs_release_phone(phone); |
futex_up(&rootfs_futex); |
ipc_answer_0(rid, rc); |
return; |
} |
async_wait_for(msg, &rc); |
vfs_release_phone(phone); |
if (rc != EOK) { |
147,12 → 162,16 |
ipc_answer_0(rid, rc); |
return; |
} |
rindex = (fs_index_t) IPC_GET_ARG1(answer); |
rsize = (size_t) IPC_GET_ARG2(answer); |
rlnkcnt = (unsigned) IPC_GET_ARG3(answer); |
mr_res.triplet.fs_handle = fs_handle; |
mr_res.triplet.dev_handle = dev_handle; |
mr_res.triplet.index = (fs_index_t) rindex; |
mr_res.size = (size_t) rsize; |
mr_res.lnkcnt = (unsigned) rlnkcnt; |
mr_res.triplet.index = rindex; |
mr_res.size = rsize; |
mr_res.lnkcnt = rlnkcnt; |
mr_res.type = VFS_NODE_DIRECTORY; |
rootfs.fs_handle = fs_handle; |
182,12 → 201,41 |
* handles, and we know the mount point VFS node. |
*/ |
int mountee_phone = vfs_grab_phone(fs_handle); |
assert(mountee_phone >= 0); |
vfs_release_phone(mountee_phone); |
phone = vfs_grab_phone(mp_res.triplet.fs_handle); |
rc = async_req_4_0(phone, VFS_MOUNT, |
msg = async_send_4(phone, VFS_MOUNT, |
(ipcarg_t) mp_res.triplet.dev_handle, |
(ipcarg_t) mp_res.triplet.index, |
(ipcarg_t) fs_handle, |
(ipcarg_t) dev_handle); |
(ipcarg_t) dev_handle, &answer); |
/* send connection */ |
rc = async_req_1_0(phone, IPC_M_CONNECTION_CLONE, mountee_phone); |
if (rc != EOK) { |
async_wait_for(msg, NULL); |
vfs_release_phone(phone); |
/* Mount failed, drop reference to mp_node. */ |
if (mp_node) |
vfs_node_put(mp_node); |
ipc_answer_0(rid, rc); |
return; |
} |
/* send the mount options */ |
rc = ipc_data_write_start(phone, (void *)opts, str_size(opts)); |
if (rc != EOK) { |
async_wait_for(msg, NULL); |
vfs_release_phone(phone); |
/* Mount failed, drop reference to mp_node. */ |
if (mp_node) |
vfs_node_put(mp_node); |
ipc_answer_0(rid, rc); |
return; |
} |
async_wait_for(msg, &rc); |
vfs_release_phone(phone); |
if (rc != EOK) { |
196,6 → 244,21 |
vfs_node_put(mp_node); |
} |
rindex = (fs_index_t) IPC_GET_ARG1(answer); |
rsize = (size_t) IPC_GET_ARG2(answer); |
rlnkcnt = (unsigned) IPC_GET_ARG3(answer); |
mr_res.triplet.fs_handle = fs_handle; |
mr_res.triplet.dev_handle = dev_handle; |
mr_res.triplet.index = rindex; |
mr_res.size = rsize; |
mr_res.lnkcnt = rlnkcnt; |
mr_res.type = VFS_NODE_DIRECTORY; |
/* Add reference to the mounted root. */ |
mr_node = vfs_node_get(&mr_res); |
assert(mr_node); |
ipc_answer_0(rid, rc); |
} |
216,10 → 279,12 |
ipc_answer_0(pr->callid, EOK); |
/* Do the mount */ |
vfs_mount_internal(pr->rid, pr->dev_handle, fs_handle, pr->mp); |
vfs_mount_internal(pr->rid, pr->dev_handle, fs_handle, pr->mp, |
pr->opts); |
free(pr->fs_name); |
free(pr->mp); |
free(pr->opts); |
list_remove(cur); |
free(pr); |
goto loop; |
272,12 → 337,47 |
/* Deliver the mount point. */ |
ipcarg_t retval = ipc_data_write_finalize(callid, mp, size); |
if (retval != EOK) { |
ipc_answer_0(rid, EREFUSED); |
ipc_answer_0(rid, retval); |
free(mp); |
return; |
} |
mp[size] = '\0'; |
/* Now we expect to receive the mount options. */ |
if (!ipc_data_write_receive(&callid, &size)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
free(mp); |
return; |
} |
/* Check the offered options size. */ |
if (size < 0 || size > MAX_MNTOPTS_LEN) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
free(mp); |
return; |
} |
/* Allocate buffer for the mount options. */ |
char *opts = (char *) malloc(size + 1); |
if (!opts) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
free(mp); |
return; |
} |
/* Deliver the mount options. */ |
retval = ipc_data_write_finalize(callid, opts, size); |
if (retval != EOK) { |
ipc_answer_0(rid, retval); |
free(mp); |
free(opts); |
return; |
} |
opts[size] = '\0'; |
/* |
* Now, we expect the client to send us data with the name of the file |
* system. |
286,6 → 386,7 |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
free(mp); |
free(opts); |
return; |
} |
297,6 → 398,7 |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
free(mp); |
free(opts); |
return; |
} |
306,8 → 408,9 |
char *fs_name = (char *) malloc(size + 1); |
if (fs_name == NULL) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, EREFUSED); |
ipc_answer_0(rid, ENOMEM); |
free(mp); |
free(opts); |
return; |
} |
314,14 → 417,30 |
/* Deliver the file system name. */ |
retval = ipc_data_write_finalize(callid, fs_name, size); |
if (retval != EOK) { |
ipc_answer_0(rid, EREFUSED); |
ipc_answer_0(rid, retval); |
free(mp); |
free(opts); |
free(fs_name); |
return; |
} |
fs_name[size] = '\0'; |
/* |
* Wait for IPC_M_PING so that we can return an error if we don't know |
* fs_name. |
*/ |
ipc_call_t data; |
callid = async_get_call(&data); |
if (IPC_GET_METHOD(data) != IPC_M_PING) { |
ipc_answer_0(callid, ENOTSUP); |
ipc_answer_0(rid, ENOTSUP); |
free(mp); |
free(opts); |
free(fs_name); |
return; |
} |
/* |
* Check if we know a file system with the same name as is in fs_name. |
* This will also give us its file system handle. |
*/ |
328,18 → 447,22 |
fs_handle_t fs_handle = fs_name_to_handle(fs_name, true); |
if (!fs_handle) { |
if (flags & IPC_FLAG_BLOCKING) { |
pending_req_t *pr; |
/* Blocking mount, add to pending list */ |
pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t)); |
pr = (pending_req_t *) malloc(sizeof(pending_req_t)); |
if (!pr) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
free(mp); |
free(fs_name); |
free(opts); |
return; |
} |
pr->fs_name = fs_name; |
pr->mp = mp; |
pr->opts = opts; |
pr->callid = callid; |
pr->rid = rid; |
pr->dev_handle = dev_handle; |
352,6 → 475,7 |
ipc_answer_0(rid, ENOENT); |
free(mp); |
free(fs_name); |
free(opts); |
return; |
} |
359,9 → 483,10 |
ipc_answer_0(callid, EOK); |
/* Do the mount */ |
vfs_mount_internal(rid, dev_handle, fs_handle, mp); |
vfs_mount_internal(rid, dev_handle, fs_handle, mp, opts); |
free(mp); |
free(fs_name); |
free(opts); |
} |
void vfs_open(ipc_callid_t rid, ipc_call_t *request) |
859,8 → 984,16 |
} |
oldc[olen] = '\0'; |
newc[nlen] = '\0'; |
if (!str_lcmp(newc, oldc, str_length(oldc))) { |
/* oldc is a prefix of newc */ |
if ((!str_lcmp(newc, oldc, str_length(oldc))) && |
((newc[str_length(oldc)] == '/') || |
(str_length(oldc) == 1) || |
(str_length(oldc) == str_length(newc)))) { |
/* |
* oldc is a prefix of newc and either |
* - newc continues with a / where oldc ends, or |
* - oldc was / itself, or |
* - oldc and newc are equal. |
*/ |
ipc_answer_0(rid, EINVAL); |
free(old); |
free(new); |
888,8 → 1021,23 |
free(new); |
return; |
} |
/* Determine the path to the parent of the node with the new name. */ |
char *parentc = str_dup(newc); |
if (!parentc) { |
rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
free(old); |
free(new); |
return; |
} |
char *lastsl = str_rchr(parentc + 1, L'/'); |
if (lastsl) |
*lastsl = '\0'; |
else |
parentc[1] = '\0'; |
/* Lookup parent of the new file name. */ |
rc = vfs_lookup_internal(newc, L_PARENT, &new_par_lr, NULL); |
rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL); |
free(parentc); /* not needed anymore */ |
if (rc != EOK) { |
rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
/branches/dd/uspace/srv/vfs/vfs.h |
---|
38,6 → 38,7 |
#include <futex.h> |
#include <rwlock.h> |
#include <sys/types.h> |
#include <devmap.h> |
#include <bool.h> |
// FIXME: according to CONFIG_DEBUG |
49,7 → 50,6 |
/* Basic types. */ |
typedef int16_t fs_handle_t; |
typedef int16_t dev_handle_t; |
typedef uint32_t fs_index_t; |
typedef enum { |
166,11 → 166,6 |
* VFS_UNLINK. |
*/ |
#define L_UNLINK 32 |
/** |
* L_PARENT performs a lookup but returns the triplet of the parent node. |
* This flag may not be combined with any other lookup flag. |
*/ |
#define L_PARENT 64 |
typedef enum vfs_node_type { |
VFS_NODE_UNKNOWN, |
254,6 → 249,8 |
extern uint8_t *plb; /**< Path Lookup Buffer */ |
extern link_t plb_head; /**< List of active PLB entries. */ |
#define MAX_MNTOPTS_LEN 256 |
/** Holding this rwlock prevents changes in file system namespace. */ |
extern rwlock_t namespace_rwlock; |
/branches/dd/uspace/srv/vfs/Makefile |
---|
69,7 → 69,7 |
disasm: $(OUTPUT).disasm |
$(OUTPUT).disasm: $(OUTPUT) |
$(OBJDUMP) -d $< >$@ |
$(OBJDUMP) -d $< > $@ |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
/branches/dd/uspace/srv/vfs/vfs_file.c |
---|
103,7 → 103,7 |
*/ |
int vfs_fd_free(int fd) |
{ |
if ((fd >= MAX_OPEN_FILES) || (files[fd] == NULL)) |
if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (files[fd] == NULL)) |
return EBADF; |
vfs_file_delref(files[fd]); |
files[fd] = NULL; |
150,7 → 150,7 |
*/ |
vfs_file_t *vfs_file_get(int fd) |
{ |
if (fd < MAX_OPEN_FILES) |
if ((fd >= 0) && (fd < MAX_OPEN_FILES)) |
return files[fd]; |
return NULL; |
} |
/branches/dd/uspace/Makefile |
---|
37,6 → 37,7 |
lib/libblock \ |
lib/softint \ |
lib/softfloat \ |
srv/bd/gxe_bd \ |
srv/ns \ |
srv/loader \ |
srv/fb \ |
45,6 → 46,7 |
srv/rd \ |
srv/fs/fat \ |
srv/fs/tmpfs \ |
srv/fs/devfs \ |
srv/vfs \ |
srv/devmap \ |
app/tetris \ |
/branches/dd/HelenOS.config |
---|
290,12 → 290,6 |
% Deadlock detection support for spinlocks |
! [CONFIG_DEBUG=y&CONFIG_SMP=y] CONFIG_DEBUG_SPINLOCK (y/n) |
% Improved support for hyperthreading |
! [PLATFORM=amd64&CONFIG_SMP=y] CONFIG_HT (y/n) |
% Improved support for hyperthreading |
! [PLATFORM=ia32&PROCESSOR!=athlon_xp&PROCESSOR!=athlon_mp&PROCESSOR!=pentium3&CONFIG_SMP=y] CONFIG_HT (y/n) |
% Lazy FPU context switching |
! [CONFIG_FPU=y] CONFIG_FPU_LAZY (y/n) |
332,7 → 326,7 |
% Input device class |
@ "generic" Keyboard or serial line |
@ "none" No input device |
! [PLATFORM=ia32|PLATFORM=arm32|PLATFORM=amd64|PLATFORM=mips32|PLATFORM=sparc64] CONFIG_HID_IN (choice) |
! [PLATFORM=ia32|PLATFORM=arm32|PLATFORM=amd64|PLATFORM=mips32|PLATFORM=ppc32|PLATFORM=sparc64] CONFIG_HID_IN (choice) |
% Input device class |
@ "generic" Keyboard or serial line |
378,6 → 372,9 |
% Support for GXemul printer |
! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=serial)&PLATFORM=arm32] CONFIG_ARM_PRN (y/n) |
% Support for VIA CUDA controller |
! [CONFIG_HID_IN=generic&PLATFORM=ppc32] CONFIG_VIA_CUDA (y/n) |
% Support for NS16550 controller |
! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=keyboard)&PLATFORM=sparc64&MACHINE=generic] CONFIG_NS16550 (y/n) |
/branches/dd/boot/arch/sparc64/loader/asm.S |
---|
40,7 → 40,7 |
.global jump_to_kernel |
halt: |
b halt |
ba %xcc, halt |
nop |
memcpy: |
116,7 → 116,7 |
set subarchitecture, %g2 |
ldub [%g2], %g2 |
cmp %g2, 3 |
be 1f |
be %xcc, 1f |
nop |
0: |
call icache_flush |
/branches/dd/boot/arch/sparc64/loader/boot.S |
---|
43,7 → 43,7 |
.global start |
start: |
b 1f |
ba %xcc, 1f |
nop |
/* |
83,7 → 83,7 |
call ofw_init ! initialize OpenFirmware |
stx %o4, [%l0] |
b bootstrap |
ba %xcc, bootstrap |
nop |
.align STACK_ALIGNMENT |
/branches/dd/boot/arch/sparc64/loader/Makefile |
---|
101,8 → 101,9 |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/pci/pci |
$(USPACEDIR)/srv/pci/pci \ |
$(USPACEDIR)/srv/fs/devfs/devfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs |
ifeq ($(MACHINE),generic) |
RD_SRVS += \ |
/branches/dd/boot/arch/ia64/loader/Makefile |
---|
100,6 → 100,7 |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/fs/devfs/devfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat |
/branches/dd/boot/arch/arm32/loader/Makefile |
---|
89,6 → 89,7 |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/fs/devfs/devfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat |
/branches/dd/boot/arch/ppc32/Makefile.inc |
---|
32,8 → 32,10 |
$(BASE)/image.iso: depend arch/$(BARCH)/loader/image.boot |
mkdir -p $(TMP)/boot |
mkdir -p $(TMP)/ppc |
cp arch/$(BARCH)/loader/image.boot $(TMP)/boot/image.boot |
cp arch/$(BARCH)/yaboot/ofboot.b $(TMP)/boot/ofboot.b |
cp arch/$(BARCH)/yaboot/bootinfo.txt $(TMP)/ppc/bootinfo.txt |
cp arch/$(BARCH)/yaboot/yaboot $(TMP)/boot/yaboot |
cp arch/$(BARCH)/yaboot/yaboot.conf $(TMP)/boot/yaboot.conf |
mkisofs -hfs -part -map arch/$(BARCH)/yaboot/maps -no-desktop -hfs-volid "HelenOS" -hfs-bless $(TMP)/boot -r -o $@ $(TMP)/ |
/branches/dd/boot/arch/ppc32/loader/ofwarch.c |
---|
52,7 → 52,8 |
{ |
char device_name[BUF_SIZE]; |
if (ofw_get_property(ofw_aliases, "macio", device_name, sizeof(device_name)) <= 0) |
if ((ofw_get_property(ofw_aliases, "macio", device_name, sizeof(device_name)) <= 0) |
&& (ofw_get_property(ofw_aliases, "mac-io", device_name, sizeof(device_name)) <= 0)) |
return false; |
phandle device = ofw_find_device(device_name); |
/branches/dd/boot/arch/ppc32/loader/Makefile |
---|
88,6 → 88,7 |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/fs/devfs/devfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat |
/branches/dd/boot/arch/ppc32/yaboot/yaboot.conf |
---|
1,4 → 1,5 |
device=cd: |
timeout=0 |
image=/boot/image.boot |
label=HelenOS |
/branches/dd/boot/arch/ppc32/yaboot/ofboot.b |
---|
3,7 → 3,7 |
MacRISC |
</COMPATIBLE> |
<DESCRIPTION> |
text |
HelenOS |
</DESCRIPTION> |
<BOOT-SCRIPT> |
" screen" output |
/branches/dd/boot/arch/ppc32/yaboot/bootinfo.txt |
---|
0,0 → 1,5 |
<chrp-boot> |
<description>HelenOS</description> |
<os-name>HelenOS</os-name> |
<boot-script>boot cd:,\boot\yaboot</boot-script> |
</chrp-boot> |
/branches/dd/boot/arch/amd64/Makefile.inc |
---|
47,6 → 47,7 |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/fs/devfs/devfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat |
/branches/dd/boot/arch/mips32/loader/Makefile |
---|
101,8 → 101,10 |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/fs/devfs/devfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat |
$(USPACEDIR)/srv/fs/fat/fat \ |
$(USPACEDIR)/srv/bd/gxe_bd/gxe_bd |
RD_APPS = \ |
$(USPACEDIR)/app/tetris/tetris \ |
/branches/dd/boot/arch/ia32/Makefile.inc |
---|
47,6 → 47,7 |
$(USPACEDIR)/srv/fb/fb \ |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/fs/devfs/devfs \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat |
/branches/dd/defaults/ppc32/Makefile.config |
---|
25,6 → 25,9 |
# Compile kernel tests |
CONFIG_TEST = y |
# Input device class |
CONFIG_HID_IN = generic |
# Output device class |
CONFIG_HID_OUT = generic |
/branches/dd/defaults/amd64/Makefile.config |
---|
16,9 → 16,6 |
# Support for SMP |
CONFIG_SMP = y |
# Improved support for hyperthreading |
CONFIG_HT = y |
# Lazy FPU context switching |
CONFIG_FPU_LAZY = y |
/branches/dd/defaults/ia32/Makefile.config |
---|
22,9 → 22,6 |
# Support for SMP |
CONFIG_SMP = y |
# Improved support for hyperthreading |
CONFIG_HT = y |
# Lazy FPU context switching |
CONFIG_FPU_LAZY = y |