Subversion Repositories HelenOS

Compare Revisions

No changes between revisions

Ignore whitespace Rev 3674 → Rev 3675

/branches/tracing/contrib/util/DownloadAndPatchSILO.sh
0,0 → 1,74
#!/bin/bash
 
# Download SILO and patch it so that it can be used to create a bootable CD
# for the Serengeti machine
# by Pavel Rimsky <rimskyp@seznam.cz>
# portions by Martin Decky <martin@decky.cz>
#
# GPL'ed, copyleft
#
 
# stuff to be downloaded
SILO_DOWNLOAD_FILE='silo-loaders-1.4.11.tar.gz'
SILO_DOWNLOAD_URL='http://silo.auxio.org/pub/silo/old/'$SILO_DOWNLOAD_FILE
 
# check whether the last command failed, if so, write an error message and exit
check_error() {
if [ "$1" -ne "0" ]; then
echo
echo "Script failed: $2"
exit
fi
}
 
# temporary files are to be stored in /tmp
# the resulting file in the current directory
WD=`pwd`
cd /tmp
 
# download SILO from its official website
echo ">>> Downloading SILO"
wget $SILO_DOWNLOAD_URL
check_error $? "Error downloading SILO."
 
# unpack the downloaded file
echo ">>> Unpacking tarball"
tar xvzf $SILO_DOWNLOAD_FILE
check_error $? "Error unpacking tarball."
 
# CD to the unpacked directory
echo ">>> Changing to the unpacked SILO directory"
cd boot
check_error $? "Changing directory failed."
 
# patch it - remove bytes 512 to 512 + 32 (counted from 0), which belong to
# the ELF header which is not recognized by the Serengeti firmware
echo ">>> Patching SILO"
(((xxd -p -l 512 isofs.b) && (xxd -p -s 544 isofs.b)) | xxd -r -p) \
> isofs.b.patched
check_error $? "Patching SILO failed"
mv isofs.b.patched isofs.b
 
# get rid of files which are not needed for creating the bootable CD
echo ">>> Purging SILO directory"
for file in `ls`; do
if [ \( -f $file \) -a \( $file != "isofs.b" \) -a \( $file != "second.b" \) ];
then
rm -fr $file;
fi
done
check_error $? "Purging SILO directory failed"
 
# create the gzipped tarball with patched SILO
echo ">>> Creating tarball with patched SILO"
tar cvzf silo.patched.tar.gz *.b
check_error $? "Creating tarball with patched SILO failed"
 
# and move it to the directory where the user expects it to be
echo ">>> Moving the tarball with patched SILO to the current directory"
mv silo.patched.tar.gz $WD
check_error $? "Moving the tarball with patched SILO failed"
 
# move back to the working directory from /tmp
cd $WD
 
/branches/tracing/kernel/test/debug/mips1.c
38,10 → 38,10
 
#include <arch.h>
 
char * test_mips1(bool quiet)
char *test_mips1(bool quiet)
{
if (!quiet)
printf("You should enter kconsole debug mode now.\n");
printf("If kconsole is compiled in, you should enter debug mode now.\n");
asm volatile (
"break\n"
/branches/tracing/kernel/kernel.config
76,6 → 76,11
@ "opteron" Opteron
! [ARCH=amd64] MACHINE (choice)
 
# CPU type
@ "us" UltraSPARC I-II subarchitecture
@ "us3" UltraSPARC III-IV subarchitecture
! [ARCH=sparc64] MACHINE (choice)
 
# Machine type
@ "msim" MSIM Simulator
@ "simics" Virtutech Simics simulator
138,10 → 143,21
# Support for Z8530 serial port
! [ARCH=sparc64] CONFIG_Z8530 (y/n)
 
# Support for NS16550 serial port
! [ARCH=sparc64|ARCH=ia64] CONFIG_NS16550 (y/n)
# Support for NS16550 serial port
! [ARCH=sparc64|(ARCH=ia64&MACHINE!=ski)] CONFIG_NS16550 (n/y)
 
# Support for Serengeti console
! [ARCH=sparc64] CONFIG_SGCN (y/n)
 
# IOSapic on default address support
! [ARCH=ia64&MACHINE!=ski] CONFIG_IOSAPIC (y/n)
 
# Interrupt-driven driver for Legacy Keyboard?
! [CONFIG_NS16550=n&CONFIG_IOSAPIC=y&MACHINE!=ski] CONFIG_I8042_INTERRUPT_DRIVEN (y/n)
 
# Interrupt-driven driver for NS16550?
! [CONFIG_NS16550=y&((ARCH!=ia64)|CONFIG_IOSAPIC=y)&MACHINE!=ski] CONFIG_NS16550_INTERRUPT_DRIVEN (y/n)
 
# Virtually indexed D-cache support
! [ARCH=sparc64] CONFIG_VIRT_IDX_DCACHE (y/n)
 
150,12 → 166,15
 
## Debugging configuration directives
 
# General debuging and assert checking
# General debugging and assert checking
! CONFIG_DEBUG (y/n)
 
# Extensive debugging output
! [CONFIG_DEBUG=y] CONFIG_EDEBUG (n/y)
# Kernel console support
! CONFIG_KCONSOLE (y/n)
 
# Detailed kernel logging
! CONFIG_LOG (n/y)
 
# Deadlock detection support for spinlocks
! [CONFIG_DEBUG=y&CONFIG_SMP=y] CONFIG_DEBUG_SPINLOCK (y/n)
 
/branches/tracing/kernel/genarch/include/kbd/z8530.h
39,17 → 39,18
 
#include <console/chardev.h>
#include <ipc/irq.h>
#include <ddi/irq.h>
 
extern bool z8530_belongs_to_kernel;
 
extern void z8530_init(devno_t devno, inr_t inr, uintptr_t vaddr);
extern void z8530_init(devno_t, uintptr_t, inr_t, cir_t, void *);
extern void z8530_poll(void);
extern void z8530_grab(void);
extern void z8530_release(void);
extern void z8530_interrupt(void);
extern char z8530_key_read(chardev_t *d);
extern char z8530_key_read(chardev_t *);
extern irq_ownership_t z8530_claim(void);
extern void z8530_irq_handler(irq_t *irq, void *arg, ...);
extern void z8530_irq_handler(irq_t *, void *, ...);
 
#endif
 
/branches/tracing/kernel/genarch/include/kbd/ns16550.h
38,15 → 38,16
#define KERN_NS16550_H_
 
#include <console/chardev.h>
#include <ddi/irq.h>
#include <ipc/irq.h>
 
extern void ns16550_init(devno_t devno, inr_t inr, uintptr_t vaddr);
extern void ns16550_init(devno_t, uintptr_t, inr_t, cir_t, void *);
extern void ns16550_poll(void);
extern void ns16550_grab(void);
extern void ns16550_release(void);
extern char ns16550_key_read(chardev_t *d);
extern char ns16550_key_read(chardev_t *);
extern irq_ownership_t ns16550_claim(void);
extern void ns16550_irq_handler(irq_t *irq, void *arg, ...);
extern void ns16550_irq_handler(irq_t *, void *, ...);
 
#include <arch/types.h>
#ifndef ia64
58,6 → 59,7
#define IIR_REG 2 /** Interrupt Ident Register (read). */
#define FCR_REG 2 /** FIFO control register (write). */
#define LCR_REG 3 /** Line Control register. */
#define MCR_REG 4 /** Modem Control Register. */
#define LSR_REG 5 /** Line Status Register. */
 
#define IER_ERBFI 0x01 /** Enable Receive Buffer Full Interrupt. */
64,57 → 66,68
 
#define LCR_DLAB 0x80 /** Divisor Latch Access bit. */
 
#define MCR_OUT2 0x08 /** OUT2. */
 
/** Structure representing the ns16550 device. */
typedef struct {
devno_t devno;
volatile ioport_t io_port; /** Memory mapped registers of the ns16550. */
/** Memory mapped registers of the ns16550. */
volatile ioport_t io_port;
} ns16550_t;
 
static inline uint8_t ns16550_rbr_read(ns16550_t *dev)
{
return inb(dev->io_port+RBR_REG);
return inb(dev->io_port + RBR_REG);
}
static inline void ns16550_rbr_write(ns16550_t *dev, uint8_t v)
{
outb(dev->io_port+RBR_REG,v);
outb(dev->io_port + RBR_REG, v);
}
 
static inline uint8_t ns16550_ier_read(ns16550_t *dev)
{
return inb(dev->io_port+IER_REG);
return inb(dev->io_port + IER_REG);
}
 
static inline void ns16550_ier_write(ns16550_t *dev, uint8_t v)
{
outb(dev->io_port+IER_REG,v);
outb(dev->io_port + IER_REG, v);
}
 
static inline uint8_t ns16550_iir_read(ns16550_t *dev)
{
return inb(dev->io_port+IIR_REG);
return inb(dev->io_port + IIR_REG);
}
 
static inline void ns16550_fcr_write(ns16550_t *dev, uint8_t v)
{
outb(dev->io_port+FCR_REG,v);
outb(dev->io_port + FCR_REG, v);
}
 
static inline uint8_t ns16550_lcr_read(ns16550_t *dev)
{
return inb(dev->io_port+LCR_REG);
return inb(dev->io_port + LCR_REG);
}
 
static inline void ns16550_lcr_write(ns16550_t *dev, uint8_t v)
{
outb(dev->io_port+LCR_REG,v);
outb(dev->io_port + LCR_REG, v);
}
 
static inline uint8_t ns16550_lsr_read(ns16550_t *dev)
{
return inb(dev->io_port+LSR_REG);
return inb(dev->io_port + LSR_REG);
}
 
static inline uint8_t ns16550_mcr_read(ns16550_t *dev)
{
return inb(dev->io_port + MCR_REG);
}
 
static inline void ns16550_mcr_write(ns16550_t *dev, uint8_t v)
{
outb(dev->io_port + MCR_REG, v);
}
 
#endif
 
/branches/tracing/kernel/genarch/include/fb/visuals.h
44,6 → 44,7
#define VISUAL_RGB_0_8_8_8 5
 
#define VISUAL_BGR_0_8_8_8 6
#define VISUAL_SB1500_PALETTE 7
 
#endif
 
/branches/tracing/kernel/genarch/include/fb/fb.h
38,8 → 38,34
#include <arch/types.h>
#include <synch/spinlock.h>
 
/**
* Properties of the framebuffer device.
*/
typedef struct fb_properties {
/** Physical address of the framebuffer device. */
uintptr_t addr;
 
/**
* Address where the first (top left) pixel is mapped,
* relative to "addr".
*/
unsigned int offset;
 
/** Screen width in pixels. */
unsigned int x;
 
/** Screen height in pixels. */
unsigned int y;
 
/** Bytes per one scanline. */
unsigned int scan;
 
/** Color model. */
unsigned int visual;
} fb_properties_t;
 
SPINLOCK_EXTERN(fb_lock);
void fb_init(uintptr_t addr, unsigned int x, unsigned int y, unsigned int scan, unsigned int visual);
void fb_init(fb_properties_t *props);
 
#endif
 
/branches/tracing/kernel/genarch/include/ofw/ofw_tree.h
30,6 → 30,7
#define KERN_OFW_TREE_H_
 
#include <arch/types.h>
#include <ddi/irq.h>
#include <typedefs.h>
 
#define OFW_TREE_PROPERTY_MAX_NAMELEN 32
43,11 → 44,11
ofw_tree_node_t *peer;
ofw_tree_node_t *child;
 
uint32_t node_handle; /**< Old OpenFirmware node handle. */
uint32_t node_handle; /**< Old OpenFirmware node handle. */
 
char *da_name; /**< Disambigued name. */
char *da_name; /**< Disambigued name. */
 
unsigned properties; /**< Number of properties. */
unsigned properties; /**< Number of properties. */
ofw_tree_property_t *property;
/**
105,7 → 106,7
uint32_t child_space;
uint32_t child_base;
uint32_t parent_space;
uint64_t parent_base; /* group phys.mid and phys.lo together */
uint64_t parent_base; /* group phys.mid and phys.lo together */
uint32_t size;
} __attribute__ ((packed));
typedef struct ofw_ebus_range ofw_ebus_range_t;
127,8 → 128,8
typedef struct ofw_ebus_intr_mask ofw_ebus_intr_mask_t;
 
struct ofw_pci_reg {
uint32_t space; /* needs to be masked to obtain pure space id */
uint64_t addr; /* group phys.mid and phys.lo together */
uint32_t space; /* needs to be masked to obtain pure space id */
uint64_t addr; /* group phys.mid and phys.lo together */
uint64_t size;
} __attribute__ ((packed));
typedef struct ofw_pci_reg ofw_pci_reg_t;
135,7 → 136,7
 
struct ofw_pci_range {
uint32_t space;
uint64_t child_base; /* group phys.mid and phys.lo together */
uint64_t child_base; /* group phys.mid and phys.lo together */
uint64_t parent_base;
uint64_t size;
} __attribute__ ((packed));
160,27 → 161,43
} __attribute__ ((packed));
typedef struct ofw_upa_reg ofw_upa_reg_t;
 
extern void ofw_tree_init(ofw_tree_node_t *root);
extern void ofw_tree_init(ofw_tree_node_t *);
extern void ofw_tree_print(void);
extern const char *ofw_tree_node_name(const ofw_tree_node_t *node);
extern ofw_tree_node_t *ofw_tree_lookup(const char *path);
extern ofw_tree_property_t *ofw_tree_getprop(const ofw_tree_node_t *node, const char *name);
extern ofw_tree_node_t *ofw_tree_find_child(ofw_tree_node_t *node, const char *name);
extern ofw_tree_node_t *ofw_tree_find_child_by_device_type(ofw_tree_node_t *node, const char *device_type);
extern ofw_tree_node_t *ofw_tree_find_peer_by_device_type(ofw_tree_node_t *node, const char *device_type);
extern ofw_tree_node_t *ofw_tree_find_node_by_handle(ofw_tree_node_t *root, uint32_t handle);
extern const char *ofw_tree_node_name(const ofw_tree_node_t *);
extern ofw_tree_node_t *ofw_tree_lookup(const char *);
extern ofw_tree_property_t *ofw_tree_getprop(const ofw_tree_node_t *,
const char *);
extern ofw_tree_node_t *ofw_tree_find_child(ofw_tree_node_t *, const char *);
extern ofw_tree_node_t *ofw_tree_find_child_by_device_type(ofw_tree_node_t *,
const char *);
extern ofw_tree_node_t *ofw_tree_find_peer_by_device_type(ofw_tree_node_t *,
const char *);
extern ofw_tree_node_t *ofw_tree_find_peer_by_name(ofw_tree_node_t *node,
const char *name);
extern ofw_tree_node_t *ofw_tree_find_node_by_handle(ofw_tree_node_t *,
uint32_t);
 
extern bool ofw_fhc_apply_ranges(ofw_tree_node_t *node, ofw_fhc_reg_t *reg, uintptr_t *pa);
extern bool ofw_central_apply_ranges(ofw_tree_node_t *node, ofw_central_reg_t *reg, uintptr_t *pa);
extern bool ofw_ebus_apply_ranges(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uintptr_t *pa);
extern bool ofw_pci_apply_ranges(ofw_tree_node_t *node, ofw_pci_reg_t *reg, uintptr_t *pa);
extern bool ofw_sbus_apply_ranges(ofw_tree_node_t *node, ofw_sbus_reg_t *reg, uintptr_t *pa);
extern bool ofw_upa_apply_ranges(ofw_tree_node_t *node, ofw_upa_reg_t *reg, uintptr_t *pa);
extern bool ofw_fhc_apply_ranges(ofw_tree_node_t *, ofw_fhc_reg_t *,
uintptr_t *);
extern bool ofw_central_apply_ranges(ofw_tree_node_t *, ofw_central_reg_t *,
uintptr_t *);
extern bool ofw_ebus_apply_ranges(ofw_tree_node_t *, ofw_ebus_reg_t *,
uintptr_t *);
extern bool ofw_pci_apply_ranges(ofw_tree_node_t *, ofw_pci_reg_t *,
uintptr_t *);
extern bool ofw_sbus_apply_ranges(ofw_tree_node_t *, ofw_sbus_reg_t *,
uintptr_t *);
extern bool ofw_upa_apply_ranges(ofw_tree_node_t *, ofw_upa_reg_t *,
uintptr_t *);
 
extern bool ofw_pci_reg_absolutize(ofw_tree_node_t *node, ofw_pci_reg_t *reg, ofw_pci_reg_t *out);
extern bool ofw_pci_reg_absolutize(ofw_tree_node_t *, ofw_pci_reg_t *,
ofw_pci_reg_t *);
 
extern bool ofw_fhc_map_interrupt(ofw_tree_node_t *node, ofw_fhc_reg_t *reg, uint32_t interrupt, int *inr);
extern bool ofw_ebus_map_interrupt(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uint32_t interrupt, int *inr);
extern bool ofw_pci_map_interrupt(ofw_tree_node_t *node, ofw_pci_reg_t *reg, int ino, int *inr);
extern bool ofw_fhc_map_interrupt(ofw_tree_node_t *, ofw_fhc_reg_t *,
uint32_t, int *, cir_t *, void **);
extern bool ofw_ebus_map_interrupt(ofw_tree_node_t *, ofw_ebus_reg_t *,
uint32_t, int *, cir_t *, void **);
extern bool ofw_pci_map_interrupt(ofw_tree_node_t *, ofw_pci_reg_t *,
int, int *, cir_t *, void **);
 
#endif
/branches/tracing/kernel/genarch/src/kbd/ns16550.c
38,8 → 38,8
#include <genarch/kbd/key.h>
#include <genarch/kbd/scanc.h>
#include <genarch/kbd/scanc_sun.h>
#include <arch/drivers/kbd.h>
#ifndef ia64
#include <arch/drivers/kbd.h>
#include <arch/drivers/ns16550.h>
#endif
#include <ddi/irq.h>
107,11 → 107,14
 
/** Initialize ns16550.
*
* @param devno Device number.
* @param inr Interrupt number.
* @param vaddr Virtual address of device's registers.
* @param devno Device number.
* @param port Virtual/IO address of device's registers.
* @param inr Interrupt number.
* @param cir Clear interrupt function.
* @param cir_arg First argument to cir.
*/
void ns16550_init(devno_t devno, inr_t inr, ioport_t port)
void
ns16550_init(devno_t devno, ioport_t port, inr_t inr, cir_t cir, void *cir_arg)
{
chardev_initialize("ns16550_kbd", &kbrd, &ops);
stdin = &kbrd;
124,18 → 127,31
ns16550_irq.inr = inr;
ns16550_irq.claim = ns16550_claim;
ns16550_irq.handler = ns16550_irq_handler;
ns16550_irq.cir = cir;
ns16550_irq.cir_arg = cir_arg;
irq_register(&ns16550_irq);
 
 
while ((ns16550_lsr_read(&ns16550) & LSR_DATA_READY))
ns16550_rbr_read(&ns16550);
 
sysinfo_set_item_val("kbd", NULL, true);
#ifndef ia64
sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550);
#endif
sysinfo_set_item_val("kbd.devno", NULL, devno);
sysinfo_set_item_val("kbd.inr", NULL, inr);
sysinfo_set_item_val("kbd.address.virtual", NULL, port);
sysinfo_set_item_val("kbd.port", NULL, port);
 
#ifdef CONFIG_NS16550_INTERRUPT_DRIVEN
/* Enable interrupts */
ns16550_ier_write(&ns16550, IER_ERBFI);
ns16550_mcr_write(&ns16550, MCR_OUT2);
#endif
 
#ifdef ia64
uint8_t c;
// This switches rbr & ier to mode when accept baudrate constant
c = ns16550_lcr_read(&ns16550);
ns16550_lcr_write(&ns16550, 0x80 | c);
ns16550_rbr_write(&ns16550, 0x0c);
149,10 → 165,7
/** Process ns16550 interrupt. */
void ns16550_interrupt(void)
{
/* TODO
*
* ns16550 works in the polled mode so far.
*/
ns16550_poll();
}
 
/* Called from getc(). */
201,6 → 214,7
*/
void ns16550_poll(void)
{
#ifndef CONFIG_NS16550_INTERRUPT_DRIVEN
ipl_t ipl;
 
ipl = interrupts_disable();
220,6 → 234,7
 
spinlock_unlock(&ns16550_irq.lock);
interrupts_restore(ipl);
#endif
 
while (ns16550_lsr_read(&ns16550) & LSR_DATA_READY) {
uint8_t x;
251,7 → 266,10
 
void ns16550_irq_handler(irq_t *irq, void *arg, ...)
{
panic("Not yet implemented, ns16550 works in polled mode.\n");
if (irq->notif_cfg.notify && irq->notif_cfg.answerbox)
ipc_irq_send_notif(irq);
else
ns16550_interrupt();
}
 
/** @}
/branches/tracing/kernel/genarch/src/kbd/i8042.c
37,6 → 37,9
*/
 
#include <genarch/kbd/i8042.h>
#ifdef ia64
#include <arch/drivers/kbd.h>
#endif
#include <genarch/kbd/key.h>
#include <genarch/kbd/scanc.h>
#include <genarch/kbd/scanc_pc.h>
184,7 → 187,9
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.devno", NULL, kbd_devno);
sysinfo_set_item_val("kbd.inr", NULL, kbd_inr);
#ifdef KBD_LEGACY
sysinfo_set_item_val("kbd.type", NULL, KBD_LEGACY);
#endif
sysinfo_set_item_val("mouse", NULL, true);
sysinfo_set_item_val("mouse.devno", NULL, mouse_devno);
sysinfo_set_item_val("mouse.inr", NULL, mouse_inr);
/branches/tracing/kernel/genarch/src/kbd/z8530.c
43,7 → 43,6
#include <ipc/irq.h>
#include <arch/interrupt.h>
#include <arch/drivers/kbd.h>
#include <arch/drivers/fhc.h>
#include <cpu.h>
#include <arch/asm.h>
#include <arch.h>
83,12 → 82,14
*/
z8530_write_a(&z8530, WR0, WR0_TX_IP_RST);
 
z8530_write_a(&z8530, WR1, WR1_IARCSC); /* interrupt on all characters */
/* interrupt on all characters */
z8530_write_a(&z8530, WR1, WR1_IARCSC);
 
/* 8 bits per character and enable receiver */
z8530_write_a(&z8530, WR3, WR3_RX8BITSCH | WR3_RX_ENABLE);
z8530_write_a(&z8530, WR9, WR9_MIE); /* Master Interrupt Enable. */
/* Master Interrupt Enable. */
z8530_write_a(&z8530, WR9, WR9_MIE);
spinlock_lock(&z8530_irq.lock);
z8530_irq.notif_cfg.notify = false;
108,7 → 109,8
}
 
/** Initialize z8530. */
void z8530_init(devno_t devno, inr_t inr, uintptr_t vaddr)
void
z8530_init(devno_t devno, uintptr_t vaddr, inr_t inr, cir_t cir, void *cir_arg)
{
chardev_initialize("z8530_kbd", &kbrd, &ops);
stdin = &kbrd;
121,6 → 123,8
z8530_irq.inr = inr;
z8530_irq.claim = z8530_claim;
z8530_irq.handler = z8530_irq_handler;
z8530_irq.cir = cir;
z8530_irq.cir_arg = cir_arg;
irq_register(&z8530_irq);
 
sysinfo_set_item_val("kbd", NULL, true);
197,18 → 201,10
 
void z8530_irq_handler(irq_t *irq, void *arg, ...)
{
/*
* So far, we know we got this interrupt through the FHC.
* Since we don't have enough documentation about the FHC
* and because the interrupt looks like level sensitive,
* we cannot handle it by scheduling one of the level
* interrupt traps. Process the interrupt directly.
*/
if (irq->notif_cfg.notify && irq->notif_cfg.answerbox)
ipc_irq_send_notif(irq);
else
z8530_interrupt();
fhc_clear_interrupt(central_fhc, irq->inr);
}
 
/** @}
/branches/tracing/kernel/genarch/src/fb/fb.c
191,6 → 191,26
BLUE(rgb, 3);
}
 
static void sb1500rgb_byte8(void *dst, int rgb)
{
if (RED(rgb, 1) && GREEN(rgb, 1) && BLUE(rgb, 1))
*((uint8_t *) dst) = 255;
else if (RED(rgb, 1) && GREEN(rgb, 1))
*((uint8_t *) dst) = 150;
else if (GREEN(rgb, 1) && BLUE(rgb, 1))
*((uint8_t *) dst) = 47;
else if (RED(rgb, 1) && BLUE(rgb, 1))
*((uint8_t *) dst) = 48;
else if (RED(rgb, 1))
*((uint8_t *) dst) = 32;
else if (GREEN(rgb, 1))
*((uint8_t *) dst) = 47;
else if (BLUE(rgb, 1))
*((uint8_t *) dst) = 2;
else
*((uint8_t *) dst) = 1;
}
 
/** Return pixel color - 8-bit depth (color palette/3:2:3)
*
* See the comment for rgb_byte().
436,22 → 456,21
 
/** Initialize framebuffer as a chardev output device
*
* @param addr Physical address of the framebuffer
* @param x Screen width in pixels
* @param y Screen height in pixels
* @param scan Bytes per one scanline
* @param visual Color model
*
* @param props Properties of the framebuffer device.
*/
void fb_init(uintptr_t addr, unsigned int x, unsigned int y, unsigned int scan,
unsigned int visual)
void fb_init(fb_properties_t *props)
{
switch (visual) {
switch (props->visual) {
case VISUAL_INDIRECT_8:
rgb2scr = rgb_byte8;
scr2rgb = byte8_rgb;
pixelbytes = 1;
break;
case VISUAL_SB1500_PALETTE:
rgb2scr = sb1500rgb_byte8;
scr2rgb = byte8_rgb;
pixelbytes = 1;
break;
case VISUAL_RGB_5_5_5:
rgb2scr = rgb_byte555;
scr2rgb = byte555_rgb;
486,19 → 505,20
panic("Unsupported visual.\n");
}
unsigned int fbsize = scan * y;
unsigned int fbsize = props->scan * props->y + props->offset;
/* Map the framebuffer */
fbaddress = (uint8_t *) hw_map((uintptr_t) addr, fbsize);
fbaddress = (uint8_t *) hw_map((uintptr_t) props->addr, fbsize);
fbaddress += props->offset;
xres = x;
yres = y;
scanline = scan;
xres = props->x;
yres = props->y;
scanline = props->scan;
rows = y / FONT_SCANLINES;
columns = x / COL_WIDTH;
rows = props->y / FONT_SCANLINES;
columns = props->x / COL_WIDTH;
 
fb_parea.pbase = (uintptr_t) addr;
fb_parea.pbase = (uintptr_t) props->addr;
fb_parea.vbase = (uintptr_t) fbaddress;
fb_parea.frames = SIZE2FRAMES(fbsize);
fb_parea.cacheable = false;
508,9 → 528,9
sysinfo_set_item_val("fb.kind", NULL, 1);
sysinfo_set_item_val("fb.width", NULL, xres);
sysinfo_set_item_val("fb.height", NULL, yres);
sysinfo_set_item_val("fb.scanline", NULL, scan);
sysinfo_set_item_val("fb.visual", NULL, visual);
sysinfo_set_item_val("fb.address.physical", NULL, addr);
sysinfo_set_item_val("fb.scanline", NULL, props->scan);
sysinfo_set_item_val("fb.visual", NULL, props->visual);
sysinfo_set_item_val("fb.address.physical", NULL, props->addr);
sysinfo_set_item_val("fb.invert-colors", NULL, invert_colors);
 
/* Allocate double buffer */
524,6 → 544,7
blankline = (uint8_t *) malloc(ROW_BYTES, FRAME_ATOMIC);
if (!blankline)
panic("Failed to allocate blank line for framebuffer.");
unsigned int x, y;
for (y = 0; y < FONT_SCANLINES; y++)
for (x = 0; x < xres; x++)
(*rgb2scr)(&blankline[POINTPOS(x, y)], COLOR(BGCOLOR));
/branches/tracing/kernel/genarch/src/ofw/ebus.c
44,7 → 44,8
#include <macros.h>
 
/** Apply EBUS ranges to EBUS register. */
bool ofw_ebus_apply_ranges(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uintptr_t *pa)
bool
ofw_ebus_apply_ranges(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uintptr_t *pa)
{
ofw_tree_property_t *prop;
ofw_ebus_range_t *range;
62,11 → 63,13
for (i = 0; i < ranges; i++) {
if (reg->space != range[i].child_space)
continue;
if (overlaps(reg->addr, reg->size, range[i].child_base, range[i].size)) {
if (overlaps(reg->addr, reg->size, range[i].child_base,
range[i].size)) {
ofw_pci_reg_t pci_reg;
pci_reg.space = range[i].parent_space;
pci_reg.addr = range[i].parent_base + (reg->addr - range[i].child_base);
pci_reg.addr = range[i].parent_base +
(reg->addr - range[i].child_base);
pci_reg.size = reg->size;
return ofw_pci_apply_ranges(node->parent, &pci_reg, pa);
76,7 → 79,9
return false;
}
 
bool ofw_ebus_map_interrupt(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uint32_t interrupt, int *inr)
bool
ofw_ebus_map_interrupt(ofw_tree_node_t *node, ofw_ebus_reg_t *reg,
uint32_t interrupt, int *inr, cir_t *cir, void **cir_arg)
{
ofw_tree_property_t *prop;
ofw_tree_node_t *controller;
104,8 → 109,8
unsigned int i;
for (i = 0; i < count; i++) {
if ((intr_map[i].space == space) && (intr_map[i].addr == addr)
&& (intr_map[i].intr == intr))
if ((intr_map[i].space == space) &&
(intr_map[i].addr == addr) && (intr_map[i].intr == intr))
goto found;
}
return false;
113,10 → 118,12
found:
/*
* We found the device that functions as an interrupt controller
* for the interrupt. We also found partial mapping from interrupt to INO.
* for the interrupt. We also found partial mapping from interrupt to
* INO.
*/
 
controller = ofw_tree_find_node_by_handle(ofw_tree_lookup("/"), intr_map[i].controller_handle);
controller = ofw_tree_find_node_by_handle(ofw_tree_lookup("/"),
intr_map[i].controller_handle);
if (!controller)
return false;
130,7 → 137,8
/*
* Let the PCI do the next step in mapping the interrupt.
*/
if (!ofw_pci_map_interrupt(controller, NULL, intr_map[i].controller_ino, inr))
if (!ofw_pci_map_interrupt(controller, NULL, intr_map[i].controller_ino,
inr, cir, cir_arg))
return false;
 
return true;
/branches/tracing/kernel/genarch/src/ofw/fhc.c
109,7 → 109,9
return false;
}
 
bool ofw_fhc_map_interrupt(ofw_tree_node_t *node, ofw_fhc_reg_t *reg, uint32_t interrupt, int *inr)
bool
ofw_fhc_map_interrupt(ofw_tree_node_t *node, ofw_fhc_reg_t *reg,
uint32_t interrupt, int *inr, cir_t *cir, void **cir_arg)
{
fhc_t *fhc = NULL;
if (!node->device) {
126,6 → 128,8
fhc_enable_interrupt(fhc, interrupt);
*inr = interrupt;
*cir = fhc_clear_interrupt;
*cir_arg = fhc;
return true;
}
 
/branches/tracing/kernel/genarch/src/ofw/ofw_tree.c
54,12 → 54,14
 
/** Get OpenFirmware node property.
*
* @param node Node in which to lookup the property.
* @param name Name of the property.
* @param node Node in which to lookup the property.
* @param name Name of the property.
*
* @return Pointer to the property structure or NULL if no such property.
* @return Pointer to the property structure or NULL if no such
* property.
*/
ofw_tree_property_t *ofw_tree_getprop(const ofw_tree_node_t *node, const char *name)
ofw_tree_property_t *
ofw_tree_getprop(const ofw_tree_node_t *node, const char *name)
{
unsigned int i;
73,9 → 75,9
 
/** Return value of the 'name' property.
*
* @param node Node of interest.
* @param node Node of interest.
*
* @return Value of the 'name' property belonging to the node.
* @return Value of the 'name' property belonging to the node.
*/
const char *ofw_tree_node_name(const ofw_tree_node_t *node)
{
93,10 → 95,11
 
/** Lookup child of given name.
*
* @param node Node whose child is being looked up.
* @param name Name of the child being looked up.
* @param node Node whose child is being looked up.
* @param name Name of the child being looked up.
*
* @return NULL if there is no such child or pointer to the matching child node.
* @return NULL if there is no such child or pointer to the
* matching child node.
*/
ofw_tree_node_t *ofw_tree_find_child(ofw_tree_node_t *node, const char *name)
{
127,12 → 130,14
 
/** Lookup first child of given device type.
*
* @param node Node whose child is being looked up.
* @param name Device type of the child being looked up.
* @param node Node whose child is being looked up.
* @param name Device type of the child being looked up.
*
* @return NULL if there is no such child or pointer to the matching child node.
* @return NULL if there is no such child or pointer to the
* matching child node.
*/
ofw_tree_node_t *ofw_tree_find_child_by_device_type(ofw_tree_node_t *node, const char *name)
ofw_tree_node_t *
ofw_tree_find_child_by_device_type(ofw_tree_node_t *node, const char *name)
{
ofw_tree_node_t *cur;
ofw_tree_property_t *prop;
153,12 → 158,14
* Child nodes are looked up recursively contrary to peer nodes that
* are looked up iteratively to avoid stack overflow.
*
* @param root Root of the searched subtree.
* @param handle OpenFirmware handle.
* @param root Root of the searched subtree.
* @param handle OpenFirmware handle.
*
* @return NULL if there is no such node or pointer to the matching node.
* @return NULL if there is no such node or pointer to the matching
* node.
*/
ofw_tree_node_t *ofw_tree_find_node_by_handle(ofw_tree_node_t *root, uint32_t handle)
ofw_tree_node_t *
ofw_tree_find_node_by_handle(ofw_tree_node_t *root, uint32_t handle)
{
ofw_tree_node_t *cur;
 
180,12 → 187,14
 
/** Lookup first peer of given device type.
*
* @param node Node whose peer is being looked up.
* @param name Device type of the child being looked up.
* @param node Node whose peer is being looked up.
* @param name Device type of the child being looked up.
*
* @return NULL if there is no such child or pointer to the matching child node.
* @return NULL if there is no such child or pointer to the
* matching child node.
*/
ofw_tree_node_t *ofw_tree_find_peer_by_device_type(ofw_tree_node_t *node, const char *name)
ofw_tree_node_t *
ofw_tree_find_peer_by_device_type(ofw_tree_node_t *node, const char *name)
{
ofw_tree_node_t *cur;
ofw_tree_property_t *prop;
202,15 → 211,41
}
 
 
/** Lookup first peer of given name.
*
* @param node Node whose peer is being looked up.
* @param name Name of the child being looked up.
*
* @return NULL if there is no such peer or pointer to the matching
* peer node.
*/
ofw_tree_node_t *
ofw_tree_find_peer_by_name(ofw_tree_node_t *node, const char *name)
{
ofw_tree_node_t *cur;
ofw_tree_property_t *prop;
for (cur = node->peer; cur; cur = cur->peer) {
prop = ofw_tree_getprop(cur, "name");
if (!prop || !prop->value)
continue;
if (strcmp(prop->value, name) == 0)
return cur;
}
return NULL;
}
 
/** Lookup OpenFirmware node by its path.
*
* @param path Path to the node.
* @param path Path to the node.
*
* @return NULL if there is no such node or pointer to the leaf node.
* @return NULL if there is no such node or pointer to the leaf
* node.
*/
ofw_tree_node_t *ofw_tree_lookup(const char *path)
{
char buf[NAME_BUF_LEN+1];
char buf[NAME_BUF_LEN + 1];
ofw_tree_node_t *node = ofw_root;
index_t i, j;
236,8 → 271,8
* Child nodes are processed recursively and peer nodes are processed
* iteratively in order to avoid stack overflow.
*
* @param node Root of the subtree.
* @param path Current path, NULL for the very root of the entire tree.
* @param node Root of the subtree.
* @param path Current path, NULL for the very root of the entire tree.
*/
static void ofw_tree_node_print(const ofw_tree_node_t *node, const char *path)
{
/branches/tracing/kernel/genarch/src/ofw/pci.c
49,7 → 49,8
 
#define PCI_IGN 0x1f
 
bool ofw_pci_apply_ranges(ofw_tree_node_t *node, ofw_pci_reg_t *reg, uintptr_t *pa)
bool
ofw_pci_apply_ranges(ofw_tree_node_t *node, ofw_pci_reg_t *reg, uintptr_t *pa)
{
ofw_tree_property_t *prop;
ofw_pci_range_t *range;
68,10 → 69,13
unsigned int i;
for (i = 0; i < ranges; i++) {
if ((reg->space & PCI_SPACE_MASK) != (range[i].space & PCI_SPACE_MASK))
if ((reg->space & PCI_SPACE_MASK) !=
(range[i].space & PCI_SPACE_MASK))
continue;
if (overlaps(reg->addr, reg->size, range[i].child_base, range[i].size)) {
*pa = range[i].parent_base + (reg->addr - range[i].child_base);
if (overlaps(reg->addr, reg->size, range[i].child_base,
range[i].size)) {
*pa = range[i].parent_base +
(reg->addr - range[i].child_base);
return true;
}
}
79,7 → 83,9
return false;
}
 
bool ofw_pci_reg_absolutize(ofw_tree_node_t *node, ofw_pci_reg_t *reg, ofw_pci_reg_t *out)
bool
ofw_pci_reg_absolutize(ofw_tree_node_t *node, ofw_pci_reg_t *reg,
ofw_pci_reg_t *out)
{
if (reg->space & PCI_ABS_MASK) {
/* already absolute */
103,7 → 109,8
unsigned int i;
for (i = 0; i < assigned_addresses; i++) {
if ((assigned_address[i].space & PCI_REG_MASK) == (reg->space & PCI_REG_MASK)) {
if ((assigned_address[i].space & PCI_REG_MASK) ==
(reg->space & PCI_REG_MASK)) {
out->space = assigned_address[i].space;
out->addr = reg->addr + assigned_address[i].addr;
out->size = reg->size;
119,7 → 126,9
* So far, we only know how to map interrupts of non-PCI devices connected
* to a PCI bridge.
*/
bool ofw_pci_map_interrupt(ofw_tree_node_t *node, ofw_pci_reg_t *reg, int ino, int *inr)
bool
ofw_pci_map_interrupt(ofw_tree_node_t *node, ofw_pci_reg_t *reg, int ino,
int *inr, cir_t *cir, void **cir_arg)
{
pci_t *pci = node->device;
if (!pci) {
132,6 → 141,8
pci_enable_interrupt(pci, ino);
 
*inr = (PCI_IGN << IGN_SHIFT) | ino;
*cir = pci_clear_interrupt;
*cir_arg = pci;
 
return true;
}
/branches/tracing/kernel/generic/include/byteorder.h
51,6 → 51,14
#define uint32_t_be2host(n) (n)
#define uint64_t_be2host(n) (n)
 
#define host2uint16_t_le(n) uint16_t_byteorder_swap(n)
#define host2uint32_t_le(n) uint32_t_byteorder_swap(n)
#define host2uint64_t_le(n) uint64_t_byteorder_swap(n)
 
#define host2uint16_t_be(n) (n)
#define host2uint32_t_be(n) (n)
#define host2uint64_t_be(n) (n)
 
#else
 
#define uint16_t_le2host(n) (n)
61,6 → 69,14
#define uint32_t_be2host(n) uint32_t_byteorder_swap(n)
#define uint64_t_be2host(n) uint64_t_byteorder_swap(n)
 
#define host2uint16_t_le(n) (n)
#define host2uint32_t_le(n) (n)
#define host2uint64_t_le(n) (n)
 
#define host2uint16_t_be(n) uint16_t_byteorder_swap(n)
#define host2uint32_t_be(n) uint32_t_byteorder_swap(n)
#define host2uint64_t_be(n) uint64_t_byteorder_swap(n)
 
#endif
 
static inline uint64_t uint64_t_byteorder_swap(uint64_t n)
/branches/tracing/kernel/generic/include/ddi/irq.h
83,6 → 83,9
struct irq;
typedef void (* irq_handler_t)(struct irq *irq, void *arg, ...);
 
/** Type for function used to clear the interrupt. */
typedef void (* cir_t)(void *arg, inr_t inr);
 
/** IPC notification config structure.
*
* Primarily, this structure is encapsulated in the irq_t structure.
144,6 → 147,11
/** Argument for the handler. */
void *arg;
 
/** Clear interrupt routine. */
cir_t cir;
/** First argument to the clear interrupt routine. */
void *cir_arg;
 
/** Notification configuration structure. */
ipc_notif_cfg_t notif_cfg;
} irq_t;
/branches/tracing/kernel/generic/include/adt/bitmap.h
49,6 → 49,14
extern void bitmap_clear_range(bitmap_t *bitmap, index_t start, count_t bits);
extern void bitmap_copy(bitmap_t *dst, bitmap_t *src, count_t bits);
 
static inline int bitmap_get(bitmap_t *bitmap,index_t bit)
{
if(bit >= bitmap->bits)
return 0;
return !! ((bitmap->map)[bit/8] & (1 << (bit & 7)));
}
 
 
#endif
 
/** @}
/branches/tracing/kernel/generic/src/ddi/irq.c
145,6 → 145,8
irq->claim = NULL;
irq->handler = NULL;
irq->arg = NULL;
irq->cir = NULL;
irq->cir_arg = NULL;
irq->notif_cfg.notify = false;
irq->notif_cfg.answerbox = NULL;
irq->notif_cfg.code = NULL;
/branches/tracing/kernel/generic/src/mm/tlb.c
134,9 → 134,7
 
void tlb_shootdown_ipi_send(void)
{
#ifndef ia64
ipi_broadcast(VECTOR_TLB_SHOOTDOWN_IPI);
#endif
}
 
/** Receive TLB shootdown message. */
/branches/tracing/kernel/generic/src/ipc/irq.c
100,7 → 100,7
*((uint64_t *) code->cmds[i].addr) =
code->cmds[i].value;
break;
#if defined(ia32) || defined(amd64)
#if defined(ia32) || defined(amd64) || defined(ia64)
case CMD_PORT_READ_1:
dstval = inb((long) code->cmds[i].addr);
break;
/branches/tracing/kernel/Makefile
126,6 → 126,18
DEFS += -DCONFIG_NS16550
endif
 
ifeq ($(CONFIG_I8042_INTERRUPT_DRIVEN),y)
DEFS += -DCONFIG_I8042_INTERRUPT_DRIVEN
endif
 
ifeq ($(CONFIG_NS16550_INTERRUPT_DRIVEN),y)
DEFS += -DCONFIG_NS16550_INTERRUPT_DRIVEN
endif
 
ifeq ($(CONFIG_IOSAPIC),y)
DEFS += -DCONFIG_IOSAPIC
endif
 
ifeq ($(CONFIG_VIRT_IDX_DCACHE),y)
DEFS += -DCONFIG_VIRT_IDX_DCACHE
endif
/branches/tracing/kernel/arch/sparc64/include/regdef.h
55,8 → 55,11
#define WSTATE_NORMAL(n) (n)
#define WSTATE_OTHER(n) ((n) << 3)
 
#define UPA_CONFIG_MID_SHIFT 17
#define UPA_CONFIG_MID_MASK 0x1f
/*
* The following definitions concern the UPA_CONFIG register on US and the
* FIREPLANE_CONFIG register on US3.
*/
#define ICBUS_CONFIG_MID_SHIFT 17
 
#endif
 
/branches/tracing/kernel/arch/sparc64/include/cpu_node.h
0,0 → 1,58
/*
* Copyright (c) 2005 Pavel Rimsky
* 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 sparc64
* @{
*/
/** @file
*/
 
#ifndef KERN_sparc64_CPU_NODE_H_
#define KERN_sparc64_CPU_NODE_H_
 
#include <genarch/ofw/ofw_tree.h>
 
 
/** Finds the parent node of all the CPU nodes (nodes named "cpu" or "cmp").
*
* Depending on the machine type (and possibly the OFW version), CPUs can be
* at "/" or at "/ssm@0,0".
*/
static inline ofw_tree_node_t *cpus_parent(void)
{
ofw_tree_node_t *parent;
parent = ofw_tree_find_child(ofw_tree_lookup("/"), "ssm@0,0");
if (parent == NULL)
parent = ofw_tree_lookup("/");
return parent;
}
 
#endif
 
/** @}
*/
/branches/tracing/kernel/arch/sparc64/include/arch.h
41,7 → 41,7
#define ASI_AIUS 0x11 /** Access to secondary context with user privileges. */
#define ASI_NUCLEUS_QUAD_LDD 0x24 /** ASI for 16-byte atomic loads. */
#define ASI_DCACHE_TAG 0x47 /** ASI D-Cache Tag. */
#define ASI_UPA_CONFIG 0x4a /** ASI of the UPA_CONFIG register. */
#define ASI_ICBUS_CONFIG 0x4a /** ASI of the UPA_CONFIG/FIREPLANE_CONFIG register. */
 
#define NWINDOWS 8 /** Number of register window sets. */
 
/branches/tracing/kernel/arch/sparc64/include/asm.h
136,6 → 136,28
asm volatile ("wr %0, %1, %%tick_cmpr\n" : : "r" (v), "i" (0));
}
 
/** Read STICK_compare Register.
*
* @return Value of STICK_compare register.
*/
static inline uint64_t stick_compare_read(void)
{
uint64_t v;
asm volatile ("rd %%asr25, %0\n" : "=r" (v));
return v;
}
 
/** Write STICK_compare Register.
*
* @param v New value of STICK_comapre register.
*/
static inline void stick_compare_write(uint64_t v)
{
asm volatile ("wr %0, %1, %%asr25\n" : : "r" (v), "i" (0));
}
 
/** Read TICK Register.
*
* @return Value of TICK register.
407,15 → 429,6
asm volatile ("wrpr %g0, %g0, %tl\n");
}
 
/** Read UPA_CONFIG register.
*
* @return Value of the UPA_CONFIG register.
*/
static inline uint64_t upa_config_read(void)
{
return asi_u64_read(ASI_UPA_CONFIG, 0);
}
 
extern void cpu_halt(void);
extern void cpu_sleep(void);
extern void asm_delay_loop(const uint32_t usec);
/branches/tracing/kernel/arch/sparc64/include/trap/interrupt.h
49,21 → 49,43
 
 
/* Interrupt ASI registers. */
#define ASI_UDB_INTR_W 0x77
#define ASI_INTR_W 0x77
#define ASI_INTR_DISPATCH_STATUS 0x48
#define ASI_UDB_INTR_R 0x7f
#define ASI_INTR_R 0x7f
#define ASI_INTR_RECEIVE 0x49
 
/* VA's used with ASI_UDB_INTR_W register. */
/* VA's used with ASI_INTR_W register. */
#if defined (US)
#define ASI_UDB_INTR_W_DATA_0 0x40
#define ASI_UDB_INTR_W_DATA_1 0x50
#define ASI_UDB_INTR_W_DATA_2 0x60
#define ASI_UDB_INTR_W_DISPATCH 0x70
#elif defined (US3)
#define VA_INTR_W_DATA_0 0x40
#define VA_INTR_W_DATA_1 0x48
#define VA_INTR_W_DATA_2 0x50
#define VA_INTR_W_DATA_3 0x58
#define VA_INTR_W_DATA_4 0x60
#define VA_INTR_W_DATA_5 0x68
#define VA_INTR_W_DATA_6 0x80
#define VA_INTR_W_DATA_7 0x88
#endif
#define VA_INTR_W_DISPATCH 0x70
 
/* VA's used with ASI_UDB_INTR_R register. */
/* VA's used with ASI_INTR_R register. */
#if defined(US)
#define ASI_UDB_INTR_R_DATA_0 0x40
#define ASI_UDB_INTR_R_DATA_1 0x50
#define ASI_UDB_INTR_R_DATA_2 0x60
#elif defined (US3)
#define VA_INTR_R_DATA_0 0x40
#define VA_INTR_R_DATA_1 0x48
#define VA_INTR_R_DATA_2 0x50
#define VA_INTR_R_DATA_3 0x58
#define VA_INTR_R_DATA_4 0x60
#define VA_INTR_R_DATA_5 0x68
#define VA_INTR_R_DATA_6 0x80
#define VA_INTR_R_DATA_7 0x88
#endif
 
/* Shifts in the Interrupt Vector Dispatch virtual address. */
#define INTR_VEC_DISPATCH_MID_SHIFT 14
/branches/tracing/kernel/arch/sparc64/include/mm/frame.h
59,8 → 59,13
union frame_address {
uintptr_t address;
struct {
#if defined (US)
unsigned : 23;
uint64_t pfn : 28; /**< Physical Frame Number. */
#elif defined (US3)
unsigned : 21;
uint64_t pfn : 30; /**< Physical Frame Number. */
#endif
unsigned offset : 13; /**< Offset. */
} __attribute__ ((packed));
};
/branches/tracing/kernel/arch/sparc64/include/mm/tte.h
50,6 → 50,7
 
#include <arch/types.h>
 
/* TTE tag's VA_tag field contains bits <63:VA_TAG_PAGE_SHIFT> of the VA */
#define VA_TAG_PAGE_SHIFT 22
 
/** Translation Table Entry - Tag. */
75,8 → 76,13
unsigned nfo : 1; /**< No-Fault-Only. */
unsigned ie : 1; /**< Invert Endianness. */
unsigned soft2 : 9; /**< Software defined field. */
#if defined (US)
unsigned diag : 9; /**< Diagnostic data. */
unsigned pfn : 28; /**< Physical Address bits, bits 40:13. */
#elif defined (US3)
unsigned : 7; /**< Reserved. */
unsigned pfn : 30; /**< Physical Address bits, bits 42:13 */
#endif
unsigned soft : 6; /**< Software defined field. */
unsigned l : 1; /**< Lock. */
unsigned cp : 1; /**< Cacheable in physically indexed cache. */
/branches/tracing/kernel/arch/sparc64/include/mm/cache_spec.h
38,19 → 38,20
/*
* The following macros are valid for the following processors:
*
* UltraSPARC, UltraSPARC II, UltraSPARC IIi
* UltraSPARC, UltraSPARC II, UltraSPARC IIi, UltraSPARC III,
* UltraSPARC III+, UltraSPARC IV, UltraSPARC IV+
*
* Should we support other UltraSPARC processors, we need to make sure that
* the macros are defined correctly for them.
*/
 
#if defined (US)
#define DCACHE_SIZE (16 * 1024)
#elif defined (US3)
#define DCACHE_SIZE (64 * 1024)
#endif
#define DCACHE_LINE_SIZE 32
 
#define ICACHE_SIZE (16 * 1024)
#define ICACHE_WAYS 2
#define ICACHE_LINE_SIZE 32
 
#endif
 
/** @}
/branches/tracing/kernel/arch/sparc64/include/mm/mmu.h
35,8 → 35,10
#ifndef KERN_sparc64_MMU_H_
#define KERN_sparc64_MMU_H_
 
#if defined(US)
/* LSU Control Register ASI. */
#define ASI_LSU_CONTROL_REG 0x45 /**< Load/Store Unit Control Register. */
#endif
 
/* I-MMU ASIs. */
#define ASI_IMMU 0x50
52,7 → 54,12
#define VA_IMMU_SFSR 0x18 /**< IMMU sync fault status register. */
#define VA_IMMU_TSB_BASE 0x28 /**< IMMU TSB base register. */
#define VA_IMMU_TAG_ACCESS 0x30 /**< IMMU TLB tag access register. */
#if defined (US3)
#define VA_IMMU_PRIMARY_EXTENSION 0x48 /**< IMMU TSB primary extension register */
#define VA_IMMU_NUCLEUS_EXTENSION 0x58 /**< IMMU TSB nucleus extension register */
#endif
 
 
/* D-MMU ASIs. */
#define ASI_DMMU 0x58
#define ASI_DMMU_TSB_8KB_PTR_REG 0x59
73,6 → 80,11
#define VA_DMMU_TAG_ACCESS 0x30 /**< DMMU TLB tag access register. */
#define VA_DMMU_VA_WATCHPOINT_REG 0x38 /**< DMMU VA data watchpoint register. */
#define VA_DMMU_PA_WATCHPOINT_REG 0x40 /**< DMMU PA data watchpoint register. */
#if defined (US3)
#define VA_DMMU_PRIMARY_EXTENSION 0x48 /**< DMMU TSB primary extension register */
#define VA_DMMU_SECONDARY_EXTENSION 0x50 /**< DMMU TSB secondary extension register */
#define VA_DMMU_NUCLEUS_EXTENSION 0x58 /**< DMMU TSB nucleus extension register */
#endif
 
#ifndef __ASM__
 
80,6 → 92,7
#include <arch/barrier.h>
#include <arch/types.h>
 
#if defined(US)
/** LSU Control Register. */
typedef union {
uint64_t value;
100,6 → 113,7
} __attribute__ ((packed));
} lsu_cr_reg_t;
#endif /* US */
 
#endif /* !def __ASM__ */
 
/branches/tracing/kernel/arch/sparc64/include/mm/tlb.h
35,9 → 35,17
#ifndef KERN_sparc64_TLB_H_
#define KERN_sparc64_TLB_H_
 
#if defined (US)
#define ITLB_ENTRY_COUNT 64
#define DTLB_ENTRY_COUNT 64
#define DTLB_MAX_LOCKED_ENTRIES DTLB_ENTRY_COUNT
#endif
 
/** TLB_DSMALL is the only of the three DMMUs that can hold locked entries. */
#if defined (US3)
#define DTLB_MAX_LOCKED_ENTRIES 16
#endif
 
#define MEM_CONTEXT_KERNEL 0
#define MEM_CONTEXT_TEMP 1
 
53,6 → 61,9
/* TLB Demap Operation types. */
#define TLB_DEMAP_PAGE 0
#define TLB_DEMAP_CONTEXT 1
#if defined (US3)
#define TLB_DEMAP_ALL 2
#endif
 
#define TLB_DEMAP_TYPE_SHIFT 6
 
61,6 → 72,18
#define TLB_DEMAP_SECONDARY 1
#define TLB_DEMAP_NUCLEUS 2
 
/* There are more TLBs in one MMU in US3, their codes are defined here. */
#if defined (US3)
/* D-MMU: one small (16-entry) TLB and two big (512-entry) TLBs */
#define TLB_DSMALL 0
#define TLB_DBIG_0 2
#define TLB_DBIG_1 3
/* I-MMU: one small (16-entry) TLB and one big TLB */
#define TLB_ISMALL 0
#define TLB_IBIG 2
#endif
 
#define TLB_DEMAP_CONTEXT_SHIFT 4
 
/* TLB Tag Access shifts */
76,6 → 99,8
#include <arch/asm.h>
#include <arch/barrier.h>
#include <arch/types.h>
#include <arch/register.h>
#include <arch/cpu.h>
 
union tlb_context_reg {
uint64_t v;
90,6 → 115,9
typedef tte_data_t tlb_data_t;
 
/** I-/D-TLB Data Access Address in Alternate Space. */
 
#if defined (US)
 
union tlb_data_access_addr {
uint64_t value;
struct {
98,9 → 126,54
unsigned : 3;
} __attribute__ ((packed));
};
typedef union tlb_data_access_addr tlb_data_access_addr_t;
typedef union tlb_data_access_addr tlb_tag_read_addr_t;
typedef union tlb_data_access_addr dtlb_data_access_addr_t;
typedef union tlb_data_access_addr dtlb_tag_read_addr_t;
typedef union tlb_data_access_addr itlb_data_access_addr_t;
typedef union tlb_data_access_addr itlb_tag_read_addr_t;
 
#elif defined (US3)
 
/*
* In US3, I-MMU and D-MMU have different formats of the data
* access register virtual address. In the corresponding
* structures the member variable for the entry number is
* called "local_tlb_entry" - it contrasts with the "tlb_entry"
* for the US data access register VA structure. The rationale
* behind this is to prevent careless mistakes in the code
* caused by setting only the entry number and not the TLB
* number in the US3 code (when taking the code from US).
*/
 
union dtlb_data_access_addr {
uint64_t value;
struct {
uint64_t : 45;
unsigned : 1;
unsigned tlb_number : 2;
unsigned : 4;
unsigned local_tlb_entry : 9;
unsigned : 3;
} __attribute__ ((packed));
};
typedef union dtlb_data_access_addr dtlb_data_access_addr_t;
typedef union dtlb_data_access_addr dtlb_tag_read_addr_t;
 
union itlb_data_access_addr {
uint64_t value;
struct {
uint64_t : 45;
unsigned : 1;
unsigned tlb_number : 2;
unsigned : 6;
unsigned local_tlb_entry : 7;
unsigned : 3;
} __attribute__ ((packed));
};
typedef union itlb_data_access_addr itlb_data_access_addr_t;
typedef union itlb_data_access_addr itlb_tag_read_addr_t;
 
#endif
 
/** I-/D-TLB Tag Read Register. */
union tlb_tag_read_reg {
uint64_t value;
118,8 → 191,13
uint64_t value;
struct {
uint64_t vpn: 51; /**< Virtual Address bits 63:13. */
#if defined (US)
unsigned : 6; /**< Ignored. */
unsigned type : 1; /**< The type of demap operation. */
#elif defined (US3)
unsigned : 5; /**< Ignored. */
unsigned type: 2; /**< The type of demap operation. */
#endif
unsigned context : 2; /**< Context register selection. */
unsigned : 4; /**< Zero. */
} __attribute__ ((packed));
130,10 → 208,19
union tlb_sfsr_reg {
uint64_t value;
struct {
#if defined (US)
unsigned long : 40; /**< Implementation dependent. */
unsigned asi : 8; /**< ASI. */
unsigned : 2;
unsigned ft : 7; /**< Fault type. */
#elif defined (US3)
unsigned long : 39; /**< Implementation dependent. */
unsigned nf : 1; /**< Non-faulting load. */
unsigned asi : 8; /**< ASI. */
unsigned tm : 1; /**< I-TLB miss. */
unsigned : 3; /**< Reserved. */
unsigned ft : 5; /**< Fault type. */
#endif
unsigned e : 1; /**< Side-effect bit. */
unsigned ct : 2; /**< Context Register selection. */
unsigned pr : 1; /**< Privilege bit. */
144,9 → 231,53
};
typedef union tlb_sfsr_reg tlb_sfsr_reg_t;
 
#if defined (US3)
 
/*
* Functions for determining the number of entries in TLBs. They either return
* a constant value or a value based on the CPU autodetection.
*/
 
/**
* Determine the number of entries in the DMMU's small TLB.
*/
static inline uint16_t tlb_dsmall_size(void)
{
return 16;
}
 
/**
* Determine the number of entries in each DMMU's big TLB.
*/
static inline uint16_t tlb_dbig_size(void)
{
return 512;
}
 
/**
* Determine the number of entries in the IMMU's small TLB.
*/
static inline uint16_t tlb_ismall_size(void)
{
return 16;
}
 
/**
* Determine the number of entries in the IMMU's big TLB.
*/
static inline uint16_t tlb_ibig_size(void)
{
if (((ver_reg_t) ver_read()).impl == IMPL_ULTRASPARCIV_PLUS)
return 512;
else
return 128;
}
 
#endif
 
/** Read MMU Primary Context Register.
*
* @return Current value of Primary Context Register.
* @return Current value of Primary Context Register.
*/
static inline uint64_t mmu_primary_context_read(void)
{
155,7 → 286,7
 
/** Write MMU Primary Context Register.
*
* @param v New value of Primary Context Register.
* @param v New value of Primary Context Register.
*/
static inline void mmu_primary_context_write(uint64_t v)
{
165,7 → 296,7
 
/** Read MMU Secondary Context Register.
*
* @return Current value of Secondary Context Register.
* @return Current value of Secondary Context Register.
*/
static inline uint64_t mmu_secondary_context_read(void)
{
174,7 → 305,7
 
/** Write MMU Primary Context Register.
*
* @param v New value of Primary Context Register.
* @param v New value of Primary Context Register.
*/
static inline void mmu_secondary_context_write(uint64_t v)
{
182,15 → 313,18
flush_pipeline();
}
 
#if defined (US)
 
/** Read IMMU TLB Data Access Register.
*
* @param entry TLB Entry index.
* @param entry TLB Entry index.
*
* @return Current value of specified IMMU TLB Data Access Register.
* @return Current value of specified IMMU TLB Data Access
* Register.
*/
static inline uint64_t itlb_data_access_read(index_t entry)
{
tlb_data_access_addr_t reg;
itlb_data_access_addr_t reg;
reg.value = 0;
reg.tlb_entry = entry;
199,12 → 333,12
 
/** Write IMMU TLB Data Access Register.
*
* @param entry TLB Entry index.
* @param value Value to be written.
* @param entry TLB Entry index.
* @param value Value to be written.
*/
static inline void itlb_data_access_write(index_t entry, uint64_t value)
{
tlb_data_access_addr_t reg;
itlb_data_access_addr_t reg;
reg.value = 0;
reg.tlb_entry = entry;
214,13 → 348,14
 
/** Read DMMU TLB Data Access Register.
*
* @param entry TLB Entry index.
* @param entry TLB Entry index.
*
* @return Current value of specified DMMU TLB Data Access Register.
* @return Current value of specified DMMU TLB Data Access
* Register.
*/
static inline uint64_t dtlb_data_access_read(index_t entry)
{
tlb_data_access_addr_t reg;
dtlb_data_access_addr_t reg;
reg.value = 0;
reg.tlb_entry = entry;
229,12 → 364,12
 
/** Write DMMU TLB Data Access Register.
*
* @param entry TLB Entry index.
* @param value Value to be written.
* @param entry TLB Entry index.
* @param value Value to be written.
*/
static inline void dtlb_data_access_write(index_t entry, uint64_t value)
{
tlb_data_access_addr_t reg;
dtlb_data_access_addr_t reg;
reg.value = 0;
reg.tlb_entry = entry;
244,13 → 379,13
 
/** Read IMMU TLB Tag Read Register.
*
* @param entry TLB Entry index.
* @param entry TLB Entry index.
*
* @return Current value of specified IMMU TLB Tag Read Register.
* @return Current value of specified IMMU TLB Tag Read Register.
*/
static inline uint64_t itlb_tag_read_read(index_t entry)
{
tlb_tag_read_addr_t tag;
itlb_tag_read_addr_t tag;
 
tag.value = 0;
tag.tlb_entry = entry;
259,13 → 394,13
 
/** Read DMMU TLB Tag Read Register.
*
* @param entry TLB Entry index.
* @param entry TLB Entry index.
*
* @return Current value of specified DMMU TLB Tag Read Register.
* @return Current value of specified DMMU TLB Tag Read Register.
*/
static inline uint64_t dtlb_tag_read_read(index_t entry)
{
tlb_tag_read_addr_t tag;
dtlb_tag_read_addr_t tag;
 
tag.value = 0;
tag.tlb_entry = entry;
272,9 → 407,120
return asi_u64_read(ASI_DTLB_TAG_READ_REG, tag.value);
}
 
#elif defined (US3)
 
 
/** Read IMMU TLB Data Access Register.
*
* @param tlb TLB number (one of TLB_ISMALL or TLB_IBIG)
* @param entry TLB Entry index.
*
* @return Current value of specified IMMU TLB Data Access
* Register.
*/
static inline uint64_t itlb_data_access_read(int tlb, index_t entry)
{
itlb_data_access_addr_t reg;
reg.value = 0;
reg.tlb_number = tlb;
reg.local_tlb_entry = entry;
return asi_u64_read(ASI_ITLB_DATA_ACCESS_REG, reg.value);
}
 
/** Write IMMU TLB Data Access Register.
* @param tlb TLB number (one of TLB_ISMALL or TLB_IBIG)
* @param entry TLB Entry index.
* @param value Value to be written.
*/
static inline void itlb_data_access_write(int tlb, index_t entry,
uint64_t value)
{
itlb_data_access_addr_t reg;
reg.value = 0;
reg.tlb_number = tlb;
reg.local_tlb_entry = entry;
asi_u64_write(ASI_ITLB_DATA_ACCESS_REG, reg.value, value);
flush_pipeline();
}
 
/** Read DMMU TLB Data Access Register.
*
* @param tlb TLB number (one of TLB_DSMALL, TLB_DBIG, TLB_DBIG)
* @param entry TLB Entry index.
*
* @return Current value of specified DMMU TLB Data Access
* Register.
*/
static inline uint64_t dtlb_data_access_read(int tlb, index_t entry)
{
dtlb_data_access_addr_t reg;
reg.value = 0;
reg.tlb_number = tlb;
reg.local_tlb_entry = entry;
return asi_u64_read(ASI_DTLB_DATA_ACCESS_REG, reg.value);
}
 
/** Write DMMU TLB Data Access Register.
*
* @param tlb TLB number (one of TLB_DSMALL, TLB_DBIG_0, TLB_DBIG_1)
* @param entry TLB Entry index.
* @param value Value to be written.
*/
static inline void dtlb_data_access_write(int tlb, index_t entry,
uint64_t value)
{
dtlb_data_access_addr_t reg;
reg.value = 0;
reg.tlb_number = tlb;
reg.local_tlb_entry = entry;
asi_u64_write(ASI_DTLB_DATA_ACCESS_REG, reg.value, value);
membar();
}
 
/** Read IMMU TLB Tag Read Register.
*
* @param tlb TLB number (one of TLB_ISMALL or TLB_IBIG)
* @param entry TLB Entry index.
*
* @return Current value of specified IMMU TLB Tag Read Register.
*/
static inline uint64_t itlb_tag_read_read(int tlb, index_t entry)
{
itlb_tag_read_addr_t tag;
 
tag.value = 0;
tag.tlb_number = tlb;
tag.local_tlb_entry = entry;
return asi_u64_read(ASI_ITLB_TAG_READ_REG, tag.value);
}
 
/** Read DMMU TLB Tag Read Register.
*
* @param tlb TLB number (one of TLB_DSMALL, TLB_DBIG_0, TLB_DBIG_1)
* @param entry TLB Entry index.
*
* @return Current value of specified DMMU TLB Tag Read Register.
*/
static inline uint64_t dtlb_tag_read_read(int tlb, index_t entry)
{
dtlb_tag_read_addr_t tag;
 
tag.value = 0;
tag.tlb_number = tlb;
tag.local_tlb_entry = entry;
return asi_u64_read(ASI_DTLB_TAG_READ_REG, tag.value);
}
 
#endif
 
 
/** Write IMMU TLB Tag Access Register.
*
* @param v Value to be written.
* @param v Value to be written.
*/
static inline void itlb_tag_access_write(uint64_t v)
{
284,7 → 530,7
 
/** Read IMMU TLB Tag Access Register.
*
* @return Current value of IMMU TLB Tag Access Register.
* @return Current value of IMMU TLB Tag Access Register.
*/
static inline uint64_t itlb_tag_access_read(void)
{
293,7 → 539,7
 
/** Write DMMU TLB Tag Access Register.
*
* @param v Value to be written.
* @param v Value to be written.
*/
static inline void dtlb_tag_access_write(uint64_t v)
{
303,7 → 549,7
 
/** Read DMMU TLB Tag Access Register.
*
* @return Current value of DMMU TLB Tag Access Register.
* @return Current value of DMMU TLB Tag Access Register.
*/
static inline uint64_t dtlb_tag_access_read(void)
{
313,7 → 559,7
 
/** Write IMMU TLB Data in Register.
*
* @param v Value to be written.
* @param v Value to be written.
*/
static inline void itlb_data_in_write(uint64_t v)
{
323,7 → 569,7
 
/** Write DMMU TLB Data in Register.
*
* @param v Value to be written.
* @param v Value to be written.
*/
static inline void dtlb_data_in_write(uint64_t v)
{
333,7 → 579,7
 
/** Read ITLB Synchronous Fault Status Register.
*
* @return Current content of I-SFSR register.
* @return Current content of I-SFSR register.
*/
static inline uint64_t itlb_sfsr_read(void)
{
342,7 → 588,7
 
/** Write ITLB Synchronous Fault Status Register.
*
* @param v New value of I-SFSR register.
* @param v New value of I-SFSR register.
*/
static inline void itlb_sfsr_write(uint64_t v)
{
352,7 → 598,7
 
/** Read DTLB Synchronous Fault Status Register.
*
* @return Current content of D-SFSR register.
* @return Current content of D-SFSR register.
*/
static inline uint64_t dtlb_sfsr_read(void)
{
361,7 → 607,7
 
/** Write DTLB Synchronous Fault Status Register.
*
* @param v New value of D-SFSR register.
* @param v New value of D-SFSR register.
*/
static inline void dtlb_sfsr_write(uint64_t v)
{
371,7 → 617,7
 
/** Read DTLB Synchronous Fault Address Register.
*
* @return Current content of D-SFAR register.
* @return Current content of D-SFAR register.
*/
static inline uint64_t dtlb_sfar_read(void)
{
380,10 → 626,11
 
/** Perform IMMU TLB Demap Operation.
*
* @param type Selects between context and page demap.
* @param type Selects between context and page demap (and entire MMU
* demap on US3).
* @param context_encoding Specifies which Context register has Context ID for
* demap.
* @param page Address which is on the page to be demapped.
* demap.
* @param page Address which is on the page to be demapped.
*/
static inline void itlb_demap(int type, int context_encoding, uintptr_t page)
{
397,18 → 644,19
da.context = context_encoding;
da.vpn = pg.vpn;
asi_u64_write(ASI_IMMU_DEMAP, da.value, 0); /* da.value is the
* address within the
* ASI */
/* da.value is the address within the ASI */
asi_u64_write(ASI_IMMU_DEMAP, da.value, 0);
 
flush_pipeline();
}
 
/** Perform DMMU TLB Demap Operation.
*
* @param type Selects between context and page demap.
* @param type Selects between context and page demap (and entire MMU
* demap on US3).
* @param context_encoding Specifies which Context register has Context ID for
* demap.
* @param page Address which is on the page to be demapped.
* demap.
* @param page Address which is on the page to be demapped.
*/
static inline void dtlb_demap(int type, int context_encoding, uintptr_t page)
{
422,17 → 670,17
da.context = context_encoding;
da.vpn = pg.vpn;
asi_u64_write(ASI_DMMU_DEMAP, da.value, 0); /* da.value is the
* address within the
* ASI */
/* da.value is the address within the ASI */
asi_u64_write(ASI_DMMU_DEMAP, da.value, 0);
 
membar();
}
 
extern void fast_instruction_access_mmu_miss(unative_t unused, istate_t *istate);
extern void fast_data_access_mmu_miss(tlb_tag_access_reg_t tag, istate_t *istate);
extern void fast_data_access_protection(tlb_tag_access_reg_t tag , istate_t *istate);
extern void fast_instruction_access_mmu_miss(unative_t, istate_t *);
extern void fast_data_access_mmu_miss(tlb_tag_access_reg_t, istate_t *);
extern void fast_data_access_protection(tlb_tag_access_reg_t , istate_t *);
 
extern void dtlb_insert_mapping(uintptr_t page, uintptr_t frame, int pagesize, bool locked, bool cacheable);
extern void dtlb_insert_mapping(uintptr_t, uintptr_t, int, bool, bool);
 
extern void dump_sfsr_and_sfar(void);
 
/branches/tracing/kernel/arch/sparc64/include/mm/cache.h
38,15 → 38,6
#include <mm/page.h>
#include <mm/frame.h>
 
#define dcache_flush_page(p) \
dcache_flush_color(PAGE_COLOR((p)))
#define dcache_flush_frame(p, f) \
dcache_flush_tag(PAGE_COLOR((p)), ADDR2PFN((f)));
 
extern void dcache_flush(void);
extern void dcache_flush_color(int c);
extern void dcache_flush_tag(int c, pfn_t tag);
 
#endif
 
/** @}
/branches/tracing/kernel/arch/sparc64/include/mm/tsb.h
107,6 → 107,55
asi_u64_write(ASI_DMMU, VA_DMMU_TSB_BASE, v);
}
 
#if defined (US3)
 
/** Write DTSB Primary Extension register.
*
* @param v New content of the DTSB Primary Extension register.
*/
static inline void dtsb_primary_extension_write(uint64_t v)
{
asi_u64_write(ASI_DMMU, VA_DMMU_PRIMARY_EXTENSION, v);
}
 
/** Write DTSB Secondary Extension register.
*
* @param v New content of the DTSB Secondary Extension register.
*/
static inline void dtsb_secondary_extension_write(uint64_t v)
{
asi_u64_write(ASI_DMMU, VA_DMMU_SECONDARY_EXTENSION, v);
}
 
/** Write DTSB Nucleus Extension register.
*
* @param v New content of the DTSB Nucleus Extension register.
*/
static inline void dtsb_nucleus_extension_write(uint64_t v)
{
asi_u64_write(ASI_DMMU, VA_DMMU_NUCLEUS_EXTENSION, v);
}
 
/** Write ITSB Primary Extension register.
*
* @param v New content of the ITSB Primary Extension register.
*/
static inline void itsb_primary_extension_write(uint64_t v)
{
asi_u64_write(ASI_IMMU, VA_IMMU_PRIMARY_EXTENSION, v);
}
 
/** Write ITSB Nucleus Extension register.
*
* @param v New content of the ITSB Nucleus Extension register.
*/
static inline void itsb_nucleus_extension_write(uint64_t v)
{
asi_u64_write(ASI_IMMU, VA_IMMU_NUCLEUS_EXTENSION, v);
}
 
#endif
 
/* Forward declarations. */
struct as;
struct pte;
/branches/tracing/kernel/arch/sparc64/include/register.h
117,23 → 117,6
};
typedef union fprs_reg fprs_reg_t;
 
/** UPA_CONFIG register.
*
* Note that format of this register differs significantly from
* processor version to version. The format defined here
* is the common subset for all supported processor versions.
*/
union upa_config {
uint64_t value;
struct {
uint64_t : 34;
unsigned pcon : 8; /**< Processor configuration. */
unsigned mid : 5; /**< Module (processor) ID register. */
unsigned pcap : 17; /**< Processor capabilities. */
} __attribute__ ((packed));
};
typedef union upa_config upa_config_t;
 
#endif
 
/** @}
/branches/tracing/kernel/arch/sparc64/include/cpu.h
35,15 → 35,6
#ifndef KERN_sparc64_CPU_H_
#define KERN_sparc64_CPU_H_
 
#include <arch/types.h>
#include <typedefs.h>
#include <arch/register.h>
#include <arch/asm.h>
 
#ifdef CONFIG_SMP
#include <arch/mm/cache.h>
#endif
 
#define MANUF_FUJITSU 0x04
#define MANUF_ULTRASPARC 0x17 /**< UltraSPARC I, UltraSPARC II */
#define MANUF_SUN 0x3e
52,14 → 43,29
#define IMPL_ULTRASPARCII 0x11
#define IMPL_ULTRASPARCII_I 0x12
#define IMPL_ULTRASPARCII_E 0x13
#define IMPL_ULTRASPARCIII 0x15
#define IMPL_ULTRASPARCIII 0x14
#define IMPL_ULTRASPARCIII_PLUS 0x15
#define IMPL_ULTRASPARCIII_I 0x16
#define IMPL_ULTRASPARCIV 0x18
#define IMPL_ULTRASPARCIV_PLUS 0x19
 
#define IMPL_SPARC64V 0x5
 
#ifndef __ASM__
 
#include <arch/types.h>
#include <typedefs.h>
#include <arch/register.h>
#include <arch/regdef.h>
#include <arch/asm.h>
 
#ifdef CONFIG_SMP
#include <arch/mm/cache.h>
#endif
 
typedef struct {
uint32_t mid; /**< Processor ID as read from
UPA_CONFIG. */
UPA_CONFIG/FIREPLANE_CONFIG. */
ver_reg_t ver;
uint32_t clock_frequency; /**< Processor frequency in Hz. */
uint64_t next_tick_cmpr; /**< Next clock interrupt should be
66,8 → 72,28
generated when the TICK register
matches this value. */
} cpu_arch_t;
 
 
/**
* Reads the module ID (agent ID/CPUID) of the current CPU.
*/
static inline uint32_t read_mid(void)
{
uint64_t icbus_config = asi_u64_read(ASI_ICBUS_CONFIG, 0);
icbus_config = icbus_config >> ICBUS_CONFIG_MID_SHIFT;
#if defined (US)
return icbus_config & 0x1f;
#elif defined (US3)
if (((ver_reg_t) ver_read()).impl == IMPL_ULTRASPARCIII_I)
return icbus_config & 0x1f;
else
return icbus_config & 0x3ff;
#endif
}
 
#endif
 
#endif
 
/** @}
*/
/branches/tracing/kernel/arch/sparc64/include/drivers/sgcn.h
0,0 → 1,126
/*
* Copyright (c) 2008 Pavel Rimsky
* 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 sparc64
* @{
*/
/** @file
*/
 
#ifndef KERN_sparc64_SGCN_H_
#define KERN_sparc64_SGCN_H_
 
#include <arch/types.h>
 
/* number of bytes in the TOC magic, including the terminating '\0' */
#define TOC_MAGIC_BYTES 8
 
/* number of bytes in the TOC key, including the terminating '\0' */
#define TOC_KEY_SIZE 8
 
/* maximum number of entries in the SRAM table of contents */
#define MAX_TOC_ENTRIES 32
 
/* number of bytes in the SGCN buffer magic, including the terminating '\0' */
#define SGCN_MAGIC_BYTES 4
 
/**
* Entry in the SRAM table of contents. Describes one segment of the SRAM
* which serves a particular purpose (e.g. OBP serial console, Solaris serial
* console, Solaris mailbox,...).
*/
typedef struct {
/** key (e.g. "OBPCONS", "SOLCONS", "SOLMBOX",...) */
char key[TOC_KEY_SIZE];
/** size of the segment in bytes */
uint32_t size;
/** offset of the segment within SRAM */
uint32_t offset;
} __attribute ((packed)) toc_entry_t;
 
/**
* SRAM table of contents. Describes all segments within the SRAM.
*/
typedef struct {
/** hard-wired to "TOCSRAM" */
char magic[TOC_MAGIC_BYTES];
/** we don't need this */
char unused[8];
/** TOC entries */
toc_entry_t keys[MAX_TOC_ENTRIES];
} __attribute__ ((packed)) iosram_toc_t;
 
/**
* SGCN buffer header. It is placed at the very beginning of the SGCN
* buffer.
*/
typedef struct {
/** hard-wired to "CON" */
char magic[SGCN_MAGIC_BYTES];
/** we don't need this */
char unused[8];
/** offset within the SGCN buffer of the input buffer start */
uint32_t in_begin;
/** offset within the SGCN buffer of the input buffer end */
uint32_t in_end;
/** offset within the SGCN buffer of the input buffer read pointer */
uint32_t in_rdptr;
/** offset within the SGCN buffer of the input buffer write pointer */
uint32_t in_wrptr;
 
/** offset within the SGCN buffer of the output buffer start */
uint32_t out_begin;
/** offset within the SGCN buffer of the output buffer end */
uint32_t out_end;
/** offset within the SGCN buffer of the output buffer read pointer */
uint32_t out_rdptr;
/** offset within the SGCN buffer of the output buffer write pointer */
uint32_t out_wrptr;
} __attribute__ ((packed)) sgcn_buffer_header_t;
 
void sgcn_grab(void);
void sgcn_release(void);
void sgcn_poll(void);
void sgcn_init(void);
 
#endif
 
/** @}
*/
/branches/tracing/kernel/arch/sparc64/include/drivers/pci.h
51,8 → 51,8
};
 
struct pci_operations {
void (* enable_interrupt)(pci_t *pci, int inr);
void (* clear_interrupt)(pci_t *pci, int inr);
void (* enable_interrupt)(pci_t *, int);
void (* clear_interrupt)(pci_t *, int);
};
 
struct pci {
61,9 → 61,9
volatile uint64_t *reg; /**< Registers including interrupt registers. */
};
 
extern pci_t *pci_init(ofw_tree_node_t *node);
extern void pci_enable_interrupt(pci_t *pci, int inr);
extern void pci_clear_interrupt(pci_t *pci, int inr);
extern pci_t *pci_init(ofw_tree_node_t *);
extern void pci_enable_interrupt(pci_t *, int);
extern void pci_clear_interrupt(void *, int);
 
#endif
 
/branches/tracing/kernel/arch/sparc64/include/drivers/fhc.h
44,9 → 44,9
 
extern fhc_t *central_fhc;
 
extern fhc_t *fhc_init(ofw_tree_node_t *node);
extern void fhc_enable_interrupt(fhc_t *fhc, int inr);
extern void fhc_clear_interrupt(fhc_t *fhc, int inr);
extern fhc_t *fhc_init(ofw_tree_node_t *);
extern void fhc_enable_interrupt(fhc_t *, int);
extern void fhc_clear_interrupt(void *, int);
 
#endif
 
/branches/tracing/kernel/arch/sparc64/include/drivers/kbd.h
41,7 → 41,8
typedef enum {
KBD_UNKNOWN,
KBD_Z8530,
KBD_NS16550
KBD_NS16550,
KBD_SGCN
} kbd_type_t;
 
extern kbd_type_t kbd_type;
/branches/tracing/kernel/arch/sparc64/include/drivers/scr.h
42,7 → 42,8
SCR_UNKNOWN,
SCR_ATYFB,
SCR_FFB,
SCR_CGSIX
SCR_CGSIX,
SCR_XVR
} scr_type_t;
 
extern scr_type_t scr_type;
/branches/tracing/kernel/arch/sparc64/include/cpu_family.h
0,0 → 1,82
/*
* Copyright (c) 2008 Pavel Rimsky
* 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 sparc64
* @{
*/
/** @file
*/
 
#ifndef KERN_sparc64_CPU_FAMILY_H_
#define KERN_sparc64_CPU_FAMILY_H_
 
#include <arch.h>
#include <cpu.h>
#include <arch/register.h>
#include <arch/asm.h>
 
/**
* Find the processor (sub)family.
*
* @return true iff the CPU belongs to the US family
*/
static inline bool is_us(void)
{
int impl = ((ver_reg_t) ver_read()).impl;
return (impl == IMPL_ULTRASPARCI) || (impl == IMPL_ULTRASPARCII) ||
(impl == IMPL_ULTRASPARCII_I) || (impl == IMPL_ULTRASPARCII_E);
}
 
/**
* Find the processor (sub)family.
*
* @return true iff the CPU belongs to the US-III subfamily
*/
static inline bool is_us_iii(void)
{
int impl = ((ver_reg_t) ver_read()).impl;
return (impl == IMPL_ULTRASPARCIII) ||
(impl == IMPL_ULTRASPARCIII_PLUS) ||
(impl == IMPL_ULTRASPARCIII_I);
}
 
/**
* Find the processor (sub)family.
*
* @return true iff the CPU belongs to the US-IV subfamily
*/
static inline bool is_us_iv(void)
{
int impl = ((ver_reg_t) ver_read()).impl;
return (impl == IMPL_ULTRASPARCIV) || (impl == IMPL_ULTRASPARCIV_PLUS);
}
#endif
 
/** @}
*/
/branches/tracing/kernel/arch/sparc64/Makefile.inc
80,6 → 80,18
DEFS += -DCONFIG_SMP
endif
 
ifeq ($(CONFIG_SGCN),y)
DEFS += -DCONFIG_SGCN
endif
 
ifeq ($(MACHINE),us)
DEFS += -DUS
endif
 
ifeq ($(MACHINE),us3)
DEFS += -DUS3
endif
 
ARCH_SOURCES = \
arch/$(ARCH)/src/cpu/cpu.c \
arch/$(ARCH)/src/asm.S \
106,8 → 118,10
arch/$(ARCH)/src/drivers/tick.c \
arch/$(ARCH)/src/drivers/kbd.c \
arch/$(ARCH)/src/drivers/scr.c \
arch/$(ARCH)/src/drivers/sgcn.c \
arch/$(ARCH)/src/drivers/pci.c
 
 
ifeq ($(CONFIG_SMP),y)
ARCH_SOURCES += \
arch/$(ARCH)/src/smp/ipi.c \
/branches/tracing/kernel/arch/sparc64/src/smp/smp.c
35,6 → 35,7
#include <smp/smp.h>
#include <genarch/ofw/ofw_tree.h>
#include <cpu.h>
#include <arch/cpu_family.h>
#include <arch/cpu.h>
#include <arch.h>
#include <config.h>
43,6 → 44,7
#include <synch/synch.h>
#include <synch/waitq.h>
#include <print.h>
#include <arch/cpu_node.h>
 
/**
* This global variable is used to pick-up application processors
61,15 → 63,55
ofw_tree_node_t *node;
count_t cnt = 0;
node = ofw_tree_find_child_by_device_type(ofw_tree_lookup("/"), "cpu");
while (node) {
cnt++;
node = ofw_tree_find_peer_by_device_type(node, "cpu");
if (is_us() || is_us_iii()) {
node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu");
while (node) {
cnt++;
node = ofw_tree_find_peer_by_device_type(node, "cpu");
}
} else if (is_us_iv()) {
node = ofw_tree_find_child(cpus_parent(), "cmp");
while (node) {
cnt += 2;
node = ofw_tree_find_peer_by_name(node, "cmp");
}
}
config.cpu_count = max(1, cnt);
}
 
/**
* Wakes up the CPU which is represented by the "node" OFW tree node.
* If "node" represents the current CPU, calling the function has
* no effect.
*/
static void wakeup_cpu(ofw_tree_node_t *node)
{
uint32_t mid;
ofw_tree_property_t *prop;
/* 'upa-portid' for US, 'portid' for US-III, 'cpuid' for US-IV */
prop = ofw_tree_getprop(node, "upa-portid");
if ((!prop) || (!prop->value))
prop = ofw_tree_getprop(node, "portid");
if ((!prop) || (!prop->value))
prop = ofw_tree_getprop(node, "cpuid");
if (!prop || prop->value == NULL)
return;
mid = *((uint32_t *) prop->value);
if (CPU->arch.mid == mid)
return;
 
waking_up_mid = mid;
if (waitq_sleep_timeout(&ap_completion_wq, 1000000, SYNCH_FLAGS_NONE) ==
ESYNCH_TIMEOUT)
printf("%s: waiting for processor (mid = %" PRIu32
") timed out\n", __func__, mid);
}
 
/** Wake application processors up. */
void kmp(void *arg)
{
76,31 → 118,18
ofw_tree_node_t *node;
int i;
node = ofw_tree_find_child_by_device_type(ofw_tree_lookup("/"), "cpu");
for (i = 0; node; node = ofw_tree_find_peer_by_device_type(node, "cpu"), i++) {
uint32_t mid;
ofw_tree_property_t *prop;
prop = ofw_tree_getprop(node, "upa-portid");
if (!prop || !prop->value)
continue;
mid = *((uint32_t *) prop->value);
if (CPU->arch.mid == mid) {
/*
* Skip the current CPU.
*/
continue;
if (is_us() || is_us_iii()) {
node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu");
for (i = 0; node;
node = ofw_tree_find_peer_by_device_type(node, "cpu"), i++)
wakeup_cpu(node);
} else if (is_us_iv()) {
node = ofw_tree_find_child(cpus_parent(), "cmp");
while (node) {
wakeup_cpu(ofw_tree_find_child(node, "cpu@0"));
wakeup_cpu(ofw_tree_find_child(node, "cpu@1"));
node = ofw_tree_find_peer_by_name(node, "cmp");
}
 
/*
* Processor with ID == mid can proceed with its initialization.
*/
waking_up_mid = mid;
if (waitq_sleep_timeout(&ap_completion_wq, 1000000, SYNCH_FLAGS_NONE) == ESYNCH_TIMEOUT)
printf("%s: waiting for processor (mid = %" PRIu32 ") timed out\n",
__func__, mid);
}
}
 
/branches/tracing/kernel/arch/sparc64/src/smp/ipi.c
46,6 → 46,33
#include <time/delay.h>
#include <panic.h>
 
/** Set the contents of the outgoing interrupt vector data.
*
* The first data item (data 0) will be set to the value of func, the
* rest of the vector will contain zeros.
*
* This is a helper function used from within the cross_call function.
*
* @param func value the first data item of the vector will be set to
*/
static inline void set_intr_w_data(void (* func)(void))
{
#if defined (US)
asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_0, (uintptr_t) func);
asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_1, 0);
asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_2, 0);
#elif defined (US3)
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_0, (uintptr_t) func);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_1, 0);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_2, 0);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_3, 0);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_4, 0);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_5, 0);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_6, 0);
asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_7, 0);
#endif
}
 
/** Invoke function on another processor.
*
* Currently, only functions without arguments are supported.
73,14 → 100,13
if (status & INTR_DISPATCH_STATUS_BUSY)
panic("Interrupt Dispatch Status busy bit set\n");
ASSERT(!(pstate_read() & PSTATE_IE_BIT));
do {
asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_0,
(uintptr_t) func);
asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_1, 0);
asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_2, 0);
asi_u64_write(ASI_UDB_INTR_W,
set_intr_w_data(func);
asi_u64_write(ASI_INTR_W,
(mid << INTR_VEC_DISPATCH_MID_SHIFT) |
ASI_UDB_INTR_W_DISPATCH, 0);
VA_INTR_W_DISPATCH, 0);
membar();
/branches/tracing/kernel/arch/sparc64/src/ddi/ddi.c
41,7 → 41,7
* Interrupts are disabled and task is locked.
*
* @param task Task.
* @param ioaddr Startign I/O space address.
* @param ioaddr Starting I/O space address.
* @param size Size of the enabled I/O range.
*
* @return 0 on success or an error code from errno.h.
/branches/tracing/kernel/arch/sparc64/src/console.c
38,6 → 38,8
#include <arch/drivers/scr.h>
#include <arch/drivers/kbd.h>
 
#include <arch/drivers/sgcn.h>
 
#ifdef CONFIG_Z8530
#include <genarch/kbd/z8530.h>
#endif
54,24 → 56,25
#include <genarch/ofw/ofw_tree.h>
#include <arch.h>
#include <panic.h>
#include <func.h>
#include <print.h>
 
#define KEYBOARD_POLL_PAUSE 50000 /* 50ms */
 
/** Initialize kernel console to use framebuffer and keyboard directly. */
void standalone_sparc64_console_init(void)
/**
* Initialize kernel console to use framebuffer and keyboard directly.
* Called on UltraSPARC machines with standard keyboard and framebuffer.
*
* @param aliases the "/aliases" OBP node
*/
static void standard_console_init(ofw_tree_node_t *aliases)
{
stdin = NULL;
 
ofw_tree_node_t *aliases;
ofw_tree_property_t *prop;
ofw_tree_node_t *screen;
ofw_tree_node_t *keyboard;
aliases = ofw_tree_lookup("/aliases");
if (!aliases)
panic("Can't find /aliases.\n");
prop = ofw_tree_getprop(aliases, "screen");
if (!prop)
panic("Can't find property \"screen\".\n");
95,6 → 98,36
kbd_init(keyboard);
}
 
/** Initilize I/O on the Serengeti machine. */
static void serengeti_init(void)
{
sgcn_init();
}
 
/**
* Initialize input/output. Auto-detects the type of machine
* and calls the appropriate I/O init routine.
*/
void standalone_sparc64_console_init(void)
{
ofw_tree_node_t *aliases;
ofw_tree_property_t *prop;
aliases = ofw_tree_lookup("/aliases");
if (!aliases)
panic("Can't find /aliases.\n");
/* "def-cn" = "default console" */
prop = ofw_tree_getprop(aliases, "def-cn");
if ((!prop) || (!prop->value) || (strcmp(prop->value, "/sgcn") != 0)) {
standard_console_init(aliases);
} else {
serengeti_init();
}
}
 
 
/** Kernel thread for polling keyboard.
*
* @param arg Ignored.
112,11 → 145,27
}
#endif
 
#ifdef CONFIG_NS16550
#ifdef CONFIG_NS16550_INTERRUPT_DRIVEN
if (kbd_type == KBD_NS16550) {
/*
* The ns16550 driver is interrupt-driven.
*/
return;
}
#endif
#endif
while (1) {
#ifdef CONFIG_NS16550
#ifndef CONFIG_NS16550_INTERRUPT_DRIVEN
if (kbd_type == KBD_NS16550)
ns16550_poll();
#endif
#endif
#ifdef CONFIG_SGCN
if (kbd_type == KBD_SGCN)
sgcn_poll();
#endif
thread_usleep(KEYBOARD_POLL_PAUSE);
}
}
137,6 → 186,11
ns16550_grab();
break;
#endif
#ifdef CONFIG_SGCN
case KBD_SGCN:
sgcn_grab();
break;
#endif
default:
break;
}
158,6 → 212,11
ns16550_release();
break;
#endif
#ifdef CONFIG_SGCN
case KBD_SGCN:
sgcn_release();
break;
#endif
default:
break;
}
/branches/tracing/kernel/arch/sparc64/src/sparc64.c
86,7 → 86,7
* But we only create 128 buckets.
*/
irq_init(1 << 11, 128);
 
standalone_sparc64_console_init();
}
}
/branches/tracing/kernel/arch/sparc64/src/trap/interrupt.c
67,11 → 67,19
*/
void interrupt(int n, istate_t *istate)
{
uint64_t status;
uint64_t intrcv;
uint64_t data0;
status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
if (status & (!INTR_DISPATCH_STATUS_BUSY))
panic("Interrupt Dispatch Status busy bit not set\n");
 
intrcv = asi_u64_read(ASI_INTR_RECEIVE, 0);
data0 = asi_u64_read(ASI_UDB_INTR_R, ASI_UDB_INTR_R_DATA_0);
#if defined (US)
data0 = asi_u64_read(ASI_INTR_R, ASI_UDB_INTR_R_DATA_0);
#elif defined (US3)
data0 = asi_u64_read(ASI_INTR_R, VA_INTR_R_DATA_0);
#endif
 
irq_t *irq = irq_dispatch_and_lock(data0);
if (irq) {
79,6 → 87,12
* The IRQ handler was found.
*/
irq->handler(irq, irq->arg);
/*
* See if there is a clear-interrupt-routine and call it.
*/
if (irq->cir) {
irq->cir(irq->cir_arg, irq->inr);
}
spinlock_unlock(&irq->lock);
} else if (data0 > config.base) {
/*
98,7 → 112,7
*/
#ifdef CONFIG_DEBUG
printf("cpu%u: spurious interrupt (intrcv=%#" PRIx64
", data0=%#" PRIx64 ")\n", CPU->id, intrcv, data0);
", data0=%#" PRIx64 ")\n", CPU->id, intrcv, data0);
#endif
}
 
/branches/tracing/kernel/arch/sparc64/src/cpu/cpu.c
32,12 → 32,46
/** @file
*/
 
#include <arch/cpu_family.h>
#include <cpu.h>
#include <arch.h>
#include <genarch/ofw/ofw_tree.h>
#include <arch/drivers/tick.h>
#include <print.h>
#include <arch/cpu_node.h>
 
/**
* Finds out the clock frequency of the current CPU.
*
* @param node node representing the current CPU in the OFW tree
* @return clock frequency if "node" is the current CPU and no error
* occurs, -1 if "node" is not the current CPU or on error
*/
static int find_cpu_frequency(ofw_tree_node_t *node)
{
ofw_tree_property_t *prop;
uint32_t mid;
 
/* 'upa-portid' for US, 'portid' for US-III, 'cpuid' for US-IV */
prop = ofw_tree_getprop(node, "upa-portid");
if ((!prop) || (!prop->value))
prop = ofw_tree_getprop(node, "portid");
if ((!prop) || (!prop->value))
prop = ofw_tree_getprop(node, "cpuid");
if (prop && prop->value) {
mid = *((uint32_t *) prop->value);
if (mid == CPU->arch.mid) {
prop = ofw_tree_getprop(node, "clock-frequency");
if (prop && prop->value) {
return *((uint32_t *) prop->value);
}
}
}
return -1;
}
 
/** Perform sparc64 specific initialization of the processor structure for the
* current processor.
*/
44,34 → 78,37
void cpu_arch_init(void)
{
ofw_tree_node_t *node;
uint32_t mid;
uint32_t clock_frequency = 0;
upa_config_t upa_config;
upa_config.value = upa_config_read();
CPU->arch.mid = upa_config.mid;
CPU->arch.mid = read_mid();
/*
* Detect processor frequency.
*/
node = ofw_tree_find_child_by_device_type(ofw_tree_lookup("/"), "cpu");
while (node) {
ofw_tree_property_t *prop;
prop = ofw_tree_getprop(node, "upa-portid");
if (prop && prop->value) {
mid = *((uint32_t *) prop->value);
if (mid == CPU->arch.mid) {
prop = ofw_tree_getprop(node,
"clock-frequency");
if (prop && prop->value)
clock_frequency = *((uint32_t *)
prop->value);
}
if (is_us() || is_us_iii()) {
node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu");
while (node) {
int f = find_cpu_frequency(node);
if (f != -1)
clock_frequency = (uint32_t) f;
node = ofw_tree_find_peer_by_device_type(node, "cpu");
}
node = ofw_tree_find_peer_by_device_type(node, "cpu");
} else if (is_us_iv()) {
node = ofw_tree_find_child(cpus_parent(), "cmp");
while (node) {
int f;
f = find_cpu_frequency(
ofw_tree_find_child(node, "cpu@0"));
if (f != -1)
clock_frequency = (uint32_t) f;
f = find_cpu_frequency(
ofw_tree_find_child(node, "cpu@1"));
if (f != -1)
clock_frequency = (uint32_t) f;
node = ofw_tree_find_peer_by_name(node, "cmp");
}
}
 
CPU->arch.clock_frequency = clock_frequency;
tick_init();
}
124,6 → 161,15
case IMPL_ULTRASPARCIII:
impl = "UltraSPARC III";
break;
case IMPL_ULTRASPARCIII_PLUS:
impl = "UltraSPARC III+";
break;
case IMPL_ULTRASPARCIII_I:
impl = "UltraSPARC IIIi";
break;
case IMPL_ULTRASPARCIV:
impl = "UltraSPARC IV";
break;
case IMPL_ULTRASPARCIV_PLUS:
impl = "UltraSPARC IV+";
break;
/branches/tracing/kernel/arch/sparc64/src/mm/tlb.c
54,14 → 54,13
#include <arch/mm/tsb.h>
#endif
 
static void dtlb_pte_copy(pte_t *t, index_t index, bool ro);
static void itlb_pte_copy(pte_t *t, index_t index);
static void do_fast_instruction_access_mmu_miss_fault(istate_t *istate,
const char *str);
static void do_fast_data_access_mmu_miss_fault(istate_t *istate,
tlb_tag_access_reg_t tag, const char *str);
static void do_fast_data_access_protection_fault(istate_t *istate,
tlb_tag_access_reg_t tag, const char *str);
static void dtlb_pte_copy(pte_t *, index_t, bool);
static void itlb_pte_copy(pte_t *, index_t);
static void do_fast_instruction_access_mmu_miss_fault(istate_t *, const char *);
static void do_fast_data_access_mmu_miss_fault(istate_t *, tlb_tag_access_reg_t,
const char *);
static void do_fast_data_access_protection_fault(istate_t *,
tlb_tag_access_reg_t, const char *);
 
char *context_encoding[] = {
"Primary",
86,11 → 85,11
 
/** Insert privileged mapping into DMMU TLB.
*
* @param page Virtual page address.
* @param frame Physical frame address.
* @param pagesize Page size.
* @param locked True for permanent mappings, false otherwise.
* @param cacheable True if the mapping is cacheable, false otherwise.
* @param page Virtual page address.
* @param frame Physical frame address.
* @param pagesize Page size.
* @param locked True for permanent mappings, false otherwise.
* @param cacheable True if the mapping is cacheable, false otherwise.
*/
void dtlb_insert_mapping(uintptr_t page, uintptr_t frame, int pagesize,
bool locked, bool cacheable)
103,7 → 102,7
pg.address = page;
fr.address = frame;
 
tag.value = ASID_KERNEL;
tag.context = ASID_KERNEL;
tag.vpn = pg.vpn;
 
dtlb_tag_access_write(tag.value);
126,10 → 125,10
 
/** Copy PTE to TLB.
*
* @param t Page Table Entry to be copied.
* @param index Zero if lower 8K-subpage, one if higher 8K-subpage.
* @param ro If true, the entry will be created read-only, regardless of its
* w field.
* @param t Page Table Entry to be copied.
* @param index Zero if lower 8K-subpage, one if higher 8K-subpage.
* @param ro If true, the entry will be created read-only, regardless
* of its w field.
*/
void dtlb_pte_copy(pte_t *t, index_t index, bool ro)
{
165,8 → 164,8
 
/** Copy PTE to ITLB.
*
* @param t Page Table Entry to be copied.
* @param index Zero if lower 8K-subpage, one if higher 8K-subpage.
* @param t Page Table Entry to be copied.
* @param index Zero if lower 8K-subpage, one if higher 8K-subpage.
*/
void itlb_pte_copy(pte_t *t, index_t index)
{
235,10 → 234,11
* Note that some faults (e.g. kernel faults) were already resolved by the
* low-level, assembly language part of the fast_data_access_mmu_miss handler.
*
* @param tag Content of the TLB Tag Access register as it existed when the
* trap happened. This is to prevent confusion created by clobbered
* Tag Access register during a nested DTLB miss.
* @param istate Interrupted state saved on the stack.
* @param tag Content of the TLB Tag Access register as it existed
* when the trap happened. This is to prevent confusion
* created by clobbered Tag Access register during a nested
* DTLB miss.
* @param istate Interrupted state saved on the stack.
*/
void fast_data_access_mmu_miss(tlb_tag_access_reg_t tag, istate_t *istate)
{
287,10 → 287,11
 
/** DTLB protection fault handler.
*
* @param tag Content of the TLB Tag Access register as it existed when the
* trap happened. This is to prevent confusion created by clobbered
* Tag Access register during a nested DTLB miss.
* @param istate Interrupted state saved on the stack.
* @param tag Content of the TLB Tag Access register as it existed
* when the trap happened. This is to prevent confusion
* created by clobbered Tag Access register during a nested
* DTLB miss.
* @param istate Interrupted state saved on the stack.
*/
void fast_data_access_protection(tlb_tag_access_reg_t tag, istate_t *istate)
{
331,6 → 332,26
}
}
 
/** Print TLB entry (for debugging purposes).
*
* The diag field has been left out in order to make this function more generic
* (there is no diag field in US3 architeture).
*
* @param i TLB entry number
* @param t TLB entry tag
* @param d TLB entry data
*/
static void print_tlb_entry(int i, tlb_tag_read_reg_t t, tlb_data_t d)
{
printf("%d: vpn=%#llx, context=%d, v=%d, size=%d, nfo=%d, "
"ie=%d, soft2=%#x, pfn=%#x, soft=%#x, l=%d, "
"cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n", i, t.vpn,
t.context, d.v, d.size, d.nfo, d.ie, d.soft2,
d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g);
}
 
#if defined (US)
 
/** Print contents of both TLBs. */
void tlb_print(void)
{
342,12 → 363,7
for (i = 0; i < ITLB_ENTRY_COUNT; i++) {
d.value = itlb_data_access_read(i);
t.value = itlb_tag_read_read(i);
 
printf("%d: vpn=%#llx, context=%d, v=%d, size=%d, nfo=%d, "
"ie=%d, soft2=%#x, diag=%#x, pfn=%#x, soft=%#x, l=%d, "
"cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n", i, t.vpn,
t.context, d.v, d.size, d.nfo, d.ie, d.soft2, d.diag,
d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g);
print_tlb_entry(i, t, d);
}
 
printf("D-TLB contents:\n");
354,16 → 370,57
for (i = 0; i < DTLB_ENTRY_COUNT; i++) {
d.value = dtlb_data_access_read(i);
t.value = dtlb_tag_read_read(i);
printf("%d: vpn=%#llx, context=%d, v=%d, size=%d, nfo=%d, "
"ie=%d, soft2=%#x, diag=%#x, pfn=%#x, soft=%#x, l=%d, "
"cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n", i, t.vpn,
t.context, d.v, d.size, d.nfo, d.ie, d.soft2, d.diag,
d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g);
print_tlb_entry(i, t, d);
}
}
 
#elif defined (US3)
 
/** Print contents of all TLBs. */
void tlb_print(void)
{
int i;
tlb_data_t d;
tlb_tag_read_reg_t t;
printf("TLB_ISMALL contents:\n");
for (i = 0; i < tlb_ismall_size(); i++) {
d.value = dtlb_data_access_read(TLB_ISMALL, i);
t.value = dtlb_tag_read_read(TLB_ISMALL, i);
print_tlb_entry(i, t, d);
}
printf("TLB_IBIG contents:\n");
for (i = 0; i < tlb_ibig_size(); i++) {
d.value = dtlb_data_access_read(TLB_IBIG, i);
t.value = dtlb_tag_read_read(TLB_IBIG, i);
print_tlb_entry(i, t, d);
}
printf("TLB_DSMALL contents:\n");
for (i = 0; i < tlb_dsmall_size(); i++) {
d.value = dtlb_data_access_read(TLB_DSMALL, i);
t.value = dtlb_tag_read_read(TLB_DSMALL, i);
print_tlb_entry(i, t, d);
}
printf("TLB_DBIG_1 contents:\n");
for (i = 0; i < tlb_dbig_size(); i++) {
d.value = dtlb_data_access_read(TLB_DBIG_0, i);
t.value = dtlb_tag_read_read(TLB_DBIG_0, i);
print_tlb_entry(i, t, d);
}
printf("TLB_DBIG_2 contents:\n");
for (i = 0; i < tlb_dbig_size(); i++) {
d.value = dtlb_data_access_read(TLB_DBIG_1, i);
t.value = dtlb_tag_read_read(TLB_DBIG_1, i);
print_tlb_entry(i, t, d);
}
}
 
#endif
 
void do_fast_instruction_access_mmu_miss_fault(istate_t *istate,
const char *str)
{
411,30 → 468,71
sfsr.value = dtlb_sfsr_read();
sfar = dtlb_sfar_read();
#if defined (US)
printf("DTLB SFSR: asi=%#x, ft=%#x, e=%d, ct=%d, pr=%d, w=%d, ow=%d, "
"fv=%d\n", sfsr.asi, sfsr.ft, sfsr.e, sfsr.ct, sfsr.pr, sfsr.w,
sfsr.ow, sfsr.fv);
#elif defined (US3)
printf("DTLB SFSR: nf=%d, asi=%#x, tm=%d, ft=%#x, e=%d, ct=%d, pr=%d, "
"w=%d, ow=%d, fv=%d\n", sfsr.nf, sfsr.asi, sfsr.tm, sfsr.ft,
sfsr.e, sfsr.ct, sfsr.pr, sfsr.w, sfsr.ow, sfsr.fv);
#endif
printf("DTLB SFAR: address=%p\n", sfar);
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
 
/** Invalidate all unlocked ITLB and DTLB entries. */
void tlb_invalidate_all(void)
{
int i;
tlb_data_t d;
tlb_tag_read_reg_t t;
 
/*
* Walk all ITLB and DTLB entries and remove all unlocked mappings.
*
* The kernel doesn't use global mappings so any locked global mappings
* found must have been created by someone else. Their only purpose now
* found must have been created by someone else. Their only purpose now
* is to collide with proper mappings. Invalidate immediately. It should
* be safe to invalidate them as late as now.
*/
 
#if defined (US)
tlb_data_t d;
tlb_tag_read_reg_t t;
 
for (i = 0; i < ITLB_ENTRY_COUNT; i++) {
d.value = itlb_data_access_read(i);
if (!d.l || d.g) {
444,7 → 542,7
itlb_data_access_write(i, d.value);
}
}
 
for (i = 0; i < DTLB_ENTRY_COUNT; i++) {
d.value = dtlb_data_access_read(i);
if (!d.l || d.g) {
454,7 → 552,21
dtlb_data_access_write(i, d.value);
}
}
 
#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);
#endif
 
}
 
/** Invalidate all ITLB and DTLB entries that belong to specified ASID
484,9 → 596,9
/** Invalidate all ITLB and DTLB entries for specified page range in specified
* address space.
*
* @param asid Address Space ID.
* @param page First page which to sweep out from ITLB and DTLB.
* @param cnt Number of ITLB and DTLB entries to invalidate.
* @param asid Address Space ID.
* @param page First page which to sweep out from ITLB and DTLB.
* @param cnt Number of ITLB and DTLB entries to invalidate.
*/
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
{
/branches/tracing/kernel/arch/sparc64/src/mm/as.c
164,7 → 164,25
itsb_base_write(tsb_base.value);
tsb_base.base = ((uintptr_t) as->arch.dtsb) >> MMU_PAGE_WIDTH;
dtsb_base_write(tsb_base.value);
#if defined (US3)
/*
* Clear the extension registers.
* In HelenOS, primary and secondary context registers contain
* equal values and kernel misses (context 0, ie. the nucleus context)
* are excluded from the TSB miss handler, so it makes no sense
* to have separate TSBs for primary, secondary and nucleus contexts.
* Clearing the extension registers will ensure that the value of the
* TSB Base register will be used as an address of TSB, making the code
* compatible with the US port.
*/
itsb_primary_extension_write(0);
itsb_nucleus_extension_write(0);
dtsb_primary_extension_write(0);
dtsb_secondary_extension_write(0);
dtsb_nucleus_extension_write(0);
#endif
#endif
}
 
/** Perform sparc64-specific tasks when an address space is removed from the
/branches/tracing/kernel/arch/sparc64/src/mm/cache.S
47,45 → 47,3
retl
! beware SF Erratum #51, do not put the MEMBAR here
nop
 
/** Flush only D-cache lines of one virtual color.
*
* @param o0 Virtual color to be flushed.
*/
.global dcache_flush_color
dcache_flush_color:
mov (DCACHE_SIZE / DCACHE_LINE_SIZE) / 2, %g1
set DCACHE_SIZE / 2, %g2
sllx %g2, %o0, %g2
sub %g2, DCACHE_LINE_SIZE, %g2
0: stxa %g0, [%g2] ASI_DCACHE_TAG
membar #Sync
subcc %g1, 1, %g1
bnz,pt %xcc, 0b
sub %g2, DCACHE_LINE_SIZE, %g2
retl
nop
 
/** Flush only D-cache lines of one virtual color and one tag.
*
* @param o0 Virtual color to lookup the tag.
* @param o1 Tag of the cachelines to be flushed.
*/
.global dcache_flush_tag
dcache_flush_tag:
mov (DCACHE_SIZE / DCACHE_LINE_SIZE) / 2, %g1
set DCACHE_SIZE / 2, %g2
sllx %g2, %o0, %g2
sub %g2, DCACHE_LINE_SIZE, %g2
0: ldxa [%g2] ASI_DCACHE_TAG, %g3
srlx %g3, DCACHE_TAG_SHIFT, %g3
cmp %g3, %o1
bnz 1f
nop
stxa %g0, [%g2] ASI_DCACHE_TAG
membar #Sync
1: subcc %g1, 1, %g1
bnz,pt %xcc, 0b
sub %g2, DCACHE_LINE_SIZE, %g2
retl
nop
/branches/tracing/kernel/arch/sparc64/src/mm/tsb.c
112,9 → 112,9
tsb->data.value = 0;
tsb->data.size = PAGESIZE_8K;
tsb->data.pfn = (t->frame >> MMU_FRAME_WIDTH) + index;
tsb->data.cp = t->c;
tsb->data.p = t->k; /* p as privileged */
tsb->data.v = t->p;
tsb->data.cp = t->c; /* cp as cache in phys.-idxed, c as cacheable */
tsb->data.p = t->k; /* p as privileged, k as kernel */
tsb->data.v = t->p; /* v as valid, p as present */
write_barrier();
173,3 → 173,4
 
/** @}
*/
 
/branches/tracing/kernel/arch/sparc64/src/mm/page.c
52,7 → 52,7
uintptr_t virt_page;
uintptr_t phys_page;
int pagesize_code;
} bsp_locked_dtlb_entry[DTLB_ENTRY_COUNT];
} bsp_locked_dtlb_entry[DTLB_MAX_LOCKED_ENTRIES];
 
/** Number of entries in bsp_locked_dtlb_entry array. */
static count_t bsp_locked_dtlb_entries = 0;
166,3 → 166,4
 
/** @}
*/
 
/branches/tracing/kernel/arch/sparc64/src/drivers/fhc.c
101,8 → 101,9
}
}
 
void fhc_clear_interrupt(fhc_t *fhc, int inr)
void fhc_clear_interrupt(void *fhcp, int inr)
{
fhc_t *fhc = (fhc_t *)fhcp;
ASSERT(fhc->uart_imap);
 
switch (inr) {
/branches/tracing/kernel/arch/sparc64/src/drivers/kbd.c
63,6 → 63,8
uintptr_t aligned_addr;
ofw_tree_property_t *prop;
const char *name;
cir_t cir;
void *cir_arg;
name = ofw_tree_node_name(node);
103,11 → 105,14
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)) {
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)) {
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;
}
115,11 → 120,14
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)) {
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)) {
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;
};
142,16 → 150,17
switch (kbd_type) {
#ifdef CONFIG_Z8530
case KBD_Z8530:
z8530_init(devno, inr, vaddr);
z8530_init(devno, vaddr, inr, cir, cir_arg);
break;
#endif
#ifdef CONFIG_NS16550
case KBD_NS16550:
ns16550_init(devno, inr, (ioport_t)vaddr);
ns16550_init(devno, (ioport_t)vaddr, inr, cir, cir_arg);
break;
#endif
default:
printf("Kernel is not compiled with the necessary keyboard driver this machine requires.\n");
printf("Kernel is not compiled with the necessary keyboard "
"driver this machine requires.\n");
}
}
 
/branches/tracing/kernel/arch/sparc64/src/drivers/scr.c
55,6 → 55,10
void scr_init(ofw_tree_node_t *node)
{
ofw_tree_property_t *prop;
ofw_pci_reg_t *pci_reg;
ofw_pci_reg_t pci_abs_reg;
ofw_upa_reg_t *upa_reg;
ofw_sbus_reg_t *sbus_reg;
const char *name;
name = ofw_tree_node_name(node);
61,6 → 65,8
if (strcmp(name, "SUNW,m64B") == 0)
scr_type = SCR_ATYFB;
else if (strcmp(name, "SUNW,XVR-100") == 0)
scr_type = SCR_XVR;
else if (strcmp(name, "SUNW,ffb") == 0)
scr_type = SCR_FFB;
else if (strcmp(name, "cgsix") == 0)
67,7 → 73,7
scr_type = SCR_CGSIX;
if (scr_type == SCR_UNKNOWN) {
printf("Unknown keyboard device.\n");
printf("Unknown screen device.\n");
return;
}
106,15 → 112,15
return;
}
ofw_pci_reg_t *fb_reg = &((ofw_pci_reg_t *) prop->value)[1];
ofw_pci_reg_t abs_reg;
pci_reg = &((ofw_pci_reg_t *) prop->value)[1];
if (!ofw_pci_reg_absolutize(node, fb_reg, &abs_reg)) {
if (!ofw_pci_reg_absolutize(node, pci_reg, &pci_abs_reg)) {
printf("Failed to absolutize fb register.\n");
return;
}
if (!ofw_pci_apply_ranges(node->parent, &abs_reg , &fb_addr)) {
if (!ofw_pci_apply_ranges(node->parent, &pci_abs_reg,
&fb_addr)) {
printf("Failed to determine screen address.\n");
return;
}
142,12 → 148,54
}
break;
case SCR_XVR:
if (prop->size / sizeof(ofw_pci_reg_t) < 2) {
printf("Too few screen registers.\n");
return;
}
pci_reg = &((ofw_pci_reg_t *) prop->value)[1];
if (!ofw_pci_reg_absolutize(node, pci_reg, &pci_abs_reg)) {
printf("Failed to absolutize fb register.\n");
return;
}
if (!ofw_pci_apply_ranges(node->parent, &pci_abs_reg,
&fb_addr)) {
printf("Failed to determine screen address.\n");
return;
}
 
switch (fb_depth) {
case 8:
fb_scanline = fb_linebytes * (fb_depth >> 3);
visual = VISUAL_SB1500_PALETTE;
break;
case 16:
fb_scanline = fb_linebytes * (fb_depth >> 3);
visual = VISUAL_RGB_5_6_5;
break;
case 24:
fb_scanline = fb_linebytes * 4;
visual = VISUAL_RGB_8_8_8_0;
break;
case 32:
fb_scanline = fb_linebytes * (fb_depth >> 3);
visual = VISUAL_RGB_0_8_8_8;
break;
default:
printf("Unsupported bits per pixel.\n");
return;
}
break;
case SCR_FFB:
fb_scanline = 8192;
visual = VISUAL_BGR_0_8_8_8;
 
ofw_upa_reg_t *reg = &((ofw_upa_reg_t *) prop->value)[FFB_REG_24BPP];
if (!ofw_upa_apply_ranges(node->parent, reg, &fb_addr)) {
upa_reg = &((ofw_upa_reg_t *) prop->value)[FFB_REG_24BPP];
if (!ofw_upa_apply_ranges(node->parent, upa_reg, &fb_addr)) {
printf("Failed to determine screen address.\n");
return;
}
164,8 → 212,8
return;
}
ofw_sbus_reg_t *cg6_reg = &((ofw_sbus_reg_t *) prop->value)[0];
if (!ofw_sbus_apply_ranges(node->parent, cg6_reg, &fb_addr)) {
sbus_reg = &((ofw_sbus_reg_t *) prop->value)[0];
if (!ofw_sbus_apply_ranges(node->parent, sbus_reg, &fb_addr)) {
printf("Failed to determine screen address.\n");
return;
}
175,7 → 223,15
panic("Unexpected type.\n");
}
 
fb_init(fb_addr, fb_width, fb_height, fb_scanline, visual);
fb_properties_t props = {
.addr = fb_addr,
.offset = 0,
.x = fb_width,
.y = fb_height,
.scan = fb_scanline,
.visual = visual,
};
fb_init(&props);
}
 
/** @}
/branches/tracing/kernel/arch/sparc64/src/drivers/tick.c
45,11 → 45,12
 
#define TICK_RESTART_TIME 50 /* Worst case estimate. */
 
/** Initialize tick interrupt. */
/** Initialize tick and stick interrupt. */
void tick_init(void)
{
/* initialize TICK interrupt */
tick_compare_reg_t compare;
 
interrupt_register(14, "tick_int", tick_interrupt);
compare.int_dis = false;
compare.tick_cmpr = CPU->arch.clock_frequency / HZ;
56,6 → 57,21
CPU->arch.next_tick_cmpr = compare.tick_cmpr;
tick_compare_write(compare.value);
tick_write(0);
 
#if defined (US3)
/* disable STICK interrupts and clear any pending ones */
tick_compare_reg_t stick_compare;
softint_reg_t clear;
 
stick_compare.value = stick_compare_read();
stick_compare.int_dis = true;
stick_compare.tick_cmpr = 0;
stick_compare_write(stick_compare.value);
 
clear.value = 0;
clear.stick_int = 1;
clear_softint_write(clear.value);
#endif
}
 
/** Process tick interrupt.
67,7 → 83,7
{
softint_reg_t softint, clear;
uint64_t drift;
 
softint.value = softint_read();
/*
/branches/tracing/kernel/arch/sparc64/src/drivers/sgcn.c
0,0 → 1,450
/*
* Copyright (c) 2008 Pavel Rimsky
* 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 sparc64
* @{
*/
/**
* @file
* @brief SGCN driver.
*/
 
#include <arch/drivers/sgcn.h>
#include <arch/drivers/kbd.h>
#include <genarch/ofw/ofw_tree.h>
#include <debug.h>
#include <func.h>
#include <print.h>
#include <mm/page.h>
#include <ipc/irq.h>
#include <ddi/ddi.h>
#include <ddi/device.h>
#include <console/chardev.h>
#include <console/console.h>
#include <ddi/device.h>
#include <sysinfo/sysinfo.h>
#include <synch/spinlock.h>
 
/*
* Physical address at which the SBBC starts. This value has been obtained
* by inspecting (using Simics) memory accesses made by OBP. It is valid
* for the Simics-simulated Serengeti machine. The author of this code is
* not sure whether this value is valid generally.
*/
#define SBBC_START 0x63000000000
 
/* offset of SRAM within the SBBC memory */
#define SBBC_SRAM_OFFSET 0x900000
 
/* size (in bytes) of the physical memory area which will be mapped */
#define MAPPED_AREA_SIZE (128 * 1024)
 
/* magic string contained at the beginning of SRAM */
#define SRAM_TOC_MAGIC "TOCSRAM"
 
/*
* Key into the SRAM table of contents which identifies the entry
* describing the OBP console buffer. It is worth mentioning
* that the OBP console buffer is not the only console buffer
* which can be used. It is, however, used because when the kernel
* is running, the OBP buffer is not used by OBP any more but OBP
* has already made neccessary arangements so that the output will
* be read from the OBP buffer and input will go to the OBP buffer.
* Therefore HelenOS needs to make no such arrangements any more.
*/
#define CONSOLE_KEY "OBPCONS"
 
/* magic string contained at the beginning of the console buffer */
#define SGCN_BUFFER_MAGIC "CON"
 
/**
* The driver is polling based, but in order to notify the userspace
* of a key being pressed, we need to supply the interface with some
* interrupt number. The interrupt number can be arbitrary as it it
* will never be used for identifying HW interrupts, but only in
* notifying the userspace.
*/
#define FICTIONAL_INR 1
 
 
/*
* Returns a pointer to the object of a given type which is placed at the given
* offset from the SRAM beginning.
*/
#define SRAM(type, offset) ((type *) (sram_begin + (offset)))
 
/* Returns a pointer to the SRAM table of contents. */
#define SRAM_TOC (SRAM(iosram_toc_t, 0))
 
/*
* Returns a pointer to the object of a given type which is placed at the given
* offset from the console buffer beginning.
*/
#define SGCN_BUFFER(type, offset) \
((type *) (sgcn_buffer_begin + (offset)))
 
/** 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;
 
/**
* starting address of the SGCN buffer, will be set by the
* init_sgcn_buffer_begin function
*/
static uintptr_t sgcn_buffer_begin;
 
/**
* SGCN IRQ structure. So far used only for notifying the userspace of the
* key being pressed, not for kernel being informed about keyboard interrupts.
*/
static irq_t sgcn_irq;
 
// TODO think of a way how to synchronize accesses to SGCN buffer between the kernel and the userspace
 
/*
* Ensures that writing to the buffer and consequent update of the write pointer
* are together one atomic operation.
*/
SPINLOCK_INITIALIZE(sgcn_output_lock);
 
/*
* Prevents the input buffer read/write pointers from getting to inconsistent
* state.
*/
SPINLOCK_INITIALIZE(sgcn_input_lock);
 
 
/* functions referenced from definitions of I/O operations structures */
static void sgcn_noop(chardev_t *);
static void sgcn_putchar(chardev_t *, const char);
static char sgcn_key_read(chardev_t *);
 
/** character device operations */
static chardev_operations_t sgcn_ops = {
.suspend = sgcn_noop,
.resume = sgcn_noop,
.read = sgcn_key_read,
.write = sgcn_putchar
};
 
/** SGCN character device */
chardev_t sgcn_io;
 
/**
* Registers the physical area of the SRAM so that the userspace SGCN
* driver can map it. Moreover, it sets some sysinfo values (SRAM address
* and SRAM size).
*/
static void register_sram_parea(uintptr_t sram_begin_physical)
{
static parea_t sram_parea;
sram_parea.pbase = sram_begin_physical;
sram_parea.vbase = (uintptr_t) sram_begin;
sram_parea.frames = MAPPED_AREA_SIZE / FRAME_SIZE;
sram_parea.cacheable = false;
ddi_parea_register(&sram_parea);
sysinfo_set_item_val("sram.area.size", NULL, MAPPED_AREA_SIZE);
sysinfo_set_item_val("sram.address.physical", NULL,
sram_begin_physical);
}
 
/**
* Initializes the starting address of SRAM.
*
* The SRAM starts 0x900000 + C bytes behind the SBBC start in the
* physical memory, where C is the value read from the "iosram-toc"
* property of the "/chosen" OBP node. The sram_begin variable will
* be set to the virtual address which maps to the SRAM physical
* address.
*
* It also registers the physical area of SRAM and sets some sysinfo
* values (SRAM address and SRAM size).
*/
static void init_sram_begin(void)
{
ofw_tree_node_t *chosen;
ofw_tree_property_t *iosram_toc;
uintptr_t sram_begin_physical;
 
chosen = ofw_tree_lookup("/chosen");
if (!chosen)
panic("Can't find /chosen.\n");
 
iosram_toc = ofw_tree_getprop(chosen, "iosram-toc");
if (!iosram_toc)
panic("Can't find property \"iosram-toc\".\n");
if (!iosram_toc->value)
panic("Can't find SRAM TOC.\n");
 
sram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET
+ *((uint32_t *) iosram_toc->value);
sram_begin = hw_map(sram_begin_physical, MAPPED_AREA_SIZE);
register_sram_parea(sram_begin_physical);
}
 
/**
* Initializes the starting address of the SGCN buffer.
*
* The offset of the SGCN buffer within SRAM is obtained from the
* SRAM table of contents. The table of contents contains
* information about several buffers, among which there is an OBP
* console buffer - this one will be used as the SGCN buffer.
*
* This function also writes the offset of the SGCN buffer within SRAM
* under the sram.buffer.offset sysinfo key.
*/
static void sgcn_buffer_begin_init(void)
{
init_sram_begin();
ASSERT(strcmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0);
/* lookup TOC entry with the correct key */
uint32_t i;
for (i = 0; i < MAX_TOC_ENTRIES; i++) {
if (strcmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0)
break;
}
ASSERT(i < MAX_TOC_ENTRIES);
sgcn_buffer_begin = sram_begin + SRAM_TOC->keys[i].offset;
sysinfo_set_item_val("sram.buffer.offset", NULL,
SRAM_TOC->keys[i].offset);
}
 
/**
* Default suspend/resume operation for the input device.
*/
static void sgcn_noop(chardev_t *d)
{
}
 
/**
* Writes a single character to the SGCN (circular) output buffer
* and updates the output write pointer so that SGCN gets to know
* that the character has been written.
*/
static void sgcn_do_putchar(const char c)
{
uint32_t begin = SGCN_BUFFER_HEADER->out_begin;
uint32_t end = SGCN_BUFFER_HEADER->out_end;
uint32_t size = end - begin;
/* we need pointers to volatile variables */
volatile char *buf_ptr = (volatile char *)
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr);
volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr);
volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr);
 
/*
* Write the character and increment the write pointer modulo the
* output buffer size. Note that if we are to rewrite a character
* which has not been read by the SGCN controller yet (i.e. the output
* buffer is full), we need to wait until the controller reads some more
* characters. We wait actively, which means that all threads waiting
* for the lock are blocked. However, this situation is
* 1) rare - the output buffer is big, so filling the whole
* output buffer is improbable
* 2) short-lasting - it will take the controller only a fraction
* of millisecond to pick the unread characters up
* 3) not serious - the blocked threads are those that print something
* to user console, which is not a time-critical operation
*/
uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin;
while (*out_rdptr_ptr == new_wrptr)
;
*buf_ptr = c;
*out_wrptr_ptr = new_wrptr;
}
 
/**
* SGCN output operation. Prints a single character to the SGCN. If the line
* feed character is written ('\n'), the carriage return character ('\r') is
* written straight away.
*/
static void sgcn_putchar(struct chardev * cd, const char c)
{
spinlock_lock(&sgcn_output_lock);
sgcn_do_putchar(c);
if (c == '\n') {
sgcn_do_putchar('\r');
}
spinlock_unlock(&sgcn_output_lock);
}
 
/**
* Called when actively reading the character. Not implemented yet.
*/
static char sgcn_key_read(chardev_t *d)
{
return (char) 0;
}
 
/**
* The driver works in polled mode, so no interrupt should be handled by it.
*/
static irq_ownership_t sgcn_claim(void)
{
return IRQ_DECLINE;
}
 
/**
* The driver works in polled mode, so no interrupt should be handled by it.
*/
static void sgcn_irq_handler(irq_t *irq, void *arg, ...)
{
panic("Not yet implemented, SGCN works in polled mode.\n");
}
 
/**
* Grabs the input for kernel.
*/
void sgcn_grab(void)
{
ipl_t ipl = interrupts_disable();
volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
/* skip all the user typed before the grab and hasn't been processed */
spinlock_lock(&sgcn_input_lock);
*in_rdptr_ptr = *in_wrptr_ptr;
spinlock_unlock(&sgcn_input_lock);
 
spinlock_lock(&sgcn_irq.lock);
sgcn_irq.notif_cfg.notify = false;
spinlock_unlock(&sgcn_irq.lock);
interrupts_restore(ipl);
}
 
/**
* Releases the input so that userspace can use it.
*/
void sgcn_release(void)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&sgcn_irq.lock);
if (sgcn_irq.notif_cfg.answerbox)
sgcn_irq.notif_cfg.notify = true;
spinlock_unlock(&sgcn_irq.lock);
interrupts_restore(ipl);
}
 
/**
* Function regularly called by the keyboard polling thread. Finds out whether
* there are some unread characters in the input queue. If so, it picks them up
* and sends them to the upper layers of HelenOS.
*/
void sgcn_poll(void)
{
uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
uint32_t end = SGCN_BUFFER_HEADER->in_end;
uint32_t size = end - begin;
spinlock_lock(&sgcn_input_lock);
ipl_t ipl = interrupts_disable();
spinlock_lock(&sgcn_irq.lock);
/* we need pointers to volatile variables */
volatile char *buf_ptr = (volatile char *)
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
if (*in_rdptr_ptr != *in_wrptr_ptr) {
if (sgcn_irq.notif_cfg.notify && sgcn_irq.notif_cfg.answerbox) {
ipc_irq_send_notif(&sgcn_irq);
spinlock_unlock(&sgcn_irq.lock);
interrupts_restore(ipl);
spinlock_unlock(&sgcn_input_lock);
return;
}
}
spinlock_unlock(&sgcn_irq.lock);
interrupts_restore(ipl);
 
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;
if (c == '\r') {
c = '\n';
}
chardev_push_character(&sgcn_io, c);
}
spinlock_unlock(&sgcn_input_lock);
}
 
/**
* A public function which initializes I/O from/to Serengeti console
* and sets it as a default input/output.
*/
void sgcn_init(void)
{
sgcn_buffer_begin_init();
 
kbd_type = KBD_SGCN;
 
devno_t devno = device_assign_devno();
irq_initialize(&sgcn_irq);
sgcn_irq.devno = devno;
sgcn_irq.inr = FICTIONAL_INR;
sgcn_irq.claim = sgcn_claim;
sgcn_irq.handler = sgcn_irq_handler;
irq_register(&sgcn_irq);
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.type", NULL, KBD_SGCN);
sysinfo_set_item_val("kbd.devno", NULL, devno);
sysinfo_set_item_val("kbd.inr", NULL, FICTIONAL_INR);
sysinfo_set_item_val("fb.kind", NULL, 4);
chardev_initialize("sgcn_io", &sgcn_io, &sgcn_ops);
stdin = &sgcn_io;
stdout = &sgcn_io;
}
 
/** @}
*/
/branches/tracing/kernel/arch/sparc64/src/drivers/pci.c
45,40 → 45,37
#include <func.h>
#include <arch/asm.h>
 
#define PCI_SABRE_REGS_REG 0
#define SABRE_INTERNAL_REG 0
#define PSYCHO_INTERNAL_REG 2
 
#define PCI_SABRE_IMAP_BASE 0x200
#define PCI_SABRE_ICLR_BASE 0x300
#define OBIO_IMR_BASE 0x200
#define OBIO_IMR(ino) (OBIO_IMR_BASE + ((ino) & INO_MASK))
 
#define PCI_PSYCHO_REGS_REG 2
#define OBIO_CIR_BASE 0x300
#define OBIO_CIR(ino) (OBIO_CIR_BASE + ((ino) & INO_MASK))
 
#define PCI_PSYCHO_IMAP_BASE 0x200
#define PCI_PSYCHO_ICLR_BASE 0x300
static void obio_enable_interrupt(pci_t *, int);
static void obio_clear_interrupt(pci_t *, int);
 
static pci_t *pci_sabre_init(ofw_tree_node_t *node);
static void pci_sabre_enable_interrupt(pci_t *pci, int inr);
static void pci_sabre_clear_interrupt(pci_t *pci, int inr);
static pci_t *pci_sabre_init(ofw_tree_node_t *);
static pci_t *pci_psycho_init(ofw_tree_node_t *);
 
static pci_t *pci_psycho_init(ofw_tree_node_t *node);
static void pci_psycho_enable_interrupt(pci_t *pci, int inr);
static void pci_psycho_clear_interrupt(pci_t *pci, int inr);
 
/** PCI operations for Sabre model. */
static pci_operations_t pci_sabre_ops = {
.enable_interrupt = pci_sabre_enable_interrupt,
.clear_interrupt = pci_sabre_clear_interrupt
.enable_interrupt = obio_enable_interrupt,
.clear_interrupt = obio_clear_interrupt
};
/** PCI operations for Psycho model. */
static pci_operations_t pci_psycho_ops = {
.enable_interrupt = pci_psycho_enable_interrupt,
.clear_interrupt = pci_psycho_clear_interrupt
.enable_interrupt = obio_enable_interrupt,
.clear_interrupt = obio_clear_interrupt
};
 
/** Initialize PCI controller (model Sabre).
*
* @param node OpenFirmware device tree node of the Sabre.
* @param node OpenFirmware device tree node of the Sabre.
*
* @return Address of the initialized PCI structure.
* @return Address of the initialized PCI structure.
*/
pci_t *pci_sabre_init(ofw_tree_node_t *node)
{
95,11 → 92,12
ofw_upa_reg_t *reg = prop->value;
count_t regs = prop->size / sizeof(ofw_upa_reg_t);
 
if (regs < PCI_SABRE_REGS_REG + 1)
if (regs < SABRE_INTERNAL_REG + 1)
return NULL;
 
uintptr_t paddr;
if (!ofw_upa_apply_ranges(node->parent, &reg[PCI_SABRE_REGS_REG], &paddr))
if (!ofw_upa_apply_ranges(node->parent, &reg[SABRE_INTERNAL_REG],
&paddr))
return NULL;
 
pci = (pci_t *) malloc(sizeof(pci_t), FRAME_ATOMIC);
108,7 → 106,7
 
pci->model = PCI_SABRE;
pci->op = &pci_sabre_ops;
pci->reg = (uint64_t *) hw_map(paddr, reg[PCI_SABRE_REGS_REG].size);
pci->reg = (uint64_t *) hw_map(paddr, reg[SABRE_INTERNAL_REG].size);
 
return pci;
}
116,9 → 114,9
 
/** Initialize the Psycho PCI controller.
*
* @param node OpenFirmware device tree node of the Psycho.
* @param node OpenFirmware device tree node of the Psycho.
*
* @return Address of the initialized PCI structure.
* @return Address of the initialized PCI structure.
*/
pci_t *pci_psycho_init(ofw_tree_node_t *node)
{
135,11 → 133,12
ofw_upa_reg_t *reg = prop->value;
count_t regs = prop->size / sizeof(ofw_upa_reg_t);
 
if (regs < PCI_PSYCHO_REGS_REG + 1)
if (regs < PSYCHO_INTERNAL_REG + 1)
return NULL;
 
uintptr_t paddr;
if (!ofw_upa_apply_ranges(node->parent, &reg[PCI_PSYCHO_REGS_REG], &paddr))
if (!ofw_upa_apply_ranges(node->parent, &reg[PSYCHO_INTERNAL_REG],
&paddr))
return NULL;
 
pci = (pci_t *) malloc(sizeof(pci_t), FRAME_ATOMIC);
148,31 → 147,21
 
pci->model = PCI_PSYCHO;
pci->op = &pci_psycho_ops;
pci->reg = (uint64_t *) hw_map(paddr, reg[PCI_PSYCHO_REGS_REG].size);
pci->reg = (uint64_t *) hw_map(paddr, reg[PSYCHO_INTERNAL_REG].size);
 
return pci;
}
 
void pci_sabre_enable_interrupt(pci_t *pci, int inr)
void obio_enable_interrupt(pci_t *pci, int inr)
{
pci->reg[PCI_SABRE_IMAP_BASE + (inr & INO_MASK)] |= IMAP_V_MASK;
pci->reg[OBIO_IMR(inr & INO_MASK)] |= IMAP_V_MASK;
}
 
void pci_sabre_clear_interrupt(pci_t *pci, int inr)
void obio_clear_interrupt(pci_t *pci, int inr)
{
pci->reg[PCI_SABRE_ICLR_BASE + (inr & INO_MASK)] = 0;
pci->reg[OBIO_CIR(inr & INO_MASK)] = 0; /* set IDLE */
}
 
void pci_psycho_enable_interrupt(pci_t *pci, int inr)
{
pci->reg[PCI_PSYCHO_IMAP_BASE + (inr & INO_MASK)] |= IMAP_V_MASK;
}
 
void pci_psycho_clear_interrupt(pci_t *pci, int inr)
{
pci->reg[PCI_PSYCHO_ICLR_BASE + (inr & INO_MASK)] = 0;
}
 
/** Initialize PCI controller. */
pci_t *pci_init(ofw_tree_node_t *node)
{
215,14 → 204,14
 
void pci_enable_interrupt(pci_t *pci, int inr)
{
ASSERT(pci->model);
ASSERT(pci->op && pci->op->enable_interrupt);
pci->op->enable_interrupt(pci, inr);
}
 
void pci_clear_interrupt(pci_t *pci, int inr)
void pci_clear_interrupt(void *pcip, int inr)
{
ASSERT(pci->model);
pci_t *pci = (pci_t *)pcip;
 
ASSERT(pci->op && pci->op->clear_interrupt);
pci->op->clear_interrupt(pci, inr);
}
/branches/tracing/kernel/arch/sparc64/src/start.S
27,6 → 27,7
#
 
#include <arch/arch.h>
#include <arch/cpu.h>
#include <arch/regdef.h>
#include <arch/boot/boot.h>
#include <arch/stack.h>
47,6 → 48,16
#define BSP_FLAG 1
 
/*
* 2^PHYSMEM_ADDR_SIZE is the size of the physical address space on
* a given processor.
*/
#if defined (US)
#define PHYSMEM_ADDR_SIZE 41
#elif defined (US3)
#define PHYSMEM_ADDR_SIZE 43
#endif
 
/*
* Here is where the kernel is passed control from the boot loader.
*
* The registers are expected to be in this state:
67,11 → 78,13
and %o0, %l0, %l7 ! l7 <= bootstrap processor?
andn %o0, %l0, %l6 ! l6 <= start of physical memory
 
! Get bits 40:13 of physmem_base.
! Get bits (PHYSMEM_ADDR_SIZE - 1):13 of physmem_base.
srlx %l6, 13, %l5
sllx %l5, 13 + (63 - 40), %l5
srlx %l5, 63 - 40, %l5 ! l5 <= physmem_base[40:13]
! l5 <= physmem_base[(PHYSMEM_ADDR_SIZE - 1):13]
sllx %l5, 13 + (63 - (PHYSMEM_ADDR_SIZE - 1)), %l5
srlx %l5, 63 - (PHYSMEM_ADDR_SIZE - 1), %l5
/*
* Setup basic runtime environment.
*/
83,6 → 96,8
! consistent
wrpr %g0, NWINDOWS - 1, %cleanwin ! prevent needless clean_window
! traps for kernel
wrpr %g0, 0, %wstate ! use default spill/fill trap
 
wrpr %g0, 0, %tl ! TL = 0, primary context
! register is used
244,7 → 259,8
 
/*
* Precompute kernel 8K TLB data template.
* %l5 contains starting physical address bits [40:13]
* %l5 contains starting physical address
* bits [(PHYSMEM_ADDR_SIZE - 1):13]
*/
sethi %hi(kernel_8k_tlb_data_template), %l4
ldx [%l4 + %lo(kernel_8k_tlb_data_template)], %l3
282,15 → 298,32
nop
 
 
1:
#ifdef CONFIG_SMP
/*
* Determine the width of the MID and save its mask to %g3. The width
* is
* * 5 for US and US-IIIi,
* * 10 for US3 except US-IIIi.
*/
#if defined(US)
mov 0x1f, %g3
#elif defined(US3)
mov 0x3ff, %g3
rdpr %ver, %g2
sllx %g2, 16, %g2
srlx %g2, 48, %g2
cmp %g2, IMPL_ULTRASPARCIII_I
move %xcc, 0x1f, %g3
#endif
 
/*
* Read MID from the processor.
*/
1:
ldxa [%g0] ASI_UPA_CONFIG, %g1
srlx %g1, UPA_CONFIG_MID_SHIFT, %g1
and %g1, UPA_CONFIG_MID_MASK, %g1
ldxa [%g0] ASI_ICBUS_CONFIG, %g1
srlx %g1, ICBUS_CONFIG_MID_SHIFT, %g1
and %g1, %g3, %g1
 
#ifdef CONFIG_SMP
/*
* Active loop for APs until the BSP picks them up. A processor cannot
* leave the loop until the global variable 'waking_up_mid' equals its
/branches/tracing/kernel/arch/ia64/include/interrupt.h
50,10 → 50,13
#define IVT_FIRST 0
 
/** External Interrupt vectors. */
 
#define VECTOR_TLB_SHOOTDOWN_IPI 0xf0
#define INTERRUPT_TIMER 255
#define IRQ_KBD 241
#define IRQ_MOUSE 252
#define IRQ_KBD (0x01+LAGACY_INTERRUPT_BASE)
#define IRQ_MOUSE (0x0c+LAGACY_INTERRUPT_BASE)
#define INTERRUPT_SPURIOUS 15
#define LAGACY_INTERRUPT_BASE 0x20
 
/** General Exception codes. */
#define GE_ILLEGALOP 0
150,6 → 153,7
extern void external_interrupt(uint64_t vector, istate_t *istate);
extern void disabled_fp_register(uint64_t vector, istate_t *istate);
 
 
#endif
 
/** @}
/branches/tracing/kernel/arch/ia64/include/proc/task.h
31,14 → 31,19
*/
/** @file
*/
#include <proc/task.h>
 
#ifndef KERN_ia64_TASK_H_
#define KERN_ia64_TASK_H_
 
#include <adt/bitmap.h>
 
typedef struct {
bitmap_t *iomap;
} task_arch_t;
 
#define task_create_arch(t)
 
#define task_create_arch(t) {(t)->arch.iomap=NULL;}
#define task_destroy_arch(t)
 
#endif
/branches/tracing/kernel/arch/ia64/include/bootinfo.h
67,6 → 67,7
unsigned long sys_freq;
unsigned long freq_scale;
unsigned int wakeup_intno;
int hello_configured;
 
} bootinfo_t;
 
/branches/tracing/kernel/arch/ia64/include/mm/page.h
48,8 → 48,15
#define IO_PAGE_WIDTH 26 /* 64M */
#define FW_PAGE_WIDTH 28 /* 256M */
 
/** Staticly mapped IO spaces */
#define USPACE_IO_PAGE_WIDTH 12 /* 4K */
 
 
 
/** Staticly mapped IO spaces - offsets to 0xe...00 of virtual adresses
becauce of "minimal virtual bits implemented is 51"
it is possible to have here values up to 0x0007000000000000
*/
 
/* Firmware area (bellow 4GB in phys mem) */
#define FW_OFFSET 0x00000000F0000000
/* Legacy IO space */
/branches/tracing/kernel/arch/ia64/include/mm/tlb.h
46,8 → 46,8
/** Data and instruction Translation Register indices. */
#define DTR_KERNEL 0
#define ITR_KERNEL 0
#define DTR_KSTACK1 1
#define DTR_KSTACK2 2
#define DTR_KSTACK1 4
#define DTR_KSTACK2 5
 
/** Portion of TLB insertion format data structure. */
union tlb_entry {
/branches/tracing/kernel/arch/ia64/include/cpu.h
87,6 → 87,8
static inline void ipi_send_ipi(int id,int eid,int intno)
{
(bootinfo->sapic)[2*(id*256+eid)]=intno;
srlz_d();
 
}
 
 
/branches/tracing/kernel/arch/ia64/include/drivers/kbd.h
0,0 → 1,48
/*
* Copyright (c) 2006 Jakub Jermar, Jakub Vana
* 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 ia6464
* @{
*/
/** @file
*/
 
#ifndef KERN_ia64_KBD_H_
#define KERN_ia64_KBD_H_
 
 
#define KBD_UNKNOWN 0
#define KBD_SKI 1
#define KBD_LEGACY 2
#define KBD_NS16550 3
 
 
#endif
 
/** @}
*/
/branches/tracing/kernel/arch/ia64/src/ia64.c
60,13 → 60,16
#include <arch/atomic.h>
#include <panic.h>
#include <print.h>
#include <sysinfo/sysinfo.h>
 
/*NS16550 as a COM 1*/
#define NS16550_IRQ 4
#define NS16550_IRQ (4+LAGACY_INTERRUPT_BASE)
#define NS16550_PORT 0x3f8
 
bootinfo_t *bootinfo;
 
static uint64_t iosapic_base=0xfec00000;
 
void arch_pre_main(void)
{
/* Setup usermode init tasks. */
110,10 → 113,40
}
 
static void iosapic_init(void)
{
 
uint64_t IOSAPIC = PA2KA((unative_t)(iosapic_base))|FW_OFFSET;
int i;
int myid,myeid;
myid=ia64_get_cpu_id();
myeid=ia64_get_cpu_eid();
 
for(i=0;i<16;i++)
{
if(i==2) continue; //Disable Cascade interrupt
((uint32_t*)(IOSAPIC+0x00))[0]=0x10+2*i;
srlz_d();
((uint32_t*)(IOSAPIC+0x10))[0]=LAGACY_INTERRUPT_BASE+i;
srlz_d();
((uint32_t*)(IOSAPIC+0x00))[0]=0x10+2*i+1;
srlz_d();
((uint32_t*)(IOSAPIC+0x10))[0]=myid<<(56-32) | myeid<<(48-32);
srlz_d();
}
 
}
 
 
void arch_post_mm_init(void)
{
if(config.cpu_active==1)
{
iosapic_init();
irq_init(INR_COUNT, INR_COUNT);
#ifdef SKI
ski_init_console();
121,7 → 154,8
ega_init();
#endif
}
it_init();
it_init();
}
 
void arch_post_cpu_init(void)
139,9 → 173,14
static void i8042_kkbdpoll(void *arg)
{
while (1) {
i8042_poll();
#ifdef CONFIG_NS16550
#ifndef CONFIG_NS16550_INTERRUPT_DRIVEN
ns16550_poll();
#endif
#else
#ifndef CONFIG_I8042_INTERRUPT_DRIVEN
i8042_poll();
#endif
#endif
thread_usleep(POLL_INTERVAL);
}
148,6 → 187,14
}
#endif
 
 
void end_of_irq_void(void *cir_arg __attribute__((unused)),inr_t inr __attribute__((unused)));
void end_of_irq_void(void *cir_arg __attribute__((unused)),inr_t inr __attribute__((unused)))
{
return;
}
 
 
void arch_post_smp_init(void)
{
 
165,13 → 212,13
 
#ifdef I460GX
devno_t kbd = device_assign_devno();
devno_t mouse = device_assign_devno();
/* keyboard controller */
i8042_init(kbd, IRQ_KBD, mouse, IRQ_MOUSE);
 
#ifdef CONFIG_NS16550
ns16550_init(kbd, NS16550_IRQ, NS16550_PORT); // as a COM 1
ns16550_init(kbd, NS16550_PORT, NS16550_IRQ,end_of_irq_void,NULL); // as a COM 1
#else
devno_t mouse = device_assign_devno();
i8042_init(kbd, IRQ_KBD, mouse, IRQ_MOUSE);
#endif
thread_t *t;
t = thread_create(i8042_kkbdpoll, NULL, TASK, 0, "kkbdpoll", true);
182,6 → 229,15
#endif
 
}
sysinfo_set_item_val("ia64_iospace", NULL, true);
sysinfo_set_item_val("ia64_iospace.address", NULL, true);
sysinfo_set_item_val("ia64_iospace.address.virtual", NULL, IO_OFFSET);
 
 
 
 
 
}
 
 
231,6 → 287,12
{
#ifdef SKI
ski_kbd_grab();
#else
#ifdef CONFIG_NS16550
ns16550_grab();
#else
i8042_grab();
#endif
#endif
}
/** Return console to userspace
240,6 → 302,13
{
#ifdef SKI
ski_kbd_release();
#else
#ifdef CONFIG_NS16550
ns16550_release();
#else
i8042_release();
#endif
 
#endif
}
 
/branches/tracing/kernel/arch/ia64/src/ski/ski.c
44,6 → 44,7
#include <proc/thread.h>
#include <synch/spinlock.h>
#include <arch/asm.h>
#include <arch/drivers/kbd.h>
 
#define SKI_KBD_INR 0
 
227,6 → 228,7
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.inr", NULL, SKI_KBD_INR);
sysinfo_set_item_val("kbd.devno", NULL, ski_kbd_devno);
sysinfo_set_item_val("kbd.type", NULL, KBD_SKI);
}
 
void ski_kbd_grab(void)
/branches/tracing/kernel/arch/ia64/src/smp/smp.c
96,12 → 96,28
 
void ipi_broadcast_arch(int ipi )
{
ipi_broadcast_arch_all(ipi);
int id,eid;
int myid,myeid;
myid=ia64_get_cpu_id();
myeid=ia64_get_cpu_eid();
 
//printf("Sending ipi %d on %d\n",ipi,CPU->id);
for(id=0;id<256;id++)
for(eid=0;eid<256;eid++)
if((id!=myid) || (eid!=myeid))
if(cpu_by_id_eid_list[id][eid])
ipi_send_ipi(id,eid,ipi);
 
}
 
 
void smp_init(void)
{
if(!bootinfo->hello_configured) return;
//If we have not system prepared by hello, we are not able to start AP's
//this means we are running on simulator
sapic_init();
ipi_broadcast_arch_all(bootinfo->wakeup_intno);
volatile long long brk;
/branches/tracing/kernel/arch/ia64/src/ddi/ddi.c
1,5 → 1,5
/*
* Copyright (c) 2006 Jakub Jermar
* Copyright (c) 2006 Jakub Jermar, Jakub vana
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
35,7 → 35,12
#include <ddi/ddi.h>
#include <proc/task.h>
#include <arch/types.h>
#include <mm/slab.h>
#include <errno.h>
 
#define IO_MEMMAP_PAGES 16384
#define PORTS_PER_PAGE 4
 
/** Enable I/O space range for task.
*
* Interrupts are disabled and task is locked.
48,6 → 53,23
*/
int ddi_iospace_enable_arch(task_t *task, uintptr_t ioaddr, size_t size)
{
 
if(!task->arch.iomap)
{
uint8_t *map;
task->arch.iomap=malloc(sizeof(bitmap_t),0);
map=malloc(BITS2BYTES(IO_MEMMAP_PAGES),0);
if(!map)
return ENOMEM;
bitmap_initialize(task->arch.iomap,map,IO_MEMMAP_PAGES);
bitmap_clear_range(task->arch.iomap,0,IO_MEMMAP_PAGES);
}
uintptr_t iopage = ioaddr / PORTS_PER_PAGE;
size = ALIGN_UP (size+ioaddr-4*iopage,PORTS_PER_PAGE);
bitmap_set_range(task->arch.iomap,iopage,size/4);
 
 
return 0;
}
 
/branches/tracing/kernel/arch/ia64/src/mm/tlb.c
475,6 → 475,73
}
}
 
 
 
static int is_io_page_accessible(int page)
{
if(TASK->arch.iomap) return bitmap_get(TASK->arch.iomap,page);
else return 0;
}
 
#define IO_FRAME_BASE 0xFFFFC000000
 
/** There is special handling of memmaped lagacy io, because
* of 4KB sized access
* only for userspace
*
* @param va virtual address of page fault
* @param istate Structure with saved interruption state.
*
*
* @return 1 on success, 0 on fail
*/
static int try_memmap_io_insertion(uintptr_t va, istate_t *istate)
{
if((va >= IO_OFFSET ) && (va < IO_OFFSET + (1<<IO_PAGE_WIDTH)))
if(TASK){
uint64_t io_page=(va & ((1<<IO_PAGE_WIDTH)-1)) >> (USPACE_IO_PAGE_WIDTH);
if(is_io_page_accessible(io_page)){
//printf("Insert %llX\n",va);
 
uint64_t page,frame;
 
page = IO_OFFSET + (1 << USPACE_IO_PAGE_WIDTH) * io_page;
frame = IO_FRAME_BASE + (1 << USPACE_IO_PAGE_WIDTH) * io_page;
 
 
tlb_entry_t entry;
entry.word[0] = 0;
entry.word[1] = 0;
entry.p = true; /* present */
entry.ma = MA_UNCACHEABLE;
entry.a = true; /* already accessed */
entry.d = true; /* already dirty */
entry.pl = PL_USER;
entry.ar = AR_READ | AR_WRITE;
entry.ppn = frame >> PPN_SHIFT; //MUSIM spocitat frame
entry.ps = USPACE_IO_PAGE_WIDTH;
dtc_mapping_insert(page, TASK->as->asid, entry); //Musim zjistit ASID
return 1;
}else {
fault_if_from_uspace(istate,"IO access fault at %p",va);
return 0;
}
} else
return 0;
else
return 0;
return 0;
 
}
 
 
 
 
/** Data TLB fault handler for faults with VHPT turned off.
*
* @param vector Interruption vector.
511,10 → 578,11
dtc_pte_copy(t);
page_table_unlock(AS, true);
} else {
page_table_unlock(AS, true);
if (try_memmap_io_insertion(va,istate)) return;
/*
* Forward the page fault to the address space page fault handler.
*/
page_table_unlock(AS, true);
if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
fault_if_from_uspace(istate,"Page fault at %p",va);
panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip);
/branches/tracing/kernel/arch/ia64/src/interrupt.c
53,6 → 53,7
#include <ipc/irq.h>
#include <ipc/ipc.h>
#include <synch/spinlock.h>
#include <mm/tlb.h>
 
#define VECTORS_64_BUNDLE 20
#define VECTORS_16_BUNDLE 48
234,19 → 235,19
vector_to_string(vector));
}
 
static void end_of_local_irq(void)
{
asm volatile ("mov cr.eoi=r0;;");
}
 
 
void external_interrupt(uint64_t vector, istate_t *istate)
{
irq_t *irq;
cr_ivr_t ivr;
ivr.value = ivr_read();
srlz_d();
 
irq = irq_dispatch_and_lock(ivr.vector);
if (irq) {
irq->handler(irq, irq->arg);
spinlock_unlock(&irq->lock);
} else {
switch (ivr.vector) {
case INTERRUPT_SPURIOUS:
#ifdef CONFIG_DEBUG
254,12 → 255,60
#endif
break;
 
#ifdef CONFIG_SMP
case VECTOR_TLB_SHOOTDOWN_IPI:
tlb_shootdown_ipi_recv();
end_of_local_irq();
break;
#endif
 
case INTERRUPT_TIMER:
{
 
irq_t *irq = irq_dispatch_and_lock(ivr.vector);
if (irq) {
irq->handler(irq, irq->arg);
spinlock_unlock(&irq->lock);
} else {
panic("\nUnhandled Internal Timer Interrupt (%d)\n",ivr.vector);
}
}
break;
default:
panic("\nUnhandled External Interrupt Vector %d\n",
ivr.vector);
{
 
int ack=false;
irq_t *irq = irq_dispatch_and_lock(ivr.vector);
if (irq) {
/*
* The IRQ handler was found.
*/
if (irq->preack) {
/* Send EOI before processing the interrupt */
end_of_local_irq();
ack=true;
}
irq->handler(irq, irq->arg);
spinlock_unlock(&irq->lock);
} else {
/*
* Unhandled interrupt.
*/
end_of_local_irq();
ack=true;
#ifdef CONFIG_DEBUG
printf("\nUnhandled External Interrupt Vector %d\n",ivr.vector);
#endif
}
if(!ack) end_of_local_irq();
 
}
 
 
break;
}
}
}
 
/** @}
/branches/tracing/kernel/arch/ia64/src/drivers/ega.c
46,12 → 46,18
#include <console/console.h>
#include <sysinfo/sysinfo.h>
#include <arch/drivers/ega.h>
#include <ddi/ddi.h>
 
 
/*
* The EGA driver.
* Simple and short. Function for displaying characters and "scrolling".
*/
 
 
static parea_t ega_parea; /**< Physical memory area for EGA video RAM. */
 
 
SPINLOCK_INITIALIZE(egalock);
static uint32_t ega_cursor;
static uint8_t *videoram;
75,12 → 81,21
 
chardev_initialize("ega_out", &ega_console, &ega_ops);
stdout = &ega_console;
 
 
ega_parea.pbase = VIDEORAM & 0xffffffff;
ega_parea.vbase = (uintptr_t) videoram;
ega_parea.frames = 1;
ega_parea.cacheable = false;
ddi_parea_register(&ega_parea);
 
sysinfo_set_item_val("fb", NULL, true);
sysinfo_set_item_val("fb.kind", NULL, 2);
sysinfo_set_item_val("fb.width", NULL, ROW);
sysinfo_set_item_val("fb.height", NULL, ROWS);
sysinfo_set_item_val("fb.address.physical", NULL, VIDEORAM);
sysinfo_set_item_val("fb.blinking", NULL, true);
sysinfo_set_item_val("fb.address.physical", NULL, VIDEORAM & 0xffffffff);
#ifndef CONFIG_FB
putchar('\n');
/branches/tracing/kernel/arch/arm32/src/arm32.c
86,7 → 86,15
console_init(device_assign_devno());
 
#ifdef CONFIG_FB
fb_init(machine_get_fb_address(), 640, 480, 1920, VISUAL_RGB_8_8_8);
fb_properties_t prop = {
.addr = machine_get_fb_address(),
.offset = 0,
.x = 640,
.y = 480,
.scan = 1920,
.visual = VISUAL_RGB_8_8_8,
};
fb_init(&prop);
#endif
}
 
/branches/tracing/kernel/arch/ppc32/src/ppc32.c
94,7 → 94,15
default:
panic("Unsupported bits per pixel");
}
fb_init(bootinfo.screen.addr, bootinfo.screen.width, bootinfo.screen.height, bootinfo.screen.scanline, visual);
fb_properties_t prop = {
.addr = bootinfo.screen.addr,
.offset = 0,
.x = bootinfo.screen.width,
.y = bootinfo.screen.height,
.scan = bootinfo.screen.scanline,
.visual = visual,
};
fb_init(&prop);
/* Initialize IRQ routing */
irq_init(IRQ_COUNT, IRQ_COUNT);
103,7 → 111,8
pic_init(bootinfo.keyboard.addr, PAGE_SIZE);
/* Initialize I/O controller */
cuda_init(device_assign_devno(), bootinfo.keyboard.addr + 0x16000, 2 * PAGE_SIZE);
cuda_init(device_assign_devno(),
bootinfo.keyboard.addr + 0x16000, 2 * PAGE_SIZE);
/* Merge all zones to 1 big zone */
zone_merge_all();
128,7 → 137,10
 
void userspace(uspace_arg_t *kernel_uarg)
{
userspace_asm((uintptr_t) kernel_uarg->uspace_uarg, (uintptr_t) kernel_uarg->uspace_stack + THREAD_STACK_SIZE - SP_DELTA, (uintptr_t) kernel_uarg->uspace_entry);
userspace_asm((uintptr_t) kernel_uarg->uspace_uarg,
(uintptr_t) kernel_uarg->uspace_stack +
THREAD_STACK_SIZE - SP_DELTA,
(uintptr_t) kernel_uarg->uspace_entry);
/* Unreachable */
for (;;)
/branches/tracing/kernel/arch/mips32/src/mips32.c
126,7 → 126,15
console_init(device_assign_devno());
#ifdef CONFIG_FB
/* GXemul framebuffer */
fb_init(0x12000000, 640, 480, 1920, VISUAL_RGB_8_8_8);
fb_properties_t gxemul_prop = {
.addr = 0x12000000,
.offset = 0,
.x = 640,
.y = 480,
.scan = 1920,
.visual = VISUAL_RGB_8_8_8,
};
fb_init(&gxemul_prop);
#endif
sysinfo_set_item_val("machine." STRING(MACHINE), NULL, 1);
}
/branches/tracing/kernel/arch/ia32/src/asm.S
158,6 → 158,7
*/
.global sysenter_handler
sysenter_handler:
sti
pushl %ebp # remember user stack
pushl %edi # remember return user address
 
/branches/tracing/kernel/arch/ia32/src/drivers/vesa.c
86,7 → 86,15
panic("Unsupported bits per pixel");
}
fb_init(vesa_ph_addr, vesa_width, vesa_height, vesa_scanline, visual);
fb_properties_t vesa_props = {
.addr = vesa_ph_addr,
.offset = 0,
.x = vesa_width,
.y = vesa_height,
.scan = vesa_scanline,
.visual = visual,
};
fb_init(&vesa_props);
}
 
#endif
/branches/tracing/uspace/app/bdsh/cmds/modules/cp/cp.c
30,6 → 30,11
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include "config.h"
#include "util.h"
#include "errors.h"
37,37 → 42,183
#include "cp.h"
#include "cmds.h"
 
static char *cmdname = "cp";
#define CP_VERSION "0.0.1"
#define CP_DEFAULT_BUFLEN 1024
 
/* Dispays help for cp in various levels */
static const char *cmdname = "cp";
 
static struct option const long_options[] = {
{ "buffer", required_argument, 0, 'b' },
{ "force", no_argument, 0, 'f' },
{ "recursive", no_argument, 0, 'r' },
{ "help", no_argument, 0, 'h' },
{ "version", no_argument, 0, 'v' },
{ "verbose", no_argument, 0, 'V' },
{ 0, 0, 0, 0 }
};
 
static int strtoint(const char *s1)
{
long t1;
 
if (-1 == (t1 = strtol(s1, (char **) NULL, 10)))
return -1;
 
if (t1 <= 0)
return -1;
 
return (int) t1;
}
 
static int64_t copy_file(const char *src, const char *dest, size_t blen, int vb)
{
int fd1, fd2, bytes = 0;
off_t total = 0;
int64_t copied = 0;
char *buff = NULL;
 
if (vb)
printf("Copying %s to %s\n", src, dest);
 
if (-1 == (fd1 = open(src, O_RDONLY))) {
printf("Unable to open source file %s\n", src);
return -1;
}
 
if (-1 == (fd2 = open(dest, O_CREAT))) {
printf("Unable to open destination file %s\n", dest);
close(fd1);
return -1;
}
 
total = lseek(fd1, 0, SEEK_END);
 
if (vb)
printf("%d bytes to copy\n", total);
 
lseek(fd1, 0, SEEK_SET);
 
if (NULL == (buff = (char *) malloc(blen))) {
printf("Unable to allocate enough memory to read %s\n",
src);
copied = -1;
goto out;
}
 
for (;;) {
ssize_t res;
 
bytes = read(fd1, buff, blen);
if (bytes <= 0)
break;
copied += bytes;
res = bytes;
do {
/*
* Theoretically, it may not be enough to call write()
* only once. Also the previous read() may have
* returned less data than requested.
*/
bytes = write(fd2, buff, res);
if (bytes < 0)
goto err;
res -= bytes;
} while (res > 0);
assert(res == 0);
}
 
if (bytes < 0) {
err:
printf("Error copying %s, (%d)\n", src, bytes);
copied = bytes;
}
 
out:
close(fd1);
close(fd2);
if (buff)
free(buff);
return copied;
}
 
void help_cmd_cp(unsigned int level)
{
printf("This is the %s help for '%s'.\n",
level ? EXT_HELP : SHORT_HELP, cmdname);
static char helpfmt[] =
"Usage: %s [options] <source> <dest>\n"
"Options: (* indicates not yet implemented)\n"
" -h, --help A short option summary\n"
" -v, --version Print version information and exit\n"
"* -V, --verbose Be annoyingly noisy about what's being done\n"
"* -f, --force Do not complain when <dest> exists\n"
"* -r, --recursive Copy entire directories\n"
" -b, --buffer ## Set the read buffer size to ##\n"
"Currently, %s is under development, some options may not work.\n";
if (level == HELP_SHORT) {
printf("`%s' copies files and directories\n", cmdname);
} else {
help_cmd_cp(HELP_SHORT);
printf(helpfmt, cmdname, cmdname);
}
 
return;
}
 
/* Main entry point for cp, accepts an array of arguments */
int cmd_cp(char **argv)
{
unsigned int argc;
unsigned int i;
unsigned int argc, buffer = 0, verbose = 0;
int c, opt_ind;
int64_t ret;
 
/* Count the arguments */
for (argc = 0; argv[argc] != NULL; argc ++);
argc = cli_count_args(argv);
 
printf("%s %s\n", TEST_ANNOUNCE, cmdname);
printf("%d arguments passed to %s", argc - 1, cmdname);
for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
c = getopt_long(argc, argv, "hvVfrb:", long_options, &opt_ind);
switch (c) {
case 'h':
help_cmd_cp(1);
return CMD_SUCCESS;
case 'v':
printf("%d\n", CP_VERSION);
return CMD_SUCCESS;
case 'V':
verbose = 1;
break;
case 'f':
break;
case 'r':
break;
case 'b':
if (-1 == (buffer = strtoint(optarg))) {
printf("%s: Invalid buffer specification, "
"(should be a number greater than zero)\n",
cmdname);
return CMD_FAILURE;
}
if (verbose)
printf("Buffer = %d\n", buffer);
break;
}
}
 
if (argc < 2) {
printf("\n");
return CMD_SUCCESS;
if (buffer == 0)
buffer = CP_DEFAULT_BUFLEN;
 
argc -= optind;
 
if (argc != 2) {
printf("%s: invalid number of arguments. Try %s --help\n",
cmdname, cmdname);
return CMD_FAILURE;
}
 
printf(":\n");
for (i = 1; i < argc; i++)
printf("[%d] -> %s\n", i, argv[i]);
ret = copy_file(argv[optind], argv[optind + 1], buffer, verbose);
 
return CMD_SUCCESS;
if (verbose)
printf("%d bytes copied\n", ret);
 
if (ret >= 0)
return CMD_SUCCESS;
else
return CMD_FAILURE;
}
 
/branches/tracing/uspace/app/init/init.c
112,6 → 112,7
console_wait();
version_print();
spawn("/app/klog");
spawn("/app/bdsh");
return 0;
/branches/tracing/uspace/dist/readme
0,0 → 1,0
Lorem ipsum.
/branches/tracing/uspace/lib/libfs/libfs.c
196,12 → 196,15
nodep = ops->node_get(dev_handle,
index);
if (nodep) {
if (!ops->link(cur, nodep, component)) {
int rc;
 
rc = ops->link(cur, nodep, component);
if (rc != EOK) {
if (lflag & L_CREATE) {
(void)ops->destroy(
nodep);
}
ipc_answer_0(rid, ENOSPC);
ipc_answer_0(rid, rc);
} else {
ipc_answer_5(rid, EOK,
fs_handle, dev_handle,
266,10 → 269,13
else
nodep = ops->node_get(dev_handle, index);
if (nodep) {
if (!ops->link(cur, nodep, component)) {
int rc;
 
rc = ops->link(cur, nodep, component);
if (rc != EOK) {
if (lflag & L_CREATE)
(void)ops->destroy(nodep);
ipc_answer_0(rid, ENOSPC);
ipc_answer_0(rid, rc);
} else {
ipc_answer_5(rid, EOK,
fs_handle, dev_handle,
/branches/tracing/uspace/lib/libfs/libfs.h
47,7 → 47,7
void (* node_put)(void *);
void * (* create)(dev_handle_t, int);
int (* destroy)(void *);
bool (* link)(void *, void *, const char *);
int (* link)(void *, void *, const char *);
int (* unlink)(void *, void *);
fs_index_t (* index_get)(void *);
size_t (* size_get)(void *);
/branches/tracing/uspace/lib/libc/include/libc.h
39,12 → 39,18
#include <kernel/syscall/syscall.h>
#include <libarch/syscall.h>
 
#define __SYSCALL0(id) __syscall0(0, 0, 0, 0, 0, 0, id)
#define __SYSCALL1(id, p1) __syscall1(p1, 0, 0, 0, 0, 0, id)
#define __SYSCALL2(id, p1, p2) __syscall2(p1, p2, 0, 0, 0, 0, id)
#define __SYSCALL3(id, p1, p2, p3) __syscall3(p1, p2, p3, 0, 0, 0, id)
#define __SYSCALL4(id, p1, p2, p3, p4) __syscall4(p1, p2, p3, p4, 0, 0, id)
#define __SYSCALL5(id, p1, p2, p3, p4, p5) __syscall5(p1, p2, p3, p4, p5, 0, id)
#define __SYSCALL0(id) \
__syscall0(0, 0, 0, 0, 0, 0, id)
#define __SYSCALL1(id, p1) \
__syscall1(p1, 0, 0, 0, 0, 0, id)
#define __SYSCALL2(id, p1, p2) \
__syscall2(p1, p2, 0, 0, 0, 0, id)
#define __SYSCALL3(id, p1, p2, p3) \
__syscall3(p1, p2, p3, 0, 0, 0, id)
#define __SYSCALL4(id, p1, p2, p3, p4) \
__syscall4(p1, p2, p3, p4, 0, 0, id)
#define __SYSCALL5(id, p1, p2, p3, p4, p5) \
__syscall5(p1, p2, p3, p4, p5, 0, id)
#define __SYSCALL6(id, p1, p2, p3, p4, p5, p6) \
__syscall6(p1, p2, p3, p4, p5, p6, id)
 
/branches/tracing/uspace/lib/libc/include/ctype.h
79,11 → 79,19
static inline int tolower(int c)
{
if (isupper(c))
return (c + ('a' - 'A' > 0 ? 'a' - 'A' : 'A' - 'a'));
return (c + ('a' - 'A'));
else
return c;
}
 
static inline int toupper(int c)
{
if (islower(c))
return (c + ('A' - 'a'));
else
return c;
}
 
#endif
 
/** @}
/branches/tracing/uspace/lib/libc/include/ipc/loader.h
44,7 → 44,7
LOADER_SET_ARGS,
LOADER_LOAD,
LOADER_RUN
} fb_request_t;
} loader_request_t;
 
#endif
 
/branches/tracing/uspace/lib/libc/include/errno.h
47,6 → 47,7
#define ERANGE (-263)
#define EXDEV (-264)
#define EIO (-265)
#define EMLINK (-266)
 
#endif
 
/branches/tracing/uspace/lib/libc/arch/ia64/include/ddi.h
0,0 → 1,98
/*
* Copyright (c) 2005 Jakub Jermar, Jakub Vana
* 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 LIBC_ia64_DDI_H_
#define LIBC_ia64_DDI_H_
 
#include <libarch/types.h>
 
typedef uint64_t ioport_t;
 
uint64_t get_ia64_iospace_address(void);
 
extern uint64_t ia64_iospace_address;
 
#define IA64_IOSPACE_ADDRESS (ia64_iospace_address?ia64_iospace_address:(ia64_iospace_address=get_ia64_iospace_address()))
 
static inline void outb(ioport_t port,uint8_t v)
{
*((uint8_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
static inline void outw(ioport_t port,uint16_t v)
{
*((uint16_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
static inline void outl(ioport_t port,uint32_t v)
{
*((uint32_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
 
 
static inline uint8_t inb(ioport_t port)
{
asm volatile ("mf\n" ::: "memory");
 
return *((uint8_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 ))));
}
 
static inline uint16_t inw(ioport_t port)
{
asm volatile ("mf\n" ::: "memory");
 
return *((uint16_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xffE) | ( (port >> 2) << 12 ))));
}
 
static inline uint32_t inl(ioport_t port)
{
asm volatile ("mf\n" ::: "memory");
 
return *((uint32_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 ))));
}
 
 
 
 
#endif
 
/** @}
*/
/branches/tracing/uspace/lib/libc/arch/ia64/Makefile.inc
41,7 → 41,8
 
ARCH_SOURCES += arch/$(ARCH)/src/syscall.S \
arch/$(ARCH)/src/fibril.S \
arch/$(ARCH)/src/tls.c
arch/$(ARCH)/src/tls.c\
arch/$(ARCH)/src/ddi.c
 
BFD_NAME = elf64-ia64-little
BFD_ARCH = ia64-elf64
/branches/tracing/uspace/lib/libc/arch/ia64/src/ddi.c
0,0 → 1,13
#include <libarch/ddi.h>
#include <sysinfo.h>
 
uint64_t ia64_iospace_address=0;
 
 
uint64_t get_ia64_iospace_address(void)
{
 
return sysinfo_value("ia64_iospace.address.virtual");
 
}
 
/branches/tracing/uspace/srv/kbd/genarch/include/nofb.h
0,0 → 1,48
/*
* Copyright (c) 2008 Pavel Rimsky
* 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 kbd
* @{
*/
/** @file
*/
 
#ifndef KBD_genarch_NOFB_H_
#define KBD_genarch_NOFB_H_
 
 
#include <key_buffer.h>
#include <genarch/scanc.h>
 
extern int kbd_process_no_fb(keybuffer_t *keybuffer, int scan_code);
 
#endif
 
/**
* @}
*/
/branches/tracing/uspace/srv/kbd/genarch/src/nofb.c
0,0 → 1,187
/*
* Copyright (c) 2006 Josef Cejka
* 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 kbdmips32 mips32
* @brief HelenOS mips32 arch dependent parts of uspace keyboard handler.
* @ingroup kbd
* @{
*/
/** @file
*/
 
#include <genarch/nofb.h>
#include <stdio.h> // DELETE!!!
 
#define KEY_F1 0x504f1bL
#define KEY_F2 0x514f1bL
#define KEY_F3 0x524f1bL
#define KEY_F4 0x534f1bL
#define KEY_F5 0x35315b1bL
#define KEY_F6 0x37315b1bL
#define KEY_F7 0x38315b1bL
#define KEY_F8 0x39315b1bL
#define KEY_F9 0x30325b1bL
#define KEY_F10 0x31325b1bL
#define KEY_F11 0x33325b1bL
#define KEY_F12 0x34325b1bL
 
/**
* Processes the key pressed - pushes the key code into the key buffer.
* Used in MSIM and Serengeti, i.e. non-framebuffer consoles.
*/
int kbd_process_no_fb(keybuffer_t *keybuffer, int scan_code)
{
static unsigned long buf = 0;
static int count = 0;
if(scan_code == 0x7e) {
switch (buf) {
case KEY_F5:
keybuffer_push(keybuffer,FUNCTION_KEYS | 5);
buf = count = 0;
return 1;
case KEY_F6:
keybuffer_push(keybuffer,FUNCTION_KEYS | 6);
buf = count = 0;
return 1;
case KEY_F7:
keybuffer_push(keybuffer,FUNCTION_KEYS | 7);
buf = count = 0;
return 1;
case KEY_F8:
keybuffer_push(keybuffer,FUNCTION_KEYS | 8);
buf = count = 0;
return 1;
case KEY_F9:
keybuffer_push(keybuffer,FUNCTION_KEYS | 9);
buf = count = 0;
return 1;
case KEY_F10:
keybuffer_push(keybuffer,FUNCTION_KEYS | 10);
buf = count = 0;
return 1;
case KEY_F11:
keybuffer_push(keybuffer,FUNCTION_KEYS | 11);
buf = count = 0;
return 1;
case KEY_F12:
keybuffer_push(keybuffer,FUNCTION_KEYS | 12);
buf = count = 0;
return 1;
default:
keybuffer_push(keybuffer, buf & 0xff);
keybuffer_push(keybuffer, (buf >> 8) &0xff);
keybuffer_push(keybuffer, (buf >> 16) &0xff);
keybuffer_push(keybuffer, (buf >> 24) &0xff);
keybuffer_push(keybuffer, scan_code);
buf = count = 0;
return 1;
}
}
 
buf |= ((unsigned long) scan_code)<<(8*(count++));
if((buf & 0xff) != (KEY_F1 & 0xff)) {
keybuffer_push(keybuffer, buf);
buf = count = 0;
return 1;
}
 
if (count <= 1)
return 1;
 
if ((buf & 0xffff) != (KEY_F1 & 0xffff)
&& (buf & 0xffff) != (KEY_F5 & 0xffff) ) {
 
keybuffer_push(keybuffer, buf & 0xff);
keybuffer_push(keybuffer, (buf >> 8) &0xff);
buf = count = 0;
return 1;
}
 
if (count <= 2)
return 1;
 
switch (buf) {
case KEY_F1:
keybuffer_push(keybuffer,FUNCTION_KEYS | 1);
buf = count = 0;
return 1;
case KEY_F2:
keybuffer_push(keybuffer,FUNCTION_KEYS | 2);
buf = count = 0;
return 1;
case KEY_F3:
keybuffer_push(keybuffer,FUNCTION_KEYS | 3);
buf = count = 0;
return 1;
case KEY_F4:
keybuffer_push(keybuffer,FUNCTION_KEYS | 4);
buf = count = 0;
return 1;
}
 
 
if((buf & 0xffffff) != (KEY_F5 & 0xffffff)
&& (buf & 0xffffff) != (KEY_F9 & 0xffffff)) {
 
keybuffer_push(keybuffer, buf & 0xff);
keybuffer_push(keybuffer, (buf >> 8) & 0xff);
keybuffer_push(keybuffer, (buf >> 16) & 0xff);
buf=count=0;
return 1;
}
 
if (count <= 3)
return 1;
switch (buf) {
case KEY_F5:
case KEY_F6:
case KEY_F7:
case KEY_F8:
case KEY_F9:
case KEY_F10:
case KEY_F11:
case KEY_F12:
return 1;
default:
keybuffer_push(keybuffer, buf & 0xff);
keybuffer_push(keybuffer, (buf >> 8) &0xff);
keybuffer_push(keybuffer, (buf >> 16) &0xff);
keybuffer_push(keybuffer, (buf >> 24) &0xff);
buf = count = 0;
return 1;
}
 
return 1;
}
 
/** @}
*/
/branches/tracing/uspace/srv/kbd/Makefile
59,6 → 59,15
genarch/src/kbd.c
CFLAGS += -DMOUSE_ENABLED
endif
ifeq ($(ARCH), ia64)
ARCH_SOURCES += \
arch/$(ARCH)/src/mouse.c \
arch/$(ARCH)/src/scanc.c \
arch/$(ARCH)/src/lkbd.c
GENARCH_SOURCES = \
genarch/src/kbd.c
CFLAGS += -DMOUSE_ENABLED
endif
ifeq ($(ARCH), amd64)
ARCH_SOURCES += \
arch/$(ARCH)/src/mouse.c \
69,16 → 78,21
endif
ifeq ($(ARCH), sparc64)
ARCH_SOURCES += \
arch/$(ARCH)/src/scanc.c
arch/$(ARCH)/src/scanc.c \
arch/$(ARCH)/src/sgcn.c
GENARCH_SOURCES = \
genarch/src/kbd.c
genarch/src/kbd.c \
genarch/src/nofb.c
endif
ifeq ($(ARCH), arm32)
ARCH_SOURCES += \
arch/$(ARCH)/src/kbd_gxemul.c
endif
ifeq ($(ARCH), mips32)
GENARCH_SOURCES += \
genarch/src/nofb.c
endif
 
 
GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES)))
ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES)))
GENARCH_OBJECTS := $(addsuffix .o,$(basename $(GENARCH_SOURCES)))
/branches/tracing/uspace/srv/kbd/arch/sparc64/include/sgcn.h
0,0 → 1,46
/*
* Copyright (c) 2008 Pavel Rimsky
* 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 kbdsparc64 sparc64
* @brief Serengeti-specific parts of uspace keyboard handler.
* @ingroup kbd
* @{
*/
/** @file
*/
 
#ifndef KBD_sparc64_SGCN_H_
#define KBD_sparc64_SGCN_H_
 
void sgcn_init(void);
void sgcn_key_pressed(void);
 
#endif
 
/** @}
*/
/branches/tracing/uspace/srv/kbd/arch/sparc64/src/kbd.c
35,6 → 35,7
*/
 
#include <arch/kbd.h>
#include <arch/sgcn.h>
#include <ipc/ipc.h>
#include <sysinfo.h>
#include <kbd.h>
78,6 → 79,7
 
#define KBD_Z8530 1
#define KBD_NS16550 2
#define KBD_SGCN 3
 
int kbd_arch_init(void)
{
91,6 → 93,9
ns16550_cmds[0].addr = (void *) sysinfo_value("kbd.address.virtual");
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), 0, &ns16550_kbd);
break;
case KBD_SGCN:
sgcn_init();
break;
default:
break;
}
100,6 → 105,11
/** Process keyboard events */
int kbd_arch_process(keybuffer_t *keybuffer, ipc_call_t *call)
{
if (sysinfo_value("kbd.type") == KBD_SGCN) {
sgcn_key_pressed();
return 1;
}
int scan_code = IPC_GET_ARG1(*call);
 
if (scan_code == KBD_ALL_KEYS_UP)
/branches/tracing/uspace/srv/kbd/arch/sparc64/src/sgcn.c
0,0 → 1,147
/*
* Copyright (c) 2008 Pavel Rimsky
* 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 kbdsparc64 sparc64
* @brief Serengeti-specific parts of uspace keyboard handler.
* @ingroup kbd
* @{
*/
/** @file
*/
 
#include <arch/sgcn.h>
#include <as.h>
#include <ddi.h>
#include <ipc/ipc.h>
#include <kbd.h>
#include <genarch/nofb.h>
#include <genarch/kbd.h>
#include <sysinfo.h>
#include <stdio.h>
#include <futex.h>
 
/**
* SGCN buffer header. It is placed at the very beginning of the SGCN
* buffer.
*/
typedef struct {
/** hard-wired to "CON" */
char magic[4];
/** we don't need this */
char unused[8];
/** offset within the SGCN buffer of the input buffer start */
uint32_t in_begin;
/** offset within the SGCN buffer of the input buffer end */
uint32_t in_end;
/** offset within the SGCN buffer of the input buffer read pointer */
uint32_t in_rdptr;
/** offset within the SGCN buffer of the input buffer write pointer */
uint32_t in_wrptr;
} __attribute__ ((packed)) sgcn_buffer_header_t;
 
/*
* Returns a pointer to the object of a given type which is placed at the given
* offset from the console buffer beginning.
*/
#define SGCN_BUFFER(type, offset) \
((type *) (sram_virt_addr + sram_buffer_offset + (offset)))
 
/** Returns a pointer to the console buffer header. */
#define SGCN_BUFFER_HEADER (SGCN_BUFFER(sgcn_buffer_header_t, 0))
 
extern keybuffer_t keybuffer;
 
/**
* Virtual address mapped to SRAM.
*/
static uintptr_t sram_virt_addr;
 
/**
* SGCN buffer offset within SGCN.
*/
static uintptr_t sram_buffer_offset;
 
/**
* Initializes the SGCN driver.
* Maps the physical memory (SRAM) and registers the interrupt.
*/
void sgcn_init(void)
{
sram_virt_addr = (uintptr_t) as_get_mappable_page(
sysinfo_value("sram.area.size"));
int result = physmem_map(
(void *) sysinfo_value("sram.address.physical"),
(void *) sram_virt_addr,
sysinfo_value("sram.area.size") / PAGE_SIZE,
AS_AREA_READ | AS_AREA_WRITE
);
if (result != 0) {
printf("SGCN: uspace driver could not map physical memory.");
}
sram_buffer_offset = sysinfo_value("sram.buffer.offset");
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"),
0, (void *) 0);
}
 
/**
* Handler of the "key pressed" event. Reads codes of all the pressed keys from
* the buffer.
*/
void sgcn_key_pressed(void)
{
char c;
uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
uint32_t end = SGCN_BUFFER_HEADER->in_end;
uint32_t size = end - begin;
volatile char *buf_ptr = (volatile char *)
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
while (*in_rdptr_ptr != *in_wrptr_ptr) {
c = *buf_ptr;
*in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
buf_ptr = (volatile char *)
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
if (c == '\r') {
c = '\n';
}
kbd_process_no_fb(&keybuffer, c);
}
}
 
/** @}
*/
/branches/tracing/uspace/srv/kbd/arch/ia64/include/lkbd.h
0,0 → 1,76
/*
* Copyright (c) 2006 Josef Cejka
* 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 kbdamd64 amd64
* @brief HelenOS ia32 / amd64 arch dependent parts of uspace keyboard and mouse handler.
* @ingroup kbd
* @{
*/
 
/** @file
* @ingroup kbdia32
*/
 
#ifndef KBD_ia32_KBD_H_
#define KBD_ia32_KBD_H_
 
#include <ddi.h>
#include <libarch/ddi.h>
 
#define i8042_DATA 0x60
#define i8042_STATUS 0X64
 
 
typedef unsigned char u8;
typedef short u16;
 
static inline void i8042_data_write(u8 data)
{
outb(i8042_DATA, data);
}
 
static inline u8 i8042_data_read(void)
{
return inb(i8042_DATA);
}
 
static inline u8 i8042_status_read(void)
{
return inb(i8042_STATUS);
}
 
static inline void i8042_command_write(u8 command)
{
outb(i8042_STATUS, command);
}
 
#endif
 
/**
* @}
*/
/branches/tracing/uspace/srv/kbd/arch/ia64/include/scanc.h
0,0 → 1,59
/*
* Copyright (c) 2001-2004 Jakub Jermar
* Copyright (c) 2006 Josef Cejka
* 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 kbdia32
* @{
*/
/** @file
* @ingroup kbdamd64
*/
 
#ifndef KBD_ia32_SCANC_H_
#define KBD_ia32_SCANC_H_
 
/** Scancodes. */
#define SC_ESC 0x01
#define SC_BACKSPACE 0x0e
#define SC_LSHIFT 0x2a
#define SC_RSHIFT 0x36
#define SC_CAPSLOCK 0x3a
#define SC_SPEC_ESCAPE 0xe0
#define SC_LEFTARR 0x4b
#define SC_RIGHTARR 0x4d
#define SC_UPARR 0x48
#define SC_DOWNARR 0x50
#define SC_DELETE 0x53
#define SC_HOME 0x47
#define SC_END 0x4f
 
#endif
 
/**
* @}
*/
/branches/tracing/uspace/srv/kbd/arch/ia64/src/kbd.c
39,7 → 39,30
#include <sysinfo.h>
#include <kbd.h>
#include <keys.h>
#include <stdio.h>
#include <stdlib.h>
 
#include <unistd.h>
#include <align.h>
#include <async.h>
#include <ipc/ipc.h>
#include <errno.h>
#include <stdio.h>
#include <ddi.h>
#include <sysinfo.h>
#include <as.h>
#include <ipc/fb.h>
#include <ipc/ipc.h>
#include <ipc/ns.h>
#include <ipc/services.h>
#include <libarch/ddi.h>
 
 
extern int lkbd_arch_process(keybuffer_t *keybuffer, ipc_call_t *call);
extern int lkbd_arch_init(void);
 
 
 
#define KEY_F1 0x504f1b
#define KEY_F2 0x514f1b
#define KEY_F3 0x524f1b
53,8 → 76,45
#define KEY_F11 0x7e33325b1b
#define KEY_F12 0x7e34325b1b
 
 
 
 
#define NSKEY_F1 0x415b5b1b
#define NSKEY_F2 0x425b5b1b
#define NSKEY_F3 0x435b5b1b
#define NSKEY_F4 0x445b5b1b
#define NSKEY_F5 0x455b5b1b
#define NSKEY_F6 0x37315b1b
#define NSKEY_F7 0x38315b1b
#define NSKEY_F8 0x39315b1b
#define NSKEY_F9 0x30325b1b
#define NSKEY_F10 0x31325b1b
#define NSKEY_F11 0x33325b1b
#define NSKEY_F12 0x34325b1b
 
 
#define FUNCTION_KEYS 0x100
 
 
#define KBD_SKI 1
#define KBD_LEGACY 2
#define KBD_NS16550 3
 
 
 
 
/* NS16550 registers */
#define RBR_REG 0 /** Receiver Buffer Register. */
#define IER_REG 1 /** Interrupt Enable Register. */
#define IIR_REG 2 /** Interrupt Ident Register (read). */
#define FCR_REG 2 /** FIFO control register (write). */
#define LCR_REG 3 /** Line Control register. */
#define MCR_REG 4 /** Modem Control Register. */
#define LSR_REG 5 /** Line Status Register. */
 
 
 
 
irq_cmd_t ski_cmds[1] = {
{ CMD_IA64_GETCHAR, 0, 0, 2 }
};
64,10 → 124,33
ski_cmds
};
 
 
 
irq_cmd_t ns16550_cmds[1] = {
{ CMD_PORT_READ_1, 0, 0, 2 },
};
 
irq_code_t ns16550_kbd = {
1,
ns16550_cmds
};
 
 
uint16_t ns16550_port;
 
int kbd_type;
 
int kbd_arch_init(void)
{
if (sysinfo_value("kbd")) {
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), 0, &ski_kbd);
kbd_type=sysinfo_value("kbd.type");
if(kbd_type==KBD_SKI) ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), 0, &ski_kbd);
if(kbd_type==KBD_LEGACY) return lkbd_arch_init();
if(kbd_type==KBD_NS16550) {
ns16550_kbd.cmds[0].addr= (void *) (sysinfo_value("kbd.port")+RBR_REG);
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), 0, &ns16550_kbd);
iospace_enable(task_get_id(),ns16550_port=sysinfo_value("kbd.port"),8);
}
return 0;
}
return 1;
81,14 → 164,163
return "0123456789ABCDEF"[v];
}
*/
#define LSR_DATA_READY 0x01
 
int kbd_arch_process(keybuffer_t *keybuffer, ipc_call_t *call)
int kbd_ns16550_process(keybuffer_t *keybuffer, ipc_call_t *call)
{
static unsigned long buf = 0;
static int count = 0, esc_count=0;
 
int scan_code = IPC_GET_ARG2(*call);
 
if (scan_code == 0x1b) {
esc_count++;
if (esc_count == 3) {
__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE);
}
} else {
esc_count = 0;
}
 
if(scan_code==0x0d) return 1; //Delete CR
if(scan_code==0x7f) scan_code='\b'; //Convert backspace
 
if(scan_code == 0x7e) {
switch (buf) {
case NSKEY_F6:
keybuffer_push(keybuffer,FUNCTION_KEYS | 6);
buf = count = 0;
return 1;
case NSKEY_F7:
keybuffer_push(keybuffer,FUNCTION_KEYS | 7);
buf = count = 0;
return 1;
case NSKEY_F8:
keybuffer_push(keybuffer,FUNCTION_KEYS | 8);
buf = count = 0;
return 1;
case NSKEY_F9:
keybuffer_push(keybuffer,FUNCTION_KEYS | 9);
buf = count = 0;
return 1;
case NSKEY_F10:
keybuffer_push(keybuffer,FUNCTION_KEYS | 10);
buf = count = 0;
return 1;
case NSKEY_F11:
keybuffer_push(keybuffer,FUNCTION_KEYS | 11);
buf = count = 0;
return 1;
case NSKEY_F12:
keybuffer_push(keybuffer,FUNCTION_KEYS | 12);
buf = count = 0;
return 1;
default:
keybuffer_push(keybuffer, buf & 0xff);
keybuffer_push(keybuffer, (buf >> 8) &0xff);
keybuffer_push(keybuffer, (buf >> 16) &0xff);
keybuffer_push(keybuffer, (buf >> 24) &0xff);
keybuffer_push(keybuffer, scan_code);
buf = count = 0;
return 1;
}
}
 
buf |= ((unsigned long) scan_code)<<(8*(count++));
if((buf & 0xff) != (NSKEY_F1 & 0xff)) {
keybuffer_push(keybuffer, buf);
buf = count = 0;
return 1;
}
 
if (count <= 1)
return 1;
 
if ((buf & 0xffff) != (NSKEY_F1 & 0xffff)) {
 
keybuffer_push(keybuffer, buf & 0xff);
keybuffer_push(keybuffer, (buf >> 8) &0xff);
buf = count = 0;
return 1;
}
 
if (count <= 2)
return 1;
 
 
if ((buf & 0xffffff) != (NSKEY_F1 & 0xffffff)
&& (buf & 0xffffff) != (NSKEY_F6 & 0xffffff)
&& (buf & 0xffffff) != (NSKEY_F9 & 0xffffff) ) {
 
keybuffer_push(keybuffer, buf & 0xff);
keybuffer_push(keybuffer, (buf >> 8) &0xff);
keybuffer_push(keybuffer, (buf >> 16) &0xff);
buf = count = 0;
return 1;
}
 
if (count <= 3)
return 1;
 
switch (buf) {
case NSKEY_F1:
keybuffer_push(keybuffer,FUNCTION_KEYS | 1);
buf = count = 0;
return 1;
case NSKEY_F2:
keybuffer_push(keybuffer,FUNCTION_KEYS | 2);
buf = count = 0;
return 1;
case NSKEY_F3:
keybuffer_push(keybuffer,FUNCTION_KEYS | 3);
buf = count = 0;
return 1;
case NSKEY_F4:
keybuffer_push(keybuffer,FUNCTION_KEYS | 4);
buf = count = 0;
return 1;
case NSKEY_F5:
keybuffer_push(keybuffer,FUNCTION_KEYS | 5);
buf = count = 0;
return 1;
}
 
 
switch (buf) {
case NSKEY_F6:
case NSKEY_F7:
case NSKEY_F8:
case NSKEY_F9:
case NSKEY_F10:
case NSKEY_F11:
case NSKEY_F12:
return 1;
default:
keybuffer_push(keybuffer, buf & 0xff);
keybuffer_push(keybuffer, (buf >> 8) &0xff);
keybuffer_push(keybuffer, (buf >> 16) &0xff);
keybuffer_push(keybuffer, (buf >> 24) &0xff);
buf = count = 0;
return 1;
}
return 1;
}
 
 
 
 
 
 
 
int kbd_ski_process(keybuffer_t *keybuffer, ipc_call_t *call)
{
static unsigned long long buf = 0;
static int count = 0;
static int esc_count = 0;
int scan_code = IPC_GET_ARG2(*call);
 
/*
* Please preserve this code (it can be used to determine scancodes)
*/
155,10 → 387,21
}
buf = count = 0;
}
 
return 1;
}
 
int kbd_arch_process(keybuffer_t *keybuffer, ipc_call_t *call)
{
printf("KBD Key pressed: %x(%c)\n",IPC_GET_ARG2(*call),IPC_GET_ARG2(*call));
if(kbd_type==KBD_SKI) return kbd_ski_process(keybuffer,call);
if(kbd_type==KBD_NS16550) return kbd_ns16550_process(keybuffer,call);
if(kbd_type==KBD_LEGACY) return lkbd_arch_process(keybuffer,call);
 
}
 
 
 
/**
* @}
*/
/branches/tracing/uspace/srv/kbd/arch/ia64/src/scanc.c
0,0 → 1,202
/*
* Copyright (c) 2001-2004 Jakub Jermar
* Copyright (c) 2006 Josef Cejka
* 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 kbdia32
* @brief Scancodes for PC keyboards.
* @{
*/
/** @file
* @ingroup kbdamd64
*/
 
#include <genarch/scanc.h>
 
/** Primary meaning of scancodes. */
int sc_primary_map[] = {
SPECIAL, /* 0x00 */
SPECIAL, /* 0x01 - Esc */
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=',
'\b', /* 0x0e - Backspace */
'\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
SPECIAL, /* 0x1d - LCtrl */
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'',
'`',
SPECIAL, /* 0x2a - LShift */
'\\',
'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
SPECIAL, /* 0x36 - RShift */
'*',
SPECIAL, /* 0x38 - LAlt */
' ',
SPECIAL, /* 0x3a - CapsLock */
(FUNCTION_KEYS | 1), /* 0x3b - F1 */
(FUNCTION_KEYS | 2), /* 0x3c - F2 */
(FUNCTION_KEYS | 3), /* 0x3d - F3 */
(FUNCTION_KEYS | 4), /* 0x3e - F4 */
(FUNCTION_KEYS | 5), /* 0x3f - F5 */
(FUNCTION_KEYS | 6), /* 0x40 - F6 */
(FUNCTION_KEYS | 7), /* 0x41 - F7 */
(FUNCTION_KEYS | 8), /* 0x42 - F8 */
(FUNCTION_KEYS | 9), /* 0x43 - F9 */
(FUNCTION_KEYS | 10), /* 0x44 - F10 */
SPECIAL, /* 0x45 - NumLock */
SPECIAL, /* 0x46 - ScrollLock */
'7', '8', '9', '-',
'4', '5', '6', '+',
'1', '2', '3',
'0', '.',
SPECIAL, /* 0x54 - Alt-SysRq */
SPECIAL, /* 0x55 - F11/F12/PF1/FN */
SPECIAL, /* 0x56 - unlabelled key next to LAlt */
(FUNCTION_KEYS | 11), /* 0x57 - F11 */
(FUNCTION_KEYS | 12), /* 0x58 - F12 */
SPECIAL, /* 0x59 */
SPECIAL, /* 0x5a */
SPECIAL, /* 0x5b */
SPECIAL, /* 0x5c */
SPECIAL, /* 0x5d */
SPECIAL, /* 0x5e */
SPECIAL, /* 0x5f */
SPECIAL, /* 0x60 */
SPECIAL, /* 0x61 */
SPECIAL, /* 0x62 */
SPECIAL, /* 0x63 */
SPECIAL, /* 0x64 */
SPECIAL, /* 0x65 */
SPECIAL, /* 0x66 */
SPECIAL, /* 0x67 */
SPECIAL, /* 0x68 */
SPECIAL, /* 0x69 */
SPECIAL, /* 0x6a */
SPECIAL, /* 0x6b */
SPECIAL, /* 0x6c */
SPECIAL, /* 0x6d */
SPECIAL, /* 0x6e */
SPECIAL, /* 0x6f */
SPECIAL, /* 0x70 */
SPECIAL, /* 0x71 */
SPECIAL, /* 0x72 */
SPECIAL, /* 0x73 */
SPECIAL, /* 0x74 */
SPECIAL, /* 0x75 */
SPECIAL, /* 0x76 */
SPECIAL, /* 0x77 */
SPECIAL, /* 0x78 */
SPECIAL, /* 0x79 */
SPECIAL, /* 0x7a */
SPECIAL, /* 0x7b */
SPECIAL, /* 0x7c */
SPECIAL, /* 0x7d */
SPECIAL, /* 0x7e */
SPECIAL, /* 0x7f */
};
 
/** Secondary meaning of scancodes. */
int sc_secondary_map[] = {
SPECIAL, /* 0x00 */
0x1b, /* 0x01 - Esc */
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+',
SPECIAL, /* 0x0e - Backspace */
'\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n',
SPECIAL, /* 0x1d - LCtrl */
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"',
'~',
SPECIAL, /* 0x2a - LShift */
'|',
'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?',
SPECIAL, /* 0x36 - RShift */
'*',
SPECIAL, /* 0x38 - LAlt */
' ',
SPECIAL, /* 0x3a - CapsLock */
SPECIAL, /* 0x3b - F1 */
SPECIAL, /* 0x3c - F2 */
SPECIAL, /* 0x3d - F3 */
SPECIAL, /* 0x3e - F4 */
SPECIAL, /* 0x3f - F5 */
SPECIAL, /* 0x40 - F6 */
SPECIAL, /* 0x41 - F7 */
SPECIAL, /* 0x42 - F8 */
SPECIAL, /* 0x43 - F9 */
SPECIAL, /* 0x44 - F10 */
SPECIAL, /* 0x45 - NumLock */
SPECIAL, /* 0x46 - ScrollLock */
'7', '8', '9', '-',
'4', '5', '6', '+',
'1', '2', '3',
'0', '.',
SPECIAL, /* 0x54 - Alt-SysRq */
SPECIAL, /* 0x55 - F11/F12/PF1/FN */
SPECIAL, /* 0x56 - unlabelled key next to LAlt */
SPECIAL, /* 0x57 - F11 */
SPECIAL, /* 0x58 - F12 */
SPECIAL, /* 0x59 */
SPECIAL, /* 0x5a */
SPECIAL, /* 0x5b */
SPECIAL, /* 0x5c */
SPECIAL, /* 0x5d */
SPECIAL, /* 0x5e */
SPECIAL, /* 0x5f */
SPECIAL, /* 0x60 */
SPECIAL, /* 0x61 */
SPECIAL, /* 0x62 */
SPECIAL, /* 0x63 */
SPECIAL, /* 0x64 */
SPECIAL, /* 0x65 */
SPECIAL, /* 0x66 */
SPECIAL, /* 0x67 */
SPECIAL, /* 0x68 */
SPECIAL, /* 0x69 */
SPECIAL, /* 0x6a */
SPECIAL, /* 0x6b */
SPECIAL, /* 0x6c */
SPECIAL, /* 0x6d */
SPECIAL, /* 0x6e */
SPECIAL, /* 0x6f */
SPECIAL, /* 0x70 */
SPECIAL, /* 0x71 */
SPECIAL, /* 0x72 */
SPECIAL, /* 0x73 */
SPECIAL, /* 0x74 */
SPECIAL, /* 0x75 */
SPECIAL, /* 0x76 */
SPECIAL, /* 0x77 */
SPECIAL, /* 0x78 */
SPECIAL, /* 0x79 */
SPECIAL, /* 0x7a */
SPECIAL, /* 0x7b */
SPECIAL, /* 0x7c */
SPECIAL, /* 0x7d */
SPECIAL, /* 0x7e */
SPECIAL, /* 0x7f */
};
 
/**
* @}
*/
/branches/tracing/uspace/srv/kbd/arch/ia64/src/mouse.c
0,0 → 1,117
/*
* Copyright (c) 2006 Ondrej Palkovsky
* 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 <ipc/ipc.h>
#include <async.h>
#include <kbd.h>
#include <keys.h>
 
#define i8042_MOUSE_DATA 0x20
 
#define BUFSIZE 3
 
typedef struct {
union {
unsigned char data[BUFSIZE];
struct {
unsigned leftbtn : 1;
unsigned rightbtn : 1;
unsigned middlebtn : 1;
unsigned isone : 1; /* Always one */
unsigned xsign : 1;
unsigned ysign : 1;
unsigned xovfl : 1;
unsigned yovfl : 1;
unsigned char x;
unsigned char y;
} val;
}u;
}ps2packet_t;
 
static ps2packet_t buf;
static int bufpos = 0;
static int leftbtn = 0;
static int rightbtn = 0;
static int middlebtn = 0;
 
/** Convert 9-bit 2-complement signed number to integer */
static int bit9toint(int sign, unsigned char data)
{
int tmp;
 
if (!sign)
return data;
 
tmp = ((unsigned char)~data) + 1;
return -tmp;
}
 
/** Process mouse data
*
* @return True if mouse command was recognized and processed
*/
int mouse_arch_process(int phoneid, ipc_call_t *call)
{
int status = IPC_GET_ARG1(*call);
int data = IPC_GET_ARG2(*call);
int x,y;
 
if (!(status & i8042_MOUSE_DATA))
return 0;
 
/* Check that we have not lost synchronization */
if (bufpos == 0 && !(data & 0x8))
return 1; /* Synchro lost, ignore byte */
 
buf.u.data[bufpos++] = data;
if (bufpos == BUFSIZE) {
bufpos = 0;
if (phoneid != -1) {
if (buf.u.val.leftbtn ^ leftbtn) {
leftbtn = buf.u.val.leftbtn;
async_msg_1(phoneid, KBD_MS_LEFT, leftbtn);
}
if (buf.u.val.rightbtn & rightbtn) {
rightbtn = buf.u.val.middlebtn;
async_msg_1(phoneid, KBD_MS_RIGHT, rightbtn);
}
if (buf.u.val.rightbtn & rightbtn) {
middlebtn = buf.u.val.middlebtn;
async_msg_1(phoneid, KBD_MS_MIDDLE, middlebtn);
}
x = bit9toint(buf.u.val.xsign, buf.u.val.x);
y = bit9toint(buf.u.val.ysign, buf.u.val.y);
if (x || y)
async_msg_2(phoneid, KBD_MS_MOVE, (ipcarg_t)x,
(ipcarg_t)(-y));
}
}
 
return 1;
}
/branches/tracing/uspace/srv/kbd/arch/ia64/src/lkbd.c
0,0 → 1,166
/*
* Copyright (c) 2001-2004 Jakub Jermar
* Copyright (c) 2006 Josef Cejka
* 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 kbdia64 ia64
* @brief HelenOS ia64
* @ingroup kbd
* @{
*/
/** @file
* @ingroup kbdia64
*/
 
#include <arch/lkbd.h>
#include <ipc/ipc.h>
#include <unistd.h>
#include <kbd.h>
#include <keys.h>
#include <genarch/kbd.h>
#include <sysinfo.h>
 
/* Interesting bits for status register */
#define i8042_OUTPUT_FULL 0x1
#define i8042_INPUT_FULL 0x2
#define i8042_MOUSE_DATA 0x20
 
/* Command constants */
#define i8042_CMD_KBD 0x60
#define i8042_CMD_MOUSE 0xd4
 
/* Keyboard cmd byte */
#define i8042_KBD_IE 0x1
#define i8042_MOUSE_IE 0x2
#define i8042_KBD_DISABLE 0x10
#define i8042_MOUSE_DISABLE 0x20
#define i8042_KBD_TRANSLATE 0x40
 
/* Mouse constants */
#define MOUSE_OUT_INIT 0xf4
#define MOUSE_ACK 0xfa
 
#define KEY_RELEASE 0x80
 
static volatile int keyflags; /**< Tracking of multiple keypresses. */
static volatile int lockflags; /**< Tracking of multiple keys lockings. */
 
irq_cmd_t i8042_cmds[2] = {
{ CMD_PORT_READ_1, (void *) 0x64, 0, 1 },
{ CMD_PORT_READ_1, (void *) 0x60, 0, 2 }
};
 
irq_code_t i8042_kbd = {
2,
i8042_cmds
};
 
static void wait_ready(void) {
while (i8042_status_read() & i8042_INPUT_FULL)
;
}
 
/** Register uspace irq handler
* @return
*/
int lkbd_arch_init(void)
{
int i;
int mouseenabled = 0;
 
iospace_enable(task_get_id(), (void *) i8042_DATA, 5);
/* Disable kbd, enable mouse */
i8042_command_write(i8042_CMD_KBD);
wait_ready();
i8042_command_write(i8042_CMD_KBD);
wait_ready();
i8042_data_write(i8042_KBD_DISABLE);
wait_ready();
 
/* Flush all current IO */
while (i8042_status_read() & i8042_OUTPUT_FULL)
i8042_data_read();
/* Initialize mouse */
i8042_command_write(i8042_CMD_MOUSE);
wait_ready();
i8042_data_write(MOUSE_OUT_INIT);
wait_ready();
int mouseanswer = 0;
for (i=0;i < 1000; i++) {
int status = i8042_status_read();
if (status & i8042_OUTPUT_FULL) {
int data = i8042_data_read();
if (status & i8042_MOUSE_DATA) {
mouseanswer = data;
break;
}
}
usleep(1000);
}
if (mouseanswer == MOUSE_ACK) {
/* enable mouse */
mouseenabled = 1;
ipc_register_irq(sysinfo_value("mouse.inr"), sysinfo_value("mouse.devno"), 0, &i8042_kbd);
}
/* Enable kbd */
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), 0, &i8042_kbd);
 
int newcontrol = i8042_KBD_IE | i8042_KBD_TRANSLATE;
if (mouseenabled)
newcontrol |= i8042_MOUSE_IE;
i8042_command_write(i8042_CMD_KBD);
wait_ready();
i8042_data_write(newcontrol);
wait_ready();
return 0;
}
 
/** Process keyboard & mouse events */
int lkbd_arch_process(keybuffer_t *keybuffer, ipc_call_t *call)
{
int status = IPC_GET_ARG1(*call);
 
if ((status & i8042_MOUSE_DATA))
return 0;
int scan_code = IPC_GET_ARG2(*call);
if (scan_code & KEY_RELEASE)
key_released(keybuffer, scan_code ^ KEY_RELEASE);
else
key_pressed(keybuffer, scan_code);
return 1;
}
 
/**
* @}
*/
/branches/tracing/uspace/srv/kbd/arch/mips32/src/kbd.c
34,6 → 34,7
/** @file
*/
#include <arch/kbd.h>
#include <genarch/nofb.h>
#include <ipc/ipc.h>
#include <sysinfo.h>
#include <kbd.h>
99,146 → 100,6
}
*/
 
static int kbd_arch_process_no_fb(keybuffer_t *keybuffer, int scan_code)
{
 
static unsigned long buf = 0;
static int count = 0;
 
/* Please preserve this code (it can be used to determine scancodes)
keybuffer_push(keybuffer, to_hex((scan_code>>4)&0xf));
keybuffer_push(keybuffer, to_hex(scan_code&0xf));
keybuffer_push(keybuffer, ' ');
keybuffer_push(keybuffer, ' ');
return 1;
*/
if(scan_code == 0x7e) {
switch (buf) {
case MSIM_KEY_F5:
keybuffer_push(keybuffer,FUNCTION_KEYS | 5);
buf = count = 0;
return 1;
case MSIM_KEY_F6:
keybuffer_push(keybuffer,FUNCTION_KEYS | 6);
buf = count = 0;
return 1;
case MSIM_KEY_F7:
keybuffer_push(keybuffer,FUNCTION_KEYS | 7);
buf = count = 0;
return 1;
case MSIM_KEY_F8:
keybuffer_push(keybuffer,FUNCTION_KEYS | 8);
buf = count = 0;
return 1;
case MSIM_KEY_F9:
keybuffer_push(keybuffer,FUNCTION_KEYS | 9);
buf = count = 0;
return 1;
case MSIM_KEY_F10:
keybuffer_push(keybuffer,FUNCTION_KEYS | 10);
buf = count = 0;
return 1;
case MSIM_KEY_F11:
keybuffer_push(keybuffer,FUNCTION_KEYS | 11);
buf = count = 0;
return 1;
case MSIM_KEY_F12:
keybuffer_push(keybuffer,FUNCTION_KEYS | 12);
buf = count = 0;
return 1;
default:
keybuffer_push(keybuffer, buf & 0xff);
keybuffer_push(keybuffer, (buf >> 8) &0xff);
keybuffer_push(keybuffer, (buf >> 16) &0xff);
keybuffer_push(keybuffer, (buf >> 24) &0xff);
keybuffer_push(keybuffer, scan_code);
buf = count = 0;
return 1;
}
}
 
buf |= ((unsigned long) scan_code)<<(8*(count++));
if((buf & 0xff) != (MSIM_KEY_F1 & 0xff)) {
keybuffer_push(keybuffer, buf);
buf = count = 0;
return 1;
}
 
if (count <= 1)
return 1;
 
if ((buf & 0xffff) != (MSIM_KEY_F1 & 0xffff)
&& (buf & 0xffff) != (MSIM_KEY_F5 & 0xffff) ) {
 
keybuffer_push(keybuffer, buf & 0xff);
keybuffer_push(keybuffer, (buf >> 8) &0xff);
buf = count = 0;
return 1;
}
 
if (count <= 2)
return 1;
 
switch (buf) {
case MSIM_KEY_F1:
keybuffer_push(keybuffer,FUNCTION_KEYS | 1);
buf = count = 0;
return 1;
case MSIM_KEY_F2:
keybuffer_push(keybuffer,FUNCTION_KEYS | 2);
buf = count = 0;
return 1;
case MSIM_KEY_F3:
keybuffer_push(keybuffer,FUNCTION_KEYS | 3);
buf = count = 0;
return 1;
case MSIM_KEY_F4:
keybuffer_push(keybuffer,FUNCTION_KEYS | 4);
buf = count = 0;
return 1;
}
 
 
if((buf & 0xffffff) != (MSIM_KEY_F5 & 0xffffff)
&& (buf & 0xffffff) != (MSIM_KEY_F9 & 0xffffff)) {
 
keybuffer_push(keybuffer, buf & 0xff);
keybuffer_push(keybuffer, (buf >> 8) & 0xff);
keybuffer_push(keybuffer, (buf >> 16) & 0xff);
buf=count=0;
return 1;
}
 
if (count <= 3)
return 1;
switch (buf) {
case MSIM_KEY_F5:
case MSIM_KEY_F6:
case MSIM_KEY_F7:
case MSIM_KEY_F8:
case MSIM_KEY_F9:
case MSIM_KEY_F10:
case MSIM_KEY_F11:
case MSIM_KEY_F12:
return 1;
default:
keybuffer_push(keybuffer, buf & 0xff);
keybuffer_push(keybuffer, (buf >> 8) &0xff);
keybuffer_push(keybuffer, (buf >> 16) &0xff);
keybuffer_push(keybuffer, (buf >> 24) &0xff);
buf = count = 0;
return 1;
}
return 1;
}
 
 
 
static int kbd_arch_process_fb(keybuffer_t *keybuffer, int scan_code)
{
static unsigned long buf = 0;
371,7 → 232,7
if (fb_fb)
return kbd_arch_process_fb(keybuffer, scan_code);
 
return kbd_arch_process_no_fb(keybuffer, scan_code);
return kbd_process_no_fb(keybuffer, scan_code);
}
/** @}
*/
/branches/tracing/uspace/srv/console/console.c
327,7 → 327,6
break;
case KBD_PUSHCHAR:
/* got key from keyboard driver */
retval = 0;
c = IPC_GET_ARG1(call);
/* switch to another virtual console */
/branches/tracing/uspace/srv/console/gcons.c
250,8 → 250,8
*/
void gcons_mouse_move(int dx, int dy)
{
mouse_x = limit(mouse_x+dx, 0, xres);
mouse_y = limit(mouse_y+dy, 0, yres);
mouse_x = limit(mouse_x + dx, 0, xres);
mouse_y = limit(mouse_y + dy, 0, yres);
 
async_msg_2(fbphone, FB_POINTER_MOVE, mouse_x, mouse_y);
}
258,7 → 258,7
 
static int gcons_find_conbut(int x, int y)
{
int status_start = STATUS_START + (xres - 800) / 2;;
int status_start = STATUS_START + (xres - 800) / 2;
 
if (y < STATUS_TOP || y >= STATUS_TOP + STATUS_HEIGHT)
return -1;
268,10 → 268,10
if (x >= status_start + (STATUS_WIDTH + STATUS_SPACE) * CONSOLE_COUNT)
return -1;
if (((x - status_start) % (STATUS_WIDTH+STATUS_SPACE)) < STATUS_SPACE)
if (((x - status_start) % (STATUS_WIDTH + STATUS_SPACE)) < STATUS_SPACE)
return -1;
return (x - status_start) / (STATUS_WIDTH+STATUS_SPACE);
return (x - status_start) / (STATUS_WIDTH + STATUS_SPACE);
}
 
/** Handle mouse click
/branches/tracing/uspace/srv/fb/sgcn.h
0,0 → 1,46
/*
* Copyright (c) 2008 Pavel Rimsky
* 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.
*/
 
/** @defgroup sgcnfb SGCN
* @brief userland driver of the Serengeti console output
* @{
*/
/** @file
*/
 
#ifndef FB_SGCN_H_
#define FB_SGCN_H_
 
int sgcn_init(void);
 
#endif
 
/**
* @}
*/
/branches/tracing/uspace/srv/fb/serial_console.c
0,0 → 1,110
/*
* Copyright (c) 2006 Ondrej Palkovsky
* Copyright (c) 2008 Martin Decky
* Copyright (c) 2008 Pavel Rimsky
* 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.
*/
 
/**
* @defgroup serial Serial console
* @brief Serial console services (putc, puts, clear screen, cursor goto,...)
* @{
*/
 
/** @file
*/
 
#include <stdio.h>
 
#include "serial_console.h"
 
#define MAX_CONTROL 20
 
static uint32_t width;
static uint32_t height;
static putc_function_t putc_function;
 
void serial_puts(char *str)
{
while (*str)
putc_function(*(str++));
}
 
void serial_goto(const unsigned int row, const unsigned int col)
{
if ((row > height) || (col > width))
return;
char control[20];
snprintf(control, 20, "\033[%u;%uf", row + 1, col + 1);
serial_puts(control);
}
 
void serial_clrscr(void)
{
serial_puts("\033[2J");
}
 
void serial_scroll(int i)
{
if (i > 0) {
serial_goto(height - 1, 0);
while (i--)
serial_puts("\033D");
} else if (i < 0) {
serial_goto(0, 0);
while (i++)
serial_puts("\033M");
}
}
 
void serial_set_style(const unsigned int mode)
{
char control[MAX_CONTROL];
snprintf(control, MAX_CONTROL, "\033[%um", mode);
serial_puts(control);
}
 
void serial_cursor_disable(void)
{
serial_puts("\033[?25l");
}
 
void serial_cursor_enable(void)
{
serial_puts("\033[?25h");
}
 
void serial_console_init(putc_function_t putc_fn, uint32_t w, uint32_t h)
{
width = w;
height = h;
putc_function = putc_fn;
}
 
/**
* @}
*/
/branches/tracing/uspace/srv/fb/msim.c
49,6 → 49,7
#include <align.h>
#include <ddi.h>
 
#include "serial_console.h"
#include "msim.h"
 
#define WIDTH 80
66,57 → 67,6
*virt_addr = c;
}
 
static void msim_puts(char *str)
{
while (*str)
*virt_addr = *(str++);
}
 
static void msim_clrscr(void)
{
msim_puts("\033[2J");
}
 
static void msim_goto(const unsigned int row, const unsigned int col)
{
if ((row > HEIGHT) || (col > WIDTH))
return;
char control[MAX_CONTROL];
snprintf(control, MAX_CONTROL, "\033[%u;%uf", row + 1, col + 1);
msim_puts(control);
}
 
static void msim_set_style(const unsigned int mode)
{
char control[MAX_CONTROL];
snprintf(control, MAX_CONTROL, "\033[%um", mode);
msim_puts(control);
}
 
static void msim_cursor_disable(void)
{
msim_puts("\033[?25l");
}
 
static void msim_cursor_enable(void)
{
msim_puts("\033[?25h");
}
 
static void msim_scroll(int i)
{
if (i > 0) {
msim_goto(HEIGHT - 1, 0);
while (i--)
msim_puts("\033D");
} else if (i < 0) {
msim_goto(0, 0);
while (i++)
msim_puts("\033M");
}
}
 
static void msim_client_connection(ipc_callid_t iid, ipc_call_t *icall)
{
int retval;
141,9 → 91,9
/* Clear the terminal, set scrolling region
to 0 - 25 lines */
msim_clrscr();
msim_goto(0, 0);
msim_puts("\033[0;25r");
serial_clrscr();
serial_goto(0, 0);
serial_puts("\033[0;25r");
while (true) {
callid = async_get_call(&call);
157,7 → 107,7
newrow = IPC_GET_ARG2(call);
newcol = IPC_GET_ARG3(call);
if ((lastcol != newcol) || (lastrow != newrow))
msim_goto(newrow, newcol);
serial_goto(newrow, newcol);
lastcol = newcol + 1;
lastrow = newrow;
msim_putc(c);
166,7 → 116,7
case FB_CURSOR_GOTO:
newrow = IPC_GET_ARG1(call);
newcol = IPC_GET_ARG2(call);
msim_goto(newrow, newcol);
serial_goto(newrow, newcol);
lastrow = newrow;
lastcol = newcol;
retval = 0;
175,7 → 125,7
ipc_answer_2(callid, EOK, HEIGHT, WIDTH);
continue;
case FB_CLEAR:
msim_clrscr();
serial_clrscr();
retval = 0;
break;
case FB_SET_STYLE:
182,9 → 132,9
fgcolor = IPC_GET_ARG1(call);
bgcolor = IPC_GET_ARG2(call);
if (fgcolor < bgcolor)
msim_set_style(0);
serial_set_style(0);
else
msim_set_style(7);
serial_set_style(7);
retval = 0;
break;
case FB_SCROLL:
193,15 → 143,15
retval = EINVAL;
break;
}
msim_scroll(i);
msim_goto(lastrow, lastcol);
serial_scroll(i);
serial_goto(lastrow, lastcol);
retval = 0;
break;
case FB_CURSOR_VISIBILITY:
if(IPC_GET_ARG1(call))
msim_cursor_enable();
serial_cursor_enable();
else
msim_cursor_disable();
serial_cursor_disable();
retval = 0;
break;
default:
218,6 → 168,8
physmem_map(phys_addr, virt_addr, 1, AS_AREA_READ | AS_AREA_WRITE);
serial_console_init(msim_putc, WIDTH, HEIGHT);
async_set_client_connection(msim_client_connection);
return 0;
}
/branches/tracing/uspace/srv/fb/serial_console.h
0,0 → 1,52
/*
* Copyright (c) 2008 Pavel Rimsky
* 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.
*/
 
/**
* @defgroup serial Serial console
* @brief Serial console services (putc, puts, clear screen, cursor goto,...)
* @{
*/
 
/** @file
*/
 
#ifndef FB_SERIAL_CONSOLE_H_
#define FB_SERIAL_CONSOLE_H_
 
typedef void (*putc_function_t)(char);
 
void serial_puts(char *str);
void serial_goto(const unsigned int row, const unsigned int col);
void serial_clrscr(void);
void serial_scroll(int i);
void serial_set_style(const unsigned int mode);
void serial_cursor_disable(void);
void serial_cursor_enable(void);
void serial_console_init(putc_function_t putc_fn, uint32_t w, uint32_t h);
 
#endif
/branches/tracing/uspace/srv/fb/main.c
38,6 → 38,7
#include "fb.h"
#include "ega.h"
#include "msim.h"
#include "sgcn.h"
#include "main.h"
 
#define NAME "fb"
79,6 → 80,12
initialized = true;
}
#endif
#ifdef SGCN_ENABLED
if ((!initialized) && (sysinfo_value("fb.kind") == 4)) {
if (sgcn_init() == 0)
initialized = true;
}
#endif
 
if (!initialized)
return -1;
/branches/tracing/uspace/srv/fb/sgcn.c
0,0 → 1,250
/*
* Copyright (c) 2006 Ondrej Palkovsky
* Copyright (c) 2008 Martin Decky
* Copyright (c) 2008 Pavel Rimsky
* 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.
*/
 
/** @defgroup sgcnfb SGCN
* @brief userland driver of the Serengeti console output
* @{
*/
/** @file
*/
 
#include <async.h>
#include <ipc/ipc.h>
#include <ipc/fb.h>
#include <sysinfo.h>
#include <as.h>
#include <errno.h>
#include <stdio.h>
#include <ddi.h>
 
#include "serial_console.h"
#include "sgcn.h"
 
#define WIDTH 80
#define HEIGHT 24
 
/**
* Virtual address mapped to SRAM.
*/
static uintptr_t sram_virt_addr;
 
/**
* SGCN buffer offset within SGCN.
*/
static uintptr_t sram_buffer_offset;
 
/* Allow only 1 connection */
static int client_connected = 0;
 
/**
* SGCN buffer header. It is placed at the very beginning of the SGCN
* buffer.
*/
typedef struct {
/** hard-wired to "CON" */
char magic[4];
/** we don't need this */
char unused[24];
 
/** offset within the SGCN buffer of the output buffer start */
uint32_t out_begin;
/** offset within the SGCN buffer of the output buffer end */
uint32_t out_end;
/** offset within the SGCN buffer of the output buffer read pointer */
uint32_t out_rdptr;
/** offset within the SGCN buffer of the output buffer write pointer */
uint32_t out_wrptr;
} __attribute__ ((packed)) sgcn_buffer_header_t;
 
 
/*
* Returns a pointer to the object of a given type which is placed at the given
* offset from the console buffer beginning.
*/
#define SGCN_BUFFER(type, offset) \
((type *) (sram_virt_addr + sram_buffer_offset + (offset)))
 
/** Returns a pointer to the console buffer header. */
#define SGCN_BUFFER_HEADER (SGCN_BUFFER(sgcn_buffer_header_t, 0))
 
/**
* Pushes the character to the SGCN serial.
* @param c character to be pushed
*/
static void sgcn_putc(char c)
{
uint32_t begin = SGCN_BUFFER_HEADER->out_begin;
uint32_t end = SGCN_BUFFER_HEADER->out_end;
uint32_t size = end - begin;
/* we need pointers to volatile variables */
volatile char *buf_ptr = (volatile char *)
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr);
volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr);
volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr);
 
uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin;
while (*out_rdptr_ptr == new_wrptr)
;
*buf_ptr = c;
*out_wrptr_ptr = new_wrptr;
}
 
/**
* Main function of the thread serving client connections.
*/
static void sgcn_client_connection(ipc_callid_t iid, ipc_call_t *icall)
{
int retval;
ipc_callid_t callid;
ipc_call_t call;
char c;
int lastcol = 0;
int lastrow = 0;
int newcol;
int newrow;
int fgcolor;
int bgcolor;
int i;
if (client_connected) {
ipc_answer_0(iid, ELIMIT);
return;
}
client_connected = 1;
ipc_answer_0(iid, EOK);
/* Clear the terminal, set scrolling region
to 0 - 24 lines */
serial_clrscr();
serial_goto(0, 0);
serial_puts("\033[0;24r");
while (true) {
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
client_connected = 0;
ipc_answer_0(callid, EOK);
return;
case FB_PUTCHAR:
c = IPC_GET_ARG1(call);
newrow = IPC_GET_ARG2(call);
newcol = IPC_GET_ARG3(call);
if ((lastcol != newcol) || (lastrow != newrow))
serial_goto(newrow, newcol);
lastcol = newcol + 1;
lastrow = newrow;
sgcn_putc(c);
retval = 0;
break;
case FB_CURSOR_GOTO:
newrow = IPC_GET_ARG1(call);
newcol = IPC_GET_ARG2(call);
serial_goto(newrow, newcol);
lastrow = newrow;
lastcol = newcol;
retval = 0;
break;
case FB_GET_CSIZE:
ipc_answer_2(callid, EOK, HEIGHT, WIDTH);
continue;
case FB_CLEAR:
serial_clrscr();
retval = 0;
break;
case FB_SET_STYLE:
fgcolor = IPC_GET_ARG1(call);
bgcolor = IPC_GET_ARG2(call);
if (fgcolor < bgcolor)
serial_set_style(0);
else
serial_set_style(7);
retval = 0;
break;
case FB_SCROLL:
i = IPC_GET_ARG1(call);
if ((i > HEIGHT) || (i < -HEIGHT)) {
retval = EINVAL;
break;
}
serial_scroll(i);
serial_goto(lastrow, lastcol);
retval = 0;
break;
case FB_CURSOR_VISIBILITY:
if(IPC_GET_ARG1(call))
serial_cursor_enable();
else
serial_cursor_disable();
retval = 0;
break;
default:
retval = ENOENT;
}
ipc_answer_0(callid, retval);
}
}
 
/**
* Initializes the SGCN serial driver.
*/
int sgcn_init(void)
{
sram_virt_addr = (uintptr_t) as_get_mappable_page(
sysinfo_value("sram.area.size"));
int result = physmem_map(
(void *) sysinfo_value("sram.address.physical"),
(void *) sram_virt_addr,
sysinfo_value("sram.area.size") / PAGE_SIZE,
AS_AREA_READ | AS_AREA_WRITE
);
if (result != 0) {
printf("SGCN: uspace driver couldn't map physical memory: %d\n",
result);
}
serial_console_init(sgcn_putc, WIDTH, HEIGHT);
sram_buffer_offset = sysinfo_value("sram.buffer.offset");
async_set_client_connection(sgcn_client_connection);
return 0;
}
 
/**
* @}
*/
/branches/tracing/uspace/srv/fb/ega.c
64,9 → 64,12
#define EGA_IO_ADDRESS 0x3d4
#define EGA_IO_SIZE 2
 
#define NORMAL_COLOR 0x0f
#define INVERTED_COLOR 0xf0
int ega_normal_color=0x0f;
int ega_inverted_color=0xf0;
 
#define NORMAL_COLOR ega_normal_color
#define INVERTED_COLOR ega_inverted_color
 
#define EGA_STYLE(fg,bg) ((fg) > (bg) ? NORMAL_COLOR : INVERTED_COLOR)
 
/* Allow only 1 connection */
76,7 → 79,7
static unsigned int scr_height;
static char *scr_addr;
 
static unsigned int style = NORMAL_COLOR;
static unsigned int style;
 
static void clrscr(void)
{
312,6 → 315,13
ega_ph_addr = (void *) sysinfo_value("fb.address.physical");
scr_width = sysinfo_value("fb.width");
scr_height = sysinfo_value("fb.height");
if(sysinfo_value("fb.blinking"))
{
ega_normal_color&=0x77;
ega_inverted_color&=0x77;
}
style = NORMAL_COLOR;
 
iospace_enable(task_get_id(), (void *) EGA_IO_ADDRESS, 2);
 
sz = scr_width * scr_height * 2;
/branches/tracing/uspace/srv/fb/Makefile
56,14 → 56,24
SOURCES += ega.c
CFLAGS += -DEGA_ENABLED
endif
ifeq ($(ARCH), ia64)
SOURCES += ega.c
CFLAGS += -DEGA_ENABLED
endif
ifeq ($(ARCH), amd64)
SOURCES += ega.c
CFLAGS += -DEGA_ENABLED
endif
ifeq ($(ARCH), mips32)
SOURCES += msim.c
SOURCES += msim.c \
serial_console.c
CFLAGS += -DMSIM_ENABLED -DFB_INVERT_ENDIAN
endif
ifeq ($(ARCH), sparc64)
SOURCES += sgcn.c \
serial_console.c
CFLAGS += -DSGCN_ENABLED
endif
 
CFLAGS += -D$(ARCH)
 
/branches/tracing/uspace/srv/fs/tmpfs/tmpfs_dump.c
59,6 → 59,7
{
struct rdentry entry;
libfs_ops_t *ops = &tmpfs_libfs_ops;
int rc;
do {
char *fname;
93,7 → 94,8
}
fname[entry.len] = 0;
if (!ops->link((void *) parent, (void *) node, fname)) {
rc = ops->link((void *) parent, (void *) node, fname);
if (rc != EOK) {
ops->destroy((void *) node);
free(fname);
return false;
134,8 → 136,9
return false;
}
fname[entry.len] = 0;
if (!ops->link((void *) parent, (void *) node, fname)) {
 
rc = ops->link((void *) parent, (void *) node, fname);
if (rc != EOK) {
ops->destroy((void *) node);
free(fname);
return false;
/branches/tracing/uspace/srv/fs/tmpfs/tmpfs_ops.c
75,7 → 75,7
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 bool tmpfs_link_node(void *, void *, const char *);
static int tmpfs_link_node(void *, void *, const char *);
static int tmpfs_unlink_node(void *, void *);
static int tmpfs_destroy_node(void *);
 
308,7 → 308,7
return (void *) node;
}
 
bool tmpfs_link_node(void *prnt, void *chld, const char *nm)
int tmpfs_link_node(void *prnt, void *chld, const char *nm)
{
tmpfs_dentry_t *parentp = (tmpfs_dentry_t *) prnt;
tmpfs_dentry_t *childp = (tmpfs_dentry_t *) chld;
317,13 → 317,13
 
tmpfs_name_t *namep = malloc(sizeof(tmpfs_name_t));
if (!namep)
return false;
return ENOMEM;
tmpfs_name_initialize(namep);
size_t len = strlen(nm);
namep->name = malloc(len + 1);
if (!namep->name) {
free(namep);
return false;
return ENOMEM;
}
strcpy(namep->name, nm);
namep->parent = parentp;
343,7 → 343,7
parentp->child = childp;
}
 
return true;
return EOK;
}
 
int tmpfs_unlink_node(void *prnt, void *chld)
/branches/tracing/uspace/srv/fs/fat/fat_idx.c
423,6 → 423,32
return fidx;
}
 
void fat_idx_hashin(fat_idx_t *idx)
{
unsigned long pkey[] = {
[UPH_DH_KEY] = idx->dev_handle,
[UPH_PFC_KEY] = idx->pfc,
[UPH_PDI_KEY] = idx->pdi,
};
 
futex_down(&used_futex);
hash_table_insert(&up_hash, pkey, &idx->uph_link);
futex_up(&used_futex);
}
 
void fat_idx_hashout(fat_idx_t *idx)
{
unsigned long pkey[] = {
[UPH_DH_KEY] = idx->dev_handle,
[UPH_PFC_KEY] = idx->pfc,
[UPH_PDI_KEY] = idx->pdi,
};
 
futex_down(&used_futex);
hash_table_remove(&up_hash, pkey, 3);
futex_up(&used_futex);
}
 
fat_idx_t *
fat_idx_get_by_index(dev_handle_t dev_handle, fs_index_t index)
{
/branches/tracing/uspace/srv/fs/fat/fat.h
209,6 → 209,8
extern fat_idx_t *fat_idx_get_by_pos(dev_handle_t, fat_cluster_t, unsigned);
extern fat_idx_t *fat_idx_get_by_index(dev_handle_t, fs_index_t);
extern void fat_idx_destroy(fat_idx_t *);
extern void fat_idx_hashin(fat_idx_t *);
extern void fat_idx_hashout(fat_idx_t *);
 
extern int fat_idx_init(void);
extern void fat_idx_fini(void);
/branches/tracing/uspace/srv/fs/fat/fat_dentry.c
36,16 → 36,81
*/
 
#include "fat_dentry.h"
#include <ctype.h>
#include <string.h>
 
#define FAT_PAD ' '
static bool is_d_char(const char ch)
{
if (isalnum(ch) || ch == '_')
return true;
else
return false;
}
 
#define FAT_DENTRY_UNUSED 0x00
#define FAT_DENTRY_E5_ESC 0x05
#define FAT_DENTRY_DOT 0x2e
#define FAT_DENTRY_ERASED 0xe5
/** Compare path component with the name read from the dentry.
*
* This function compares the path component with the name read from the dentry.
* The comparison is case insensitive and tolerates a mismatch on the trailing
* dot character at the end of the name (i.e. when there is a dot, but no
* extension).
*
* @param name Node name read from the dentry.
* @param component Path component.
*
* @return Zero on match, non-zero otherwise.
*/
int fat_dentry_namecmp(char *name, const char *component)
{
int rc;
if (!(rc = stricmp(name, component)))
return rc;
if (!strchr(name, '.')) {
/*
* There is no '.' in the name, so we know that there is enough
* space for appending an extra '.' to name.
*/
name[strlen(name)] = '.';
name[strlen(name) + 1] = '\0';
rc = stricmp(name, component);
}
return rc;
}
 
void dentry_name_canonify(fat_dentry_t *d, char *buf)
bool fat_dentry_name_verify(const char *name)
{
unsigned i, dot;
bool dot_found = false;
 
for (i = 0; name[i]; i++) {
if (name[i] == '.') {
if (dot_found) {
return false;
} else {
dot_found = true;
dot = i;
}
} else {
if (!is_d_char(name[i]))
return false;
}
}
 
if (dot_found) {
if (dot > FAT_NAME_LEN)
return false;
if (i - dot > FAT_EXT_LEN + 1)
return false;
} else {
if (i > FAT_NAME_LEN)
return false;
}
 
return true;
}
 
void fat_dentry_name_get(const fat_dentry_t *d, char *buf)
{
int i;
 
for (i = 0; i < FAT_NAME_LEN; i++) {
71,8 → 136,47
*buf = '\0';
}
 
fat_dentry_clsf_t fat_classify_dentry(fat_dentry_t *d)
void fat_dentry_name_set(fat_dentry_t *d, const char *name)
{
int i;
const char fake_ext[] = " ";
 
 
for (i = 0; i < FAT_NAME_LEN; i++) {
switch ((uint8_t) *name) {
case 0xe5:
d->name[i] = FAT_DENTRY_E5_ESC;
name++;
break;
case '\0':
case '.':
d->name[i] = FAT_PAD;
break;
default:
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:
d->ext[i] = FAT_DENTRY_E5_ESC;
name++;
break;
case '\0':
d->ext[i] = FAT_PAD;
break;
default:
d->ext[i] = toupper(*name++);
break;
}
}
}
 
fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d)
{
if (d->attr & FAT_ATTR_VOLLABEL) {
/* volume label entry */
return FAT_DENTRY_SKIP;
79,7 → 183,7
}
if (d->name[0] == FAT_DENTRY_ERASED) {
/* not-currently-used entry */
return FAT_DENTRY_SKIP;
return FAT_DENTRY_FREE;
}
if (d->name[0] == FAT_DENTRY_UNUSED) {
/* never used entry */
/branches/tracing/uspace/srv/fs/fat/fat_dentry.h
34,17 → 34,30
#define FAT_FAT_DENTRY_H_
 
#include <stdint.h>
#include <bool.h>
 
#define FAT_NAME_LEN 8
#define FAT_EXT_LEN 3
 
#define FAT_NAME_DOT ". "
#define FAT_NAME_DOT_DOT ".. "
#define FAT_EXT_PAD " "
 
#define FAT_ATTR_RDONLY (1 << 0)
#define FAT_ATTR_VOLLABEL (1 << 3)
#define FAT_ATTR_SUBDIR (1 << 4)
 
#define FAT_PAD ' '
 
#define FAT_DENTRY_UNUSED 0x00
#define FAT_DENTRY_E5_ESC 0x05
#define FAT_DENTRY_DOT 0x2e
#define FAT_DENTRY_ERASED 0xe5
 
typedef enum {
FAT_DENTRY_SKIP,
FAT_DENTRY_LAST,
FAT_DENTRY_FREE,
FAT_DENTRY_VALID
} fat_dentry_clsf_t;
 
70,8 → 83,11
uint32_t size;
} __attribute__ ((packed)) fat_dentry_t;
 
extern void dentry_name_canonify(fat_dentry_t *, char *);
extern fat_dentry_clsf_t fat_classify_dentry(fat_dentry_t *);
extern int fat_dentry_namecmp(char *, const char *);
extern bool fat_dentry_name_verify(const char *);
extern void fat_dentry_name_get(const fat_dentry_t *, char *);
extern void fat_dentry_name_set(fat_dentry_t *, const char *);
extern fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *);
 
#endif
 
/branches/tracing/uspace/srv/fs/fat/fat_fat.c
182,7 → 182,7
boundary = ROUND_UP(nodep->size, bps * spc);
 
/* zero out already allocated space */
for (o = nodep->size - 1; o < pos && o < boundary;
for (o = nodep->size; o < pos && o < boundary;
o = ALIGN_DOWN(o + bps, bps)) {
int flags = (o % bps == 0) ?
BLOCK_FLAGS_NOREAD : BLOCK_FLAGS_NONE;
285,10 → 285,10
}
}
 
/** Allocate clusters in FAT1.
/** Allocate clusters in all copies of FAT.
*
* This function will attempt to allocate the requested number of clusters in
* the first FAT instance. The FAT will be altered so that the allocated
* all instances of the FAT. The FAT will be altered so that the allocated
* clusters form an independent chain (i.e. a chain which does not belong to any
* file yet).
*
315,7 → 315,7
unsigned b, c, cl;
 
lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
if (lifo)
if (!lifo)
return ENOMEM;
bps = uint16_t_le2host(bs->bps);
326,8 → 326,8
* Search FAT1 for unused clusters.
*/
futex_down(&fat_alloc_lock);
for (b = 0, cl = 0; b < sf; blk++) {
blk = block_get(dev_handle, rscnt + b, BLOCK_FLAGS_NOREAD);
for (b = 0, cl = 0; b < sf; b++) {
blk = block_get(dev_handle, rscnt + b, BLOCK_FLAGS_NONE);
for (c = 0; c < bps / sizeof(fat_cluster_t); c++, cl++) {
fat_cluster_t *clst = (fat_cluster_t *)blk->data + c;
if (uint16_t_le2host(*clst) == FAT_CLST_RES0) {
385,8 → 385,8
 
/* Mark all clusters in the chain as free in all copies of FAT. */
while (firstc < FAT_CLST_LAST1) {
assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);
nextc = fat_get_cluster(bs, dev_handle, firstc);
assert(nextc >= FAT_CLST_FIRST && nextc < FAT_CLST_BAD);
for (fatno = FAT1; fatno < bs->fatcnt; fatno++)
fat_set_cluster(bs, dev_handle, fatno, firstc,
FAT_CLST_RES0);
409,7 → 409,7
if (fat_cluster_walk(bs, dev_handle, nodep->firstc, &lcl,
(uint16_t) -1) == 0) {
/* No clusters allocated to the node yet. */
nodep->firstc = host2uint16_t_le(mcl);
nodep->firstc = mcl;
nodep->dirty = true; /* need to sync node */
return;
}
/branches/tracing/uspace/srv/fs/fat/fat.c
116,6 → 116,9
case VFS_TRUNCATE:
fat_truncate(callid, &call);
break;
case VFS_DESTROY:
fat_destroy(callid, &call);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
/branches/tracing/uspace/srv/fs/fat/fat_ops.c
94,10 → 94,14
d = ((fat_dentry_t *)b->data) + (node->idx->pdi % dps);
 
d->firstc = host2uint16_t_le(node->firstc);
if (node->type == FAT_FILE)
if (node->type == FAT_FILE) {
d->size = host2uint32_t_le(node->size);
/* TODO: update other fields? (e.g time fields, attr field) */
} else if (node->type == FAT_DIRECTORY) {
d->attr = FAT_ATTR_SUBDIR;
}
/* TODO: update other fields? (e.g time fields) */
b->dirty = true; /* need to sync block */
block_put(b);
}
223,7 → 227,7
static void fat_node_put(void *);
static void *fat_create_node(dev_handle_t, int);
static int fat_destroy_node(void *);
static bool fat_link(void *, void *, const char *);
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 *);
284,25 → 288,58
{
fat_idx_t *idxp;
fat_node_t *nodep;
fat_bs_t *bs;
fat_cluster_t mcl, lcl;
uint16_t bps;
int rc;
 
bs = block_bb_get(dev_handle);
bps = uint16_t_le2host(bs->bps);
if (flags & L_DIRECTORY) {
/* allocate a cluster */
rc = fat_alloc_clusters(bs, dev_handle, 1, &mcl, &lcl);
if (rc != EOK)
return NULL;
}
 
nodep = fat_node_get_new();
if (!nodep)
if (!nodep) {
fat_free_clusters(bs, dev_handle, mcl);
return NULL;
}
idxp = fat_idx_get_new(dev_handle);
if (!idxp) {
fat_free_clusters(bs, dev_handle, mcl);
fat_node_put(nodep);
return NULL;
}
/* idxp->lock held */
if (flags & L_DIRECTORY) {
int i;
block_t *b;
 
/*
* Populate the new cluster with unused dentries.
*/
for (i = 0; i < bs->spc; i++) {
b = _fat_block_get(bs, dev_handle, mcl, i,
BLOCK_FLAGS_NOREAD);
/* mark all dentries as never-used */
memset(b->data, 0, bps);
b->dirty = false;
block_put(b);
}
nodep->type = FAT_DIRECTORY;
nodep->firstc = mcl;
nodep->size = bps * bs->spc;
} else {
nodep->type = FAT_FILE;
nodep->firstc = FAT_CLST_RES0;
nodep->size = 0;
}
nodep->size = 0;
nodep->firstc = FAT_CLST_RES0;
nodep->lnkcnt = 0; /* not linked anywhere */
nodep->refcnt = 1;
nodep->dirty = true;
 
nodep->idx = idxp;
idxp->nodep = nodep;
341,14 → 378,174
return EOK;
}
 
bool fat_link(void *prnt, void *chld, const char *name)
int fat_link(void *prnt, void *chld, const char *name)
{
return false; /* not supported at the moment */
fat_node_t *parentp = (fat_node_t *)prnt;
fat_node_t *childp = (fat_node_t *)chld;
fat_dentry_t *d;
fat_bs_t *bs;
block_t *b;
int i, j;
uint16_t bps;
unsigned dps;
unsigned blocks;
 
futex_down(&childp->lock);
if (childp->lnkcnt == 1) {
/*
* On FAT, we don't support multiple hard links.
*/
futex_up(&childp->lock);
return EMLINK;
}
assert(childp->lnkcnt == 0);
futex_up(&childp->lock);
 
if (!fat_dentry_name_verify(name)) {
/*
* Attempt to create unsupported name.
*/
return ENOTSUP;
}
 
/*
* Get us an unused parent node's dentry or grow the parent and allocate
* a new one.
*/
futex_down(&parentp->idx->lock);
bs = block_bb_get(parentp->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
 
blocks = parentp->size / bps;
 
for (i = 0; i < blocks; i++) {
b = fat_block_get(bs, parentp, i, BLOCK_FLAGS_NONE);
for (j = 0; j < dps; j++) {
d = ((fat_dentry_t *)b->data) + j;
switch (fat_classify_dentry(d)) {
case FAT_DENTRY_SKIP:
case FAT_DENTRY_VALID:
/* skipping used and meta entries */
continue;
case FAT_DENTRY_FREE:
case FAT_DENTRY_LAST:
/* found an empty slot */
goto hit;
}
}
block_put(b);
}
/*
* We need to grow the parent in order to create a new unused dentry.
*/
futex_up(&parentp->idx->lock);
return ENOTSUP; /* XXX */
 
hit:
/*
* At this point we only establish the link between the parent and the
* child. The dentry, except of the name and the extension, will remain
* uninitialized until the the corresponding node is synced. Thus the
* valid dentry data is kept in the child node structure.
*/
memset(d, 0, sizeof(fat_dentry_t));
fat_dentry_name_set(d, name);
b->dirty = true; /* need to sync block */
block_put(b);
futex_up(&parentp->idx->lock);
 
futex_down(&childp->idx->lock);
/*
* If possible, create the Sub-directory Identifier Entry and the
* Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries
* are not mandatory according to Standard ECMA-107 and HelenOS VFS does
* not use them anyway, so this is rather a sign of our good will.
*/
b = fat_block_get(bs, childp, 0, BLOCK_FLAGS_NONE);
d = (fat_dentry_t *)b->data;
if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
strcmp(d->name, FAT_NAME_DOT) == 0) {
memset(d, 0, sizeof(fat_dentry_t));
strcpy(d->name, FAT_NAME_DOT);
strcpy(d->ext, FAT_EXT_PAD);
d->attr = FAT_ATTR_SUBDIR;
d->firstc = host2uint16_t_le(childp->firstc);
/* TODO: initialize also the date/time members. */
}
d++;
if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
strcmp(d->name, FAT_NAME_DOT_DOT) == 0) {
memset(d, 0, sizeof(fat_dentry_t));
strcpy(d->name, FAT_NAME_DOT_DOT);
strcpy(d->ext, FAT_EXT_PAD);
d->attr = FAT_ATTR_SUBDIR;
d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
host2uint16_t_le(FAT_CLST_RES0) :
host2uint16_t_le(parentp->firstc);
/* TODO: initialize also the date/time members. */
}
b->dirty = true; /* need to sync block */
block_put(b);
 
childp->idx->pfc = parentp->firstc;
childp->idx->pdi = i * dps + j;
futex_up(&childp->idx->lock);
 
futex_down(&childp->lock);
childp->lnkcnt = 1;
childp->dirty = true; /* need to sync node */
futex_up(&childp->lock);
 
/*
* Hash in the index structure into the position hash.
*/
fat_idx_hashin(childp->idx);
 
return EOK;
}
 
int fat_unlink(void *prnt, void *chld)
{
return ENOTSUP; /* not supported at the moment */
fat_node_t *parentp = (fat_node_t *)prnt;
fat_node_t *childp = (fat_node_t *)chld;
fat_bs_t *bs;
fat_dentry_t *d;
uint16_t bps;
block_t *b;
 
futex_down(&parentp->lock);
futex_down(&childp->lock);
assert(childp->lnkcnt == 1);
futex_down(&childp->idx->lock);
bs = block_bb_get(childp->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
 
b = _fat_block_get(bs, childp->idx->dev_handle, childp->idx->pfc,
(childp->idx->pdi * sizeof(fat_dentry_t)) / bps,
BLOCK_FLAGS_NONE);
d = (fat_dentry_t *)b->data +
(childp->idx->pdi % (bps / sizeof(fat_dentry_t)));
/* mark the dentry as not-currently-used */
d->name[0] = FAT_DENTRY_ERASED;
b->dirty = true; /* need to sync block */
block_put(b);
 
/* remove the index structure from the position hash */
fat_idx_hashout(childp->idx);
/* clear position information */
childp->idx->pfc = FAT_CLST_RES0;
childp->idx->pdi = 0;
futex_up(&childp->idx->lock);
childp->lnkcnt = 0;
childp->dirty = true;
futex_up(&childp->lock);
futex_up(&parentp->lock);
 
return EOK;
}
 
void *fat_match(void *prnt, const char *component)
374,6 → 571,7
d = ((fat_dentry_t *)b->data) + j;
switch (fat_classify_dentry(d)) {
case FAT_DENTRY_SKIP:
case FAT_DENTRY_FREE:
continue;
case FAT_DENTRY_LAST:
block_put(b);
381,10 → 579,10
return NULL;
default:
case FAT_DENTRY_VALID:
dentry_name_canonify(d, name);
fat_dentry_name_get(d, name);
break;
}
if (stricmp(name, component) == 0) {
if (fat_dentry_namecmp(name, component) == 0) {
/* hit */
void *node;
/*
464,6 → 662,7
d = ((fat_dentry_t *)b->data) + j;
switch (fat_classify_dentry(d)) {
case FAT_DENTRY_SKIP:
case FAT_DENTRY_FREE:
continue;
case FAT_DENTRY_LAST:
block_put(b);
525,6 → 724,10
.is_file = fat_is_file
};
 
/*
* VFS operations.
*/
 
void fat_mounted(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
694,6 → 897,7
d = ((fat_dentry_t *)b->data) + o;
switch (fat_classify_dentry(d)) {
case FAT_DENTRY_SKIP:
case FAT_DENTRY_FREE:
continue;
case FAT_DENTRY_LAST:
block_put(b);
700,7 → 904,7
goto miss;
default:
case FAT_DENTRY_VALID:
dentry_name_canonify(d, name);
fat_dentry_name_get(d, name);
block_put(b);
goto hit;
}
/branches/tracing/uspace/srv/vfs/vfs_ops.c
234,6 → 234,7
mr_res.triplet.index = (fs_index_t) rindex;
mr_res.size = (size_t) rsize;
mr_res.lnkcnt = (unsigned) rlnkcnt;
mr_res.type = VFS_NODE_DIRECTORY;
 
rootfs.fs_handle = fs_handle;
rootfs.dev_handle = dev_handle;
302,6 → 303,16
int mode = IPC_GET_ARG3(*request);
size_t len;
 
/*
* Make sure that we are called with exactly one of L_FILE and
* L_DIRECTORY.
*/
if ((lflag & (L_FILE | L_DIRECTORY)) == 0 ||
(lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) {
ipc_answer_0(rid, EINVAL);
return;
}
 
if (oflag & O_CREAT)
lflag |= L_CREATE;
if (oflag & O_EXCL)
456,7 → 467,7
* the same open file at a time.
*/
futex_down(&file->lock);
 
/*
* Lock the file's node so that no other client can read/write to it at
* the same time.
465,6 → 476,15
rwlock_read_lock(&file->node->contents_rwlock);
else
rwlock_write_lock(&file->node->contents_rwlock);
 
if (file->node->type == VFS_NODE_DIRECTORY) {
/*
* Make sure that no one is modifying the namespace
* while we are in readdir().
*/
assert(read);
rwlock_read_lock(&namespace_rwlock);
}
int fs_phone = vfs_grab_phone(file->node->fs_handle);
490,6 → 510,9
ipcarg_t rc;
async_wait_for(msg, &rc);
size_t bytes = IPC_GET_ARG1(answer);
 
if (file->node->type == VFS_NODE_DIRECTORY)
rwlock_read_unlock(&namespace_rwlock);
/* Unlock the VFS node. */
if (read)
/branches/tracing/uspace/srv/vfs/vfs.h
190,8 → 190,15
*/
#define L_PARENT 64
 
typedef enum vfs_node_type {
VFS_NODE_UNKNOWN,
VFS_NODE_FILE,
VFS_NODE_DIRECTORY,
} vfs_node_type_t;
 
typedef struct {
vfs_triplet_t triplet;
vfs_node_type_t type;
size_t size;
unsigned lnkcnt;
} vfs_lookup_res_t;
213,6 → 220,9
unsigned lnkcnt;
 
link_t nh_link; /**< Node hash-table link. */
 
vfs_node_type_t type; /**< Partial info about the node type. */
 
size_t size; /**< Cached size if the node is a file. */
 
/**
/branches/tracing/uspace/srv/vfs/vfs_node.c
175,15 → 175,22
node->index = result->triplet.index;
node->size = result->size;
node->lnkcnt = result->lnkcnt;
node->type = result->type;
link_initialize(&node->nh_link);
rwlock_initialize(&node->contents_rwlock);
hash_table_insert(&nodes, key, &node->nh_link);
} else {
node = hash_table_get_instance(tmp, vfs_node_t, nh_link);
if (node->type == VFS_NODE_UNKNOWN &&
result->type != VFS_NODE_UNKNOWN) {
/* Upgrade the node type. */
node->type = result->type;
}
}
 
assert(node->size == result->size);
assert(node->lnkcnt == result->lnkcnt);
assert(node->type == result->type || result->type == VFS_NODE_UNKNOWN);
 
_vfs_node_addref(node);
futex_up(&nodes_futex);
/branches/tracing/uspace/srv/vfs/vfs_lookup.c
182,6 → 182,12
result->triplet.index = (fs_index_t) IPC_GET_ARG3(answer);
result->size = (size_t) IPC_GET_ARG4(answer);
result->lnkcnt = (unsigned) IPC_GET_ARG5(answer);
if (lflag & L_FILE)
result->type = VFS_NODE_FILE;
else if (lflag & L_DIRECTORY)
result->type = VFS_NODE_DIRECTORY;
else
result->type = VFS_NODE_UNKNOWN;
}
 
return rc;
/branches/tracing/boot/boot.config
83,5 → 83,8
@ "fat" FAT16 image
! RDFMT (choice)
 
# Preserve A.OUT header in isofs.b
! [ARCH=sparc64] CONFIG_AOUT_ISOFS_B (y/n)
 
# External ramdisk
! [ARCH=sparc64] CONFIG_RD_EXTERNAL (y/n)
/branches/tracing/boot/genarch/balloc.h
31,7 → 31,7
 
#include <types.h>
 
#define BALLOC_MAX_SIZE (1024 * 1024)
#define BALLOC_MAX_SIZE (128 * 1024)
 
typedef struct {
uintptr_t base;
/branches/tracing/boot/genarch/ofw_tree.c
121,7 → 121,6
memcpy(current_node->da_name, &path[i], len);
current_node->da_name[len] = '\0';
/*
* Recursively process the potential child node.
*/
219,10 → 218,28
ofw_tree_node_t *ofw_tree_build(void)
{
ofw_tree_node_t *root;
phandle ssm_node;
ofw_tree_node_t *ssm;
root = ofw_tree_node_alloc();
if (root)
ofw_tree_node_process(root, NULL, ofw_root);
 
/*
* The firmware client interface does not automatically include the
* "ssm" node in the list of children of "/". A nasty yet working
* solution is to explicitly stick "ssm" to the OFW tree.
*/
ssm_node = ofw_find_device("/ssm@0,0");
if (ssm_node != -1) {
ssm = ofw_tree_node_alloc();
if (ssm) {
ofw_tree_node_process(
ssm, root, ofw_find_device("/ssm@0,0"));
ssm->peer = root->child;
root->child = ssm;
}
}
return root;
}
/branches/tracing/boot/genarch/ofw.c
48,7 → 48,8
if (ofw_chosen == -1)
halt();
if (ofw_get_property(ofw_chosen, "stdout", &ofw_stdout, sizeof(ofw_stdout)) <= 0)
if (ofw_get_property(ofw_chosen, "stdout", &ofw_stdout,
sizeof(ofw_stdout)) <= 0)
ofw_stdout = 0;
ofw_root = ofw_find_device("/");
57,11 → 58,13
halt();
}
if (ofw_get_property(ofw_chosen, "mmu", &ofw_mmu, sizeof(ofw_mmu)) <= 0) {
if (ofw_get_property(ofw_chosen, "mmu", &ofw_mmu,
sizeof(ofw_mmu)) <= 0) {
puts("\r\nError: Unable to get mmu property, halted.\r\n");
halt();
}
if (ofw_get_property(ofw_chosen, "memory", &ofw_memory_prop, sizeof(ofw_memory_prop)) <= 0) {
if (ofw_get_property(ofw_chosen, "memory", &ofw_memory_prop,
sizeof(ofw_memory_prop)) <= 0) {
puts("\r\nError: Unable to get memory property, halted.\r\n");
halt();
}
81,14 → 84,18
 
/** Perform a call to OpenFirmware client interface.
*
* @param service String identifying the service requested.
* @param nargs Number of input arguments.
* @param nret Number of output arguments. This includes the return value.
* @param rets Buffer for output arguments or NULL. The buffer must accommodate nret - 1 items.
* @param service String identifying the service requested.
* @param nargs Number of input arguments.
* @param nret Number of output arguments. This includes the return
* value.
* @param rets Buffer for output arguments or NULL. The buffer must
* accommodate nret - 1 items.
*
* @return Return value returned by the client interface.
* @return Return value returned by the client interface.
*/
unsigned long ofw_call(const char *service, const int nargs, const int nret, ofw_arg_t *rets, ...)
unsigned long
ofw_call(const char *service, const int nargs, const int nret, ofw_arg_t *rets,
...)
{
va_list list;
ofw_args_t args;
119,7 → 126,9
return ofw_call("finddevice", 1, 1, NULL, name);
}
 
int ofw_get_property(const phandle device, const char *name, void *buf, const int buflen)
int
ofw_get_property(const phandle device, const char *name, void *buf,
const int buflen)
{
return ofw_call("getprop", 4, 1, NULL, device, name, buf, buflen);
}
144,7 → 153,8
unsigned int ret = 1;
if (ofw_get_property(device, "#address-cells", &ret, sizeof(ret)) <= 0)
if (ofw_get_property(ofw_root, "#address-cells", &ret, sizeof(ret)) <= 0)
if (ofw_get_property(ofw_root, "#address-cells", &ret,
sizeof(ret)) <= 0)
ret = OFW_ADDRESS_CELLS;
return ret;
156,7 → 166,8
unsigned int ret;
if (ofw_get_property(device, "#size-cells", &ret, sizeof(ret)) <= 0)
if (ofw_get_property(ofw_root, "#size-cells", &ret, sizeof(ret)) <= 0)
if (ofw_get_property(ofw_root, "#size-cells", &ret,
sizeof(ret)) <= 0)
ret = OFW_SIZE_CELLS;
return ret;
192,7 → 203,8
ofw_arg_t result[4];
int shift;
 
if (ofw_call("call-method", 3, 5, result, "translate", ofw_mmu, virt) != 0) {
if (ofw_call("call-method", 3, 5, result, "translate", ofw_mmu,
virt) != 0) {
puts("Error: MMU method translate() failed, halting.\n");
halt();
}
212,7 → 224,8
{
ofw_arg_t retaddr;
 
if (ofw_call("call-method", 5, 2, &retaddr, "claim", ofw_mmu, 0, len, virt) != 0) {
if (ofw_call("call-method", 5, 2, &retaddr, "claim", ofw_mmu, 0, len,
virt) != 0) {
puts("Error: MMU method claim() failed, halting.\n");
halt();
}
269,8 → 282,8
phys_lo = (uintptr_t) phys;
}
 
return ofw_call("call-method", 7, 1, NULL, "map", ofw_mmu, mode, size, virt,
phys_hi, phys_lo);
return ofw_call("call-method", 7, 1, NULL, "map", ofw_mmu, mode, size,
virt, phys_hi, phys_lo);
}
 
/** Save OpenFirmware physical memory map.
281,10 → 294,13
*/
int ofw_memmap(memmap_t *map)
{
unsigned int ac = ofw_get_address_cells(ofw_memory);
unsigned int sc = ofw_get_size_cells(ofw_memory);
unsigned int ac = ofw_get_address_cells(ofw_memory) /
(sizeof(uintptr_t) / sizeof(uint32_t));
unsigned int sc = ofw_get_size_cells(ofw_memory) /
(sizeof(uintptr_t) / sizeof(uint32_t));
printf("address cells: %d, size cells: %d. ", ac, sc);
 
uint32_t buf[((ac + sc) * MEMMAP_MAX_RECORDS)];
uintptr_t buf[((ac + sc) * MEMMAP_MAX_RECORDS)];
int ret = ofw_get_property(ofw_memory, "reg", buf, sizeof(buf));
if (ret <= 0) /* ret is the number of written bytes */
return false;
292,11 → 308,22
int pos;
map->total = 0;
map->count = 0;
for (pos = 0; (pos < ret / sizeof(uint32_t)) &&
for (pos = 0; (pos < ret / sizeof(uintptr_t)) &&
(map->count < MEMMAP_MAX_RECORDS); pos += ac + sc) {
void * start = (void *) ((uintptr_t) buf[pos + ac - 1]);
void *start = (void *) (buf[pos + ac - 1]);
unsigned int size = buf[pos + ac + sc - 1];
 
/*
* This is a hot fix of the issue which occurs on machines
* where there are holes in the physical memory (such as
* SunBlade 1500). Should we detect a hole in the physical
* memory, we will ignore any memory detected behind
* the hole and pretend the hole does not exist.
*/
if ((map->count > 0) && (map->zones[map->count - 1].start +
map->zones[map->count - 1].size < start))
break;
 
if (size > 0) {
map->zones[map->count].start = start;
map->zones[map->count].size = size;
308,13 → 335,13
return true;
}
 
 
int ofw_screen(screen_t *screen)
{
char device_name[BUF_SIZE];
uint32_t virtaddr;
if (ofw_get_property(ofw_aliases, "screen", device_name, sizeof(device_name)) <= 0)
if (ofw_get_property(ofw_aliases, "screen", device_name,
sizeof(device_name)) <= 0)
return false;
phandle device = ofw_find_device(device_name);
321,21 → 348,26
if (device == -1)
return false;
if (ofw_get_property(device, "address", &virtaddr, sizeof(virtaddr)) <= 0)
if (ofw_get_property(device, "address", &virtaddr,
sizeof(virtaddr)) <= 0)
return false;
 
screen->addr = (void *) ((uintptr_t) virtaddr);
 
if (ofw_get_property(device, "width", &screen->width, sizeof(screen->width)) <= 0)
if (ofw_get_property(device, "width", &screen->width,
sizeof(screen->width)) <= 0)
return false;
if (ofw_get_property(device, "height", &screen->height, sizeof(screen->height)) <= 0)
if (ofw_get_property(device, "height", &screen->height,
sizeof(screen->height)) <= 0)
return false;
if (ofw_get_property(device, "depth", &screen->bpp, sizeof(screen->bpp)) <= 0)
if (ofw_get_property(device, "depth", &screen->bpp,
sizeof(screen->bpp)) <= 0)
return false;
if (ofw_get_property(device, "linebytes", &screen->scanline, sizeof(screen->scanline)) <= 0)
if (ofw_get_property(device, "linebytes", &screen->scanline,
sizeof(screen->scanline)) <= 0)
return false;
return true;
/branches/tracing/boot/arch/sparc64/Makefile.inc
28,6 → 28,14
 
TMP = distroot
 
ifeq ($(CONFIG_AOUT_ISOFS_B),n)
SILO_PACKAGE=silo.patched.tar.gz
endif
 
ifeq ($(CONFIG_AOUT_ISOFS_B),y)
SILO_PACKAGE=silo.tar.gz
endif
 
build: $(BASE)/image.iso
 
ifeq ($(CONFIG_RD_EXTERNAL),y)
39,7 → 47,7
$(BASE)/image.iso: depend arch/$(ARCH)/loader/image.boot
mkdir -p $(TMP)/boot
mkdir -p $(TMP)/HelenOS
cat arch/$(ARCH)/silo/silo.tar.gz | (cd $(TMP)/boot; tar xvfz -)
cat arch/$(ARCH)/silo/$(SILO_PACKAGE) | (cd $(TMP)/boot; tar xvfz -)
cp arch/$(ARCH)/silo/README arch/$(ARCH)/silo/COPYING $(TMP)/boot
cat arch/$(ARCH)/silo/silo.conf | $(SILO_CONF_FILTER) >$(TMP)/boot/silo.conf
cp arch/$(ARCH)/loader/image.boot $(TMP)/HelenOS/image.boot
/branches/tracing/boot/arch/sparc64/loader/asm.S
105,9 → 105,28
* 1. Make sure that the code we have moved has drained to main memory.
* 2. Invalidate I-cache.
* 3. Flush instruction pipeline.
*/
call icache_flush
membar #StoreStore
*/
 
/*
* US3 processors have a write-invalidate cache, so explicitly
* invalidating it is not required. Whether to invalidate I-cache
* or not is decided according to the value of the global
* "subarchitecture" variable (set in the bootstrap).
*/
set subarchitecture, %g2
ldub [%g2], %g2
cmp %g2, 3
be 1f
nop
0:
call icache_flush
nop
1:
membar #StoreStore
/*
* Flush the instruction pipeline.
*/
flush %i7
 
mov %o0, %l1
134,7 → 153,6
retl
! SF Erratum #51
nop
 
.global ofw
ofw:
save %sp, -STACK_WINDOW_SAVE_AREA_SIZE, %sp
/branches/tracing/boot/arch/sparc64/loader/main.c
39,6 → 39,7
#include <string.h>
 
bootinfo_t bootinfo;
 
component_t components[COMPONENTS];
 
char *release = RELEASE;
55,6 → 56,15
char *timestamp = "";
#endif
 
/** UltraSPARC subarchitecture - 1 for US, 3 for US3 */
uint8_t subarchitecture;
 
/**
* mask of the MID field inside the ICBUS_CONFIG register shifted by
* MID_SHIFT bits to the right
*/
uint16_t mid_mask;
 
/** Print version information. */
static void version_print(void)
{
63,6 → 73,39
release, revision, timestamp);
}
 
/* the lowest ID (read from the VER register) of some US3 CPU model */
#define FIRST_US3_CPU 0x14
 
/* the greatest ID (read from the VER register) of some US3 CPU model */
#define LAST_US3_CPU 0x19
 
/* UltraSPARC IIIi processor implementation code */
#define US_IIIi_CODE 0x15
 
/**
* Sets the global variables "subarchitecture" and "mid_mask" to
* correct values.
*/
static void detect_subarchitecture(void)
{
uint64_t v;
asm volatile ("rdpr %%ver, %0\n" : "=r" (v));
v = (v << 16) >> 48;
if ((v >= FIRST_US3_CPU) && (v <= LAST_US3_CPU)) {
subarchitecture = SUBARCH_US3;
if (v == US_IIIi_CODE)
mid_mask = (1 << 5) - 1;
else
mid_mask = (1 << 10) - 1;
} else if (v < FIRST_US3_CPU) {
subarchitecture = SUBARCH_US;
mid_mask = (1 << 5) - 1;
} else {
printf("\nThis CPU is not supported by HelenOS.");
}
}
 
void bootstrap(void)
{
void *base = (void *) KERNEL_VIRTUAL_ADDRESS;
72,6 → 115,7
 
version_print();
detect_subarchitecture();
init_components(components);
 
if (!ofw_get_physmem_start(&bootinfo.physmem_start)) {
83,7 → 127,7
printf("Error: unable to get memory map, halting.\n");
halt();
}
 
if (bootinfo.memmap.total == 0) {
printf("Error: no memory detected, halting.\n");
halt();
/branches/tracing/boot/arch/sparc64/loader/main.h
41,6 → 41,9
#define BSP_PROCESSOR 1
#define AP_PROCESSOR 0
 
#define SUBARCH_US 1
#define SUBARCH_US3 3
 
typedef struct {
void *addr;
uint32_t size;
/branches/tracing/boot/arch/sparc64/loader/ofwarch.c
40,6 → 40,10
#include "main.h"
#include "asm.h"
 
/* these tho variables will be set by the detect_subarchitecture function */
extern uint8_t subarchitecture;
extern uint16_t mid_mask;
 
void write(const char *str, const int len)
{
int i;
56,36 → 60,40
return flag != -1;
}
 
int ofw_cpu(void)
/**
* Starts all CPUs represented by following siblings of the given node,
* except for the current CPU.
*
* @param child The first child of the OFW tree node whose children
* represent CPUs to be woken up.
* @param current_mid MID of the current CPU, the current CPU will
* (of course) not be woken up.
* @return Number of CPUs which have the same parent node as
* "child".
*/
static int wake_cpus_in_node(phandle child, uint64_t current_mid)
{
int cpus;
char type_name[BUF_SIZE];
 
phandle node;
node = ofw_get_child_node(ofw_root);
if (node == 0 || node == -1) {
printf("Could not find any child nodes of the root node.\n");
return 0;
}
uint64_t current_mid;
asm volatile ("ldxa [%1] %2, %0\n"
: "=r" (current_mid)
: "r" (0), "i" (ASI_UPA_CONFIG));
current_mid >>= UPA_CONFIG_MID_SHIFT;
current_mid &= UPA_CONFIG_MID_MASK;
 
int cpus;
for (cpus = 0; node != 0 && node != -1; node = ofw_get_peer_node(node),
cpus++) {
if (ofw_get_property(node, "device_type", type_name,
for (cpus = 0; child != 0 && child != -1;
child = ofw_get_peer_node(child), cpus++) {
if (ofw_get_property(child, "device_type", type_name,
sizeof(type_name)) > 0) {
if (strcmp(type_name, "cpu") == 0) {
uint32_t mid;
if (ofw_get_property(node, "upa-portid", &mid,
sizeof(mid)) <= 0)
/*
* "upa-portid" for US, "portid" for US-III,
* "cpuid" for US-IV
*/
if (ofw_get_property(
child, "upa-portid",
&mid, sizeof(mid)) <= 0
&& ofw_get_property(child, "portid",
&mid, sizeof(mid)) <= 0
&& ofw_get_property(child, "cpuid",
&mid, sizeof(mid)) <= 0)
continue;
if (current_mid != mid) {
93,7 → 101,7
* Start secondary processor.
*/
(void) ofw_call("SUNW,start-cpu", 3, 1,
NULL, node, KERNEL_VIRTUAL_ADDRESS,
NULL, child, KERNEL_VIRTUAL_ADDRESS,
bootinfo.physmem_start |
AP_PROCESSOR);
}
104,12 → 112,59
return cpus;
}
 
/**
* Finds out the current CPU's MID and wakes up all AP processors.
*/
int ofw_cpu(void)
{
int cpus;
phandle node;
phandle subnode;
phandle cpus_parent;
phandle cmp;
char name[BUF_SIZE];
 
/* get the current CPU MID */
uint64_t current_mid;
asm volatile ("ldxa [%1] %2, %0\n"
: "=r" (current_mid)
: "r" (0), "i" (ASI_ICBUS_CONFIG));
current_mid >>= ICBUS_CONFIG_MID_SHIFT;
 
current_mid &= mid_mask;
 
/* wake up CPUs */
cpus_parent = ofw_find_device("/ssm@0,0");
if (cpus_parent == 0 || cpus_parent == -1) {
cpus_parent = ofw_find_device("/");
}
 
node = ofw_get_child_node(cpus_parent);
cpus = wake_cpus_in_node(node, current_mid);
while (node != 0 && node != -1) {
if (ofw_get_property(node, "name", name,
sizeof(name)) > 0) {
if (strcmp(name, "cmp") == 0) {
subnode = ofw_get_child_node(node);
cpus += wake_cpus_in_node(subnode,
current_mid);
}
}
node = ofw_get_peer_node(node);
}
return cpus;
}
 
/** Get physical memory starting address.
*
* @param start Pointer to variable where the physical memory starting
* address will be stored.
* @param start Pointer to variable where the physical memory starting
* address will be stored.
*
* @return Non-zero on succes, zero on failure.
* @return Non-zero on succes, zero on failure.
*/
int ofw_get_physmem_start(uintptr_t *start)
{
/branches/tracing/boot/arch/sparc64/loader/register.h
33,8 → 33,7
#define PSTATE_PRIV_BIT 4
#define PSTATE_AM_BIT 8
 
#define ASI_UPA_CONFIG 0x4a
#define UPA_CONFIG_MID_SHIFT 17
#define UPA_CONFIG_MID_MASK 0x1f
#define ASI_ICBUS_CONFIG 0x4a
#define ICBUS_CONFIG_MID_SHIFT 17
 
#endif
/branches/tracing/boot/arch/sparc64/silo/silo.patched.tar.gz
0,0 → 1,372
‹;!³HìZlU~ÿÎìxwì8Éxc;N.Ï?ˆ—œkoçÇq4zÊq)¤=襳NL“6‰-bîZÕ“ÍÚñµ@×fëú"rLœÅX\tgBŽDæ莆=“¿Zq”R©ZB”Z!¹àÎöó™M–ˆ­*Ô_iwޏïûþzßï½y{v=p°µƒ¾Ê'Šgc{;¿×nÚ-~sqCtc”Ö®nh߸.Ú¾i=E×®]nýJ¹òŸ‡öÄ‚ºcßïÜ÷p_Ö¿ð,<ÿ H¶4Zºž¨úTµ¡7i£•MhTñ³—rvzµ^Q¾CSB·*ëíèR$Œ+ü,…êNõ:ó1C9ÝDµ²IJ\#²Wët*ˆ¶1KØ[t²·*~~55™üÇèæã nR ã9ñ»&®úhÊ FÒèØ…^¼Ý”ÒèkC­ÐInMjTƒ¶0Ãrð›!º¨Í(By[ê;Š(O§-ÍR„v±I§™&Cy»ÉPßi2ÊAóò¨bh‡~™Sy¼ù·.íÕ\>îÒÒ£)ÝåãÑú1$Ù ¯¹ýß³éD{4j¦-á=<ÞÕüzåò=TU€9ލÐ
ä˜iªþ%Üç·)~[©«7ÛI³/•çÀ¯à¾5]ù«\?ô’Ç#ÿ©N™NC²!9“GŒÓ2( &È’
°ÇÞÊŒ˜cË´3©
+)¢xï†<R
+¸7šô|ä;<22ÏŠåÁ}ËÃMW{¯B_2ø¬\»LuÅŸƒ2à¨ü
+ž3ŽhWñ^Öïéï&ð'¶ zý¯¢Œ¶
+s|qÙàm¹UVèÌ\
+¼õæ¯þ|XƒÞ)˜É§†J@S¡Ê!…JÙG‡äÞyàíd?÷qîeœ…¹Õخٿ"¦Êö »`ŸšwT³´(N8wÇ8¶å6ö¿¤ïÿCA!%5c3rèϝf©?W‹'ÐÇðÀ÷qJ¶$+”™A.ª*ðË1x4èå=ÆíÈDè«uš3³ŒKJ2”™Åm—xL!®Løq…e8öÖs#o…YvωS¬òu30znÎՍI1ŽEÏ”<Lã%BJÿ(úN†^˜³s§‡³Ûõð˜"ê㪑_Õ¬kÓróÃ]ižüÏaSö â!S²#6Çå„bK#AßÕ¦E°?=œ4¶æY÷áçì¶ç0VI’©2<t¾§‚6|®ÞÈ Ü×D«ÝöÂÈ¢:m/̱®¹Ëø]AßG<²½œtã<-L“™~ú_ÁoÚà“WOñÜû:^É}ÎÝ/ÎùóRÁúãõ‰£ˆv´•´#Ž°nâdHë&ÑŽñ5à9žÿ §Þ<xÒ¸øƒÊÓ«m´^ý+”˦WçXÿ*çQ5“ÿ ëÖ|Ê ÊLþpVçÀ 1=ä@¶·«¯Dtµ(6&yÝ‚qµ:IzÊËKÜß-Êc,[ç3n{ƒsSÀ0³X!—$œ¶3³ ™R­>”ߟj;óžCÖæ)ºQ´}€þè€&Zε¹”%ë´}ˆ¶[P¿Œ2æíÌ•„j…àÑlÛ™_ç¾dèÌ,Ó„[¦…å|ÊmàSåvöûiŠÀçuðýò°ÖÄ~¦&üq~èÍÏ¿ö
+øåöBip㳸å[×ù9ƒãçM;bÉ(/⼂ùx’ípµ5X¹x·Y²¯—®ỎX—™¿¢ü_ÊóÏü"ïKœÿác]Èû;˜Ïé&-âó$ËÌór½ÝˆzsgH5n,¼&þ¥—ïâ„Ð<ÿ›]ßÿ¼x:óô²vÃñ¢Ä·ÑE<ðsÉÐÙǘ7ÐÚlUŠÍhûmçЦ€ÎO–ù`¾ma´ƒocq¢
+mÀû«TØÚìÇ
+wݍ1?öÞÒ?ƒ¿oOöÕPæìK½ ÍÌsJ~:Zþ7ë¬E<¶c×ýÆþµ»ö¬ª³Ý]SlçõwJ«g^¸Ëüçïäx½owZË ƒdµ(wZ„´Ìåmþ‡ÂÖãÒ™ià*į,Ö ÖB¼f8‚õB\èrŸ»npón×/~žùaÙwÑ_Xïp|f}|Ôlí¼Ôlm¿Ülí˜k¶î9±ÑP1‡ÖäciÁ_X·þúB9U)¶A†ï± ³MbóûÑjCqVê|/²¶ûyՍ¿t–ÀºÕ&³¨»k¤z¡b=´¹çÊ€$ßnžpý8·rœôÚY2Ê òr¾é‡ÇA?{›Ø†òJn;KFMv³¡rlö`„„ºÆ|€‡*æ×9ð¼0Ãk_Ì÷Ø‘Ç^&»*3Ãyœá²Øã Mn™ëŒ/»•(­XÒ‰vC:ßisåêLþÞ·0߬› KÃî¶qý<t‡}YÖxÚ± ÝÝoµxû-_>eW&È€œä\q=/eFŠ×Ýà]-ò«ž‚_àaoU§<;zdðÝÆîë{/?¸û„ǯán.ìMÞ1‹ß‰%[¯fEì ·Œµü%K|ígá#³¯ÃGª6¸¶˜?˜
+Ÿà}B˜}kõñ´½Ê4Ýø<>î^„¯&¯Å4;úˆk¿è÷c`ÚÇgdBö×n¥¾¼¥¾Ý-*ðËócƒÎàSÂÏÝO1î;ˆy± ¿\Žò/¸<+¦D,UÿQœòyÐMrÜ÷ñœF=UTgÓêWýx9úñ ¾wý˳Ö…ˆ%3ÈsR4—IÖå\£uçF^§ð~é(¯#Ç¿
+:¶
+…cäp}Éç8Ê™7n›]ó¦+ÇpøM rŒCŽËºX† û2°oÜ(æí¸{Äç Ø'< ~ŸÝâñóY1ãïcŸmõà0þïn°Å-¿À²pqۍxÜ}¯3^»Â¯j¹\v]îzæy”!gø,ú‹ühύ~äÆôy¶ÇšðìgÁ°¿]BÿDucº‰<>#×ã±{¶Â맚|¸4y½-Åg<Ü<·ìþY ÛÌ2è~¦È'…õS‘Ÿü'héôù´°®
+£¿Àï3×{ùòW©ê˜Ê|ÀÇåÙ`ìóäÀÞ•åðà>OÞaï\ÀNù°Sæ³ bXè¼’çƒÇÔ{9¸:UY5Oþb«æë$4ä¶ÍwñzË_÷ª~žëæ±îy‚à3¨w!›YLƒm$àÅë‡=}º6Â>òö€ó{ þþ »¹v"Žç`gçŸòûÁÎØn~·úçå­~¡Í¯wtuõtÇzöÎÓ»º;ðûö;¢Ñµ Çm;wuØÍŸÙ:ÞÛÃýì=°{wç÷÷îêôñíÚÓuCöìÞËðîz»öÄÜ:£a¸Î=â½ÿCî¸]±}û~cgÏž.—MÚëvßðJ?xpo“صgï>†èît‡Ówöt?ØÕ½ÏãöZÄö»ù|ïÝ×Õ
+’â]>' Å¿óµ’åczÝ:Aﮜ
+ï¡”Á§–‚ßúw€®”Õl‰û.²îq4“çDJ4Ù‹YG6Ø‹y܏"°5ðþ*d³Nƒ-ƒßò„lËÏ–â@g°C óp¹/’ $”|žqð̇üSøÙá(|áQ›ýz~`¥-õµ6á¾~ØÃò÷KÙš?Ú¨‡9>þ:-æ{6ñRâ{1ìÇWú)ÿ t?rV#çæØ
+aÀ,î^=‡9½ÊZœr^æbD<·n£ÇíYw{ìˆx¥–»æöðä 0÷ùv÷›LâPtýgç՛ׯûÛßþö·¿Ýýí~ßo§Õ”Ò‡~ ùx—ʤ2èI吭•3Tb¹
+[’OºØVè±ÕлNŒÎ³ê~?ÏZnëe4ñ4Œ?ò»˜‡×°›2g6åڐbN¨£1€óØc-Gx… ߆ðm2¼áåƘÀLjnàãDxˆ…»¤2Ÿæ(ŠÛÅõš°¹«¼—YKIÇ$»¦Ø¹H)»¦
+é2óüdï=iLŽk
+ÊX
+^/Ý
+½ü=jS´—‰õ@ºÚTš©lèJ
+Õé.Jܞǥmö4ßÆüºg7dÙª$}K‹Ð„õAõyƯ¢ññ”-ÃøEºm†ôOÊÿ¼ß8ß6!?åUaýÜŸ¢ú=N4ﮡ};Žov_~¹É¥Ç“;¾“Žw¬Ê˜NëD®»õq¼¨gXºÛ؏ÐîÕäÃFq(ç$ÙV›}æl²3"|÷_rþ:&e´¢ùt¹v ƒVÇVÈ dPEw%§µó0ô¤nÏKÕãî¥53ô(ïa}pŒ`b&ß³â{O´Þ%yFºGÊ4ù5Í: ™æë@sÃ’<Û°[Èn\À’-²÷`%ÜY‚“ãêqÈÚñä¸Oë ÌÑóËñ©SµIÖ ó 6&öµ
+àCU)/aOÑÞ§ÁŠ:©ÍsöÄàùáü¶ìZBزGN´e×ùmÙ£1-6nË®%zf†ÂÂ<:<nË®ÕÜÄÑúضeG;<´ðmÙCáOÛ²O¤y¢-;§y
+[v-F4æ·e„ìÄ„-{4ÒS[v-!é?0nË®%Fç‹P= OÔãê¤z ·q¶ìÙz^¤-;퇒ͲàÙ…Û²óòæ·e×ès…,Dä·e×hçúH˜"ß3w®-ûfÔ}'Fòù¦+´ð1Ìýd7Ì÷jF« /ê6Bð©ÊÐ:/ùª™Éð«.èˆo">%àQ¾\8»Œ§kÃAÌ)Zñ¸ÎÛh“B<C}5Þì·ÎGën²[¾œ|Õ,î§N:E ù¾6æþ©ï'…ŒÇ¬@ƒcÞ?÷pq­õЇTC¥±üñâÂפ}þÇ;¾e•83ϲL¦;°;³%ðNf@cŽç4Ãiîd³ÐWKº0íÏ£œ_’¿žàMƒ=XÁ\wŠÖûRv§‘O ÑÇivëMqᯓ‚܏ÜAr¦Ï¥ñ¢Ï­+é;°,ÓWó½õð² âèlE~“ó]¢ÓÞd+ßéÓ»H_ÂsÑ´WIç
+¹Å÷gÀ^ßÃqaÌ6–e*_³,M88_ _Lj›/¦ýÈ·(O1}‹*Ó›Óˆçß<QŠwŠyÎ…ñ³uùå!^pýmÏ×lƒ™×¨Žv]Æý™ùþõÔ–xÞFïDc4î„6x–è$ºÈÖ}[m˜ö™f’| Ý¡ÓøÚUÌËÆúí;I_k³ s˜Ï— —J8¡»ç)à#ù¢ ´%“.ƒ|ëÿ ¼šKßÈ÷Tœûfþ”ÎlÉõñêñXËs÷ío»qáýÈ›óOäô­ææð0K?8¬7¬‹1S%Ÿ@Œûž˜ºé¤˜“Ó:ù˜×°ÎLò>å¤yhD?h“–{‡ü}($Þ)L0GñþëîâçW8©©nî¯6Å}ÔÁؘCwýdže˜=ɧƒôîCúA˜ R-‘߇4:0чãEÖ‡´¢ËÈúVt}1>¤|ÌÛwa>¤]ÃK+º.Ƈ²´è‹ñ!ÕÄ›ã,ºß]ô~ ¼»xÒñ9HøÝdç„<>¤Zý¸iÈø´©–÷!Õtÿ^ÐSøF÷ñ0÷!î§0ͱˆ‡Z.|Hµú¯#^ø&Wû&÷Žûjõ#îä^Pwæñ0ááqztïë¤t©+\…ø£:êtNRA¯ð!žèCŠ¹qüÉ}H£)ö#ü
+ Òh_?óør<Ãã>¤üýÀÔ>¤ìщ>¤ZBøF­ü>¤Zý¹}HCmŸö!%]=ԕ߇tJÙÈãCš•Ȇ9îCªÕ“ÜŽº*ÚÆ}HC«P·ì¶DxÚmk~ÒŠ,Í#9áÏïCJëòI
+Å…)ßç ²f]¸©V?ƒ¯!ȇ”ä’|HCñ‰zF®oÝ>Jß:חߏps?¾ç€wà³ùñ«¬|~|Ù²žDYÎWÖÔ~|¼ïH?¾OÉLß¹ýø¸ì8@Ã}Ôãǧ%âR'ÎïÇ—¥+§Çzî=#æǧm~|áêq?¾põõø’üø´ÍÔŸül ò㋾5îǧע–mŸÏO«çüÄ-ø9ُï¬z.?¾]Ð HF¨Ùº†™Lbm²ù™ÓÁß¼WõRÚnƒ¯OŸ@9O]&[ı^§®ìÚl"Þ󄒦ﮧ®+»œü;·ç‰9iù|ô€ÊGýô|âé´â6Ù}ÞJ&„-Fï;æ[”V@x(tQ:Kh§p!K¡¼3éL®žíi5-T†:˜9Û»™Ïs½àҁË\Wq\¨—æ„}9á;ŒòV ¼¢1¾áB
+O‚ù6â}¦a¯„™
+çµ€ñHøZ„ òà\Œx§„¹Š×9vÁ4W$°•yu„ÏäÁ_ŠøÓæR„ÿï<4_˜O$¼áóà,@üÿHÂÿÝ»[§öIÿ±Žs Ý¼R¾|›zöLD~ŽJ;ó&îçNÅCLû£LþQ&ÿ2Im&åKË•I×.l‹/ôLÉ‹=Ë'pž³± ÷^²=–ºàǶ.¸€sÜ0'{É®Nž«èíqÚ¹à»ÜæÇMë··IågÚv>Ò^8cÃoŸ&úÝÛ—„ƒÔo³ç.òsáÈF×ðÒ(ñmÂù‰SœÕH{}òìGõÑOó’ŸÑHgury†#p|<¬¦¼“ùúyÏ’”ópY·8”g3ãëxâ·˜@7ÙY?¦s\x!ŽxªRXÆ9çâv>ñs> bÏëàûÄÉ„Ø;¡ýf)‹¡7ò³¨4²‘ÚKû˜:›µ‹ô‹©{£|_Óÿ\€šýÁú0ÎÞ[ËJ>{ç8li°Ð±4èV†àAËݤk™»Y²Aç Îït³Ÿù1®ú{† ïÀåÌ?p3ÖÚ·S?-Ó|”Æí-(îC,XJ߀ÜXOLäíY&ÞÿŒ¾o™»ÅÞR‚ÛÙsö‘n£ÀTŠ£öáå[)^~bÈÔ¶è)ÿ#åÌ–/Ò|”FåótºS)gnù‰˜È›Xbœ_bÝ6&Ñ/Í~“xèš9A\Õ+^\‘A¼Jë%Ú—4ûŸfqƒï…« MW§1´é8Œ<
+-vrãj½i}dm£ÞÙÚª7·¶¬Õ¿¦olÝмºe^§¾¦©SojélÕW7vt6µD:ŒçFVëkhjÓ‘µ©AoÙ°>ÚØÞÁX/Ói%.@æû"ÍM«uûˆ™[ZÚ6e‡ÞØÒÐ~[g£8v†Ý¾¡¹³Io‹´Symtrø øu‘Ž,¦5Í‘µ(‡èonìlÔ››P$Jìlol̍_ÝÔÑiih ògcÉ©ýšÖöõ‘N½
+——W!.…ì©…l›Åæ°Eìza³Tåa‡âT\Š[Q¿P‚Š®T+†¦îäf“Š¼òrÊË%¯y¡ª¸DÉnNŸ—SVÈŠ@Ãtv)›ÍÊY»’]Í®e7²»ÝÁ6³ÝìeöŽâ¥yy‰Nä/ô2¶‰e”Œ3ãÉeÊ3ük¬8Q +~`e¬X棳¨<2?Ձäƒhòáváö3~´¨Á2÷%L EÙZŠx—Ìç‘85‰Ã/Ëœ‰ûRÜ¥<Ï•ôïp8ñsÉ_Á¤Ÿû<?ÏEþÔ¯ø§´€OAÜ%ò‚Wm®6Gø?I.ü`FœŸÃb6dK™Î*1ŽûYû>þW!þ6¶1*«¬ÎqøyžV ˜[Îˁþ…ë'2¤ò+Àñ¯@‰AÀ.ÅU,µìA`71-u3ÁU¢Ðô¬b+Y5¨£\:/We#Óû%Ö ³X™¤DÔ)È) ²ø§Òª9¤‹×¶ 4ø9%xïÅ{ç&Ž,E¨ yK8¨K-ÞUÜ.ŽÑâ)+Ù ¥LÒHWè
+³œ“Ëñ^Æa]œ+~YªÎÿK@‘‹óCPZ†Øj¤ÕðP§¡Œµ!\ƒÐÀ—&ú'®V¢dá֍ԕÌåqbûæ½™Lé6XÐÌXùãâè7‡ó·g
+¡úr>  /[Ø.ºô>ùÍ‘“Ë^¯2U Y¥òa­H>PÄ/IøeìêUÔ=9eý q@ØÁô½JcÄ0å+þ¹Pæ ‘†üõf%S"?Dòï³<ÌPáņê xánÌÿ±'Äl¼¬¯dnnÊhF‹ô[Lü0¦³Å‘M9¿dº
+(|÷M^p Ÿ1½—]ì#í@FùÇ™X@Æ ®‚↿¬V–b½o3)þcQîxÊ9ù«FûŒ?©Ä–——SÍ D—-èž-Ÿg}?¯pV÷Aý.4ª>©p• Nï=!k"_Í5ÁÓÏž_Bt읿O$ìêœOÞR\.´
+úJ Á¥ŽÆ2ÖûËq¢A²«í›Fa`Àüa•.ä¨éÕ®‹*Pë¡Ù­Á¨?”m–È#ŒpÁÂ/†ô—¬cîpôµó÷…Ï@ùËFiòú#†éõÎyÕ_è(—œXÚ‹×o(†Õ«Š%Õsè;CùØ°{nsö´ ´¬É[\r+í1Òð~w¤ÌtRFT|½yT2.¸~~ +ãA§Kx½Q#ËÂÕ=ý«8ÏR+VúԍUXӻĔŸ¨hBŒ&ˆdÝÿf19qzïÓRÚ
+àõãò&‹;Ì4-í–3PsÝì»zQ¼J`([$OJIO:âìº/©X®ÑEYõâ=p_1µ?¶J½#h«ÉBÀQÿ¢5?­;~{B™5:dAµsïñxoŒÓŽ ©øÖ„n>ý«ýjh'¾ ã”Ÿ¯zq̃ô“_njx ýÓy¡§W&à@y‡ñ^¬õ±òŽøÆÿ\YxVx?ÿH^õÈÓ¤–´uÍ’VudI¸¶\Nw‹÷6œY¯û¿r¬±ÈÂ"ÈÝ>Ó†-x^ðÍUÿàÑ°WrœÂVÞó ÂÒ¥NAðóK}êÌŸ­/{/l¾åxCô[~$Ȇu_;©¸¦Ø´ÐW±À ›,åNh!MíÅvV;ž`Èã0ŠšEÜaéLÂ?6!# ¦¨âRnĸëwÏ»`QñH à o(–ËPc§>ÌþPWuíªÊÚ¿“ù-é«>ó¸
+VDl¸¬¥ò'|Ô>åçÜ{¸~jÄϪÌb0H68ùé³ý$+´K%s§£Œ4~8ûÀ|ûRlõâÅ‘é;ð‹oëR!ªfŠûy£ÖnC¶BDqdÙ+‹"Fê¯Ü,o^ÄÕOlñzàea£ÔA`tßv@¾7ƒµ|‡Ì$z÷™jÛ\h·LKÁUž»j&ÌîìÌ¤žæâÆǨK$üy^Cеüû¢¡þŽ1ùQòNŽîÒËüŸa‰N˜*òUÎSRì¢S¤÷•Vi0U“œé q€Ú˜(fÌÚMrÉÁ~à÷
+²YíV£þú·ŽÛ4Ï-Ìœ ÞRóìÍEŠã¤ób[¿'-N”ZùžxÇ•sF&²l²Å%‰ÇwÜ6Y””‘ LßiqÈØx¸m-foËkosÿÜb²uâ¼Î%¥»1?;· 2Ç1­^£5Þ#sbY+“r}O²Õ=Ÿ5†Û -¸ž·é´Ã5Î<€÷€¬dMè-µÃ3°4´hXR‚<{×D¨ ü÷Ƚâ
+ÍsÄ
+âÛoñþìËF´Ç:€%2®Âr›&'|­G$”&HGY†¾¾Y®¨»ñ²˜C—‰~ûbZ¿ç>goåïõýü•£¼NûÌrd¨jiÑúéþS¤ë¯ùg÷vŸ9tÛ«ž½þÒçY—D¼òÒ=Ꮳž®ä[mdù§n%³?Ä}Aoqu~šã.ò³ A‡¯‰‡…Ï6ÄÞçT=çõìè
+šò!.Íç:ld~ÄÓ†Ä?ê<~wv¬J~ò‰mÂ+ï1ÚË´Â>óÌ»÷ª§^‹þz+â˵=‹`5¿ÍÄ`Â}V»ØîKÓ¹qqEP¥‡Ð
+U©ã]TÒq¹{ö»ûH»3G
+þÁ‡LîbõêÁ0ªj ¥è þ~ÑÙžáÇonf ZÍÝM-Œˆ)ŠŒWÃÁü DWÌ7gDgÙhÐ[ýÿ%¿ëDïI~¾.–»ÇÊq9DeÛŽÓÈ"dÉ2=
+­M;ÇVenª@•Ç:Õ3j×f]pÿ <'*¬¢ÛѦ×t®/\ÆFßêHt®‹ÇZNÂéÑÑú¶þtrª~[ݸº°Œ#|b^ Jå©o_¡VQRõ §×ßk>k$ñ¤«‰¾à»^yÚ¿®&®Î]O‚©°Ç1ˆ6€ØIåëÖ¤Æ_£Ÿã*Ÿ 9Äî“u>wd¬w7*Ûé~ð€÷ëò×/ªOuŒ`!Òœ¥8¶sAzîí„ M“fv­›43wÎ)æ²2ÿ2O¿ã£J¨.R÷³^®æÃ~œoqáÈ‚^]A!îqßfD<Å„}Ýߘ¼Êcc÷Ï>‹i$ü²ó)IqM”²“Yª¶
+ÉÔ<9xÍݤÉw
+njq›Oí¡Þ[7K5v[ðBí8÷øçÞ®j #§Öþ÷ü?ÌŠ_±ÐÀ;ÛÝmí%•~û?Þ#QoˆÀfŒþZ¬ìTÂñËÂçο¿ŽÄ$)´ð¡#u> ßäºð ²]¶Õ¡cW_cÆN*}fª} =Ù…ñaµÈóh*æ1órýS¹?A;ŸEzª.ÃÞ®kW2r½9†%žzbþ{oÂ6]m*¡˜ã–è³>ÕT@Û¿g–†/0và€e^ú­]¸/·ˆz°àßÃ{n‘­GŒ(=mèPƇ¥¸¿Ó–€©'çbå ÙŒ”4ø->‚M¤=œú˜º˜º¬e>ÒÖ\J½ŸÊÄTyšg6·åŸ¿y¬‚cä1C‹WÌ1³y²C]âiÞ¥ÃþÝß•J”A|_ÀÌêÁ1Z®ËêQöÜûâ{z¾±ÖûQì2˜û# ™â#v¨²õè³A
+¸aö„†ɳ'nÚ ¶ßp !žÂ«C3²¨¿Ç.4LçÊ€SVrD/´>–ÎB›Î¿®žÚë‡,[9Ú+ÙBv uÐg@0MUÇ<”µ>_Jûª*ˆAV÷‰m÷¿å¤Xm3ÁxœëšÙÿRxd
+ IӁëšpšÊäw4úÇñ<œšªËeK‘Ç—–õʼ½»ŒÍ9–6¹“=gæ'ÒsiŒg¿ÎüRl1
+ŸÐY/Óï‚ÿË‹2hg5Ï•þ¦DávómLT… <N&‰À3‚ê£äÔî·Vƒ©½”ÆS-»\{V'û0;õëj’UÜ#:Áç>‹›]Â+’º’×ݺãEìèíº[ðU£÷Îè?Îó dø寍€âŸçù±ó³=eöÅ¿X’¸ƒ¼}½Û‡£Š@êd“E‡&.Ó Óz‘@)3ì÷Ôêžt:þdŠçá;ìõÙ«Æ×u×cŽ?«M—Vuø:‰Ø+:M£0~ãÅ­a&u·ñ³÷×bòiIb#œiØS¸¹qáµ½•y›þÿÚ"C¿™½ T´Z+^<K÷1‡o÷rbn¸Kþð0ŠÜ/Ž…6O4R$¿U+Ï4bçSJ"§ÝÐ×Ñ/¨GÖroî
+Fœ4FËâ,lq! –7E‡5¹*<sV
+ï ¹BÑB’˜fK‘™l‘º²˜ônâÆs÷ºÔ;­rãˆÅÇU±¹d[–ڝV öp¬*LoF+®°-ææÿ_sC+2Z`:ð™ì­ýÕ\Èx{À®~ ¯ÀøK¤ã—t󙝆X¬Q`°1öÏ·M; ÓHKÔ”ÅÚRºÏL:àUƒ±˜À§"à×æùµ4€ÃÒFº7¬$xÆ~ÇF²rïýçrì¦>bsž^è;gX´ ¢Ñ7íSá‚„veí7°¿ó
+£eà¯8Qº—¿Éš¼Vå4qG„’‡9÷fœîÜ›ãFÁO›½^sÈ_3É*ªOrYpù"é<$Ï$ՍjìÊ¿W±È`ùG¨ÿJWß¿ŠÚ·º¯ tv<Qwbj‹½˜pÓÛAê×Hâ•”ÍDçÔŠ4:Ÿ5E8@I¦LRÀ½¤Í
+·–ºÊ UQaˆÍðÆ‚DUqíòï·Õl;Y^):CqFb°ò=™åÐa…ÔãJý2³àWQÜ·Ú{}œßçßðã7¿ô
+I ÀÚð“ÓÒ73Տo§êLDªMç|¶î`ŸÂdÍ7X½=:9ö4˜·ðVx,׈çÄ¥}*Àòƒ²Þ6—Ä{ü߬¢bES…°t ,l繶ͦ&óâÔvËûLQíS™ÕˆW¦ñIÚ‰YÓ¹Y8é·=Oö·5xµ¬sïy
+8l'Êì(‚Ž/6Ñß`ÿ’‡ßƒÎöÿó}-[íæÞäY?¹Íë×½M½Ô1\»$cô÷§·ùJÊ·Þà…w‰ÿžÐÓgÐÕ[ÔæœÍyÌ´íGŸÓÐì9P-è½MÀA0ǁ£¼E#þöÑ{rXuŠ {/ökæ«ŸI_¹P{ëcĹ.¾”{=(4œoÌówÚ¡ýbäŽ=¯A=óåM|3­8zd¬~%kЕ*Ìþ@±<“»/Y!á”ó‘aî¼ ¼" ðÁNUéÐÎü¼C“T†ZƒIîfï;ÿèœ=\Ô qž£Ì®m…–eødeц Ÿ¶ÜoO‰0CÕRW$óºñt7›/Q‹»l)O}øôìß»,«'A!¸ ûÿ¢.Ŷóµ~´6U¾8 ¤Ó.ÚªY^ ÙKØ›J 0=œ¡¥a2â%·»lè–^ÎÜË’ÜQÚ"U>À÷öPû…º°Å
+Š¦eŠw0Ïë`üºx^-.­ßW%_Qi™iÚ8 [|JÂÎý:Ÿ±†¦)½¡xd²#Áž
+o#!6×>2°Ï7Óÿ¨$ƒÚ¬|ÙøG“ðŸ*À-â\ê'/ÃǪP×67íüß’;OA‰M£‘ÿ¨üå”Ù{>²ºü–6±ûaëS;ò¥‹%‘Ù­>ñ¤DÇ+9¦mY;ÎÈÔmÿ×d`ÉÞçÊqå¥P‡z‡C}­Ò°;>ç ðùÄ 17Ëé÷Œ. &.{€íÌ•¨5°á
+ÝÒÀè?˜¢ç?W­UG4Kû¾ÅçÈ…Iõç™…6>ß,f­¼w)%bàòȬªâ™=¯èÚ¸ô…Ú=F[‘ëKø¬øª¸ñÕ‰ؤj€VÉî‚ÅwÆc¢½ù6Ôçwà¾äÞ‹m9׶½UÅר/"Ìù"˜IèWÈÿ¦€¥þëV*ë”ïS½Dv—þm3ÍQ¸|Þ·°
+%õ«+J36_KºÕŒmïÔÄ;<W£ÿ u_y}ÛR^»MÙààÔsg|]êøn¦ ëu…‚åøâýƨ‹#Côð{“e_às$?[]ƒ¾Id„èËú_Öij³\H¡°hÊÈ+“4°Î³0ÌbÌü-Ó}Ö÷áªÃ4ñ9‹¼3ƒëUÃÅ“RDò6àŸÞ× ¼8÷m 5/ëDcÑnLîà((2µuYÀ´m·dÞ&á™Oý²erŸbÖ/õâŠÜXüðÜÿÅméâ‡tRzRôb&ð9h„·òͲ†1ôÙB„ïá³3¿K©ÑN“äÀWl=¢=ï¶v¾‰»SÇÌmý{׆K Ì•_‰C9¥´×¯µZHžæÞâ<¦­ª
+S$¥ç{‘MfYO¡ ß³Íæ³_HäùÜ£ñ÷ëg[¼ÿÅòšãâÎɏÜïï?
+¶<OûØÙû1I›û‚&Cýí`ùPˆ<À™¯M•±0ªÛš¤R°]V©âo¯÷ŒØO>cFN
+¿º£+µ
+c¨Y×fênð8wW
+<—úz“ÁĜ봱²ÏA½ëìLÒ]ÿ>7Žòllºµ·òí÷I>öR½qãF«ö‚·ÅJ‘ªèËV°­Óˆ7‰¾ùr·§FåfvM%E6÷è0ðà-ÒΥݗ¿–l>`7´ÞÇgÊpC'ZcREOÞ£ÞÙàÅpE|š®ÝmÞÃÌT’ÛÊ©è
+~¯™ßN«Þ`1qšÀú§j0`¿õÚFÛŸx¤©–r‡¥†¡ü©™ÎÇbƒÏÙ‚•¤c-yÅ Ûub
+êÚ“÷
+óe™úî´“Óž4¾)ž[1ˆÖ±ðî…Úmï£à¤Ëúe–Ç·#DC£y9”@]÷pcÇ’. RL+eÓ~mݝ“½ÛÝ uÚ6ËÉŠX(Èbæû›»£øÝ"
+C8²tæîJq ¯O™y­^W(,Aúp@D^ ¿=÷ó‰²S‘ªÔ’Û‰­Oùmy.²hI»§ð~|$ì$8격ÛQê@tÕâ-×4¼µM†×ìʼ³#×Ëöè€Ëv9Jò$¶ÖŒ´å}>eögHÅÀÊè+yS½/Ñ™§W—읂¸ýÏþSÆ9†ƒ …@]´€Û"B¶îXw;ºÕFµ„û tran!õÃ}yÍWxco8”¥Ï÷¤!ð‹Î[ü]N jŒàI‘ßQÚ–c:m19_îåöÚ¾¶`TL2˜ä¹Y倫ÅTêðÿ£ÞEþ´‚ÞÉ0å2E<™–JZÿÊ}4î«Ï_â:78\­Ý÷7®îéæ
+%Bs™FfRVEX’®Lë´ïµõzð
+½µdËOÒ(Ö!℈ÞÞ(˜ãþÇÅ=öêÇÅãP‘aïÕd°ÒgF’ðÐ!JèŸÂIî{I8jt}nÂt 3ï ³`bn–I˜*òŒËÅý.5•¹Ý&µ´¬›wºúدOm€/õ¿‰¯¦v ”…Ê¿ ÃI5Üà[À\ÈÇzCÏãÄs+QÛ¼eÔÜÎ^¤7po¬?øÌ’}éü4©§•R«ù”dzÀJ‰Ä~•x ÖrånÌÿ}Ø„àlK›qÑ]b×”æ°äžïTÛñµ›½ \Ã@s€=–D°ÒÁHž×Y©16–õaè¸ñÖfÌ«®&ér»‡w–=5ÇFË-¡ t“tËÁÞÆPKV_õœ­5ñbljŽ´›lHÁH$AÚ°©“"÷ùøÃ,‰œfÆ×>nèý¯3¾M´Žo×UÔýåÙ½Bý ‘pd:JÜÎ}w¢+F,6„ö÷~&µ”Íï<4Kÿ’{âò>Ï`G¥ú#,ÏX-ѳdï6ÑÃg§UàzBBV¯³uÛГ=×8M„øFö¶î§…=3KÍ)Ì‹×Õ{
+NÇ¡\Îû&Œì<¼´`®qrõí€5¬‹•%§L­Ž‡¾ÈqêÁºž9Ø𑺼ôùÖEkA»éH‰~úLv˜µ¨%•`×—–Ù,á=Ÿ{b–ŽjŒ j^<¹ˆéȾ‡~^—KÙK×YŸÚ} ÊõÛz‹ô`8HÁ‡q÷§Z`K{9ÔGøøK0Ú“A•<Š ÍÂÞС¦ê™à¼:mœ`yÌ™åJóˆë=îU§]*2àäÑ!Q€'¥nó5Ó;Ó}F-‡µo”£¸=ӏ-þ¹ëÁ/oLÖØn‹á[çHeO†k€øp/ÝþyÝ‘¸>.`û¶ý¶§Lò¼º¥X2ÉîXß'ÓÐÉ$¯ð ˆn:pt~fÊŬúz}bßú²#ulÈiüì4Þ‰z/ƒõÝDÉ -"²åàù×pèÙ£+úwQÈÍÏÄ©qnüºwý?õJRJÆÃAéŒçy‡PNóܽ_²¥)}{Tj÷dPmä–!J«Bô÷†ÌOÿ+[¥`‰mkfÐÎÑB>"±«ýðà¾kŒÃ“ sEn½<õ­ˆÌ
+ºÍ¹×ÚuŠyŠN°ëºÕ¦Md2Î,/ïȶ¹­?{^mfJä®wŸ¸æú(±L#
+ö—·Åà:JÅwº¨Bø×›/5Æ©EÄŠÊ4[5i…b¾Î¡Æ1u(
+‘DZìiJ–{)“‚Û†H
+ÄDÒ7­bO¨¤d9GÀ3÷eÃd +J®ßeºŸx%ïý¾BA§£‚Éý½=ߛʴG©„±} £äS{žÿw<—ºO÷}~í\?îöèT±ÙhˆÀ‰<nîEŽ$è踝#8 t´K§nÿãsät¦ÍŠ3¹À1U‰­Kä*x…Xjè$´Lß›€é|‡ó\G˜QBC[Ᏼ\‡u¼2\oõ-Ôý°[Ë¢à J.¸0ïkÖço;âÿs¹ÁÛ̍e_ª³ "¹êŠ_äû?ÇŒ,ˆ åOš²ñÙê© ,ë=Aù9É»Zâ··žþ}x q‚ :o§Ï7Ù4ó% ²Å½§y:$o뛉*U•Çšm´ áÏÚ[dùÆ[~®Øú¤øq[úf±a)/7Ôa]h—yˆ,ñ¾(ÙgZoj×!·¡ÇR^ÖK«#«¯ÇÏ),ãËGyáþëNÍþº3°Ž€˜Û…ßIvc™©ïØ©¢}uÚXL2×Gy….–f~NùÛŵm½ü¹:/ꏆc,é׿¹‡}YŠ ×a¾šl!Üáy€½U½ÙR7î Âìmžq@(½V0ñ1½_=”m–W#še«l2pOw„D‚Êëoì¤1j–TbŸrÇ,BÞ†Ûpëœ×\K"^V/ØOr4ÚE7‰<2=™¿¦q yýªûX ö¯ö4‰˜Ó:¦º(i¹<ë€Òù÷¿dBzÖö(öÜ°Úý•‘<õÔýn’Æu’ѼÔpfS
+h­ÜÙ5·¿H¼+-ÉFkÄgºb£>ÇËÊ3Ôhzz\ÓÞŽrÑΤüª°qñE)ŸØ5Þí¬¹ñBÆÄîrXÂÐÎ6fTÄç×qPwò;¿xïy‘÷ w{K=¡­ÙnVô¿=„þ64N1Gk´ð¬ÈN±kŸ?Gô~\̸<¢±·Ó°à•%ö²Fkô\õ‚Èl¸õˆ÷¨Í)^/Lяõü™Måè¡-þ“2†…žî
+¼!ãÓÇÙ L x6#o_ý]Ú€I’†¸âz•kgVbØŠòþ¯Ã_YEÊn•à\¸×?!2ˆ¸'ùùAý=‰z
+`Ë/ï´Ø™9ÖÞq…Ƕ·f="»
+âÄ}05+¨'ÿEA7Â\èÔˆ‘-Fp7rºz«ù®š4„hJóbõARØó?§‚#%HR—±Ôà{hIÛ^À!‚ÚY©'¼³ú@†½Sƒ¬u¿-ùÈSË&§âV¢|¦®I¬¾3_“È×´Ë™½q57
+±I…]*o˜
+qg7Õ2?å>ßÖxóGÝ{Ñ4pG¶¼Ë»’G]³Ý'óBº¢»ÝŒÀ¤]TÁ¯md`rx7èo•ƒÄ›üœ#à´ä-;£[»|sØ­¸qDzâýºiW#m.£ùMçréx7ùrœE€BLj’òA(.袉/'DºêWíœï±`ñ»µíƒ;ðÝ—•%'¿Nêò?‘‹ù´õÊ3¢«3Z,ÜfZ=r_cµ¡Rô%¨e8ͳO¸õü&º&ê÷ÿg.œ‹ñcÉÞø{K…( í©Úõ\pÙbÿ¿-Þ¤‚Ýæ÷¡â½@ÌßlBn'x#ôºáÙð F¨o]Éî0Y6$(žƒ´À?Ùñ"彞÷XƒË¹C‡å¬!®©B‹«z°¶®½hûøKk÷®‘ ´»‰äs+ç³K•ž²Ü¤Ü´òaŽ4°ÀÔ¯˜T#;0Oð¤(©XèàZ'«{º¿rÁ¾[â\ì§YM©FXÒ®µ›iBwv¼mò3ìÂ
+ZÖiҐûògPZ³îQ›,â»ût–Ñ¥¾¤»úP¯§úÎŒÒÃ¥Ç觬W¢®¿]"Š^3~U.¾0,ªÒž6øº&ÊÝdýè½ùsS ÌCíuYï“/(Y¾5©/£o<ã1#;C*<½
+7s–]G^q6fs«“ Î|(Ùß
+òpÍ‘aDƒ3ÑbØ˘×ä‘#®R¶ò“Çà˜âõT>º·nHª]OÞ•FÍY¢XéÎ÷˜[.pŠÊÏÎÒ×>×2m:ðŸ"!Håã«–sß-Ñ6Jxž_«¤–IÈ~Ë倶¶ òéŒÖÔ[GoW sëkVWßgú·iTØÅía1qùü¢¶]þ›´^îÅ{o;{õK~lÍZUò:ûî±|½ÖáÃuØŽÂÖ °~(Êíað(öz›Ílã‡áÀX®MâNDìRzã­[þÝÇ8e,eb°„ñ/ØL×^…z¤øÜÁwHÌ4h1Æ0Á¿$°Íƒ2î–>¶³Yz⓾¢ÃŽ¾|&Ùii_•t¯mé¯]7t‡†aÛjFæ'WÎ7/ySŽ|oëÁ¾¿ •l¾úã¢+‹>dë=5.SwøÇ$Çþ2øéú·HLT·Ÿø z¦Á^ýØ4°œÄà¥½ÃZ¿ówo,ÂGÐYE'8§ÜsIãÔ«¢0¥å’½?ö?l¿¹·˜ŽÄZö˜Ó<T0XiãµÓ]ïdB2Ö4LÉ­2§ü…Bû‰Òdí§X´Ë;ï.»ä•(»ì¢>ŠÄÿ^nE+´àoN>&o×ÖW¿.Θ²!ÈwÔ¨&ˆYN˜zk3¬ïÂ;fÎ'>_£ÎUÏ$Ô@]e;üã¬\ŽÜƒžÔŽÿ8;%õty¸í`‘
+j}]ú™ýÍÌ‘Jû;~ù~ç.ëú„räQ]¹¡è0{ú’刼V1VmI
+†js^?0¯Ç¾
+­/¥Œ¬!®p‚¤­íÎB]ö«ëpÓ½½Yœ’Ó±Ñ?§;N3:›ì»uÌ ÇÊ>¦æBú`K°ÄÑÔ„±Î8uˆÀ÷ÛÈSã¨mÅΤ(9\¶LFšÛqöæ¨Ií'(/£Æ”"{5£­CtÉÜ<o¤¾ÏÔ
+ÚUÄfóƒÂûQ®‹¿ín¶ÝgŸºÕ¾o7_ßã‹ÈEA ë<‘6S÷`I:D–ŸÀ†ŠiyôŽäž‹; ƒÙÔæB¾ÙŸ¹~PõŠç¾@& Å)ù¡’_[¡.Ë7vÙ3Xå˜å:ØÒ”À~ÛÓtµ,ÏÑ‘3'í çOϘõñºÇV_ÒʲíñŽg"·-üùäì}å*ã2wìxzúåY&RúÓ\þÌjŠE.÷'çÈ\
+yóI¤dTç—£XuídqT4Î3¾r)O¥p ­­N_go¢ÉÚ²­ö”\´Ë®g{ÞªLýÎÏ”ÿÚ¼líÜ(Ùx"5ò ¸pîÝúéì?¬S´2ëþ™ˆ¢‡“‰6wNË{5.ŽÆ«+òÓÏ<îq4Íò Ä%ð@ì‹Ø}*GÕ8à¡žÊb¾ó¶9_ÏÖügÒÆIà“ÊÚmÑv˜‚Ttü†# oRú¡“hIò?Ò‚GÑS9µì£ÜJ­SÕ!‚åe•pSð©M_”‚éÃä·Ã/&ÒÎÏÆoWêBsȧ¿x¸©V´‰!ÞyZ㡝k_â7*{Õ ÌéPÈ£AOÙv´(—òÂS&›¶Î®œ•`ÈÐØ­vŒ.önH{ç¹lñú$dzAV?·iW7Ÿ÷=$–¶RO_%«)R–j'fqè.ÿmbvŸ¢üF™"níI\Αo+ØB/â/¿
+€7b‚¸^zZAÙYk:6|J¸œãÍ%9¦\¦^– n”ú‰âòè(n%mùplˆåRžZŸ^Ôž qäõ6Úh‚>¦k‘§ÎàVÑsãH¼æX§ñûã4ã²Ôk¹ñ§°%5êà¡%C­©¯õ
+ý™ì ©xVÑË_ÑvÚ:%ʧË[nö·"‡5ŠLV½‚e³òçï;Ónk#¸”*½®ÎYˆµ1;©’?þQuãmÖpAঔœVÀ½’4œã;NG“+J㝷Ä%¡˜Ó)Çðæ¡g²€1…ygænµxrÌO4xºý ñßI¦úþz9¿¢,Zªzõbѹq}^]qt]‡xG1—·6%j¢9Á¡»&SZPÍüI•kTñâÝñ"e»êËl vùOÜLDëزøºc5Vfô§Ý¡³ãk P…|Ñ0´~Õõ¹³p»~±¬kø}ÑáõÓož«WòrÓ2.úð¬lP¨I ô3éEµ·ùñ;Sb>Ñ/&z]óÅ”ø¿¶šd˜…;-Õù†úV” Iÿ' l†¾%£{þ†ëšó|-Œëú½§
+Môxé®lîC·u‰éßyªZõ<Ù䓽ֵ?Eê;ŒÊœÌÌhßL,Õ†±)‘i=:Úä¾y¥5k{Ýß›ÄD¦öãú¯y {Š¨àXàÙs—…ßá
+¢Bw~Ó¶3þ؏<QÒ(Ô»^gÈñJ ödGIÓ*F\¯t.öeDß!xÊ^]ÏʾSTÀþÌS7mÊÂ: ˜öQ·
+…µGÎ~wNÞkÞˆ¦GùúÚ)f;hOßRÔ{[øo•ç¢jÎŽ²"v Vœ8/1IÔUÃf;Ýíš©2Ìî~˜ìú;ÖþÝe¿Ûì 0*ÁB¯àI헝,òH½‘e¢tóìf}à'oÐ,²²CQO*:׊\̲œˆËRсuJ…–µrtøå¬2ìf²Ø ¤/XZ’^ÎUnšlúp·=šdÿ”/ܶÔxÇ»ØËr°$ÁèÑ.Ùxݝ£GT¯×1³õKuÏ›k£ Q=|¬Ýìÿ13܏
+~e-ô6˜-][‹WHq£^xûö!Hµð¯Ïß³ Þ€œU#?N¢Vˆí/sXæ§ÜyŸ¦ìbeñt ÚKw°ŽïÿF®4ÊÖËétaÛÄÌ*_Bôª“XÓƯ÷pÚx
+’¶¾pœ.Þ…
+Óî±|Kºœìc<L=Åæ¨}éý#~ÉvR4¨ºÞ}®:™›[‡Â)ævÄ\/ÌDf§ƒ’i>~¿X9ôg£5ÿ†Û}µ&5×”:­‰D1Kj Þ¶â×Ø(òWX\®ŽWÃQémEBÞH°¹…Ï3{¾®Ø©¼Æd“o:à¸6øyFø$©iZlÎd‹g¶e¤lº)UL@.âÚªÅ{À±ÜÚ|+
+À÷¨SñÄ—zkÎS êV³ ÎÖô~¨†Ñ%zêÎ@+1ð à ê指–Æ¢c>ë^¢[¶B2l¼}f³Ñþ‹" d,+â3s<ŽQøâìçÛCC§–ü§ý!hè;Q~!hº†Z…S,ˆÑÓãjˆ3Y;nK~°–Wp´4?ÞZtTY.Sxy•k·øDGËßr·µT¡ÿð@ägÍ<ÈTÍí´L”À¼ÁšGÝ·]C"Ú”³rªâÿÄuԏ9®Â{äv°)
+ˆÊô×@ÏW†1,Ó:,›£‘֏¼–:1¯øOŒ”`ÝÚeÚ½g
+ôqsð³w'¬\YÙ,|÷<óc¨êüÊVýiuëÊý¡µ
+}ö´àÅ­Û‚Í¥]4Ÿ!±Ü‹EÜ‹:h±æÈõ,í…Ét`
+Õ¹—”(‹69Êßk“—FÞ&ìUKŸ,ZmÇç¯]Î'ÐHðîÖA¢“p8NÌôþþ± ò7DÄQ@’²÷M’öåFÆ“ƒŸ“Õý›CÆ#.Þ 5äj¼ÑèØ÷g¼[«÷s3üoãjf `»¬Zyõ^¤ð@qا£æŶüR9*ixbÏ<Šqt³þuâQÅ#>ÓMíÊìÀÈ%¶cœ„¸çzʺs%`gËô>§µ’kâëÇxo¡AKè|GÒôSxÆ\^»åÈžá(FNI…¬ù'œý7R)™ûµÂ˜óÖ%#±üø0ˆÍ¢µa”„ÂÍ•~¹¶-ÅŠQÛ(=˼ÍÈÈ~à›‡eÑÊiR4r×ü÷ƒÓÞ¢Äc±MëZ¼ðìø-Ä„µÝvÿ…™Æ10¹mËUÉî_Í·õ!NÔLD-ï|ɾÑw¦¸óò¸
+´D±y»5â™Ç¯˜ÓÖ:–è¤K^ŒÕŸ5Eú69ñå Òçcƒ·ä*ùvÙÜ'W‡2ÓÿR#ËôHÑ›á;wa
+rEè¿ôÛÕæ樆տÙQ‘ìvì“cƒà?Ë»m‘£HwÓr(†}GàPÏ÷â·RÕ>³}Äz£ñ9µò•
+ߧœA„©úì ¿þjËÚ.ã| ÏT8’ 1/+i›6­¹þåZ¿j0ãRæب¹Øu©e]ΔYJ8…Z))Äôå`R{*ìñ>(élÙߧ pq_Ô—¿E熨œÇÅ‹¡¿{$ØM;<^¡•{À¶J Öåæ>¯æÒÊSâAõsþÖ¿;rŠ‡]*9™t¸ -÷oUÝÞ†Ï_]x}8{7VìèÁt°qÑÊ”ün—âõ;‰~sKÎÇ&"º9l¼J¦‹‚Dìþìpÿw„AüŠvãº#Ô.“o¶•Ù®ó:újiŒx,ðäÎd]-ÓK ª'‹æúDÊt2À½·J¹eù‡°tEE/èQ8Ÿ˜–¶/Ö‹qùJ,ÇIy.[Iâw ‘¹1Xå}W@q v»žç¹ÔH¶#/J
+fôŸéq1ýÖ[˜odW;~=i6ôÙ GÌ6"EÛ›B­DfLSkfj4ƒŸ:E.=–n ©¶¬¡§kš°Cl˜Ûl¼û~V¿Ä­hg„œry¾Ô_ã{Nˆ•*lûÇŽX¢ýü'~ãÑ\ Ùwù–w^Ù ö‡Ž¶ë›Ã/ñzñÊY3ÖË­Š“¬ã†pa©‘>¶d ëv{s£ZèF5§Rº"ÇÖgUmá,<‹Û#Íæ¦ÇBBŸuÞò_8sQ±Öø5Æ]¨tÞä`ÜÙÆÌ8†l õWxþC…U ÷¹•¢$‹
+aoŸø
+Å®÷ø°ëäìÕ}]畹”óå`ÑùËÔ9%ýéÓÁV|öSwç·r˃k÷ѱÃïZ$î^ˆ²?ESc•î-#›6CÏŸݬGµÆt-òI6`WøòñÊËð%Î!7²jpoæ£7ãính4§Ònf}O³Ò!Â7q6Úa,‰Ð”~^®·¬ÝõÀþø¥P/“zúW+žá¤19%ð+ó:@g­JMsÔf¨tíÐàCºl“ j1Z}a’{²² õ»kM›ÂÊë¿ûPûæúŸ· ºc©Å5‚Òc]´ ÀÅ3Ob†õä"¨‘[ç5Γ¸— # 9l
+~šzañ¯€QWp± ‰ß[p`96µØ}wþµ®ÐRñ yïJ©EfËøaQÛ‹¬ºðiÝä[.E¼áŒæ²Tœ3Âñ£˜ñ•ùG
+~D·žò×°àeE¸Õ«Csf¿<_.øŒÒˆÀ¹g'<èÜ*ö|¬šïÐœfÒá„'‹Ô—ç1ñÅ ¸'}s»ŒbY¡Cãè×JòÒ¯ÅÚz%·zÞìogµKÖ-÷§|cïG„8C"]©òœž;hC«• E:ëPÅàS×ømÒÆ×8«XÇb¾èH¿­gÓmüË~érì˜Wñ=ŸÎ/àG<ʦ#Í2wö¶ß)”¬èäõ™¤îtT×æãפx:â µ/¦ ökÛ
+ø>4©[Ê캑Á«…3=Jû‡–&Ÿ®»^ ÖYqí˜^õAÙ#Oç‡Ùn™Ÿ)œòMT¼œ
+\£}2ˆê÷»hy¶ÞÞö·Øð×~ Þ½”ïI[ÁÃ+™yµžîaoWZ«C?Ð ò;WüY­dMeà3èEÌêŽÑá÷~šîͤdCñ£®t%Ͷ\‚äVåãMG)
+1c¹ØÝðøDt\‘%¬ ‹%æÙù¹0ÏüK´ 8ðœ|+¤# û~ú™\=êH&'µ7µÅ]eÈn¶×ïIhïžÍi¿…føÛ–¿><Cdâ1¬PM”Û±~"HvPŽõïöZév@ä¦Ý¥oÇVw7æ¤Ã×« _àr§§®G°ZÌé‹×ÑTkؾØ}Ôƒ…nd›g>” ~ˤ°`•}ZpJ7ÐB9íy”‚ûÓòñi¼úh<ÚŽ¡Nt×"ðÓÖ¿%!Ow»Ø;‹î.qÓöb¯“:¡ºx,fþºÃ 1(:ÞW.j,‹ƒéÛç÷9mŽšq¤CXÇ/ç“A±*tÌ,¥Ñ?¿]>àû"_{/I¨¦J©ÖÁ'Bš7õÁê)q2×ÇP mƒ=U‰Ÿv¯µKgseÀ£;_‚4Ö°8ʧÎ÷P\`XÚŽw_…£8æ yY¼åG?kàµ8Ê­ …¼©2 ¼ ¹™µ‚­ß绹¢ª‡»-7:µp÷…è€xí³‡¬i‘<u±r…Š’ˆ_Ö¦K©Cmßœ¥‚XOsžKߪÄ݉ýh9?Üü/Zy¦/C»Í„/T"OK,M“YÐ^mÑQçZ§Q ‘M3Å2l¾]¶D›çâ|a4ø½B*ßÙ*ÛtiòàoŒh<÷EDÙ3ŦøßæY8W_MÖðš6û‚ܦ$ÄvýßÜÇ´Áu¥tãoŠˆ³o‡)܈¬¡X^¯+Ö/äoË£Œ ”p ÈÙ[v¸Ò>"ˆÜõÈЖ“{ÿìÀFöJ<>}ˆãåx†Éë>ë» Ä'àPþdÑøìà-¥DœdL¶åj"΂ݼ»F”2ÑȽ×Z@›N£/1_ˆ’»bi§ñ®I
+4jÑs’§Ž Û_vs¶Q@_T¬×ÏšúÖï½ ¬Ì›Z›¡½Ì“˜s”.vⲐ ~Üö»î†KTùç³níÁ& žoE4D}(åÎdÎáSJE›Î£Vû£©Šè™N"9sKÃð‡¨Zþ=YºUB Èþô­Oµê¼%²>ÍIãð˵Î[;Á§³I m`¶Öb+ ÔM¬þðáb–b_ÇÊïº d[©ÒùÉÅ:Ʊ
+µdÎYóÀcåXOcµç}eR9Ò<fު+ìó«ß˜“&§ksO¨éQX¥3èÎ3„â´—ÜÖ.±QF+4ð9±¹¸Í‹ß¢´G,œÛ áÙкúƒR¿ÎþE± ®@0Ó»ßV‚ü {h†ß¹qãs¡ÌäÀz _¼ÔÛK\hêe(±2i`hö1Øói‰óõÉ©`H†Ïé-ß_þ&gd°/ùþê×UºBïCRÿyLÎñp¾ŠºÊÌ,slb0knúsÖ¶öËî®ÛYgÏ/­÷Y8Wœ±,.B,v©¸§>âùjÿøÕÆ\•ÌÝ èDŸòYîNkpÃ~*ÖP‘E…ûp3¹À¤9i<=ÁÅØ ð_àZ3LV¼áÇãMá?!ºøÇLM(•g÷ü®ð¼s±^£îuW‹[?¯ÏýIl@ðb¹¸å3„Ü1eê Ñ•<C8(Ä,½tr5+Xî^–1vjíÚy~ã'ìP‹5«c3]Û—cGÌvÁ±°þýS‘þ!7çÑìKõªmç*‘Ñ}sýÖK ž6^ì±HûÂ!ÁM;â:ÚõÒ02¿ô4ùàäü–¹2ú‹3Ž›Œø‹UÜ"Rp͈Rôtå¤aqéÀ2x7®.g"€/ªÏ™æ kŒª—pU”[Gv.–«ÎɈ)Dò÷“Ïejð…es™21E÷WihTL¨kaÀƒ`ª‡õùÿµy:/l¬Ç®£ZÆ“׸­¤ùÎ?Ük:^P A”p‚Ÿ#Ž‹Eú¾55ÝâBŸiE½e\Ú}>^Üsà h¨šû µ¡h[¥E7FG»ù…är9ÀwŒ:çÂDѵr8öp
+›Qöñž^ûÓÚþ—OrÕqþorこûën¢RPS×7h2ÈÑGfî¿ä0|
+–j]yz” Þ2 Ú}#;U¸žóøئ—rAüÄæ)êrhª(/ºÜãëî {ù³‡!þõjKzÑ’1-p•²ðØóxô¹šx£Ÿbvy2Î#7 ¹¸³]¢)º¦ “çü$P ðär©¥ÿüÕ‡px ‹D(CН³X#w·ÀüÃœ•„“Ýî†79¥jÏŽsGE¬·œž.è^ر̶‰‰ ÿ…vWë” 9mWÒkÄÄÇÞmòyZ|4‡›8->Ä·5{@i'äßÈ·(¾z·Æ:6ãYöXÇš]lèâÇGÀu% å[öqº‡žæ®Ï
+¤³ØŒô®÷|1äô-xAž[ª?üÓæbDaö¡ßµÁ@‚ïd`êõ\ñ€¿7È‚2AjD”¸VMr“K[,?bÔ…?½ E´M½é$L»PŒpi•w(Ï=·3ˍ’[ŽÃz! O¸–áí£7(}A#|7"±ëõh–^K•œ æƒH»V-{wðF:Ýíg‰Åšj&Ñ‚±åu“rÁX/k>ç8ÁXß‹˜×ó&:™ˆ¼ƒ
+z¥§XC/XÓ¤gX©€êM;‹{ yìu"ï·¢ï'aQ…ìâúÚRBL`WÛ#’‹VßRB²8¤VlúÑqÓ¡qÞ‘dM*·¶àD§c/F6eر7 œÌÿ¥¾ÌÁ®o=}~qyúÚá«<¦ƒÎºlýÔ\ýX¿«L™û+ŒõSU˜¢’ü¤¿…Íé ªw¬š4R
+üéÝaxké<î[WQ½™Eû¡w6œv¬‚Úægk‘E>2¼/l`ØRÇdÙü<¶Õ;ƒ”iqöRvÏJ>ÿ%¯}@é/¯®ÐkwÐ î X¯)óʆH ¡Qà¯ÕçƒÀSÙ´åÑF%•}¬Ò8AžŒ_pHª—Å+e¤ÊÛˆ£¤}‹òâÖÑëðkO¡Ûæ
+OˆÊ–CfÊñh´ã¸À‰¤Ï9[‡ú*›þ×ÖÛ»¡à\L…™|*Ìò4GìÏ>$ôL ?¿.Ɖèµ<nW<o‰'ܐl4³ ï&{^˜é$0=–ªyVÄþà‚Ag“¶ÆΪ2ëµ"×0àH»T3BôÆ’å Š»ëT¿bDéJoÕW®ë\mÜÅ*»ÇHƒs ºÒ+s$uÁír Ú=)SFÉlh*ÄMìÁ¹lªl5uÁH·ÿœ?a3òËæâ`’ë‚WÿåèQZvÛñ|› ݐmÏrx¾sºoÏ­ #¿³®ó
+Êšˆw¦·Ç]_<7†¸-_­)JìÊÄûX̸ƒ`è0µ±ԍ¬©wdkF(Q:™lŠm~QÙ˜ÄÂ÷ ‡i8Ï2wyœä¡º}3=SŒy3±Ù6pöh WÄ]©áçð;c%¥å®cbÃ/Yì΄æ.¥œ~Å–GŠGöY°/T5©¸E¿õ}±Õ³áíSz›>GõÆaɻ궐dò…¬~Ϲ›ë©ýÓ¤
+„­zZÝÕÌìçkAô&ÒÏT‹Ø „€š«›n­ÿ“¼[
+|oZn¹’K~²Lj7ŸXó^t>ö•éñ¹/ÔhùWfjÊÿöÏO#ÿoè30zëu£Ì-^Rö\à/WÈè „lò»ÃnV A¹.|š+×\<ÜA~¦B¤÷ëø; È¶Âþaicê’tp”͸ðòX¯ûÖŠ«FÙ[v[qË´ËúvÚ›öÊ¨7þ©Ð=¿zv& ÚÖe+f0I\€‹W2ŽÅ]ë "äЭ®»¦þúŸ$Bpáº"9'?¶Ú£ñÓC ð`Í­KEñ¸ÓÍã&
+ãÑáTŽ§íÀÏêà7†ÃRï©CùSÊ÷ßü³ ~¹2&1¨nß{ÙŠVÉcãP¸%ãsùšÃ›.V”]9_ ð’ˆNR‹¿’å(„õÖ ƒâ<ç}†fœÓ«Ißã
+óô²ÖßÉI½ôN&‡\îm(påWÎ#·ý#Y9W‚Ã_F5‚yLÈýQõFî蹁âõ鞉޹ë¥W–ÿQ¯Zsâ¿ ÜSÛ­Š?Oy!fŸ²¾Ì¡<Ô“Š.¾X$Ý-‰LF}xöÜ»|Ú†gÔéýS—ðÚõ'‡ñ©`ßÅc¯â’±'CßG%h,€éå4_ü!ÞÕîi`tq•`”¤ÞÌuâûW¬~UwŸXúLÖdÌGØÚÚi.úëz{ç”ñÇE® ÅE%Ò Ó7+O¬‚ê/×ÍåÛ£ÕFÔóJo¯Ä«Êq’u‘wþ—‰#5“=kËé­Ìç’î¿y{~ÛP7yZäKÊ”IFi`Í*~ÆÖõ€eÕÏwõw‹Ù~Ë[·¸í¦>¾è²žîŽ>ªºé»û¦4©N ¨òu× I<
+ÖHúþU¯± ÐO_ŒpxdðË?`WÌ£Ô/ÏáyñœïDñËÉ™yt$ôPÙ=QÌÛ*ó:—ú‡á6$ÿ>P1"ˆ:ñ*p4˜ádÙ_šÀÛÅ4Ví«†w¤[Pió¤?H´ …㑝„‡zçŠsûÏÄc=? ]üyã/ 4ŸîUÕà,°ø—[½±b£G=ÆÐ-F±du ä·Á±ÅÅP>žÐµöàÞë!F%m˜V.=Á{ñ…2iïìQÿ€C{8ÆÆ¢cPõG†»·ç÷`Œ­¶Nˆ?!NÀ[µî_¯ã‡OožïÇ)0>lHµÀdw¦kÄ~kÞh¶zÎ[ñ4÷!íµhÃ·ß€Ÿ³âwÜ+[AÚãb›=øÓ
+´vWk''áçgz©—ïTïo¯_ÍI»ÌË.×ý=¤´Ÿ§4¿
+è¸$²ç’ü‹2Ø^xð:ÎA 7•ˆ‰ F€¦×†„ 6w ãæó=©B*‡¦K§ˆJîÜ\ÁUÔ±"„É:†°êùa…žáï•~ÀJäZVŽ–Þ]Ezx¦;º•Ó¤‰§«ÜBê–{¥b&Rk{äý4¼¼µy®) ³¶½x•Xœ]'÷žq{ö~ÒßËk1JVf¯úž5]ÎjGQ<›zÏß'> üx‚x°K>nغŽÒüäe²h÷I±þq#¥Ì–Óôþýbeëã ùi;ü”{*)oJÒEß.§“›í7’õ–¾ ûd¥¦=Rƒó'hqLÛÛÎù„Èe¿º˜£$´ô„GS¯È©éLÖMéÓ•r«ô¯¢¬ Áp½g‚iüÀô0‡¦£Ü5 >Âëz㱈,ߟƒw´­eUŒÌ犬b[ºgƒ<&yñ&8×–iaUS調ÿ~^ºç™E;ã´llËE¿ŽeÚo©ÿæ‰ÏI ÍòÞÙIL\\VçñgáäÌ%üêîÆÜ­4?¡%öTÙ\(¸°±ÞL¡(ÏS‘µV@ې XqÝ9†ù0rQG>û¼Dåšì–¦Mº³Ï8B;ðî<EfðÝBBÆ­–,‹3ҍзTÕ®>1C¿ÝÄPƒck¦P
+ Ù¸ š‹g¶.^/ûÚh5 ÁKñ¡i:¼¿â‹n#›8Éyw5Î[EæŸyz°8D§œìØ¿ÀmàXöÿ(Ynžfìœæ'¡(÷1wÈ¥ ˜óŒb$ZHQŽFß_ÉJꬒzÇ–㌞øtC ’z¤¯ž-κuº+þ0ý 2Åû¶s!x-6(ôâôñ;˜™ÓPöÁ|OÉÝÏê«Ãêféåu%,ÒŠÀ:Ô”'!6Gñ/E78+[Œ6Þ:·^16üæÓÉäàlS­@/jEÁ¹6.n\\1é–ƒ»ÚJ—Tþÿ9¬]Û\ª7T2µÎ‰Y¨¹d8Û“±Ò¸z?0G#Et$2 Ƚàaýñæ:¨pûp6Q*‡çóÑ ñØ<
+ÍÛÏ£.aüCÊ{N£p¦Rd§\g¸ÊQ¼ [R­3yü6þêîº$°àN3£¤ÁtÂÚÆŽk}JDñ¢¸¨•Q¼¨×*ßR{Ke5Á¢
+Hùç ±`•¯ïádïyëÀÈ´òÓlOpoymdð+\v Cjn<%Œ®$öR@l
+|HP;Iäi§<à={¸Îò‚~3´¾ß§ÏúSšuÁ¿Û®N-rkëáðP]…Gî1×°äÌè:n©Î˶¼Éô-fì¬~šÛ`¤‰ó¨Æ‚*X
+Lág±oª0gÅeüuFˆ­p6´ˆƒTl۝GDö_£yhÞ›•=³
+^[aÇçÔˆ6’<õ
+>™>Ï*ŏþÜ'~½ë%¡_“fJ
+vG¨§J2ÚI kËßtbçÓb½HɦÒÂ6Ý.so®yþ7øο^IÖ”(÷å7º®ðñêÛ¥ÊæÆö$·Ö‹ÇsãœCÔ™m±;û’¨¡U
+¯“U´H‰•}F§Èz°ü³çœ^nI­š.pþDÏE\ÓçhüØ®cÐãÍH{ÌÐúÚ/ß7+ì{¸×)Ѹ¥³ È£’—hgÅE "d`Y³°Þ¹ØXîBÞ+ØL6¶›upÃîI¡9€èTl?ιÃéfÚú?‘Qîû‡;uaíbÚf QÓ¢Rã½s!®m ×U‚‰ƒ ‹
+ëê‡*íg0=žVðà”¸Zq˜¯a Ó0V &$½ù'7:;PéWÃìr+­òÇôè±¾@?Þ‚;ƒìý.yà(õ”]X–cƏìUÄùO ©×Åž›ç+âó»-<r¶²|¢Ë>F{†¿z}Ó©uš!ƒ­ZK—€­—rØš;Åç{HhC Éë3-zW`ŸÏðÓ*ø¶ík¸h96z쩸1X/§m¹Âüäð|ò•oª×ú ÑNêhÕT†–³´JƒcØe¥çòÑa
+gøÞUŒ½nÒ¬z ÷Œ‚ ¾êû˜_ÍŸÈÆ}ª\D8ÖŸý‰‡kïÉ{îkárŽœqÜQ"ƒ¾Çu9ØÙ­ezï 'AÌÕ6§Ý¬aÝ-6RÈ7`·+‘ñø.ITvIÄeJˆ dÔšè`êÌÿˆ
+ñ<ìwH3RpIf ]^²A…ô¸¥QcBmtáö wšœ°Tÿäqg°ÒeG#Ìž³J‘ÜA%z ñžŒ2O (+ž£imOåæ—h)´ØƒúÁwAcÜ¥ïÚC­›V­–­ò°qÉö3íw²j+ïMC–Ÿq¶ïjA©Þó­¶71W€ 2fåžr¤Žz(92j·²ôþÕl¶€¿¸?Ï|nZø4¾ƒø€’t$#·ï'þk߇þu9^WxÅkׯr(¨ì¬kòï³ 3ŒWm©y
+ýÃW¿…DÝ÷²+ÿ.¿ýoÑ¿¸¹§»"¶×g‡1
+Õêm1í—#~gÙå:aŸ7yÞÜ}?®Í¼•Ž­ZÏ]/ç]v´ÙÍ[:qIæ¶Ä=7êHŽMCÉ]o«gPìžÔԍ”
+\öTkÿˆ2i¤7æYøà4+]úOËVXƒ,"!.ìѱ!?Œ)Þs)p~S9ËY¥evX†~ëç¤Z(¹Þc£—ºÈ?´xuë€AÙŽæàøüòõ< C5z/WÅ4¶6m,m£ƒá@ìéíÞå•ùSvuùpEråôŽÙ”¸šç¤ò:Ü]†Ú„DNæW©WqˍÿèŠ)u;ô4ñKˆ5 ®ù]¸™ìÅþqôØßXäš6}ÚMA¨û±J¼¸T=ÊŽ RFö{v,@WrµVÎo‡Z´GRZÞYÛ¿9ÚË_‚¥º«?g…O˜oÚÊhœYB0°»¤F¨_‹úI2µÎ
+é-鱃
+²3pSè€voþ4/X%¸S§|xu£€ÛÎL¬€ç||ù¤Ôÿþ?xFŽÈÒfã4
+W²ùï™Á¹õ·Õ*¹r@¸Ô·¾yc>m¯åFÇqN(ø¬@ݯ>³¦Õ¡Š°ØÝ&èeÄ6à“=ز¥WÿáK?vfu¾íd¹Öü#ÜÒúľññr·û¤c¼×=‡ÐM‚éù²n€c¬Åº`ÚŸaÎŒÛ-šó²t2©dAiþÁS*OçoEXƤ¢èyCä¹Û[·#=,†‚Xƍ¯9·ønu*·ëlw¼Ë¦£kM—Ü œAEçlj혿Ӫ`–ËçÑk(/Bi!öñäv¢¹c–r;°¦68ÚÕ<€üË|ùx‚pÜŽK5³Ž±
+LlåƒiÕ|UPc­1µ—u=X—äYþ 9^-MS;^Ai‡¯äýïï½¼ÒO/µþ©TĈˆWêòȵ¬xœÃÙkžQA/GŽŒU—jÏ—;Û=mã_X#ù«P_6©½*c"‰‡ðÇSvÍöžÎ™ æµåõdÅí`ø-.®¶?ú‘¢ZWwÇÆöd·Ä‹Æ˜K;„!yá=âç ü{•¬€ááO^ µi<êðݍCEýº2ÍÙÑE›&h^PŽOÎü¦N`JЏ:bm±—È×+GJÁêOÒ½]Ü‹œµŒ­F¨_ìÆ~ƒêŒSV  9ŽÙ1Ie=Í[þŒ†±ëÈQê #ÔyJš]Þ
+)ñóHú>V+ ú×ð
+ÆÐÜ<³H‰ßȁ¶ƒÔVƒ^ Çré†u3,¯©úEñv6æ\ÁðhÊl)Á9œŽ7:³­_q%#­ ><¹:]/KvKu.q%{éÑÚîêOcuvÂ6ümÁÆvYóæÿÿ™šï2b–õY÷
+®¬2­m_±ÃM¶oÑÄC€ýKJ
+îø÷¨×þôþe ]”†åßZZšgmL¯ˆEh¼­ T…ðOž_¸\¤ˆ€Û1¬Þ~J¨úK·Ô±Rߧ {Ýq„ª–DÏDPK xïã}•'ß½夝Yf*çѯ¶_ìŸ:õíÔ‚½Pìµõzd 4}Ifœ1Wѣ䊉‡¤|ÙîzþÖ0v?8Ê’òV/ŒVnƒ¶Î+¨YBÓ‚ÒuT»[vï¾ÅÉÝ•¼«WÕH¸Gt£ÿ­7Õ¹‰wü(•‡…]÷€ª+&„ÿhƒüPÆr9CMru¨™»Ygâ£ô`Õ‹ö¸ñ$=Y%ºìSŠ€À“ų»è+ZšÓ°‚”<:À³Óp]šÆUI‘ÚRÛÍÏúpLa£êsS›E ~ËܳÞ:Q§C‹?‰ák˜ÓÕç~<ŸIÜ…‚~õêàÀÎŤvÁÝ»‚çlÙ1÷P#ª3ZÖ?
+³G„ bÅ6òuâõš•œ„{ÙiIu…*Ë~Ì®’­D#TjYyžn%q¶üz‰"ňû,fìWä7†y^.5D­‚ƒ§¥þ䮤z(´GjTz;‡ ]#úÛU£wxhº}äýSŸñ>æÊ)$:rÑ/]p؝‹¾óAÉöµDʲ …Ýßýâþí×Õ[pQA:”î IaÔè†1ºa"J‹ÒR#D`ôF7 lÒ%=jt¼¿â½ãswnÏóœï9ǤÏ]éÊäu³†$Rº®µZ·÷K
+ñ";ZIK<O<óŽß*̤îÅË)Çã÷ìµ2„%úh¯Û·4T¤¿Çãù5ÛÈ‚B _²Ù?»§§2D¶
+3[œ2z°
+õà˜a­ânčÓû±W}`Ò ®ìâÇ
+£kº}a€02±·@ƒ#ÍU~h.j¶¥"èhXÏcaöLþÑ~&•¬
+›á:&æÇ
+†øÆË1‚•G`»._ö ±ø{‘òûýÛËž×ê<^ J;2’AN3¤ ¬rR=ç+…§c:þhWJ}®Cvf×È D})YX]Ã&x²/x× ‰+ +¾k¨–5Ŷ†à¥`{ð›i¯|ÕÐ*ÀwjÖŠ±!œý`:s³ ¢¯›yæ¢<æ_”o¨*5(,‘e–—£[ <9šê>GYµJ©¸¡¶ÈQс<Qö\+aÔÊ ¸]úóÞòÉòçfÆÀƒÛ‘Çm[Jg‹¡{Ý᤽Ϟ͡jñ ¾¿4Ï;3žÙt’6UÁÕdåÃÅÅòçz¬Nx‡p ›ÑK@ª<³'Û÷‹9Qæ̐TÔ7÷Óu©ºuò1NN°|˜§ÔêÌ!¼°âœL…Ø î?ѪaÜ{±QùqL _ £>°ì{Ñ—£l  b^ôË¡‚¸¸°H'\ÿÔzÍ+‘íï«#65Œ©aɃ¤âºõ´WW²\}©¦‡cÕQ!êzï}ÊNø¦JÉ2h8;Kdœf2žqÞ•ÏÆœïÌÚœä £Ÿ‡úçíï÷ºš®u=ÈÛ²D׬åBì+©˜i9@H®±"Ñ®ÀÈéVÚ+l ã&=wVéy¼øT}©DvšM0é/øi¼*+›Ì’d\ð_ÙI ÆgÉÁ±jÁ…ðSºzyRÂ䜤BçY6Š°ÛIÍ";Véðäor 4ž`àÙjìê,|zªrãÜëñu?çÀnÝ2ˆ£¼’3û¼v¯·gôâ'X#xñŽÙb˜ðÍÞjéxº×]ãî Œ[žŒZþ0º+<ºÛ]è\‹1”…6,.u+ŸÖDÙ‡Áîg¼î=æUKDg¯E¿à“³HBÕfÎèéj¶éšÞ–F‰¬1œ’¾Æô[)W|F‹H¸BróHýYþβzoÝaÄ=Š›ùïú>Yö:— Xm™Ç
+˜5ÑYG ý÷²_ê-ÔùíÙ·ÅSÈ’m©!sÌSjXíóä•Pͽϐ/€Öÿv­¶¦Râ„N˜NJá”^ðóòåÆBÏq™õÙÅIvŠeß̼Š/‘$noÿxøî¼PYéü‡Ú¹ÝÃ.ÙÚÚ;«)ôÆ—ᵇ]jÆo¦+­W¢Ÿ13™_<ÅÆÅJÙ@<÷Y1£=µî{Ç \‡×kT“'xË&¨ß•<Ìßý°|¹˜„óå50÷:¯&j!Å/¡™ƒ~Ð@J÷!1Mï
+•ú-gbÁ= º¡9ßïQËûéÛ æ3×Ö]åñ°!¾ý·)óå~fl|nØ°61ä²{-¦Ñ~`úÓó
+ñZ«živðsˆeÈø—<ÒñŽ¿ÔÈHI¶/—MÏ|M”±Kä}T@ª\œ®f¦–ýÎÌÁÁ³¬4PÔÿŶ߿¤Ëò”€þ·ãÝ;ëH“ž Z‚6»k÷X>ïøEÎƱq†”fÎûà…Pãï¥.Õ-šî¦y”…Öás‚~üUöYÑCŒDA„;™ÃN’Â[7.û›8<BÈÏáM´‡íÏeÚ“‡¸ž”C£µW„Ç*êùÀB•ùN-cÆ-)Ùvº•‘P™Oç3¡ÍT¬B!”Èá{Ys0AÏô•>!k9Úšê ¬äRŠ§//ŽǏ¥ðß}9’ùÌn9U&©™³°#œîá)“Û´ÙZŒÔŸQ©ö^-G™'î•ë"í]6Û‘Ç]†Õ)¯)í„‚Y.ŠÖž’‰=–l$npÛìïÛ­éijóî>ž¢êjy¹Âqæ"èX]UŸUéÿÄÿÁiìW+ie*’¡ú=ù/xDw øiýq
+Çïút¬Ô/腏š/¢ñËöc‚Ŭ“{j—‡úÙïHŒH„ÅýØX®YÄNÓäGX“ü¹6<£¤âäeô=fµbÿ)3Á®Oåm¶dÐ5!\š²cœf’5k¾{úŽ»“@±Áh_—Ü
+ ñ†)·¾Á
+õ»4¬“óy6C'
+¬ŸÉµêÙjÌ^£=òO_wؽVhXy%–Oz.ëË°º<NéŽ|æ%=«€4xuvšÙX
+U%öúŽ 'Æß®Ÿ›¥n~] ©\)ÆËÌ7{쁏>ãÝzcågzz‡‚ìÆð;SnJ#¼­5wŒIäÌ
+–îÁ|Wl$þ+´‡ý‚÷ûïËÛ¼^ÃL=Ãþ¸ñàÒ\˾ê
+Jír€g!œŸf¢dkâ¬d³z&ì-õ dx¹sA0wèìrpu;gu¹·réÈÎÌ@ËðaªÒ7EG¢& {#“ -([â؝i/¢¬ðûÆLsbERƒ•ó¿÷æ¶Íúç3gùÒ5®ÖŠV0c©´â,œW‚Hœðàà™Iíà™ÂA• ØMÜtJ~0x«¾æ6ÑFŠX6ï᦯ŠÜ‘–@”ù}i˜O7aÛ“‰-Á§øª\ ñCÏö™ Æ¥<ÆeSˆü¤ˆcÔpp­§ìñȄͬ¤¦MNûØ¢"ô7½’ è!QÍÙ€Ú¥àˆ|CÍ+ùpP"ëšÁÇVzCG'[œ¨7<ú²ÕÍýwˆVa úšœa'ˆ´«üègèw]êçý…ÔäÁ£Ž`g6¿7e?Y珶GÊŠ°0ý;LÄ%OVò*iÝ;™…›ÌL› +\zÊy8Á®ÿ:¼ØŸ#®Ãèœì
+»0e"jFìnò$Û»D#;ÉNofýüÐĉ,®ÔW`½•íàý”ºòn¯¼E`ãt§
+?§ˆàLJäî#ŽLÚ<ü#<ƒì”-™Ø(9÷¤ßoékñbÄÂ:¨é
+HŒÙqå-j8pÒW¤Aõ¦éJþ)ð/’,r×Ëñ!QMÞCÞxßáQÑÑÑ&ºÜyò¬½‰N¯µ¼ÿjű’?@×dfÒ"˜G¡ÊûZlk¨jÔ>hN¦—1žµôã7j½Ýgn)øT¥Ä .§bïA#‰>ÚhrqMèsr½åö´Ø&Z‰‹¥H@”óK®£!Páv^GÒ¤ªû¯ îj¬ˆ*3â†Ò,˜•È‘bA¨©Êˆίœyœ
+{}£¾Ø+AQݦßSs
+Îs”s6֐ø/W0LXíw²Ü¼Úƒ€‹ÿû‡äAx2bD´ÉMýa“©\mfØøÍɧ—ï7Ñ·¶?"Ý`õ`C_¾·¯Ã°l|éÅb CÄít–EYsì~OÕøhß{XrÕØ©rΣ`çËûDÿ6 dw´3ìRó IIòcU•†ì}¹¢
+˜#¤¥Ùý[éY*òg8ÏÓ)©µDàƒÈUî_™z:4mº2lú·rÀ‡[K¿R¼4«E™²À…jåÕNŠ
+~âPœñoeþ£©Þ¤BGݲÍñWµUb¢OÜ*¿ÿ,Å%72aë³sñ§L÷ÇéûlvEct`À܉–²éžk«Õ4<WGîY2H'.´Ò²ækQ?
+_tÖÚ’{6Á3á²zû²ÒȻ ñµÙÚò€þ?k^粤‘üdñšl§xQ°á»ºj¦Ò
+†ÜX±÷K3¿Ê¼ÓIÍð¡dåFsœÑ9_—ÚsÄíPµœ¼v«úo[gæ¼S¹´[h«šä…!;öÙ#âX$PÐ÷ªeŸt:o¾ngªè˜žÐô‹¡ÉCÏ›¸é¥CÇ'V·iÃaŠ˜Ðé,€Õuû5Ç@éWebé'4Q˜a:šdõ
+£ [Pàb–¦†üŒ9Øò]õí%¨÷ÙUnŒø6C–(ú™Òk²¦×·ë:…g."²~£•Â «ËÞÎê+H¯eÑ°Éi×ð»É0©M̐Qô‹8ö*ÓÉ ¸U'iåxÐbKáS½V˜¯¦a–sÜ£´}w~¤A³N:çl´7Å¡3ÎèY
+ó‰ˆ8 Ì}%s³ê:³ÚÂ$:d4Äéé´¢‚s±OŒ`'ðñˆ¿Ö¸uÇ>KÈÉ 2lº
+ˆ$6ÐYTºÕ埆&yæ½Yžñ~s›8ÝÖ)U°µFBJe(*¿÷Ò²~I Ï
+H®ˆþþýì&aÿŸç&)¡AœÏ÷ûí,¹b÷N;eë3¡‘>¦ø"#@E×–·àíFP'Ú(çÔ؁f=dÖœ[ÎGšyíÙ \”äÓyµ·ˆÐ3b*\Н3åf¬•A9וxéË¡c5óݯ„·ƒÊ›¶éÒö‹—‰
+KŸÕyŠ­r‹VZ¢S„X¨N[J ½*ͪ¢£œú˜¨=ôªƒ+¬% `?¼9ì_©ýdº˜3ƒ`¦8ØíUè"!Šmùï„¥ÈøÑ_¥/è©^dó/RðùTIO)—±â™î¶çŒõÁ§!0¥£ÕJ¦È^±W;ÛÀd†ôŒŠ'±ŠÁEOÚaJ™áÚéOøäæ3ÄõùÂõ%þúêúò~X ¡¯±Ë«B§R Q­¾pu[eð~h ý/(A<ƒ­K‡¾Õ3T' ›wŒ§3@¬‡þöÊ^ÜAÛT¡iF¢gÀh¾ùxmÈ[^I‰^Ÿ“÷V*ô;©4ójMgï¼ð Kô¼t8R”+ôuqvFŸ¿Ñ’îDWŠàÃ.»"&±¾IWð%Ëi~‡1îÑSçʤ… ¾&¦°Ö”F÷Hšgå…vÜ)ÌÔózÄߐ´« •*7•h3ÊØÜ­
+îJ,b›/"ü‹†Œ’,΄æ8fíXyç\ô2$ïܬx°ØG ñs'ƒ»—zgÁ· RpóÂÒ=߯øg›ÇÖNh±Ûøû!ZŒSƒùŠª“•¦ñcºË¸£JËÀ+çC™éæˆíSÌúqÖN`s²_j¹Òn)õ ©½˜…w´À.f›z2~Ι‡˜1KèȲp+¤d¼9ËÅMéáöUt®~e*¯"úpʁVe‘2ƒþòÍ ?v*Pwû _ Hy˜WÒdâú๸„˜ôՁÌlydx&^±·Ê­®΀~©uŽ)é“úk’—lb›Ó?Ë ¢,&шؓfåIyjˆ÷5+½Ùtgèr#Ç4~¡~¯Yoòš5a{Ò<ûO1C¡¯ôLNüŠdw6|áWÙU/á¤U7õUV®8y½õµlÁ$Ò|âÀë±cʼnÆO†‹G±€[Çs/Ê>…Ñ_\þ6/- ÛÔp׿ìL¬¸RØ=vž8` ;¹„”—Ò+©Ï.à×Ã@A ¼»Û2¾¡ñ[ tJ;<ÆÿÌv7M L!È_ê*ñ¤ÓôrßøÔe~’
+ýR'ª.°‚¼Ý¦pJúg‰°éZ˜²WðѺ
+°íǾòN§Õ²
+KŸc#fdÕ)Þ(F“?szo|}†˜8T=*ƒ»=¶O5©Wo.|¥êÑ=´U¢
+ó¤ÁìH ¯Ê0¢•ßãç浪ìš\…žÆª«Ø‘m ZåTí¾½Õ¡vRWg±²C÷¾Ö9Ú½§}—¿Î´*~Kñ¡E›ª)åÉO©–ß=ñ©qL”™[\6P?m—Ê)x»{é° ÷uûŸþœ¹P‹ÊUV@ÜqÅEUÞüùQ.ú6¯’íØõ ÂùòKÜõ2Ä}$•®ñ‚#€êJOà*œÌaäP¿„ܼŒXrÐ%ºuãƍ7nܸqãƍ7nܸqãƍ7nܸqãƍ7nܸqãƍ7nܸqãƍÿ·ÿêmf×@
\ No newline at end of file
/branches/tracing/boot/arch/ia64/loader/main.c
44,7 → 44,15
return;
}
 
#define DEFAULT_MEMORY_BASE 0x4000000
#define DEFAULT_MEMORY_SIZE 0x4000000
#define DEFAULT_LEGACY_IO_BASE 0x00000FFFFC000000
#define DEFAULT_LEGACY_IO_SIZE 0x4000000
 
#define DEFAULT_FREQ_SCALE 0x0000000100000001 // 1/1
#define DEFAULT_SYS_FREQ 100000000 //100MHz
 
 
#ifdef REVISION
char *revision = ", revision " REVISION;
#else
78,7 → 86,6
 
 
 
version_print();
 
93,7 → 100,30
printf(" %P: %s image (size %d bytes)\n", components[i].start,
components[i].name, components[i].size);
 
if(!bootinfo->hello_configured)
{
/*
* Load configuration defaults for simulators
*/
bootinfo->memmap_items=0;
bootinfo->memmap[bootinfo->memmap_items].base=DEFAULT_MEMORY_BASE;
bootinfo->memmap[bootinfo->memmap_items].size=DEFAULT_MEMORY_SIZE;
bootinfo->memmap[bootinfo->memmap_items].type=EFI_MEMMAP_FREE_MEM;
bootinfo->memmap_items++;
 
bootinfo->memmap[bootinfo->memmap_items].base=DEFAULT_LEGACY_IO_BASE;
bootinfo->memmap[bootinfo->memmap_items].size=DEFAULT_LEGACY_IO_SIZE;
bootinfo->memmap[bootinfo->memmap_items].type=EFI_MEMMAP_IO_PORTS;
bootinfo->memmap_items++;
bootinfo->freq_scale = DEFAULT_FREQ_SCALE;
bootinfo->sys_freq = DEFAULT_SYS_FREQ;
}
 
 
 
bootinfo->taskmap.count = 0;
for (i = 0; i < COMPONENTS; i++) {
 
/branches/tracing/boot/arch/ia64/loader/gefi/HelenOS/hello.c
237,6 → 237,7
bootinfo->wakeup_intno=wakeup_intno;
bootinfo->sys_freq=sys_freq;
bootinfo->freq_scale=freq_scale;
bootinfo->hello_configured=1;
 
 
bootinfo->memmap_items=0;
/branches/tracing/boot/arch/ia64/loader/gefi/HelenOS/division.c
0,0 → 1,0
link ../../../../../../uspace/lib/softint/generic/division.c
/branches/tracing/boot/arch/ia64/loader/gefi/HelenOS/division.h
0,0 → 1,0
link ../../../../../../uspace/lib/softint/include/division.h
/branches/tracing/boot/arch/ia64/loader/gefi/HelenOS/mkimage.c
0,0 → 1,17
#include<stdio.h>
#include<stdlib.h>
 
int main(int argc,char** argv)
{
FILE *fi,*fo;
int count=0;
int ch;
fi=fopen("image.bin","rb");
fo=fopen("image.c","wb");
fprintf(fo,"char HOSimage[]={\n");
if((ch=getc(fi))!=EOF) {fprintf(fo,"0x%02X",ch);count++;}
while((ch=getc(fi))!=EOF) {fprintf(fo,",0x%02X",ch);count++;}
fprintf(fo,"};\nint HOSimagesize=%d;\n",count);
return EXIT_SUCCESS;
}
 
/branches/tracing/boot/arch/ia64/loader/gefi/HelenOS/Makefile
28,7 → 28,8
CRTOBJS = ../gnuefi/crt0-efi-$(ARCH).o
LDSCRIPT = ../gnuefi/elf_$(ARCH)_efi.lds
LDFLAGS += -T $(LDSCRIPT) -shared -Bsymbolic -L../lib -L../gnuefi $(CRTOBJS)
LOADLIBES = -lefi -lgnuefi $(shell $(CC) -print-libgcc-file-name)
#LOADLIBES = -lefi -lgnuefi $(shell $(CC) -print-libgcc-file-name)
LOADLIBES = -lefi -lgnuefi
FORMAT = efi-app-$(ARCH)
 
 
46,15 → 47,18
$(OBJDUMP) -d hello.efi > hello.disass
 
#When selected first lines or second lines, select if image is linked into hello or not - usefull for network boot
#hello.so: hello.o image.o
#hello.so: hello.o image.o division.o
hello.so: hello.o image.bin
# $(LD) $(LDFLAGS) -Map hello.map hello.o image.o -o hello.so $(LOADLIBES) #link image inside hello
$(LD) $(LDFLAGS) -Map hello.map hello.o -o hello.so $(LOADLIBES) #dont link image inside hello
# $(LD) $(LDFLAGS) -Map hello.map hello.o division.o image.o -o hello.so $(LOADLIBES) #link image inside hello
$(LD) $(LDFLAGS) -Map hello.map hello.o division.o -o hello.so $(LOADLIBES) #dont link image inside hello
 
hello.o: hello.c
$(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c hello.c -o hello.o
 
division.o: division.c
$(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c division.c -o division.o
 
 
image.bin: ../../image.boot
$(OBJCOPY) -O binary ../../image.boot image.bin
 
/branches/tracing/boot/arch/ppc64/Makefile.inc
26,6 → 26,8
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
DEFS += -DOPEN_BOOT
 
build: $(BASE)/image.boot
 
$(BASE)/image.boot: depend arch/$(ARCH)/loader/image.boot
35,7 → 37,7
-rm arch/$(ARCH)/loader/image.boot
 
arch/$(ARCH)/loader/image.boot:
make -C arch/$(ARCH)/loader COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR)
make -C arch/$(ARCH)/loader COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) "DEFS=$(DEFS)"
 
clean: generic_clean
make -C arch/$(ARCH)/loader clean COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR)