Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4343 → Rev 4344

/branches/dynload/kernel/genarch/include/kbd/z8530.h
37,19 → 37,90
#ifndef KERN_Z8530_H_
#define KERN_Z8530_H_
 
#include <console/chardev.h>
#include <ipc/irq.h>
#include <ddi/irq.h>
#include <arch/types.h>
 
extern bool z8530_belongs_to_kernel;
#define WR0 0
#define WR1 1
#define WR2 2
#define WR3 3
#define WR4 4
#define WR5 5
#define WR6 6
#define WR7 7
#define WR8 8
#define WR9 9
#define WR10 10
#define WR11 11
#define WR12 12
#define WR13 13
#define WR14 14
#define WR15 15
 
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 *);
extern irq_ownership_t z8530_claim(void *);
#define RR0 0
#define RR1 1
#define RR2 2
#define RR3 3
#define RR8 8
#define RR10 10
#define RR12 12
#define RR13 13
#define RR14 14
#define RR15 15
 
/** Reset pending TX interrupt. */
#define WR0_TX_IP_RST (0x5 << 3)
#define WR0_ERR_RST (0x6 << 3)
 
/** Receive Interrupts Disabled. */
#define WR1_RID (0x0 << 3)
/** Receive Interrupt on First Character or Special Condition. */
#define WR1_RIFCSC (0x1 << 3)
/** Interrupt on All Receive Characters or Special Conditions. */
#define WR1_IARCSC (0x2 << 3)
/** Receive Interrupt on Special Condition. */
#define WR1_RISC (0x3 << 3)
/** Parity Is Special Condition. */
#define WR1_PISC (0x1 << 2)
 
/** Rx Enable. */
#define WR3_RX_ENABLE (0x1 << 0)
/** 8-bits per character. */
#define WR3_RX8BITSCH (0x3 << 6)
 
/** Master Interrupt Enable. */
#define WR9_MIE (0x1 << 3)
 
/** Receive Character Available. */
#define RR0_RCA (0x1 << 0)
 
/** z8530's registers. */
struct z8530 {
union {
ioport8_t ctl_b;
ioport8_t status_b;
} __attribute__ ((packed));
uint8_t pad1;
ioport8_t data_b;
uint8_t pad2;
union {
ioport8_t ctl_a;
ioport8_t status_a;
} __attribute__ ((packed));
uint8_t pad3;
ioport8_t data_a;
} __attribute__ ((packed));
typedef struct z8530 z8530_t;
 
/** Structure representing the z8530 device. */
typedef struct {
devno_t devno;
irq_t irq;
z8530_t *z8530;
} z8530_instance_t;
 
extern bool z8530_init(z8530_t *, devno_t, inr_t, cir_t, void *);
extern irq_ownership_t z8530_claim(irq_t *);
extern void z8530_irq_handler(irq_t *);
 
#endif
/branches/dynload/kernel/genarch/include/kbd/ns16550.h
37,30 → 37,10
#ifndef KERN_NS16550_H_
#define KERN_NS16550_H_
 
#include <console/chardev.h>
#include <ddi/irq.h>
#include <ipc/irq.h>
 
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 *);
extern irq_ownership_t ns16550_claim(void *);
extern void ns16550_irq_handler(irq_t *);
 
#include <arch/types.h>
#include <arch/drivers/kbd.h>
 
/* 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. */
 
#define IER_ERBFI 0x01 /** Enable Receive Buffer Full Interrupt. */
 
#define LCR_DLAB 0x80 /** Divisor Latch Access bit. */
67,67 → 47,31
 
#define MCR_OUT2 0x08 /** OUT2. */
 
/** NS16550 registers. */
struct ns16550 {
ioport8_t rbr; /**< Receiver Buffer Register. */
ioport8_t ier; /**< Interrupt Enable Register. */
union {
ioport8_t iir; /**< Interrupt Ident Register (read). */
ioport8_t fcr; /**< FIFO control register (write). */
} __attribute__ ((packed));
ioport8_t lcr; /**< Line Control register. */
ioport8_t mcr; /**< Modem Control Register. */
ioport8_t lsr; /**< Line Status Register. */
} __attribute__ ((packed));
typedef struct ns16550 ns16550_t;
 
/** Structure representing the ns16550 device. */
typedef struct {
typedef struct ns16550_instance {
devno_t devno;
/** Memory mapped registers of the ns16550. */
volatile ioport_t io_port;
} ns16550_t;
ns16550_t *ns16550;
irq_t irq;
} ns16550_instance_t;
 
static inline uint8_t ns16550_rbr_read(ns16550_t *dev)
{
return pio_read_8(dev->io_port + RBR_REG);
}
static inline void ns16550_rbr_write(ns16550_t *dev, uint8_t v)
{
pio_write_8(dev->io_port + RBR_REG, v);
}
extern bool ns16550_init(ns16550_t *, devno_t, inr_t, cir_t, void *);
extern irq_ownership_t ns16550_claim(irq_t *);
extern void ns16550_irq_handler(irq_t *);
 
static inline uint8_t ns16550_ier_read(ns16550_t *dev)
{
return pio_read_8(dev->io_port + IER_REG);
}
 
static inline void ns16550_ier_write(ns16550_t *dev, uint8_t v)
{
pio_write_8(dev->io_port + IER_REG, v);
}
 
static inline uint8_t ns16550_iir_read(ns16550_t *dev)
{
return pio_read_8(dev->io_port + IIR_REG);
}
 
static inline void ns16550_fcr_write(ns16550_t *dev, uint8_t v)
{
pio_write_8(dev->io_port + FCR_REG, v);
}
 
static inline uint8_t ns16550_lcr_read(ns16550_t *dev)
{
return pio_read_8(dev->io_port + LCR_REG);
}
 
static inline void ns16550_lcr_write(ns16550_t *dev, uint8_t v)
{
pio_write_8(dev->io_port + LCR_REG, v);
}
 
static inline uint8_t ns16550_lsr_read(ns16550_t *dev)
{
return pio_read_8(dev->io_port + LSR_REG);
}
 
static inline uint8_t ns16550_mcr_read(ns16550_t *dev)
{
return pio_read_8(dev->io_port + MCR_REG);
}
 
static inline void ns16550_mcr_write(ns16550_t *dev, uint8_t v)
{
pio_write_8(dev->io_port + MCR_REG, v);
}
 
#endif
 
/** @}
/branches/dynload/kernel/genarch/include/kbd/i8042.h
35,15 → 35,25
#ifndef KERN_I8042_H_
#define KERN_I8042_H_
 
#include <ddi/irq.h>
#include <arch/types.h>
#include <console/chardev.h>
#include <typedefs.h>
 
extern void i8042_init(devno_t kbd_devno, inr_t kbd_inr, devno_t mouse_devno, inr_t mouse_inr);
extern void i8042_poll(void);
extern void i8042_grab(void);
extern void i8042_release(void);
extern char i8042_key_read(chardev_t *d);
struct i8042 {
ioport8_t data;
uint8_t pad[3];
ioport8_t status;
} __attribute__ ((packed));
typedef struct i8042 i8042_t;
 
typedef struct i8042_instance {
devno_t devno;
irq_t irq;
i8042_t *i8042;
} i8042_instance_t;
 
extern bool i8042_init(i8042_t *, devno_t, inr_t);
 
#endif
 
/** @}
/branches/dynload/kernel/genarch/include/drivers/legacy/ia32/io.h
0,0 → 1,51
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
* @{
*/
/** @file
* @brief This file contains definitions used by architectures with the
* ia32 legacy I/O space (i.e. ia32, amd64 and ia64).
*/
 
#ifndef KERN_LEGACY_IA32_IO_H
#define KERN_LEGACY_IA32_IO_H
 
#include <arch/types.h>
 
#define I8042_BASE ((ioport8_t *) 0x60)
#define EGA_BASE ((ioport8_t *) 0x3d4)
#define NS16550_BASE ((ioport8_t *) 0x3f8)
 
#define EGA_VIDEORAM 0xb8000
 
#endif
 
/** @}
*/
/branches/dynload/kernel/genarch/include/drivers/ega/ega.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch_drivers
/** @addtogroup genarch_drivers
* @{
*/
/** @file
37,16 → 37,17
 
#include <arch/types.h>
 
#define ROW 80
#define ROWS 25
#define SCREEN (ROW * ROWS)
#define EGA_COLS 80
#define EGA_ROWS 25
#define EGA_SCREEN (EGA_COLS * EGA_ROWS)
#define EGA_VRAM_SIZE (2 * EGA_SCREEN)
 
/* EGA device registers. */
#define EGA_INDEX_REG 0
#define EGA_DATA_REG 1
#define EGA_INDEX_REG 0
#define EGA_DATA_REG 1
 
extern void ega_redraw(void);
extern void ega_init(ioport_t, uintptr_t);
extern void ega_init(ioport8_t *, uintptr_t);
 
#endif
 
/branches/dynload/kernel/genarch/src/kbd/ns16550.c
1,5 → 1,5
/*
* Copyright (c) 2001-2006 Jakub Jermar
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
40,7 → 40,6
#include <genarch/kbd/scanc_sun.h>
#include <arch/drivers/kbd.h>
#include <ddi/irq.h>
#include <ipc/irq.h>
#include <cpu.h>
#include <arch/asm.h>
#include <arch.h>
48,17 → 47,11
#include <console/console.h>
#include <interrupt.h>
#include <arch/interrupt.h>
#include <sysinfo/sysinfo.h>
#include <synch/spinlock.h>
#include <mm/slab.h>
 
#define LSR_DATA_READY 0x01
 
/** Structure representing the ns16550. */
static ns16550_t ns16550;
 
/** Structure for ns16550's IRQ. */
static irq_t ns16550_irq;
 
/*
* These codes read from ns16550 data register are silently ignored.
*/
70,95 → 63,53
static chardev_operations_t ops = {
.suspend = ns16550_suspend,
.resume = ns16550_resume,
.read = ns16550_key_read
};
 
void ns16550_interrupt(void);
 
/** Initialize keyboard and service interrupts using kernel routine */
void ns16550_grab(void)
{
ipl_t ipl = interrupts_disable();
 
ns16550_ier_write(&ns16550, IER_ERBFI); /* enable receiver interrupt */
while (ns16550_lsr_read(&ns16550) & LSR_DATA_READY)
(void) ns16550_rbr_read(&ns16550);
 
spinlock_lock(&ns16550_irq.lock);
ns16550_irq.notif_cfg.notify = false;
spinlock_unlock(&ns16550_irq.lock);
interrupts_restore(ipl);
}
 
/** Resume the former interrupt vector */
void ns16550_release(void)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&ns16550_irq.lock);
if (ns16550_irq.notif_cfg.answerbox)
ns16550_irq.notif_cfg.notify = true;
spinlock_unlock(&ns16550_irq.lock);
interrupts_restore(ipl);
}
 
/** Initialize ns16550.
*
* @param dev Addrress of the beginning of the device in I/O space.
* @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.
*
* @return True on success, false on failure.
*/
void
ns16550_init(devno_t devno, ioport_t port, inr_t inr, cir_t cir, void *cir_arg)
bool
ns16550_init(ns16550_t *dev, devno_t devno, inr_t inr, cir_t cir, void *cir_arg)
{
ns16550_instance_t *instance;
 
chardev_initialize("ns16550_kbd", &kbrd, &ops);
stdin = &kbrd;
ns16550.devno = devno;
ns16550.io_port = port;
instance = malloc(sizeof(ns16550_instance_t), FRAME_ATOMIC);
if (!instance)
return false;
 
instance->devno = devno;
instance->ns16550 = dev;
irq_initialize(&ns16550_irq);
ns16550_irq.devno = devno;
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);
irq_initialize(&instance->irq);
instance->irq.devno = devno;
instance->irq.inr = inr;
instance->irq.claim = ns16550_claim;
instance->irq.handler = ns16550_irq_handler;
instance->irq.instance = instance;
instance->irq.cir = cir;
instance->irq.cir_arg = cir_arg;
irq_register(&instance->irq);
 
while ((pio_read_8(&dev->lsr) & LSR_DATA_READY))
(void) pio_read_8(&dev->rbr);
while ((ns16550_lsr_read(&ns16550) & LSR_DATA_READY))
ns16550_rbr_read(&ns16550);
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550);
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);
/* Enable interrupts */
ns16550_ier_write(&ns16550, IER_ERBFI);
ns16550_mcr_write(&ns16550, MCR_OUT2);
pio_write_8(&dev->ier, IER_ERBFI);
pio_write_8(&dev->mcr, MCR_OUT2);
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);
ns16550_ier_write(&ns16550, 0x00);
ns16550_lcr_write(&ns16550, c);
ns16550_grab();
return true;
}
 
/** Process ns16550 interrupt. */
void ns16550_interrupt(void)
{
ns16550_poll();
}
 
/* Called from getc(). */
void ns16550_resume(chardev_t *d)
{
169,37 → 120,26
{
}
 
 
char ns16550_key_read(chardev_t *d)
irq_ownership_t ns16550_claim(irq_t *irq)
{
char ch;
ns16550_instance_t *ns16550_instance = irq->instance;
ns16550_t *dev = ns16550_instance->ns16550;
 
while(!(ch = active_read_buff_read())) {
uint8_t x;
while (!(ns16550_lsr_read(&ns16550) & LSR_DATA_READY));
x = ns16550_rbr_read(&ns16550);
if (x != IGNORE_CODE) {
if (x & KEY_RELEASE)
key_released(x ^ KEY_RELEASE);
else
active_read_key_pressed(x);
}
}
return ch;
if (pio_read_8(&dev->lsr) & LSR_DATA_READY)
return IRQ_ACCEPT;
else
return IRQ_DECLINE;
}
 
/** Poll for key press and release events.
*
* This function can be used to implement keyboard polling.
*/
void ns16550_poll(void)
void ns16550_irq_handler(irq_t *irq)
{
while (ns16550_lsr_read(&ns16550) & LSR_DATA_READY) {
ns16550_instance_t *ns16550_instance = irq->instance;
ns16550_t *dev = ns16550_instance->ns16550;
 
if (pio_read_8(&dev->lsr) & LSR_DATA_READY) {
uint8_t x;
x = ns16550_rbr_read(&ns16550);
x = pio_read_8(&dev->rbr);
if (x != IGNORE_CODE) {
if (x & KEY_RELEASE)
208,20 → 148,8
key_pressed(x);
}
}
}
 
irq_ownership_t ns16550_claim(void *instance)
{
return (ns16550_lsr_read(&ns16550) & LSR_DATA_READY);
}
 
void ns16550_irq_handler(irq_t *irq)
{
if (irq->notif_cfg.notify && irq->notif_cfg.answerbox)
ipc_irq_send_notif(irq);
else
ns16550_interrupt();
}
 
/** @}
*/
/branches/dynload/kernel/genarch/src/kbd/i8042.c
1,5 → 1,5
/*
* Copyright (c) 2001-2004 Jakub Jermar
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
41,7 → 41,7
#include <genarch/kbd/key.h>
#include <genarch/kbd/scanc.h>
#include <genarch/kbd/scanc_pc.h>
#include <arch/drivers/i8042.h>
#include <genarch/drivers/legacy/ia32/io.h>
#include <cpu.h>
#include <arch/asm.h>
#include <arch.h>
48,8 → 48,6
#include <console/chardev.h>
#include <console/console.h>
#include <interrupt.h>
#include <sysinfo/sysinfo.h>
#include <ipc/irq.h>
 
/* Keyboard commands. */
#define KBD_ENABLE 0xf4
75,8 → 73,8
#define i8042_COMMAND 0x69
 
#define i8042_BUFFER_FULL_MASK 0x01
#define i8042_WAIT_MASK 0x02
#define i8042_MOUSE_DATA 0x20
#define i8042_WAIT_MASK 0x02
#define i8042_MOUSE_DATA 0x20
 
static void i8042_suspend(chardev_t *);
static void i8042_resume(chardev_t *);
84,115 → 82,72
static chardev_operations_t ops = {
.suspend = i8042_suspend,
.resume = i8042_resume,
.read = i8042_key_read
};
 
/** Structure for i8042's IRQ. */
static irq_t i8042_kbd_irq;
static irq_t i8042_mouse_irq;
 
void i8042_grab(void)
static irq_ownership_t i8042_claim(irq_t *irq)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&i8042_kbd_irq.lock);
i8042_kbd_irq.notif_cfg.notify = false;
spinlock_unlock(&i8042_kbd_irq.lock);
spinlock_lock(&i8042_mouse_irq.lock);
i8042_mouse_irq.notif_cfg.notify = false;
spinlock_unlock(&i8042_mouse_irq.lock);
interrupts_restore(ipl);
i8042_instance_t *i8042_instance = irq->instance;
i8042_t *dev = i8042_instance->i8042;
if (pio_read_8(&dev->status) & i8042_BUFFER_FULL_MASK)
return IRQ_ACCEPT;
else
return IRQ_DECLINE;
}
 
void i8042_release(void)
static void i8042_irq_handler(irq_t *irq)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&i8042_kbd_irq.lock);
if (i8042_kbd_irq.notif_cfg.answerbox)
i8042_kbd_irq.notif_cfg.notify = true;
spinlock_unlock(&i8042_kbd_irq.lock);
spinlock_lock(&i8042_mouse_irq.lock);
if (i8042_mouse_irq.notif_cfg.answerbox)
i8042_mouse_irq.notif_cfg.notify = true;
spinlock_unlock(&i8042_mouse_irq.lock);
interrupts_restore(ipl);
}
i8042_instance_t *instance = irq->instance;
i8042_t *dev = instance->i8042;
 
static irq_ownership_t i8042_claim(void *instance)
{
return IRQ_ACCEPT;
}
 
static void i8042_irq_handler(irq_t *irq)
{
if (irq->notif_cfg.notify && irq->notif_cfg.answerbox)
ipc_irq_send_notif(irq);
else {
uint8_t data;
uint8_t status;
uint8_t data;
uint8_t status;
while (((status = i8042_status_read()) & i8042_BUFFER_FULL_MASK)) {
data = i8042_data_read();
if (((status = pio_read_8(&dev->status)) & i8042_BUFFER_FULL_MASK)) {
data = pio_read_8(&dev->data);
if ((status & i8042_MOUSE_DATA))
continue;
if ((status & i8042_MOUSE_DATA))
return;
 
if (data & KEY_RELEASE)
key_released(data ^ KEY_RELEASE);
else
key_pressed(data);
}
if (data & KEY_RELEASE)
key_released(data ^ KEY_RELEASE);
else
key_pressed(data);
}
}
 
/** Initialize i8042. */
void i8042_init(devno_t kbd_devno, inr_t kbd_inr, devno_t mouse_devno, inr_t mouse_inr)
bool
i8042_init(i8042_t *dev, devno_t devno, inr_t inr)
{
i8042_instance_t *instance;
 
chardev_initialize("i8042_kbd", &kbrd, &ops);
stdin = &kbrd;
irq_initialize(&i8042_kbd_irq);
i8042_kbd_irq.devno = kbd_devno;
i8042_kbd_irq.inr = kbd_inr;
i8042_kbd_irq.claim = i8042_claim;
i8042_kbd_irq.handler = i8042_irq_handler;
irq_register(&i8042_kbd_irq);
instance = malloc(sizeof(i8042_instance_t), FRAME_ATOMIC);
if (!instance)
return false;
irq_initialize(&i8042_mouse_irq);
i8042_mouse_irq.devno = mouse_devno;
i8042_mouse_irq.inr = mouse_inr;
i8042_mouse_irq.claim = i8042_claim;
i8042_mouse_irq.handler = i8042_irq_handler;
irq_register(&i8042_mouse_irq);
instance->devno = devno;
instance->i8042 = dev;
trap_virtual_enable_irqs(1 << kbd_inr);
trap_virtual_enable_irqs(1 << mouse_inr);
irq_initialize(&instance->irq);
instance->irq.devno = devno;
instance->irq.inr = inr;
instance->irq.claim = i8042_claim;
instance->irq.handler = i8042_irq_handler;
instance->irq.instance = instance;
irq_register(&instance->irq);
trap_virtual_enable_irqs(1 << inr);
/*
* Clear input buffer.
* Number of iterations is limited to prevent infinite looping.
*/
int i;
for (i = 0; (i8042_status_read() & i8042_BUFFER_FULL_MASK) && i < 100; i++) {
i8042_data_read();
}
while (pio_read_8(&dev->status) & i8042_BUFFER_FULL_MASK)
(void) pio_read_8(&dev->data);
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);
i8042_grab();
return true;
}
 
/* Called from getc(). */
205,40 → 160,5
{
}
 
char i8042_key_read(chardev_t *d)
{
char ch;
while (!(ch = active_read_buff_read())) {
uint8_t x;
while (!(i8042_status_read() & i8042_BUFFER_FULL_MASK));
x = i8042_data_read();
if (x & KEY_RELEASE)
key_released(x ^ KEY_RELEASE);
else
active_read_key_pressed(x);
}
return ch;
}
 
/** Poll for key press and release events.
*
* This function can be used to implement keyboard polling.
*/
void i8042_poll(void)
{
uint8_t x;
while (((x = i8042_status_read() & i8042_BUFFER_FULL_MASK))) {
x = i8042_data_read();
if (x & KEY_RELEASE)
key_released(x ^ KEY_RELEASE);
else
key_pressed(x);
}
}
 
/** @}
*/
/branches/dynload/kernel/genarch/src/kbd/z8530.c
1,5 → 1,5
/*
* Copyright (c) 2001-2004 Jakub Jermar
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
31,7 → 31,7
*/
/**
* @file
* @brief Zilog 8530 serial port / keyboard driver.
* @brief Zilog 8530 serial port driver.
*/
 
#include <genarch/kbd/z8530.h>
38,28 → 38,38
#include <genarch/kbd/key.h>
#include <genarch/kbd/scanc.h>
#include <genarch/kbd/scanc_sun.h>
#include <arch/drivers/z8530.h>
#include <arch/drivers/kbd.h>
#include <console/console.h>
#include <console/chardev.h>
#include <ddi/irq.h>
#include <ipc/irq.h>
#include <arch/interrupt.h>
#include <arch/drivers/kbd.h>
#include <cpu.h>
#include <arch/asm.h>
#include <arch.h>
#include <console/chardev.h>
#include <console/console.h>
#include <interrupt.h>
#include <sysinfo/sysinfo.h>
#include <print.h>
#include <mm/slab.h>
 
static inline void z8530_write(ioport8_t *ctl, uint8_t reg, uint8_t val)
{
/*
* Registers 8-15 will automatically issue the Point High
* command as their bit 3 is 1.
*/
pio_write_8(ctl, reg); /* select register */
pio_write_8(ctl, val); /* write value */
}
 
static inline uint8_t z8530_read(ioport8_t *ctl, uint8_t reg)
{
/*
* Registers 8-15 will automatically issue the Point High
* command as their bit 3 is 1.
*/
pio_write_8(ctl, reg); /* select register */
return pio_read_8(ctl);
}
 
/*
* These codes read from z8530 data register are silently ignored.
*/
#define IGNORE_CODE 0x7f /* all keys up */
 
static z8530_t z8530; /**< z8530 device structure. */
static irq_t z8530_irq; /**< z8530's IRQ. */
 
static void z8530_suspend(chardev_t *);
static void z8530_resume(chardev_t *);
 
66,86 → 76,54
static chardev_operations_t ops = {
.suspend = z8530_suspend,
.resume = z8530_resume,
.read = z8530_key_read
};
 
/** Initialize keyboard and service interrupts using kernel routine. */
void z8530_grab(void)
/** Initialize z8530. */
bool
z8530_init(z8530_t *dev, devno_t devno, inr_t inr, cir_t cir, void *cir_arg)
{
ipl_t ipl = interrupts_disable();
z8530_instance_t *instance;
 
(void) z8530_read_a(&z8530, RR8);
chardev_initialize("z8530_kbd", &kbrd, &ops);
stdin = &kbrd;
 
instance = malloc(sizeof(z8530_instance_t), FRAME_ATOMIC);
if (!instance)
return false;
 
instance->devno = devno;
instance->z8530 = dev;
 
irq_initialize(&instance->irq);
instance->irq.devno = devno;
instance->irq.inr = inr;
instance->irq.claim = z8530_claim;
instance->irq.handler = z8530_irq_handler;
instance->irq.instance = instance;
instance->irq.cir = cir;
instance->irq.cir_arg = cir_arg;
irq_register(&instance->irq);
 
(void) z8530_read(&dev->ctl_a, RR8);
 
/*
* Clear any pending TX interrupts or we never manage
* to set FHC UART interrupt state to idle.
*/
z8530_write_a(&z8530, WR0, WR0_TX_IP_RST);
z8530_write(&dev->ctl_a, WR0, WR0_TX_IP_RST);
 
/* interrupt on all characters */
z8530_write_a(&z8530, WR1, WR1_IARCSC);
z8530_write(&dev->ctl_a, WR1, WR1_IARCSC);
 
/* 8 bits per character and enable receiver */
z8530_write_a(&z8530, WR3, WR3_RX8BITSCH | WR3_RX_ENABLE);
z8530_write(&dev->ctl_a, WR3, WR3_RX8BITSCH | WR3_RX_ENABLE);
/* Master Interrupt Enable. */
z8530_write_a(&z8530, WR9, WR9_MIE);
spinlock_lock(&z8530_irq.lock);
z8530_irq.notif_cfg.notify = false;
spinlock_unlock(&z8530_irq.lock);
interrupts_restore(ipl);
}
z8530_write(&dev->ctl_a, WR9, WR9_MIE);
 
/** Resume the former IPC notification behavior. */
void z8530_release(void)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&z8530_irq.lock);
if (z8530_irq.notif_cfg.answerbox)
z8530_irq.notif_cfg.notify = true;
spinlock_unlock(&z8530_irq.lock);
interrupts_restore(ipl);
return true;
}
 
/** Initialize z8530. */
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;
 
z8530.devno = devno;
z8530.reg = (uint8_t *) vaddr;
 
irq_initialize(&z8530_irq);
z8530_irq.devno = devno;
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);
sysinfo_set_item_val("kbd.type", NULL, KBD_Z8530);
sysinfo_set_item_val("kbd.devno", NULL, devno);
sysinfo_set_item_val("kbd.inr", NULL, inr);
sysinfo_set_item_val("kbd.address.virtual", NULL, vaddr);
 
z8530_grab();
}
 
/** Process z8530 interrupt.
*
* @param n Interrupt vector.
* @param istate Interrupted state.
*/
void z8530_interrupt(void)
{
z8530_poll();
}
 
/* Called from getc(). */
void z8530_resume(chardev_t *d)
{
156,35 → 134,22
{
}
 
char z8530_key_read(chardev_t *d)
irq_ownership_t z8530_claim(irq_t *irq)
{
char ch;
z8530_instance_t *instance = irq->instance;
z8530_t *dev = instance->z8530;
 
while(!(ch = active_read_buff_read())) {
uint8_t x;
while (!(z8530_read_a(&z8530, RR0) & RR0_RCA))
;
x = z8530_read_a(&z8530, RR8);
if (x != IGNORE_CODE) {
if (x & KEY_RELEASE)
key_released(x ^ KEY_RELEASE);
else
active_read_key_pressed(x);
}
}
return ch;
return (z8530_read(&dev->ctl_a, RR0) & RR0_RCA);
}
 
/** Poll for key press and release events.
*
* This function can be used to implement keyboard polling.
*/
void z8530_poll(void)
void z8530_irq_handler(irq_t *irq)
{
z8530_instance_t *instance = irq->instance;
z8530_t *dev = instance->z8530;
uint8_t x;
 
while (z8530_read_a(&z8530, RR0) & RR0_RCA) {
x = z8530_read_a(&z8530, RR8);
if (z8530_read(&dev->ctl_a, RR0) & RR0_RCA) {
x = z8530_read(&dev->ctl_a, RR8);
if (x != IGNORE_CODE) {
if (x & KEY_RELEASE)
key_released(x ^ KEY_RELEASE);
194,18 → 159,5
}
}
 
irq_ownership_t z8530_claim(void *instance)
{
return (z8530_read_a(&z8530, RR0) & RR0_RCA);
}
 
void z8530_irq_handler(irq_t *irq)
{
if (irq->notif_cfg.notify && irq->notif_cfg.answerbox)
ipc_irq_send_notif(irq);
else
z8530_interrupt();
}
 
/** @}
*/
/branches/dynload/kernel/genarch/src/drivers/ega/ega.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genarch_drivers
/** @addtogroup genarch_drivers
* @{
*/
/**
58,7 → 58,7
static uint32_t ega_cursor;
static uint8_t *videoram;
static uint8_t *backbuf;
static ioport_t ega_base;
static ioport8_t *ega_base;
 
chardev_t ega_console;
 
67,26 → 67,50
*/
static void ega_check_cursor(void)
{
if (ega_cursor < SCREEN)
if (ega_cursor < EGA_SCREEN)
return;
 
memmove((void *) videoram, (void *) (videoram + ROW * 2),
(SCREEN - ROW) * 2);
memmove((void *) backbuf, (void *) (backbuf + ROW * 2),
(SCREEN - ROW) * 2);
memsetw(videoram + (SCREEN - ROW) * 2, ROW, 0x0720);
memsetw(backbuf + (SCREEN - ROW) * 2, ROW, 0x0720);
ega_cursor = ega_cursor - ROW;
memmove((void *) videoram, (void *) (videoram + EGA_COLS * 2),
(EGA_SCREEN - EGA_COLS) * 2);
memmove((void *) backbuf, (void *) (backbuf + EGA_COLS * 2),
(EGA_SCREEN - EGA_COLS) * 2);
memsetw(videoram + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, 0x0720);
memsetw(backbuf + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, 0x0720);
ega_cursor = ega_cursor - EGA_COLS;
}
 
static void ega_show_cursor(void)
{
pio_write_8(ega_base + EGA_INDEX_REG, 0x0a);
uint8_t stat = pio_read_8(ega_base + EGA_DATA_REG);
pio_write_8(ega_base + EGA_INDEX_REG, 0x0a);
pio_write_8(ega_base + EGA_DATA_REG, stat & (~(1 << 5)));
}
 
static void ega_move_cursor(void)
{
pio_write_8(ega_base + EGA_INDEX_REG, 0xe);
pio_write_8(ega_base + EGA_INDEX_REG, 0x0e);
pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) ((ega_cursor >> 8) & 0xff));
pio_write_8(ega_base + EGA_INDEX_REG, 0xf);
pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) (ega_cursor & 0xff));
pio_write_8(ega_base + EGA_INDEX_REG, 0x0f);
pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) (ega_cursor & 0xff));
}
 
static void ega_sync_cursor(void)
{
pio_write_8(ega_base + EGA_INDEX_REG, 0x0e);
uint8_t hi = pio_read_8(ega_base + EGA_DATA_REG);
pio_write_8(ega_base + EGA_INDEX_REG, 0x0f);
uint8_t lo = pio_read_8(ega_base + EGA_DATA_REG);
ega_cursor = (hi << 8) | lo;
if ((ega_cursor % EGA_COLS) != 0)
ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
ega_check_cursor();
ega_move_cursor();
ega_show_cursor();
}
 
static void ega_display_char(char ch, bool silent)
{
backbuf[ega_cursor * 2] = ch;
104,13 → 128,13
switch (ch) {
case '\n':
ega_cursor = (ega_cursor + ROW) - ega_cursor % ROW;
ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
break;
case '\t':
ega_cursor = (ega_cursor + 8) - ega_cursor % 8;
break;
case '\b':
if (ega_cursor % ROW)
if (ega_cursor % EGA_COLS)
ega_cursor--;
break;
default:
131,21 → 155,20
.write = ega_putchar
};
 
void ega_init(ioport_t base, uintptr_t videoram_phys)
void ega_init(ioport8_t *base, uintptr_t videoram_phys)
{
/* Initialize the software structure. */
/* Initialize the software structure. */
ega_base = base;
backbuf = (uint8_t *) malloc(SCREEN * 2, 0);
backbuf = (uint8_t *) malloc(EGA_VRAM_SIZE, 0);
if (!backbuf)
panic("Unable to allocate backbuffer.");
videoram = (uint8_t *) hw_map(videoram_phys, SCREEN * 2);
videoram = (uint8_t *) hw_map(videoram_phys, EGA_VRAM_SIZE);
/* Clear the screen and set the cursor position. */
memsetw(videoram, SCREEN, 0x0720);
memsetw(backbuf, SCREEN, 0x0720);
ega_move_cursor();
/* Synchronize the back buffer and cursor position. */
memcpy(backbuf, videoram, EGA_VRAM_SIZE);
ega_sync_cursor();
chardev_initialize("ega_out", &ega_console, &ega_ops);
stdout = &ega_console;
152,8 → 175,8
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.width", NULL, EGA_COLS);
sysinfo_set_item_val("fb.height", NULL, EGA_ROWS);
sysinfo_set_item_val("fb.blinking", NULL, true);
sysinfo_set_item_val("fb.address.physical", NULL, videoram_phys);
}
160,8 → 183,9
 
void ega_redraw(void)
{
memcpy(videoram, backbuf, SCREEN * 2);
memcpy(videoram, backbuf, EGA_VRAM_SIZE);
ega_move_cursor();
ega_show_cursor();
}
 
/** @}
/branches/dynload/kernel/generic/include/align.h
26,13 → 26,13
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup generic
/** @addtogroup generic
* @ingroup others
* @{
*/
/**
* @file
* @brief Macros for making values and addresses aligned.
* @brief Macros for making values and addresses aligned.
*/
 
#ifndef KERN_ALIGN_H_
43,7 → 43,7
* @param s Address or size to be aligned.
* @param a Size of alignment, must be power of 2.
*/
#define ALIGN_DOWN(s, a) ((s) & ~((a) - 1))
#define ALIGN_DOWN(s, a) ((s) & ~((a) - 1))
 
 
/** Align to the nearest higher address.
51,7 → 51,7
* @param s Address or size to be aligned.
* @param a Size of alignment, must be power of 2.
*/
#define ALIGN_UP(s, a) (((s) + ((a) - 1)) & ~((a) - 1))
#define ALIGN_UP(s, a) (((s) + ((a) - 1)) & ~((a) - 1))
 
#endif
 
/branches/dynload/kernel/generic/include/config.h
40,11 → 40,14
 
#define STACK_SIZE PAGE_SIZE
 
#define CONFIG_INIT_TASKS 32
#define CONFIG_INIT_TASKS 32
 
#define CONFIG_TASK_NAME_BUFLEN 32
 
typedef struct {
uintptr_t addr;
size_t size;
char name[CONFIG_TASK_NAME_BUFLEN];
} init_task_t;
 
typedef struct {
/branches/dynload/kernel/generic/include/proc/task.h
144,6 → 144,7
#endif
 
extern unative_t sys_task_get_id(task_id_t *uspace_task_id);
extern unative_t sys_task_set_name(const char *uspace_name, size_t name_len);
 
#endif
 
/branches/dynload/kernel/generic/include/main/main.h
35,8 → 35,13
#ifndef KERN_MAIN_H_
#define KERN_MAIN_H_
 
#include <arch/types.h>
 
extern uintptr_t stack_safe;
 
extern void main_bsp(void);
extern void main_ap(void);
 
#endif
 
/** @}
/branches/dynload/kernel/generic/include/ddi/irq.h
36,16 → 36,16
#define KERN_IRQ_H_
 
typedef enum {
CMD_MEM_READ_1 = 0,
CMD_MEM_READ_2,
CMD_MEM_READ_4,
CMD_MEM_READ_8,
CMD_MEM_WRITE_1,
CMD_MEM_WRITE_2,
CMD_MEM_WRITE_4,
CMD_MEM_WRITE_8,
CMD_PORT_READ_1,
CMD_PORT_WRITE_1,
CMD_PIO_READ_8 = 1,
CMD_PIO_READ_16,
CMD_PIO_READ_32,
CMD_PIO_WRITE_8,
CMD_PIO_WRITE_16,
CMD_PIO_WRITE_32,
CMD_BTEST,
CMD_PREDICATE,
CMD_ACCEPT,
CMD_DECLINE,
CMD_LAST
} irq_cmd_type;
 
52,8 → 52,9
typedef struct {
irq_cmd_type cmd;
void *addr;
unsigned long long value;
int dstarg;
unsigned long long value;
unsigned int srcarg;
unsigned int dstarg;
} irq_cmd_t;
 
typedef struct {
65,8 → 66,10
 
#include <arch/types.h>
#include <adt/list.h>
#include <adt/hash_table.h>
#include <synch/spinlock.h>
#include <proc/task.h>
#include <ipc/ipc.h>
 
typedef enum {
IRQ_DECLINE, /**< Decline to service. */
96,6 → 99,8
answerbox_t *answerbox;
/** Method to be used for the notification. */
unative_t method;
/** Arguments that will be sent if the IRQ is claimed. */
unative_t scratch[IPC_CALL_LEN];
/** Top-half pseudocode. */
irq_code_t *code;
/** Counter. */
139,7 → 144,7
/** Trigger level of the IRQ. */
irq_trigger_t trigger;
/** Claim ownership of the IRQ. */
irq_ownership_t (* claim)(void *);
irq_ownership_t (* claim)(struct irq *);
/** Handler for this IRQ and device. */
irq_handler_t handler;
/** Instance argument for the handler and the claim function. */
154,11 → 159,13
ipc_notif_cfg_t notif_cfg;
} irq_t;
 
SPINLOCK_EXTERN(irq_uspace_hash_table_lock);
extern hash_table_t irq_uspace_hash_table;
 
extern void irq_init(count_t, count_t);
extern void irq_initialize(irq_t *);
extern void irq_register(irq_t *);
extern irq_t *irq_dispatch_and_lock(inr_t);
extern irq_t *irq_find_and_lock(inr_t, devno_t);
 
#endif
 
/branches/dynload/kernel/generic/include/console/console.h
41,6 → 41,8
extern chardev_t *stdin;
extern chardev_t *stdout;
 
extern bool silent;
 
extern void klog_init(void);
extern void klog_update(void);
 
/branches/dynload/kernel/generic/include/mm/frame.h
38,34 → 38,82
 
#include <arch/types.h>
#include <adt/list.h>
#include <mm/buddy.h>
#include <synch/spinlock.h>
#include <mm/buddy.h>
#include <arch/mm/page.h>
#include <arch/mm/frame.h>
 
#define ONE_FRAME 0
#define TWO_FRAMES 1
#define FOUR_FRAMES 2
#define ONE_FRAME 0
#define TWO_FRAMES 1
#define FOUR_FRAMES 2
 
 
#ifdef ARCH_STACK_FRAMES
#define STACK_FRAMES ARCH_STACK_FRAMES
#define STACK_FRAMES ARCH_STACK_FRAMES
#else
#define STACK_FRAMES ONE_FRAME
#define STACK_FRAMES ONE_FRAME
#endif
 
/** Maximum number of zones in system. */
#define ZONES_MAX 16
/** Maximum number of zones in the system. */
#define ZONES_MAX 32
 
/** Convert the frame address to kernel va. */
#define FRAME_KA 0x1
typedef uint8_t frame_flags_t;
 
/** Convert the frame address to kernel VA. */
#define FRAME_KA 0x01
/** Do not panic and do not sleep on failure. */
#define FRAME_ATOMIC 0x2
#define FRAME_ATOMIC 0x02
/** Do not start reclaiming when no free memory. */
#define FRAME_NO_RECLAIM 0x4
/** Do not allocate above 4 GiB. */
#define FRAME_LOW_4_GiB 0x8
#define FRAME_NO_RECLAIM 0x04
 
typedef uint8_t zone_flags_t;
 
/** Available zone (free for allocation) */
#define ZONE_AVAILABLE 0x00
/** Zone is reserved (not available for allocation) */
#define ZONE_RESERVED 0x08
/** Zone is used by firmware (not available for allocation) */
#define ZONE_FIRMWARE 0x10
 
/** Currently there is no equivalent zone flags
for frame flags */
#define FRAME_TO_ZONE_FLAGS(frame_flags) 0
 
typedef struct {
count_t refcount; /**< Tracking of shared frames */
uint8_t buddy_order; /**< Buddy system block order */
link_t buddy_link; /**< Link to the next free block inside
one order */
void *parent; /**< If allocated by slab, this points there */
} frame_t;
 
typedef struct {
pfn_t base; /**< Frame_no of the first frame
in the frames array */
count_t count; /**< Size of zone */
count_t free_count; /**< Number of free frame_t
structures */
count_t busy_count; /**< Number of busy frame_t
structures */
zone_flags_t flags; /**< Type of the zone */
frame_t *frames; /**< Array of frame_t structures
in this zone */
buddy_system_t *buddy_system; /**< Buddy system for the zone */
} zone_t;
 
/*
* The zoneinfo.lock must be locked when accessing zoneinfo structure.
* Some of the attributes in zone_t structures are 'read-only'
*/
typedef struct {
SPINLOCK_DECLARE(lock);
count_t count;
zone_t info[ZONES_MAX];
} zones_t;
 
extern zones_t zones;
 
static inline uintptr_t PFN2ADDR(pfn_t frame)
{
return (uintptr_t) (frame << FRAME_WIDTH);
88,31 → 136,37
return (size_t) (frames << FRAME_WIDTH);
}
 
#define IS_BUDDY_ORDER_OK(index, order) \
static inline bool zone_flags_available(zone_flags_t flags)
{
return ((flags & (ZONE_RESERVED | ZONE_FIRMWARE)) == 0);
}
 
#define IS_BUDDY_ORDER_OK(index, order) \
((~(((unative_t) -1) << (order)) & (index)) == 0)
#define IS_BUDDY_LEFT_BLOCK(zone, frame) \
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
#define IS_BUDDY_RIGHT_BLOCK(zone, frame) \
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
#define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame) \
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
#define IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame) \
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
#define IS_BUDDY_LEFT_BLOCK(zone, frame) \
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 0)
#define IS_BUDDY_RIGHT_BLOCK(zone, frame) \
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 1)
#define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame) \
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 0)
#define IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame) \
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 1)
 
#define frame_alloc(order, flags) \
#define frame_alloc(order, flags) \
frame_alloc_generic(order, flags, NULL)
 
extern void frame_init(void);
extern void *frame_alloc_generic(uint8_t, int, unsigned int *);
extern void *frame_alloc_generic(uint8_t, frame_flags_t, count_t *);
extern void frame_free(uintptr_t);
extern void frame_reference_add(pfn_t);
 
extern int zone_create(pfn_t, count_t, pfn_t, int);
extern void *frame_get_parent(pfn_t, unsigned int);
extern void frame_set_parent(pfn_t, void *, unsigned int);
extern count_t find_zone(pfn_t frame, count_t count, count_t hint);
extern count_t zone_create(pfn_t, count_t, pfn_t, zone_flags_t);
extern void *frame_get_parent(pfn_t, count_t);
extern void frame_set_parent(pfn_t, void *, count_t);
extern void frame_mark_unavailable(pfn_t, count_t);
extern uintptr_t zone_conf_size(count_t);
extern void zone_merge(unsigned int, unsigned int);
extern bool zone_merge(count_t, count_t);
extern void zone_merge_all(void);
extern uint64_t zone_total_size(void);
 
120,7 → 174,7
* Console functions
*/
extern void zone_print_list(void);
extern void zone_print_one(unsigned int);
extern void zone_print_one(count_t);
 
#endif
 
/branches/dynload/kernel/generic/include/mm/page.h
61,7 → 61,6
extern void map_structure(uintptr_t s, size_t size);
 
extern uintptr_t hw_map(uintptr_t physaddr, size_t size);
extern void hw_area(uintptr_t *physaddr, pfn_t *frames);
 
#endif
 
/branches/dynload/kernel/generic/include/mm/slab.h
59,7 → 59,7
/* slab_reclaim constants */
 
/** Reclaim all possible memory, because we are in memory stress */
#define SLAB_RECLAIM_ALL 0x1
#define SLAB_RECLAIM_ALL 0x01
 
/* cache_create flags */
 
/branches/dynload/kernel/generic/include/mm/buddy.h
82,7 → 82,7
extern link_t *buddy_system_alloc(buddy_system_t *, uint8_t);
extern bool buddy_system_can_alloc(buddy_system_t *, uint8_t);
extern void buddy_system_free(buddy_system_t *, link_t *);
extern size_t buddy_conf_size(int);
extern size_t buddy_conf_size(size_t);
extern link_t *buddy_system_alloc_block(buddy_system_t *, link_t *);
 
#endif
/branches/dynload/kernel/generic/include/syscall/syscall.h
44,6 → 44,7
SYS_THREAD_GET_ID,
SYS_TASK_GET_ID,
SYS_TASK_SET_NAME,
SYS_PROGRAM_SPAWN_LOADER,
SYS_FUTEX_SLEEP,
/branches/dynload/kernel/generic/include/ipc/irq.h
36,7 → 36,7
#define KERN_IPC_IRQ_H_
 
/** Maximum length of IPC IRQ program */
#define IRQ_MAX_PROG_SIZE 10
#define IRQ_MAX_PROG_SIZE 20
 
#include <ipc/ipc.h>
#include <ddi/irq.h>
43,12 → 43,15
#include <arch/types.h>
#include <adt/list.h>
 
extern int ipc_irq_register(answerbox_t *box, inr_t inr, devno_t devno,
unative_t method, irq_code_t *ucode);
extern void ipc_irq_send_notif(irq_t *irq);
extern void ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno);
extern void ipc_irq_cleanup(answerbox_t *box);
extern int ipc_irq_register(answerbox_t *, inr_t, devno_t, unative_t,
irq_code_t *);
 
extern irq_ownership_t ipc_irq_top_half_claim(irq_t *);
extern void ipc_irq_top_half_handler(irq_t *);
 
extern int ipc_irq_unregister(answerbox_t *, inr_t, devno_t);
extern void ipc_irq_cleanup(answerbox_t *);
 
/*
* User friendly wrappers for ipc_irq_send_msg(). They are in the form
* ipc_irq_send_msg_m(), where m is the number of payload arguments.
66,8 → 69,8
#define ipc_irq_send_msg_5(irq, a1, a2, a3, a4, a5) \
ipc_irq_send_msg((irq), (a1), (a2), (a3), (a4), (a5))
 
extern void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2,
unative_t a3, unative_t a4, unative_t a5);
extern void ipc_irq_send_msg(irq_t *, unative_t, unative_t, unative_t, unative_t,
unative_t);
 
#endif
 
/branches/dynload/kernel/generic/src/main/kinit.c
174,9 → 174,12
printf("init[%" PRIc "].addr is not frame aligned\n", i);
continue;
}
 
char *name = init.tasks[i].name;
if (name[0] == '\0') name = "init-bin";
int rc = program_create_from_image((void *) init.tasks[i].addr,
"init-bin", &programs[i]);
name, &programs[i]);
if ((rc == 0) && (programs[i].task != NULL)) {
/*
/branches/dynload/kernel/generic/src/main/main.c
81,8 → 81,8
#include <adt/btree.h>
#include <smp/smp.h>
#include <ddi/ddi.h>
#include <main/main.h>
 
 
/** Global configuration structure. */
config_t config;
 
105,18 → 105,15
* appropriate sizes and addresses.
*/
 
/**< Virtual address of where the kernel is loaded. */
/** Virtual address of where the kernel is loaded. */
uintptr_t hardcoded_load_address = 0;
/**< Size of the kernel code in bytes. */
/** Size of the kernel code in bytes. */
size_t hardcoded_ktext_size = 0;
/**< Size of the kernel data in bytes. */
/** Size of the kernel data in bytes. */
size_t hardcoded_kdata_size = 0;
/**< Lowest safe stack virtual address. */
/** Lowest safe stack virtual address. */
uintptr_t stack_safe = 0;
 
void main_bsp(void);
void main_ap(void);
 
/*
* These two functions prevent stack from underflowing during the
* kernel boot phase when SP is set to the very top of the reserved
/branches/dynload/kernel/generic/src/ddi/ddi.c
29,10 → 29,10
/** @addtogroup genericddi
* @{
*/
 
/**
* @file
* @brief Device Driver Interface functions.
* @brief Device Driver Interface functions.
*
* This file contains functions that comprise the Device Driver Interface.
* These are the functions for mapping physical memory and enabling I/O
47,7 → 47,7
#include <mm/as.h>
#include <synch/spinlock.h>
#include <syscall/copy.h>
#include <adt/list.h>
#include <adt/btree.h>
#include <arch.h>
#include <align.h>
#include <errno.h>
55,17 → 55,13
/** This lock protects the parea_btree. */
SPINLOCK_INITIALIZE(parea_lock);
 
/** List with enabled physical memory areas. */
static LIST_INITIALIZE(parea_head);
/** B+tree with enabled physical memory areas. */
static btree_t parea_btree;
 
/** Physical memory area for devices. */
static parea_t dev_area;
 
/** Initialize DDI. */
void ddi_init(void)
{
hw_area(&dev_area.pbase, &dev_area.frames);
ddi_parea_register(&dev_area);
btree_create(&parea_btree);
}
 
/** Enable piece of physical memory for mapping by physmem_map().
72,22 → 68,16
*
* @param parea Pointer to physical area structure.
*
* @todo This function doesn't check for overlaps. It depends on the kernel to
* create disjunct physical memory areas.
*/
void ddi_parea_register(parea_t *parea)
{
ipl_t ipl;
ipl = interrupts_disable();
ipl_t ipl = interrupts_disable();
spinlock_lock(&parea_lock);
/*
* TODO: we should really check for overlaps here.
* However, we should be safe because the kernel is pretty sane.
* We don't check for overlaps here as the kernel is pretty sane.
*/
link_initialize(&parea->link);
list_append(&parea->link, &parea_head);
btree_insert(&parea_btree, (btree_key_t) parea->pbase, parea, NULL);
spinlock_unlock(&parea_lock);
interrupts_restore(ipl);
95,64 → 85,83
 
/** Map piece of physical memory into virtual address space of current task.
*
* @param pf Physical address of the starting frame.
* @param vp Virtual address of the starting page.
* @param pf Physical address of the starting frame.
* @param vp Virtual address of the starting page.
* @param pages Number of pages to map.
* @param flags Address space area flags for the mapping.
*
* @return 0 on success, EPERM if the caller lacks capabilities to use this
* syscall, ENOENT if there is no task matching the specified ID or the
* physical address space is not enabled for mapping and ENOMEM if there
* was a problem in creating address space area.
* syscall, EBADMEM if pf or vf is not page aligned, ENOENT if there
* is no task matching the specified ID or the physical address space
* is not enabled for mapping and ENOMEM if there was a problem in
* creating address space area.
*
*/
static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, pfn_t pages, int flags)
static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, count_t pages, int flags)
{
ipl_t ipl;
cap_t caps;
mem_backend_data_t backend_data;
ASSERT(TASK);
ASSERT((pf % FRAME_SIZE) == 0);
ASSERT((vp % PAGE_SIZE) == 0);
backend_data.base = pf;
backend_data.frames = pages;
/*
* Make sure the caller is authorised to make this syscall.
*/
caps = cap_get(TASK);
cap_t caps = cap_get(TASK);
if (!(caps & CAP_MEM_MANAGER))
return EPERM;
ipl = interrupts_disable();
mem_backend_data_t backend_data;
backend_data.base = pf;
backend_data.frames = pages;
/*
* Check if the physical memory area is enabled for mapping.
*/
spinlock_lock(&parea_lock);
ipl_t ipl = interrupts_disable();
bool fnd = false;
link_t *cur;
/* Find the zone of the physical memory */
spinlock_lock(&zones.lock);
count_t znum = find_zone(ADDR2PFN(pf), pages, 0);
for (cur = parea_head.next; cur != &parea_head; cur = cur->next) {
parea_t *parea = list_get_instance(cur, parea_t, link);
if ((parea->pbase <= pf) && (ADDR2PFN(pf - parea->pbase) + pages <= parea->frames)) {
fnd = true;
break;
}
if (znum == (count_t) -1) {
/* Frames not found in any zones
* -> assume it is hardware device and allow mapping
*/
spinlock_unlock(&zones.lock);
goto map;
}
spinlock_unlock(&parea_lock);
if (zones.info[znum].flags & ZONE_FIRMWARE) {
/* Frames are part of firmware */
spinlock_unlock(&zones.lock);
goto map;
}
if (!fnd) {
/*
* Physical memory area cannot be mapped.
if (zone_flags_available(zones.info[znum].flags)) {
/* Frames are part of physical memory, check if the memory
* region is enabled for mapping.
*/
interrupts_restore(ipl);
return ENOENT;
spinlock_unlock(&zones.lock);
spinlock_lock(&parea_lock);
btree_node_t *nodep;
parea_t *parea = (parea_t *) btree_search(&parea_btree,
(btree_key_t) pf, &nodep);
if ((!parea) || (parea->frames < pages))
goto err;
spinlock_unlock(&parea_lock);
goto map;
}
err:
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return ENOENT;
map:
spinlock_lock(&TASK->lock);
if (!as_area_create(TASK->as, flags, pages * PAGE_SIZE, vp, AS_AREA_ATTR_NONE,
&phys_backend, &backend_data)) {
if (!as_area_create(TASK->as, flags, pages * PAGE_SIZE, vp,
AS_AREA_ATTR_NONE, &phys_backend, &backend_data)) {
/*
* The address space area could not have been created.
* We report it using ENOMEM.
178,28 → 187,24
* @param size Size of the enabled I/O space..
*
* @return 0 on success, EPERM if the caller lacks capabilities to use this
* syscall, ENOENT if there is no task matching the specified ID.
* syscall, ENOENT if there is no task matching the specified ID.
*
*/
static int ddi_iospace_enable(task_id_t id, uintptr_t ioaddr, size_t size)
{
ipl_t ipl;
cap_t caps;
task_t *t;
int rc;
/*
* Make sure the caller is authorised to make this syscall.
*/
caps = cap_get(TASK);
cap_t caps = cap_get(TASK);
if (!(caps & CAP_IO_MANAGER))
return EPERM;
ipl = interrupts_disable();
ipl_t ipl = interrupts_disable();
spinlock_lock(&tasks_lock);
t = task_find_by_id(id);
task_t *task = task_find_by_id(id);
if ((!t) || (!context_check(CONTEXT, t->context))) {
if ((!task) || (!context_check(CONTEXT, task->context))) {
/*
* There is no task with the specified ID
* or the task belongs to a different security
209,15 → 214,16
interrupts_restore(ipl);
return ENOENT;
}
 
/* Lock the task and release the lock protecting tasks_btree. */
spinlock_lock(&t->lock);
spinlock_lock(&task->lock);
spinlock_unlock(&tasks_lock);
 
rc = ddi_iospace_enable_arch(t, ioaddr, size);
spinlock_unlock(&t->lock);
int rc = ddi_iospace_enable_arch(task, ioaddr, size);
spinlock_unlock(&task->lock);
interrupts_restore(ipl);
return rc;
}
 
229,13 → 235,14
* @param flags Flags of newly mapped pages
*
* @return 0 on success, otherwise it returns error code found in errno.h
*/
*
*/
unative_t sys_physmem_map(unative_t phys_base, unative_t virt_base,
unative_t pages, unative_t flags)
{
return (unative_t) ddi_physmem_map(ALIGN_DOWN((uintptr_t) phys_base,
FRAME_SIZE), ALIGN_DOWN((uintptr_t) virt_base, PAGE_SIZE),
(pfn_t) pages, (int) flags);
(count_t) pages, (int) flags);
}
 
/** Wrapper for SYS_ENABLE_IOSPACE syscall.
243,16 → 250,15
* @param uspace_io_arg User space address of DDI argument structure.
*
* @return 0 on success, otherwise it returns error code found in errno.h
*/
*
*/
unative_t sys_iospace_enable(ddi_ioarg_t *uspace_io_arg)
{
ddi_ioarg_t arg;
int rc;
rc = copy_from_uspace(&arg, uspace_io_arg, sizeof(ddi_ioarg_t));
int rc = copy_from_uspace(&arg, uspace_io_arg, sizeof(ddi_ioarg_t));
if (rc != 0)
return (unative_t) rc;
return (unative_t) ddi_iospace_enable((task_id_t) arg.task_id,
(uintptr_t) arg.ioaddr, (size_t) arg.size);
}
260,19 → 266,23
/** Disable or enable preemption.
*
* @param enable If non-zero, the preemption counter will be decremented,
* leading to potential enabling of preemption. Otherwise the preemption
* counter will be incremented, preventing preemption from occurring.
* leading to potential enabling of preemption. Otherwise
* the preemption counter will be incremented, preventing
* preemption from occurring.
*
* @return Zero on success or EPERM if callers capabilities are not sufficient.
*/
*
*/
unative_t sys_preempt_control(int enable)
{
if (!cap_get(TASK) & CAP_PREEMPT_CONTROL)
return EPERM;
if (enable)
preemption_enable();
else
preemption_disable();
return 0;
}
 
/branches/dynload/kernel/generic/src/ddi/irq.c
69,8 → 69,11
 
#include <ddi/irq.h>
#include <adt/hash_table.h>
#include <mm/slab.h>
#include <arch/types.h>
#include <synch/spinlock.h>
#include <console/console.h>
#include <memstr.h>
#include <arch.h>
 
#define KEY_INR 0
77,13 → 80,22
#define KEY_DEVNO 1
 
/**
* Spinlock protecting the hash table.
* Spinlock protecting the kernel IRQ hash table.
* This lock must be taken only when interrupts are disabled.
*/
SPINLOCK_INITIALIZE(irq_hash_table_lock);
static hash_table_t irq_hash_table;
SPINLOCK_INITIALIZE(irq_kernel_hash_table_lock);
/** The kernel IRQ hash table. */
static hash_table_t irq_kernel_hash_table;
 
/**
* Spinlock protecting the uspace IRQ hash table.
* This lock must be taken only when interrupts are disabled.
*/
SPINLOCK_INITIALIZE(irq_uspace_hash_table_lock);
/** The uspace IRQ hash table. */
hash_table_t irq_uspace_hash_table;
 
/**
* Hash table operations for cases when we know that
* there will be collisions between different keys.
*/
111,6 → 123,9
.remove_callback = NULL /* not used */
};
 
/** Number of buckets in either of the hash tables. */
static count_t buckets;
 
/** Initialize IRQ subsystem.
*
* @param inrs Numbers of unique IRQ numbers or INRs.
118,6 → 133,7
*/
void irq_init(count_t inrs, count_t chains)
{
buckets = chains;
/*
* Be smart about the choice of the hash table operations.
* In cases in which inrs equals the requested number of
124,10 → 140,17
* chains (i.e. where there is no collision between
* different keys), we can use optimized set of operations.
*/
if (inrs == chains)
hash_table_create(&irq_hash_table, chains, 2, &irq_lin_ops);
else
hash_table_create(&irq_hash_table, chains, 2, &irq_ht_ops);
if (inrs == chains) {
hash_table_create(&irq_uspace_hash_table, chains, 2,
&irq_lin_ops);
hash_table_create(&irq_kernel_hash_table, chains, 2,
&irq_lin_ops);
} else {
hash_table_create(&irq_uspace_hash_table, chains, 2,
&irq_ht_ops);
hash_table_create(&irq_kernel_hash_table, chains, 2,
&irq_ht_ops);
}
}
 
/** Initialize one IRQ structure.
137,23 → 160,12
*/
void irq_initialize(irq_t *irq)
{
memsetb(irq, sizeof(irq_t), 0);
link_initialize(&irq->link);
spinlock_initialize(&irq->lock, "irq.lock");
irq->preack = false;
link_initialize(&irq->notif_cfg.link);
irq->inr = -1;
irq->devno = -1;
irq->trigger = (irq_trigger_t) 0;
irq->claim = NULL;
irq->handler = NULL;
irq->instance = NULL;
irq->cir = NULL;
irq->cir_arg = NULL;
irq->notif_cfg.notify = false;
irq->notif_cfg.answerbox = NULL;
irq->notif_cfg.code = NULL;
irq->notif_cfg.method = 0;
irq->notif_cfg.counter = 0;
link_initialize(&irq->notif_cfg.link);
}
 
/** Register IRQ for device.
160,9 → 172,10
*
* The irq structure must be filled with information
* about the interrupt source and with the claim()
* function pointer and irq_handler() function pointer.
* function pointer and handler() function pointer.
*
* @param irq IRQ structure belonging to a device.
* @param irq IRQ structure belonging to a device.
* @return True on success, false on failure.
*/
void irq_register(irq_t *irq)
{
173,88 → 186,101
};
ipl = interrupts_disable();
spinlock_lock(&irq_hash_table_lock);
hash_table_insert(&irq_hash_table, key, &irq->link);
spinlock_unlock(&irq_hash_table_lock);
spinlock_lock(&irq_kernel_hash_table_lock);
spinlock_lock(&irq->lock);
hash_table_insert(&irq_kernel_hash_table, key, &irq->link);
spinlock_unlock(&irq->lock);
spinlock_unlock(&irq_kernel_hash_table_lock);
interrupts_restore(ipl);
}
 
/** Dispatch the IRQ.
/** Search and lock the uspace IRQ hash table.
*
* We assume this function is only called from interrupt
* context (i.e. that interrupts are disabled prior to
* this call).
*
* This function attempts to lookup a fitting IRQ
* structure. In case of success, return with interrupts
* disabled and holding the respective structure.
*
* @param inr Interrupt number (aka inr or irq).
*
* @return IRQ structure of the respective device or NULL.
*/
irq_t *irq_dispatch_and_lock(inr_t inr)
static irq_t *irq_dispatch_and_lock_uspace(inr_t inr)
{
link_t *lnk;
unative_t key[] = {
(unative_t) inr,
(unative_t) -1 /* search will use claim() instead of devno */
(unative_t) -1 /* search will use claim() instead of devno */
};
spinlock_lock(&irq_hash_table_lock);
 
lnk = hash_table_find(&irq_hash_table, key);
spinlock_lock(&irq_uspace_hash_table_lock);
lnk = hash_table_find(&irq_uspace_hash_table, key);
if (lnk) {
irq_t *irq;
irq = hash_table_get_instance(lnk, irq_t, link);
 
spinlock_unlock(&irq_hash_table_lock);
spinlock_unlock(&irq_uspace_hash_table_lock);
return irq;
}
spinlock_unlock(&irq_uspace_hash_table_lock);
spinlock_unlock(&irq_hash_table_lock);
 
return NULL;
return NULL;
}
 
/** Find the IRQ structure corresponding to inr and devno.
/** Search and lock the kernel IRQ hash table.
*
* This functions attempts to lookup the IRQ structure
* corresponding to its arguments. On success, this
* function returns with interrups disabled, holding
* the lock of the respective IRQ structure.
*
* This function assumes interrupts are already disabled.
*
* @param inr INR being looked up.
* @param devno Devno being looked up.
*
* @return Locked IRQ structure on success or NULL on failure.
*/
irq_t *irq_find_and_lock(inr_t inr, devno_t devno)
static irq_t *irq_dispatch_and_lock_kernel(inr_t inr)
{
link_t *lnk;
unative_t keys[] = {
unative_t key[] = {
(unative_t) inr,
(unative_t) devno
(unative_t) -1 /* search will use claim() instead of devno */
};
spinlock_lock(&irq_hash_table_lock);
 
lnk = hash_table_find(&irq_hash_table, keys);
spinlock_lock(&irq_kernel_hash_table_lock);
lnk = hash_table_find(&irq_kernel_hash_table, key);
if (lnk) {
irq_t *irq;
irq = hash_table_get_instance(lnk, irq_t, link);
 
spinlock_unlock(&irq_hash_table_lock);
spinlock_unlock(&irq_kernel_hash_table_lock);
return irq;
}
spinlock_unlock(&irq_kernel_hash_table_lock);
spinlock_unlock(&irq_hash_table_lock);
return NULL;
}
 
return NULL;
/** Dispatch the IRQ.
*
* We assume this function is only called from interrupt
* context (i.e. that interrupts are disabled prior to
* this call).
*
* This function attempts to lookup a fitting IRQ
* structure. In case of success, return with interrupts
* disabled and holding the respective structure.
*
* @param inr Interrupt number (aka inr or irq).
*
* @return IRQ structure of the respective device or NULL.
*/
irq_t *irq_dispatch_and_lock(inr_t inr)
{
irq_t *irq;
/*
* If the kernel console is silenced,
* then try first the uspace handlers,
* eventually fall back to kernel handlers.
*
* If the kernel console is active,
* then do it the other way around.
*/
if (silent) {
irq = irq_dispatch_and_lock_uspace(inr);
if (irq)
return irq;
return irq_dispatch_and_lock_kernel(inr);
}
irq = irq_dispatch_and_lock_kernel(inr);
if (irq)
return irq;
return irq_dispatch_and_lock_uspace(inr);
}
 
/** Compute hash index for the key.
273,7 → 299,7
index_t irq_ht_hash(unative_t key[])
{
inr_t inr = (inr_t) key[KEY_INR];
return inr % irq_hash_table.entries;
return inr % buckets;
}
 
/** Compare hash table element with a key.
308,7 → 334,7
if (devno == -1) {
/* Invoked by irq_dispatch_and_lock(). */
rv = ((irq->inr == inr) &&
(irq->claim(irq->instance) == IRQ_ACCEPT));
(irq->claim(irq) == IRQ_ACCEPT));
} else {
/* Invoked by irq_find_and_lock(). */
rv = ((irq->inr == inr) && (irq->devno == devno));
367,7 → 393,7
spinlock_lock(&irq->lock);
if (devno == -1) {
/* Invoked by irq_dispatch_and_lock() */
rv = (irq->claim(irq->instance) == IRQ_ACCEPT);
rv = (irq->claim(irq) == IRQ_ACCEPT);
} else {
/* Invoked by irq_find_and_lock() */
rv = (irq->devno == devno);
/branches/dynload/kernel/generic/src/console/console.c
51,24 → 51,24
#define KLOG_SIZE PAGE_SIZE
#define KLOG_LATENCY 8
 
/**< Kernel log cyclic buffer */
/** Kernel log cyclic buffer */
static char klog[KLOG_SIZE] __attribute__ ((aligned (PAGE_SIZE)));
 
/**< Kernel log initialized */
/** Kernel log initialized */
static bool klog_inited = false;
/**< First kernel log characters */
/** First kernel log characters */
static index_t klog_start = 0;
/**< Number of valid kernel log characters */
/** Number of valid kernel log characters */
static size_t klog_len = 0;
/**< Number of stored (not printed) kernel log characters */
/** Number of stored (not printed) kernel log characters */
static size_t klog_stored = 0;
/**< Number of stored kernel log characters for uspace */
/** Number of stored kernel log characters for uspace */
static size_t klog_uspace = 0;
 
/**< Silent output */
static bool silent = false;
/** Silence output */
bool silent = false;
 
/**< Kernel log spinlock */
/** Kernel log spinlock */
SPINLOCK_INITIALIZE(klog_lock);
 
/** Physical memory area used for klog buffer */
101,7 → 101,7
*
* @return Always returns IRQ_DECLINE.
*/
static irq_ownership_t klog_claim(void *instance)
static irq_ownership_t klog_claim(irq_t *irq)
{
return IRQ_DECLINE;
}
/branches/dynload/kernel/generic/src/console/cmd.c
514,23 → 514,31
*/
int cmd_help(cmd_arg_t *argv)
{
link_t *cur;
 
spinlock_lock(&cmd_lock);
link_t *cur;
size_t len = 0;
for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
cmd_info_t *hlp;
hlp = list_get_instance(cur, cmd_info_t, link);
spinlock_lock(&hlp->lock);
if (strlen(hlp->name) > len)
len = strlen(hlp->name);
spinlock_unlock(&hlp->lock);
}
for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
cmd_info_t *hlp;
hlp = list_get_instance(cur, cmd_info_t, link);
spinlock_lock(&hlp->lock);
printf("%s - %s\n", hlp->name, hlp->description);
 
printf("%-*s %s\n", len, hlp->name, hlp->description);
spinlock_unlock(&hlp->lock);
}
spinlock_unlock(&cmd_lock);
 
return 1;
}
 
948,18 → 956,23
*/
int cmd_tests(cmd_arg_t *argv)
{
size_t len = 0;
test_t *test;
for (test = tests; test->name != NULL; test++) {
if (strlen(test->name) > len)
len = strlen(test->name);
}
for (test = tests; test->name != NULL; test++)
printf("%-10s %s%s\n", test->name, test->desc, (test->safe ? "" : " (unsafe)"));
printf("%-*s %s%s\n", len, test->name, test->desc, (test->safe ? "" : " (unsafe)"));
printf("%-10s Run all safe tests\n", "*");
printf("%-*s Run all safe tests\n", len, "*");
return 1;
}
 
static bool run_test(const test_t *test)
{
printf("%s\t\t%s\n", test->name, test->desc);
printf("%s (%s)\n", test->name, test->desc);
/* Update and read thread accounting
for benchmarking */
/branches/dynload/kernel/generic/src/console/kconsole.c
103,7 → 103,7
* @return Always returns IRQ_DECLINE.
*
*/
static irq_ownership_t kconsole_claim(void *instance)
static irq_ownership_t kconsole_claim(irq_t *irq)
{
return IRQ_DECLINE;
}
/branches/dynload/kernel/generic/src/proc/task.c
249,6 → 249,35
sizeof(TASK->taskid));
}
 
/** Syscall for setting the task name.
*
* The name simplifies identifying the task in the task list.
*
* @param name The new name for the task. (typically the same
* as the command used to execute it).
*
* @return 0 on success or an error code from @ref errno.h.
*/
unative_t sys_task_set_name(const char *uspace_name, size_t name_len)
{
int rc;
char namebuf[TASK_NAME_BUFLEN];
 
/* Cap length of name and copy it from userspace. */
 
if (name_len > TASK_NAME_BUFLEN - 1)
name_len = TASK_NAME_BUFLEN - 1;
 
rc = copy_from_uspace(namebuf, uspace_name, name_len);
if (rc != 0)
return (unative_t) rc;
 
namebuf[name_len] = '\0';
strcpy(TASK->name, namebuf);
 
return EOK;
}
 
/** Find task structure corresponding to task ID.
*
* The tasks_lock must be already held by the caller of this function and
367,13 → 396,13
order(task_get_accounting(t), &cycles, &suffix);
 
#ifdef __32_BITS__
printf("%-6" PRIu64 " %-10s %-3" PRIu32 " %10p %10p %9" PRIu64
printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %10p %10p %9" PRIu64
"%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, cycles,
suffix, atomic_get(&t->refcount), atomic_get(&t->active_calls));
#endif
 
#ifdef __64_BITS__
printf("%-6" PRIu64 " %-10s %-3" PRIu32 " %18p %18p %9" PRIu64
printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %18p %18p %9" PRIu64
"%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, cycles,
suffix, atomic_get(&t->refcount), atomic_get(&t->active_calls));
#endif
398,16 → 427,16
spinlock_lock(&tasks_lock);
 
#ifdef __32_BITS__
printf("taskid name ctx address as "
printf("taskid name ctx address as "
"cycles threads calls callee\n");
printf("------ ---------- --- ---------- ---------- "
printf("------ ------------ --- ---------- ---------- "
"---------- ------- ------ ------>\n");
#endif
 
#ifdef __64_BITS__
printf("taskid name ctx address as "
printf("taskid name ctx address as "
"cycles threads calls callee\n");
printf("------ ---------- --- ------------------ ------------------ "
printf("------ ------------ --- ------------------ ------------------ "
"---------- ------- ------ ------>\n");
#endif
 
/branches/dynload/kernel/generic/src/proc/program.c
200,8 → 200,8
 
/* Cap length of name and copy it from userspace. */
 
if (name_len > THREAD_NAME_BUFLEN - 1)
name_len = THREAD_NAME_BUFLEN - 1;
if (name_len > TASK_NAME_BUFLEN - 1)
name_len = TASK_NAME_BUFLEN - 1;
 
rc = copy_from_uspace(namebuf, uspace_name, name_len);
if (rc != 0)
/branches/dynload/kernel/generic/src/mm/slab.c
173,7 → 173,7
slab_t *slab;
size_t fsize;
unsigned int i;
unsigned int zone = 0;
count_t zone = 0;
data = frame_alloc_generic(cache->order, FRAME_KA | flags, &zone);
if (!data) {
/branches/dynload/kernel/generic/src/mm/buddy.c
46,7 → 46,7
#include <macros.h>
 
/** Return size needed for the buddy configuration data. */
size_t buddy_conf_size(int max_order)
size_t buddy_conf_size(size_t max_order)
{
return sizeof(buddy_system_t) + (max_order + 1) * sizeof(link_t);
}
/branches/dynload/kernel/generic/src/mm/frame.c
1,6 → 1,7
/*
* Copyright (c) 2001-2005 Jakub Jermar
* Copyright (c) 2005 Sergey Bondari
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
33,7 → 34,7
 
/**
* @file
* @brief Physical frame allocator.
* @brief Physical frame allocator.
*
* This file contains the physical frame allocator and memory zone management.
* The frame allocator is built on top of the buddy allocator.
41,16 → 42,6
* @see buddy.c
*/
 
/*
* Locking order
*
* In order to access particular zone, the process must first lock
* the zones.lock, then lock the zone and then unlock the zones.lock.
* This insures, that we can fiddle with the zones in runtime without
* affecting the processes.
*
*/
 
#include <arch/types.h>
#include <mm/frame.h>
#include <mm/as.h>
57,7 → 48,6
#include <panic.h>
#include <debug.h>
#include <adt/list.h>
#include <synch/spinlock.h>
#include <synch/mutex.h>
#include <synch/condvar.h>
#include <arch/asm.h>
69,50 → 59,16
#include <macros.h>
#include <config.h>
 
typedef struct {
count_t refcount; /**< tracking of shared frames */
uint8_t buddy_order; /**< buddy system block order */
link_t buddy_link; /**< link to the next free block inside one
order */
void *parent; /**< If allocated by slab, this points there */
} frame_t;
zones_t zones;
 
typedef struct {
SPINLOCK_DECLARE(lock); /**< this lock protects everything below */
pfn_t base; /**< frame_no of the first frame in the frames
array */
count_t count; /**< Size of zone */
 
frame_t *frames; /**< array of frame_t structures in this
zone */
count_t free_count; /**< number of free frame_t structures */
count_t busy_count; /**< number of busy frame_t structures */
buddy_system_t *buddy_system; /**< buddy system for the zone */
int flags;
} zone_t;
 
/*
* The zoneinfo.lock must be locked when accessing zoneinfo structure.
* Some of the attributes in zone_t structures are 'read-only'
*/
 
typedef struct {
SPINLOCK_DECLARE(lock);
unsigned int count;
zone_t *info[ZONES_MAX];
} zones_t;
 
static zones_t zones;
 
/*
* Synchronization primitives used to sleep when there is no memory
* available.
*/
mutex_t mem_avail_mtx;
condvar_t mem_avail_cv;
unsigned long mem_avail_frames = 0; /**< Number of available frames. */
unsigned long mem_avail_gen = 0; /**< Generation counter. */
count_t mem_avail_req = 0; /**< Number of frames requested. */
count_t mem_avail_gen = 0; /**< Generation counter. */
 
/********************/
/* Helper functions */
128,13 → 84,12
return (index_t) (frame - zone->frames) + zone->base;
}
 
static inline int frame_index_valid(zone_t *zone, index_t index)
static inline bool frame_index_valid(zone_t *zone, index_t index)
{
return (index < zone->count);
}
 
/** Compute pfn_t from frame_t pointer & zone pointer */
static index_t make_frame_index(zone_t *zone, frame_t *frame)
static inline index_t make_frame_index(zone_t *zone, frame_t *frame)
{
return (frame - zone->frames);
}
141,7 → 96,8
 
/** Initialize frame structure.
*
* @param frame Frame structure to be initialized.
* @param frame Frame structure to be initialized.
*
*/
static void frame_initialize(frame_t *frame)
{
149,153 → 105,143
frame->buddy_order = 0;
}
 
/**********************/
/* Zoneinfo functions */
/**********************/
/*******************/
/* Zones functions */
/*******************/
 
/** Insert-sort zone into zones list.
*
* @param newzone New zone to be inserted into zone list.
* @return Zone number on success, -1 on error.
* Assume interrupts are disabled and zones lock is
* locked.
*
* @param base Base frame of the newly inserted zone.
* @param count Number of frames of the newly inserted zone.
*
* @return Zone number on success, -1 on error.
*
*/
static int zones_add_zone(zone_t *newzone)
static count_t zones_insert_zone(pfn_t base, count_t count)
{
unsigned int i, j;
ipl_t ipl;
zone_t *z;
 
ipl = interrupts_disable();
spinlock_lock(&zones.lock);
/* Try to merge */
if (zones.count + 1 == ZONES_MAX) {
printf("Maximum zone count %u exceeded!\n", ZONES_MAX);
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return -1;
return (count_t) -1;
}
count_t i;
for (i = 0; i < zones.count; i++) {
/* Check for overflow */
z = zones.info[i];
if (overlaps(newzone->base, newzone->count, z->base,
z->count)) {
/* Check for overlap */
if (overlaps(base, count,
zones.info[i].base, zones.info[i].count)) {
printf("Zones overlap!\n");
return -1;
return (count_t) -1;
}
if (newzone->base < z->base)
if (base < zones.info[i].base)
break;
}
/* Move other zones up */
for (j = i; j < zones.count; j++)
zones.info[j + 1] = zones.info[j];
count_t j;
for (j = zones.count; j > i; j--) {
zones.info[j] = zones.info[j - 1];
zones.info[j].buddy_system->data =
(void *) &zones.info[j - 1];
}
zones.info[i] = newzone;
zones.count++;
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
 
return i;
}
 
/** Try to find a zone where can we find the frame.
/** Get total available frames.
*
* Assume interrupts are disabled.
* Assume interrupts are disabled and zones lock is
* locked.
*
* @param frame Frame number contained in zone.
* @param pzone If not null, it is used as zone hint. Zone index is
* filled into the variable on success.
* @return Pointer to locked zone containing frame.
* @return Total number of available frames.
*
*/
static zone_t *find_zone_and_lock(pfn_t frame, unsigned int *pzone)
static count_t total_frames_free(void)
{
unsigned int i;
unsigned int hint = pzone ? *pzone : 0;
zone_t *z;
count_t total = 0;
count_t i;
for (i = 0; i < zones.count; i++)
total += zones.info[i].free_count;
spinlock_lock(&zones.lock);
return total;
}
 
/** Find a zone with a given frames.
*
* Assume interrupts are disabled and zones lock is
* locked.
*
* @param frame Frame number contained in zone.
* @param count Number of frames to look for.
* @param hint Used as zone hint.
*
* @return Zone index or -1 if not found.
*
*/
count_t find_zone(pfn_t frame, count_t count, count_t hint)
{
if (hint >= zones.count)
hint = 0;
i = hint;
count_t i = hint;
do {
z = zones.info[i];
spinlock_lock(&z->lock);
if (z->base <= frame && z->base + z->count > frame) {
/* Unlock the global lock */
spinlock_unlock(&zones.lock);
if (pzone)
*pzone = i;
return z;
}
spinlock_unlock(&z->lock);
 
if ((zones.info[i].base <= frame)
&& (zones.info[i].base + zones.info[i].count >= frame + count))
return i;
i++;
if (i >= zones.count)
i = 0;
} while (i != hint);
 
spinlock_unlock(&zones.lock);
return NULL;
return (count_t) -1;
}
 
/** @return True if zone can allocate specified order */
static int zone_can_alloc(zone_t *z, uint8_t order)
static bool zone_can_alloc(zone_t *zone, uint8_t order)
{
return buddy_system_can_alloc(z->buddy_system, order);
return (zone_flags_available(zone->flags)
&& buddy_system_can_alloc(zone->buddy_system, order));
}
 
/** Find and lock zone that can allocate order frames.
/** Find a zone that can allocate order frames.
*
* Assume interrupts are disabled.
* Assume interrupts are disabled and zones lock is
* locked.
*
* @param order Size (2^order) of free space we are trying to find.
* @param flags Required flags of the target zone.
* @param pzone Pointer to preferred zone or NULL, on return contains
* zone number.
* @param order Size (2^order) of free space we are trying to find.
* @param flags Required flags of the target zone.
* @param hind Preferred zone.
*
*/
static zone_t *
find_free_zone_and_lock(uint8_t order, int flags, unsigned int *pzone)
static count_t find_free_zone(uint8_t order, zone_flags_t flags, count_t hint)
{
unsigned int i;
zone_t *z;
unsigned int hint = pzone ? *pzone : 0;
/* Mask off flags that are not applicable. */
flags &= FRAME_LOW_4_GiB;
 
spinlock_lock(&zones.lock);
if (hint >= zones.count)
hint = 0;
i = hint;
count_t i = hint;
do {
z = zones.info[i];
spinlock_lock(&z->lock);
 
/*
* Check whether the zone meets the search criteria.
*/
if ((z->flags & flags) == flags) {
if ((zones.info[i].flags & flags) == flags) {
/*
* Check if the zone has 2^order frames area available.
*/
if (zone_can_alloc(z, order)) {
spinlock_unlock(&zones.lock);
if (pzone)
*pzone = i;
return z;
}
if (zone_can_alloc(&zones.info[i], order))
return i;
}
spinlock_unlock(&z->lock);
if (++i >= zones.count)
i++;
if (i >= zones.count)
i = 0;
} while (i != hint);
spinlock_unlock(&zones.lock);
return NULL;
return (count_t) -1;
}
 
/**************************/
307,82 → 253,76
* Find block that is parent of current list.
* That means go to lower addresses, until such block is found
*
* @param order Order of parent must be different then this
* parameter!!
* @param order Order of parent must be different then this
* parameter!!
*
*/
static link_t *zone_buddy_find_block(buddy_system_t *b, link_t *child,
static link_t *zone_buddy_find_block(buddy_system_t *buddy, link_t *child,
uint8_t order)
{
frame_t *frame;
zone_t *zone;
index_t index;
frame_t *frame = list_get_instance(child, frame_t, buddy_link);
zone_t *zone = (zone_t *) buddy->data;
frame = list_get_instance(child, frame_t, buddy_link);
zone = (zone_t *) b->data;
 
index = frame_index(zone, frame);
index_t index = frame_index(zone, frame);
do {
if (zone->frames[index].buddy_order != order) {
if (zone->frames[index].buddy_order != order)
return &zone->frames[index].buddy_link;
}
} while(index-- > 0);
} while (index-- > 0);
return NULL;
}
 
/** Buddy system find_buddy implementation.
*
* @param b Buddy system.
* @param block Block for which buddy should be found.
* @param buddy Buddy system.
* @param block Block for which buddy should be found.
*
* @return Buddy for given block if found.
* @return Buddy for given block if found.
*
*/
static link_t *zone_buddy_find_buddy(buddy_system_t *b, link_t *block)
static link_t *zone_buddy_find_buddy(buddy_system_t *buddy, link_t *block)
{
frame_t *frame;
zone_t *zone;
index_t index;
bool is_left, is_right;
 
frame = list_get_instance(block, frame_t, buddy_link);
zone = (zone_t *) b->data;
frame_t *frame = list_get_instance(block, frame_t, buddy_link);
zone_t *zone = (zone_t *) buddy->data;
ASSERT(IS_BUDDY_ORDER_OK(frame_index_abs(zone, frame),
frame->buddy_order));
is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame);
is_right = IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame);
 
bool is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame);
bool is_right = IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame);
ASSERT(is_left ^ is_right);
index_t index;
if (is_left) {
index = (frame_index(zone, frame)) +
(1 << frame->buddy_order);
} else { /* if (is_right) */
} else { /* if (is_right) */
index = (frame_index(zone, frame)) -
(1 << frame->buddy_order);
}
if (frame_index_valid(zone, index)) {
if (zone->frames[index].buddy_order == frame->buddy_order &&
zone->frames[index].refcount == 0) {
if ((zone->frames[index].buddy_order == frame->buddy_order) &&
(zone->frames[index].refcount == 0)) {
return &zone->frames[index].buddy_link;
}
}
 
return NULL;
return NULL;
}
 
/** Buddy system bisect implementation.
*
* @param b Buddy system.
* @param block Block to bisect.
* @param buddy Buddy system.
* @param block Block to bisect.
*
* @return Right block.
* @return Right block.
*
*/
static link_t *zone_buddy_bisect(buddy_system_t *b, link_t *block)
static link_t *zone_buddy_bisect(buddy_system_t *buddy, link_t *block)
{
frame_t *frame_l, *frame_r;
 
frame_l = list_get_instance(block, frame_t, buddy_link);
frame_r = (frame_l + (1 << (frame_l->buddy_order - 1)));
frame_t *frame_l = list_get_instance(block, frame_t, buddy_link);
frame_t *frame_r = (frame_l + (1 << (frame_l->buddy_order - 1)));
return &frame_r->buddy_link;
}
389,75 → 329,68
 
/** Buddy system coalesce implementation.
*
* @param b Buddy system.
* @param block_1 First block.
* @param block_2 First block's buddy.
* @param buddy Buddy system.
* @param block_1 First block.
* @param block_2 First block's buddy.
*
* @return Coalesced block (actually block that represents lower
* address).
* @return Coalesced block (actually block that represents lower
* address).
*
*/
static link_t *zone_buddy_coalesce(buddy_system_t *b, link_t *block_1,
link_t *block_2)
static link_t *zone_buddy_coalesce(buddy_system_t *buddy, link_t *block_1,
link_t *block_2)
{
frame_t *frame1, *frame2;
frame_t *frame1 = list_get_instance(block_1, frame_t, buddy_link);
frame_t *frame2 = list_get_instance(block_2, frame_t, buddy_link);
frame1 = list_get_instance(block_1, frame_t, buddy_link);
frame2 = list_get_instance(block_2, frame_t, buddy_link);
return frame1 < frame2 ? block_1 : block_2;
return ((frame1 < frame2) ? block_1 : block_2);
}
 
/** Buddy system set_order implementation.
*
* @param b Buddy system.
* @param block Buddy system block.
* @param order Order to set.
* @param buddy Buddy system.
* @param block Buddy system block.
* @param order Order to set.
*
*/
static void zone_buddy_set_order(buddy_system_t *b, link_t *block,
static void zone_buddy_set_order(buddy_system_t *buddy, link_t *block,
uint8_t order)
{
frame_t *frame;
frame = list_get_instance(block, frame_t, buddy_link);
frame->buddy_order = order;
list_get_instance(block, frame_t, buddy_link)->buddy_order = order;
}
 
/** Buddy system get_order implementation.
*
* @param b Buddy system.
* @param block Buddy system block.
* @param buddy Buddy system.
* @param block Buddy system block.
*
* @return Order of block.
* @return Order of block.
*
*/
static uint8_t zone_buddy_get_order(buddy_system_t *b, link_t *block)
static uint8_t zone_buddy_get_order(buddy_system_t *buddy, link_t *block)
{
frame_t *frame;
frame = list_get_instance(block, frame_t, buddy_link);
return frame->buddy_order;
return list_get_instance(block, frame_t, buddy_link)->buddy_order;
}
 
/** Buddy system mark_busy implementation.
*
* @param b Buddy system.
* @param block Buddy system block.
* @param buddy Buddy system.
* @param block Buddy system block.
*
*/
static void zone_buddy_mark_busy(buddy_system_t *b, link_t * block)
static void zone_buddy_mark_busy(buddy_system_t *buddy, link_t * block)
{
frame_t * frame;
 
frame = list_get_instance(block, frame_t, buddy_link);
frame->refcount = 1;
list_get_instance(block, frame_t, buddy_link)->refcount = 1;
}
 
/** Buddy system mark_available implementation.
*
* @param b Buddy system.
* @param block Buddy system block.
* @param buddy Buddy system.
* @param block Buddy system block.
*/
static void zone_buddy_mark_available(buddy_system_t *b, link_t *block)
static void zone_buddy_mark_available(buddy_system_t *buddy, link_t *block)
{
frame_t *frame;
frame = list_get_instance(block, frame_t, buddy_link);
frame->refcount = 0;
list_get_instance(block, frame_t, buddy_link)->refcount = 0;
}
 
static buddy_system_operations_t zone_buddy_system_operations = {
477,60 → 410,57
 
/** Allocate frame in particular zone.
*
* Assume zone is locked.
* Assume zone is locked and is available for allocation.
* Panics if allocation is impossible.
*
* @param zone Zone to allocate from.
* @param order Allocate exactly 2^order frames.
* @param zone Zone to allocate from.
* @param order Allocate exactly 2^order frames.
*
* @return Frame index in zone.
* @return Frame index in zone.
*
*/
static pfn_t zone_frame_alloc(zone_t *zone, uint8_t order)
{
pfn_t v;
link_t *tmp;
frame_t *frame;
 
ASSERT(zone_flags_available(zone->flags));
/* Allocate frames from zone buddy system */
tmp = buddy_system_alloc(zone->buddy_system, order);
link_t *link = buddy_system_alloc(zone->buddy_system, order);
ASSERT(tmp);
ASSERT(link);
/* Update zone information. */
zone->free_count -= (1 << order);
zone->busy_count += (1 << order);
 
/* Frame will be actually a first frame of the block. */
frame = list_get_instance(tmp, frame_t, buddy_link);
frame_t *frame = list_get_instance(link, frame_t, buddy_link);
/* get frame address */
v = make_frame_index(zone, frame);
return v;
/* Get frame address */
return make_frame_index(zone, frame);
}
 
/** Free frame from zone.
*
* Assume zone is locked.
* Assume zone is locked and is available for deallocation.
*
* @param zone Pointer to zone from which the frame is to be freed.
* @param frame_idx Frame index relative to zone.
* @param zone Pointer to zone from which the frame is to be freed.
* @param frame_idx Frame index relative to zone.
*
*/
static void zone_frame_free(zone_t *zone, index_t frame_idx)
{
frame_t *frame;
uint8_t order;
 
frame = &zone->frames[frame_idx];
ASSERT(zone_flags_available(zone->flags));
/* remember frame order */
order = frame->buddy_order;
 
frame_t *frame = &zone->frames[frame_idx];
/* Remember frame order */
uint8_t order = frame->buddy_order;
ASSERT(frame->refcount);
 
if (!--frame->refcount) {
buddy_system_free(zone->buddy_system, &frame->buddy_link);
/* Update zone information. */
zone->free_count += (1 << order);
zone->busy_count -= (1 << order);
547,567 → 477,630
/** Mark frame in zone unavailable to allocation. */
static void zone_mark_unavailable(zone_t *zone, index_t frame_idx)
{
frame_t *frame;
link_t *link;
 
frame = zone_get_frame(zone, frame_idx);
ASSERT(zone_flags_available(zone->flags));
frame_t *frame = zone_get_frame(zone, frame_idx);
if (frame->refcount)
return;
link = buddy_system_alloc_block(zone->buddy_system,
link_t *link = buddy_system_alloc_block(zone->buddy_system,
&frame->buddy_link);
ASSERT(link);
zone->free_count--;
 
mutex_lock(&mem_avail_mtx);
mem_avail_frames--;
mutex_unlock(&mem_avail_mtx);
}
 
/** Join two zones.
/** Merge two zones.
*
* Expect zone_t *z to point to space at least zone_conf_size large.
* Expect buddy to point to space at least zone_conf_size large.
* Assume z1 & z2 are locked and compatible and zones lock is
* locked.
*
* Assume z1 & z2 are locked.
* @param z1 First zone to merge.
* @param z2 Second zone to merge.
* @param old_z1 Original date of the first zone.
* @param buddy Merged zone buddy.
*
* @param z Target zone structure pointer.
* @param z1 Zone to merge.
* @param z2 Zone to merge.
*/
static void _zone_merge(zone_t *z, zone_t *z1, zone_t *z2)
static void zone_merge_internal(count_t z1, count_t z2, zone_t *old_z1, buddy_system_t *buddy)
{
uint8_t max_order;
unsigned int i;
int z2idx;
pfn_t frame_idx;
frame_t *frame;
 
ASSERT(!overlaps(z1->base, z1->count, z2->base, z2->count));
ASSERT(z1->base < z2->base);
 
spinlock_initialize(&z->lock, "zone_lock");
z->base = z1->base;
z->count = z2->base + z2->count - z1->base;
z->flags = z1->flags & z2->flags;
 
z->free_count = z1->free_count + z2->free_count;
z->busy_count = z1->busy_count + z2->busy_count;
ASSERT(zone_flags_available(zones.info[z1].flags));
ASSERT(zone_flags_available(zones.info[z2].flags));
ASSERT(zones.info[z1].flags == zones.info[z2].flags);
ASSERT(zones.info[z1].base < zones.info[z2].base);
ASSERT(!overlaps(zones.info[z1].base, zones.info[z1].count,
zones.info[z2].base, zones.info[z2].count));
max_order = fnzb(z->count);
 
z->buddy_system = (buddy_system_t *) &z[1];
buddy_system_create(z->buddy_system, max_order,
&zone_buddy_system_operations, (void *) z);
 
z->frames = (frame_t *)((uint8_t *) z->buddy_system +
buddy_conf_size(max_order));
for (i = 0; i < z->count; i++) {
/* This marks all frames busy */
frame_initialize(&z->frames[i]);
}
/* Difference between zone bases */
pfn_t base_diff = zones.info[z2].base - zones.info[z1].base;
zones.info[z1].count = base_diff + zones.info[z2].count;
zones.info[z1].free_count += zones.info[z2].free_count;
zones.info[z1].busy_count += zones.info[z2].busy_count;
zones.info[z1].buddy_system = buddy;
uint8_t order = fnzb(zones.info[z1].count);
buddy_system_create(zones.info[z1].buddy_system, order,
&zone_buddy_system_operations, (void *) &zones.info[z1]);
zones.info[z1].frames =
(frame_t *) ((uint8_t *) zones.info[z1].buddy_system
+ buddy_conf_size(order));
/* This marks all frames busy */
count_t i;
for (i = 0; i < zones.info[z1].count; i++)
frame_initialize(&zones.info[z1].frames[i]);
/* Copy frames from both zones to preserve full frame orders,
* parents etc. Set all free frames with refcount=0 to 1, because
* we add all free frames to buddy allocator later again, clear
* order to 0. Don't set busy frames with refcount=0, as they
* parents etc. Set all free frames with refcount = 0 to 1, because
* we add all free frames to buddy allocator later again, clearing
* order to 0. Don't set busy frames with refcount = 0, as they
* will not be reallocated during merge and it would make later
* problems with allocation/free.
*/
for (i = 0; i < z1->count; i++)
z->frames[i] = z1->frames[i];
for (i = 0; i < z2->count; i++) {
z2idx = i + (z2->base - z1->base);
z->frames[z2idx] = z2->frames[i];
}
for (i = 0; i < old_z1->count; i++)
zones.info[z1].frames[i] = old_z1->frames[i];
for (i = 0; i < zones.info[z2].count; i++)
zones.info[z1].frames[base_diff + i]
= zones.info[z2].frames[i];
i = 0;
while (i < z->count) {
if (z->frames[i].refcount) {
/* skip busy frames */
i += 1 << z->frames[i].buddy_order;
} else { /* Free frames, set refcount=1 */
/* All free frames have refcount=0, we need not
* to check the order */
z->frames[i].refcount = 1;
z->frames[i].buddy_order = 0;
while (i < zones.info[z1].count) {
if (zones.info[z1].frames[i].refcount) {
/* Skip busy frames */
i += 1 << zones.info[z1].frames[i].buddy_order;
} else {
/* Free frames, set refcount = 1
* (all free frames have refcount == 0, we need not
* to check the order)
*/
zones.info[z1].frames[i].refcount = 1;
zones.info[z1].frames[i].buddy_order = 0;
i++;
}
}
/* Add free blocks from the 2 original zones */
while (zone_can_alloc(z1, 0)) {
frame_idx = zone_frame_alloc(z1, 0);
frame = &z->frames[frame_idx];
/* Add free blocks from the original zone z1 */
while (zone_can_alloc(old_z1, 0)) {
/* Allocate from the original zone */
pfn_t frame_idx = zone_frame_alloc(old_z1, 0);
/* Free the frame from the merged zone */
frame_t *frame = &zones.info[z1].frames[frame_idx];
frame->refcount = 0;
buddy_system_free(z->buddy_system, &frame->buddy_link);
buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link);
}
while (zone_can_alloc(z2, 0)) {
frame_idx = zone_frame_alloc(z2, 0);
frame = &z->frames[frame_idx + (z2->base - z1->base)];
/* Add free blocks from the original zone z2 */
while (zone_can_alloc(&zones.info[z2], 0)) {
/* Allocate from the original zone */
pfn_t frame_idx = zone_frame_alloc(&zones.info[z2], 0);
/* Free the frame from the merged zone */
frame_t *frame = &zones.info[z1].frames[base_diff + frame_idx];
frame->refcount = 0;
buddy_system_free(z->buddy_system, &frame->buddy_link);
buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link);
}
}
 
/** Return old configuration frames into the zone.
*
* We have several cases
* - the conf. data is outside of zone -> exit, shall we call frame_free??
* - the conf. data was created by zone_create or
* updated with reduce_region -> free every frame
* We have two cases:
* - The configuration data is outside the zone
* -> do nothing (perhaps call frame_free?)
* - The configuration data was created by zone_create
* or updated by reduce_region -> free every frame
*
* @param newzone The actual zone where freeing should occur.
* @param oldzone Pointer to old zone configuration data that should
* be freed from new zone.
* @param znum The actual zone where freeing should occur.
* @param pfn Old zone configuration frame.
* @param count Old zone frame count.
*
*/
static void return_config_frames(zone_t *newzone, zone_t *oldzone)
static void return_config_frames(count_t znum, pfn_t pfn, count_t count)
{
pfn_t pfn;
frame_t *frame;
count_t cframes;
unsigned int i;
 
pfn = ADDR2PFN((uintptr_t)KA2PA(oldzone));
cframes = SIZE2FRAMES(zone_conf_size(oldzone->count));
ASSERT(zone_flags_available(zones.info[znum].flags));
if (pfn < newzone->base || pfn >= newzone->base + newzone->count)
count_t cframes = SIZE2FRAMES(zone_conf_size(count));
if ((pfn < zones.info[znum].base)
|| (pfn >= zones.info[znum].base + zones.info[znum].count))
return;
 
frame = &newzone->frames[pfn - newzone->base];
frame_t *frame
= &zones.info[znum].frames[pfn - zones.info[znum].base];
ASSERT(!frame->buddy_order);
 
count_t i;
for (i = 0; i < cframes; i++) {
newzone->busy_count++;
zone_frame_free(newzone, pfn+i-newzone->base);
zones.info[znum].busy_count++;
zone_frame_free(&zones.info[znum],
pfn - zones.info[znum].base + i);
}
}
 
/** Reduce allocated block to count of order 0 frames.
*
* The allocated block need 2^order frames of space. Reduce all frames
* in block to order 0 and free the unneeded frames. This means, that
* when freeing the previously allocated block starting with frame_idx,
* The allocated block needs 2^order frames. Reduce all frames
* in the block to order 0 and free the unneeded frames. This means that
* when freeing the previously allocated block starting with frame_idx,
* you have to free every frame.
*
* @param zone
* @param frame_idx Index to block.
* @param count Allocated space in block.
* @param znum Zone.
* @param frame_idx Index the first frame of the block.
* @param count Allocated frames in block.
*
*/
static void zone_reduce_region(zone_t *zone, pfn_t frame_idx, count_t count)
static void zone_reduce_region(count_t znum, pfn_t frame_idx, count_t count)
{
count_t i;
uint8_t order;
frame_t *frame;
ASSERT(zone_flags_available(zones.info[znum].flags));
ASSERT(frame_idx + count < zones.info[znum].count);
ASSERT(frame_idx + count < zone->count);
 
order = zone->frames[frame_idx].buddy_order;
uint8_t order = zones.info[znum].frames[frame_idx].buddy_order;
ASSERT((count_t) (1 << order) >= count);
 
/* Reduce all blocks to order 0 */
count_t i;
for (i = 0; i < (count_t) (1 << order); i++) {
frame = &zone->frames[i + frame_idx];
frame_t *frame = &zones.info[znum].frames[i + frame_idx];
frame->buddy_order = 0;
if (!frame->refcount)
frame->refcount = 1;
ASSERT(frame->refcount == 1);
}
/* Free unneeded frames */
for (i = count; i < (count_t) (1 << order); i++) {
zone_frame_free(zone, i + frame_idx);
}
for (i = count; i < (count_t) (1 << order); i++)
zone_frame_free(&zones.info[znum], i + frame_idx);
}
 
/** Merge zones z1 and z2.
*
* - the zones must be 2 zones with no zone existing in between,
* which means that z2 = z1+1
* The merged zones must be 2 zones with no zone existing in between
* (which means that z2 = z1 + 1). Both zones must be available zones
* with the same flags.
*
* - When you create a new zone, the frame allocator configuration does
* not to be 2^order size. Once the allocator is running it is no longer
* possible, merged configuration data occupies more space :-/
* When you create a new zone, the frame allocator configuration does
* not to be 2^order size. Once the allocator is running it is no longer
* possible, merged configuration data occupies more space :-/
*
* The function uses
*
*/
void zone_merge(unsigned int z1, unsigned int z2)
bool zone_merge(count_t z1, count_t z2)
{
ipl_t ipl;
zone_t *zone1, *zone2, *newzone;
unsigned int cframes;
uint8_t order;
unsigned int i;
pfn_t pfn;
 
ipl = interrupts_disable();
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
 
if ((z1 >= zones.count) || (z2 >= zones.count))
bool ret = true;
/* We can join only 2 zones with none existing inbetween,
* the zones have to be available and with the same
* set of flags
*/
if ((z1 >= zones.count) || (z2 >= zones.count)
|| (z2 - z1 != 1)
|| (!zone_flags_available(zones.info[z1].flags))
|| (!zone_flags_available(zones.info[z2].flags))
|| (zones.info[z1].flags != zones.info[z2].flags)) {
ret = false;
goto errout;
/* We can join only 2 zones with none existing inbetween */
if (z2 - z1 != 1)
goto errout;
 
zone1 = zones.info[z1];
zone2 = zones.info[z2];
spinlock_lock(&zone1->lock);
spinlock_lock(&zone2->lock);
 
cframes = SIZE2FRAMES(zone_conf_size(zone2->base + zone2->count -
zone1->base));
}
pfn_t cframes = SIZE2FRAMES(zone_conf_size(
zones.info[z2].base - zones.info[z1].base
+ zones.info[z2].count));
uint8_t order;
if (cframes == 1)
order = 0;
else
else
order = fnzb(cframes - 1) + 1;
 
/* Allocate zonedata inside one of the zones */
if (zone_can_alloc(zone1, order))
pfn = zone1->base + zone_frame_alloc(zone1, order);
else if (zone_can_alloc(zone2, order))
pfn = zone2->base + zone_frame_alloc(zone2, order);
else
goto errout2;
 
newzone = (zone_t *) PA2KA(PFN2ADDR(pfn));
 
_zone_merge(newzone, zone1, zone2);
 
/* Allocate merged zone data inside one of the zones */
pfn_t pfn;
if (zone_can_alloc(&zones.info[z1], order)) {
pfn = zones.info[z1].base + zone_frame_alloc(&zones.info[z1], order);
} else if (zone_can_alloc(&zones.info[z2], order)) {
pfn = zones.info[z2].base + zone_frame_alloc(&zones.info[z2], order);
} else {
ret = false;
goto errout;
}
/* Preserve original data from z1 */
zone_t old_z1 = zones.info[z1];
old_z1.buddy_system->data = (void *) &old_z1;
/* Do zone merging */
buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(pfn));
zone_merge_internal(z1, z2, &old_z1, buddy);
/* Free unneeded config frames */
zone_reduce_region(newzone, pfn - newzone->base, cframes);
zone_reduce_region(z1, pfn - zones.info[z1].base, cframes);
/* Subtract zone information from busy frames */
newzone->busy_count -= cframes;
 
/* Replace existing zones in zoneinfo list */
zones.info[z1] = newzone;
for (i = z2 + 1; i < zones.count; i++)
zones.info[z1].busy_count -= cframes;
/* Free old zone information */
return_config_frames(z1,
ADDR2PFN(KA2PA((uintptr_t) old_z1.frames)), old_z1.count);
return_config_frames(z1,
ADDR2PFN(KA2PA((uintptr_t) zones.info[z2].frames)),
zones.info[z2].count);
/* Move zones down */
count_t i;
for (i = z2 + 1; i < zones.count; i++) {
zones.info[i - 1] = zones.info[i];
zones.info[i - 1].buddy_system->data =
(void *) &zones.info[i - 1];
}
zones.count--;
 
/* Free old zone information */
return_config_frames(newzone, zone1);
return_config_frames(newzone, zone2);
errout2:
/* Nobody is allowed to enter to zone, so we are safe
* to touch the spinlocks last time */
spinlock_unlock(&zone1->lock);
spinlock_unlock(&zone2->lock);
errout:
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return ret;
}
 
/** Merge all zones into one big zone.
/** Merge all mergeable zones into one big zone.
*
* It is reasonable to do this on systems whose bios reports parts in chunks,
* so that we could have 1 zone (it's faster).
* It is reasonable to do this on systems where
* BIOS reports parts in chunks, so that we could
* have 1 zone (it's faster).
*
*/
void zone_merge_all(void)
{
int count = zones.count;
 
while (zones.count > 1 && --count) {
zone_merge(0, 1);
break;
count_t i = 0;
while (i < zones.count) {
if (!zone_merge(i, i + 1))
i++;
}
}
 
/** Create new frame zone.
*
* @param start Physical address of the first frame within the zone.
* @param count Count of frames in zone.
* @param z Address of configuration information of zone.
* @param flags Zone flags.
* @param zone Zone to construct.
* @param buddy Address of buddy system configuration information.
* @param start Physical address of the first frame within the zone.
* @param count Count of frames in zone.
* @param flags Zone flags.
*
* @return Initialized zone.
* @return Initialized zone.
*
*/
static void zone_construct(pfn_t start, count_t count, zone_t *z, int flags)
static void zone_construct(zone_t *zone, buddy_system_t *buddy, pfn_t start, count_t count, zone_flags_t flags)
{
unsigned int i;
uint8_t max_order;
 
spinlock_initialize(&z->lock, "zone_lock");
z->base = start;
z->count = count;
 
/* Mask off flags that are calculated automatically. */
flags &= ~FRAME_LOW_4_GiB;
/* Determine calculated flags. */
if (z->base + count < (1ULL << (32 - FRAME_WIDTH))) /* 4 GiB */
flags |= FRAME_LOW_4_GiB;
 
z->flags = flags;
 
z->free_count = count;
z->busy_count = 0;
 
/*
* Compute order for buddy system, initialize
*/
max_order = fnzb(count);
z->buddy_system = (buddy_system_t *)&z[1];
zone->base = start;
zone->count = count;
zone->flags = flags;
zone->free_count = count;
zone->busy_count = 0;
zone->buddy_system = buddy;
buddy_system_create(z->buddy_system, max_order,
&zone_buddy_system_operations, (void *) z);
/* Allocate frames _after_ the conframe */
/* Check sizes */
z->frames = (frame_t *)((uint8_t *) z->buddy_system +
buddy_conf_size(max_order));
for (i = 0; i < count; i++) {
frame_initialize(&z->frames[i]);
}
/* Stuffing frames */
for (i = 0; i < count; i++) {
z->frames[i].refcount = 0;
buddy_system_free(z->buddy_system, &z->frames[i].buddy_link);
}
if (zone_flags_available(flags)) {
/*
* Compute order for buddy system and initialize
*/
uint8_t order = fnzb(count);
buddy_system_create(zone->buddy_system, order,
&zone_buddy_system_operations, (void *) zone);
/* Allocate frames _after_ the confframe */
/* Check sizes */
zone->frames = (frame_t *) ((uint8_t *) zone->buddy_system +
buddy_conf_size(order));
count_t i;
for (i = 0; i < count; i++)
frame_initialize(&zone->frames[i]);
/* Stuffing frames */
for (i = 0; i < count; i++) {
zone->frames[i].refcount = 0;
buddy_system_free(zone->buddy_system, &zone->frames[i].buddy_link);
}
} else
zone->frames = NULL;
}
 
/** Compute configuration data size for zone.
*
* @param count Size of zone in frames.
* @return Size of zone configuration info (in bytes).
* @param count Size of zone in frames.
*
* @return Size of zone configuration info (in bytes).
*
*/
uintptr_t zone_conf_size(count_t count)
{
int size = sizeof(zone_t) + count * sizeof(frame_t);
int max_order;
 
max_order = fnzb(count);
size += buddy_conf_size(max_order);
return size;
return (count * sizeof(frame_t) + buddy_conf_size(fnzb(count)));
}
 
/** Create and add zone to system.
*
* @param start First frame number (absolute).
* @param count Size of zone in frames.
* @param confframe Where configuration frames are supposed to be.
* Automatically checks, that we will not disturb the
* kernel and possibly init. If confframe is given
* _outside_ this zone, it is expected, that the area is
* already marked BUSY and big enough to contain
* zone_conf_size() amount of data. If the confframe is
* inside the area, the zone free frame information is
* modified not to include it.
* @param start First frame number (absolute).
* @param count Size of zone in frames.
* @param confframe Where configuration frames are supposed to be.
* Automatically checks, that we will not disturb the
* kernel and possibly init. If confframe is given
* _outside_ this zone, it is expected, that the area is
* already marked BUSY and big enough to contain
* zone_conf_size() amount of data. If the confframe is
* inside the area, the zone free frame information is
* modified not to include it.
*
* @return Zone number or -1 on error.
* @return Zone number or -1 on error.
*
*/
int zone_create(pfn_t start, count_t count, pfn_t confframe, int flags)
count_t zone_create(pfn_t start, count_t count, pfn_t confframe, zone_flags_t flags)
{
zone_t *z;
uintptr_t addr;
count_t confcount;
unsigned int i;
int znum;
 
/* Theoretically we could have here 0, practically make sure
* nobody tries to do that. If some platform requires, remove
* the assert
*/
ASSERT(confframe);
/* If conframe is supposed to be inside our zone, then make sure
* it does not span kernel & init
*/
confcount = SIZE2FRAMES(zone_conf_size(count));
if (confframe >= start && confframe < start + count) {
for (; confframe < start + count; confframe++) {
addr = PFN2ADDR(confframe);
if (overlaps(addr, PFN2ADDR(confcount),
KA2PA(config.base), config.kernel_size))
continue;
if (overlaps(addr, PFN2ADDR(confcount),
KA2PA(config.stack_base), config.stack_size))
continue;
bool overlap = false;
count_t i;
for (i = 0; i < init.cnt; i++)
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
if (zone_flags_available(flags)) { /* Create available zone */
/* Theoretically we could have NULL here, practically make sure
* nobody tries to do that. If some platform requires, remove
* the assert
*/
ASSERT(confframe != NULL);
/* If confframe is supposed to be inside our zone, then make sure
* it does not span kernel & init
*/
count_t confcount = SIZE2FRAMES(zone_conf_size(count));
if ((confframe >= start) && (confframe < start + count)) {
for (; confframe < start + count; confframe++) {
uintptr_t addr = PFN2ADDR(confframe);
if (overlaps(addr, PFN2ADDR(confcount),
KA2PA(init.tasks[i].addr),
init.tasks[i].size)) {
overlap = true;
break;
}
if (overlap)
continue;
KA2PA(config.base), config.kernel_size))
continue;
if (overlaps(addr, PFN2ADDR(confcount),
KA2PA(config.stack_base), config.stack_size))
continue;
bool overlap = false;
count_t i;
for (i = 0; i < init.cnt; i++)
if (overlaps(addr, PFN2ADDR(confcount),
KA2PA(init.tasks[i].addr),
init.tasks[i].size)) {
overlap = true;
break;
}
if (overlap)
continue;
break;
}
break;
if (confframe >= start + count)
panic("Cannot find configuration data for zone.");
}
if (confframe >= start + count)
panic("Cannot find configuration data for zone.");
count_t znum = zones_insert_zone(start, count);
if (znum == (count_t) -1) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return (count_t) -1;
}
buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(confframe));
zone_construct(&zones.info[znum], buddy, start, count, flags);
/* If confdata in zone, mark as unavailable */
if ((confframe >= start) && (confframe < start + count)) {
count_t i;
for (i = confframe; i < confframe + confcount; i++)
zone_mark_unavailable(&zones.info[znum],
i - zones.info[znum].base);
}
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return znum;
}
 
z = (zone_t *) PA2KA(PFN2ADDR(confframe));
zone_construct(start, count, z, flags);
znum = zones_add_zone(z);
if (znum == -1)
return -1;
 
mutex_lock(&mem_avail_mtx);
mem_avail_frames += count;
mutex_unlock(&mem_avail_mtx);
 
/* If confdata in zone, mark as unavailable */
if (confframe >= start && confframe < start + count)
for (i = confframe; i < confframe + confcount; i++) {
zone_mark_unavailable(z, i - z->base);
}
/* Non-available zone */
count_t znum = zones_insert_zone(start, count);
if (znum == (count_t) -1) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return (count_t) -1;
}
zone_construct(&zones.info[znum], NULL, start, count, flags);
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return znum;
}
 
/***************************************/
/*******************/
/* Frame functions */
/*******************/
 
/** Set parent of frame. */
void frame_set_parent(pfn_t pfn, void *data, unsigned int hint)
void frame_set_parent(pfn_t pfn, void *data, count_t hint)
{
zone_t *zone = find_zone_and_lock(pfn, &hint);
 
ASSERT(zone);
 
zone_get_frame(zone, pfn - zone->base)->parent = data;
spinlock_unlock(&zone->lock);
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
count_t znum = find_zone(pfn, 1, hint);
ASSERT(znum != (count_t) -1);
zone_get_frame(&zones.info[znum],
pfn - zones.info[znum].base)->parent = data;
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
}
 
void *frame_get_parent(pfn_t pfn, unsigned int hint)
void *frame_get_parent(pfn_t pfn, count_t hint)
{
zone_t *zone = find_zone_and_lock(pfn, &hint);
void *res;
 
ASSERT(zone);
res = zone_get_frame(zone, pfn - zone->base)->parent;
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
spinlock_unlock(&zone->lock);
count_t znum = find_zone(pfn, 1, hint);
ASSERT(znum != (count_t) -1);
void *res = zone_get_frame(&zones.info[znum],
pfn - zones.info[znum].base)->parent;
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return res;
}
 
/** Allocate power-of-two frames of physical memory.
*
* @param order Allocate exactly 2^order frames.
* @param flags Flags for host zone selection and address processing.
* @param pzone Preferred zone.
* @param order Allocate exactly 2^order frames.
* @param flags Flags for host zone selection and address processing.
* @param pzone Preferred zone.
*
* @return Physical address of the allocated frame.
* @return Physical address of the allocated frame.
*
*/
void *frame_alloc_generic(uint8_t order, int flags, unsigned int *pzone)
void *frame_alloc_generic(uint8_t order, frame_flags_t flags, count_t *pzone)
{
count_t size = ((count_t) 1) << order;
ipl_t ipl;
int freed;
pfn_t v;
zone_t *zone;
unsigned long gen = 0;
count_t hint = pzone ? (*pzone) : 0;
loop:
ipl = interrupts_disable();
spinlock_lock(&zones.lock);
/*
* First, find suitable frame zone.
*/
zone = find_free_zone_and_lock(order, flags, pzone);
count_t znum = find_free_zone(order,
FRAME_TO_ZONE_FLAGS(flags), hint);
/* If no memory, reclaim some slab memory,
if it does not help, reclaim all */
if (!zone && !(flags & FRAME_NO_RECLAIM)) {
freed = slab_reclaim(0);
if (freed)
zone = find_free_zone_and_lock(order, flags, pzone);
if (!zone) {
if ((znum == (count_t) -1) && (!(flags & FRAME_NO_RECLAIM))) {
count_t freed = slab_reclaim(0);
if (freed > 0)
znum = find_free_zone(order,
FRAME_TO_ZONE_FLAGS(flags), hint);
if (znum == (count_t) -1) {
freed = slab_reclaim(SLAB_RECLAIM_ALL);
if (freed)
zone = find_free_zone_and_lock(order, flags,
pzone);
if (freed > 0)
znum = find_free_zone(order,
FRAME_TO_ZONE_FLAGS(flags), hint);
}
}
if (!zone) {
/*
* Sleep until some frames are available again.
*/
if (znum == (count_t) -1) {
if (flags & FRAME_ATOMIC) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return 0;
return NULL;
}
#ifdef CONFIG_DEBUG
unsigned long avail;
 
mutex_lock(&mem_avail_mtx);
avail = mem_avail_frames;
mutex_unlock(&mem_avail_mtx);
 
printf("Thread %" PRIu64 " waiting for %u frames, "
"%u available.\n", THREAD->tid, 1ULL << order, avail);
count_t avail = total_frames_free();
#endif
 
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
/*
* Sleep until some frames are available again.
*/
#ifdef CONFIG_DEBUG
printf("Thread %" PRIu64 " waiting for %" PRIc " frames, "
"%" PRIc " available.\n", THREAD->tid, size, avail);
#endif
mutex_lock(&mem_avail_mtx);
while ((mem_avail_frames < (1ULL << order)) ||
gen == mem_avail_gen)
if (mem_avail_req > 0)
mem_avail_req = min(mem_avail_req, size);
else
mem_avail_req = size;
count_t gen = mem_avail_gen;
while (gen == mem_avail_gen)
condvar_wait(&mem_avail_cv, &mem_avail_mtx);
gen = mem_avail_gen;
mutex_unlock(&mem_avail_mtx);
 
#ifdef CONFIG_DEBUG
mutex_lock(&mem_avail_mtx);
avail = mem_avail_frames;
mutex_unlock(&mem_avail_mtx);
 
printf("Thread %" PRIu64 " woken up, %u frames available.\n",
THREAD->tid, avail);
printf("Thread %" PRIu64 " woken up.\n", THREAD->tid);
#endif
 
interrupts_restore(ipl);
goto loop;
}
v = zone_frame_alloc(zone, order);
v += zone->base;
 
spinlock_unlock(&zone->lock);
pfn_t pfn = zone_frame_alloc(&zones.info[znum], order)
+ zones.info[znum].base;
mutex_lock(&mem_avail_mtx);
mem_avail_frames -= (1ULL << order);
mutex_unlock(&mem_avail_mtx);
 
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
 
if (pzone)
*pzone = znum;
if (flags & FRAME_KA)
return (void *)PA2KA(PFN2ADDR(v));
return (void *)PFN2ADDR(v);
return (void *) PA2KA(PFN2ADDR(pfn));
return (void *) PFN2ADDR(pfn);
}
 
/** Free a frame.
*
* Find respective frame structure for supplied physical frame address.
* Decrement frame reference count.
* If it drops to zero, move the frame structure to free list.
* Decrement frame reference count. If it drops to zero, move the frame
* structure to free list.
*
* @param frame Physical Address of of the frame to be freed.
* @param frame Physical Address of of the frame to be freed.
*
*/
void frame_free(uintptr_t frame)
{
ipl_t ipl;
zone_t *zone;
pfn_t pfn = ADDR2PFN(frame);
 
ipl = interrupts_disable();
 
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
/*
* First, find host frame zone for addr.
*/
zone = find_zone_and_lock(pfn, NULL);
ASSERT(zone);
pfn_t pfn = ADDR2PFN(frame);
count_t znum = find_zone(pfn, 1, NULL);
zone_frame_free(zone, pfn - zone->base);
ASSERT(znum != (count_t) -1);
spinlock_unlock(&zone->lock);
zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
/*
* Signal that some memory has been freed.
*/
mutex_lock(&mem_avail_mtx);
mem_avail_frames++;
mem_avail_gen++;
condvar_broadcast(&mem_avail_cv);
if (mem_avail_req > 0)
mem_avail_req--;
if (mem_avail_req == 0) {
mem_avail_gen++;
condvar_broadcast(&mem_avail_cv);
}
mutex_unlock(&mem_avail_mtx);
 
interrupts_restore(ipl);
}
 
/** Add reference to frame.
1115,26 → 1108,24
* Find respective frame structure for supplied PFN and
* increment frame reference count.
*
* @param pfn Frame number of the frame to be freed.
* @param pfn Frame number of the frame to be freed.
*
*/
void frame_reference_add(pfn_t pfn)
{
ipl_t ipl;
zone_t *zone;
frame_t *frame;
 
ipl = interrupts_disable();
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
/*
* First, find host frame zone for addr.
*/
zone = find_zone_and_lock(pfn, NULL);
ASSERT(zone);
count_t znum = find_zone(pfn, 1, NULL);
frame = &zone->frames[pfn - zone->base];
frame->refcount++;
ASSERT(znum != (count_t) -1);
spinlock_unlock(&zone->lock);
zones.info[znum].frames[pfn - zones.info[znum].base].refcount++;
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
}
 
1141,18 → 1132,21
/** Mark given range unavailable in frame zones. */
void frame_mark_unavailable(pfn_t start, count_t count)
{
unsigned int i;
zone_t *zone;
unsigned int prefzone = 0;
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
count_t i;
for (i = 0; i < count; i++) {
zone = find_zone_and_lock(start + i, &prefzone);
if (!zone) /* PFN not found */
count_t znum = find_zone(start + i, 1, 0);
if (znum == (count_t) -1) /* PFN not found */
continue;
zone_mark_unavailable(zone, start + i - zone->base);
 
spinlock_unlock(&zone->lock);
zone_mark_unavailable(&zones.info[znum],
start + i - zones.info[znum].base);
}
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
}
 
/** Initialize physical memory management. */
1164,6 → 1158,7
mutex_initialize(&mem_avail_mtx, MUTEX_ACTIVE);
condvar_initialize(&mem_avail_cv);
}
/* Tell the architecture to create some memory */
frame_arch_init();
if (config.cpu_active == 1) {
1178,35 → 1173,28
frame_mark_unavailable(pfn,
SIZE2FRAMES(init.tasks[i].size));
}
 
if (ballocs.size)
frame_mark_unavailable(ADDR2PFN(KA2PA(ballocs.base)),
SIZE2FRAMES(ballocs.size));
 
/* Black list first frame, as allocating NULL would
* fail in some places */
* fail in some places
*/
frame_mark_unavailable(0, 1);
}
}
 
 
/** Return total size of all zones. */
uint64_t zone_total_size(void)
{
zone_t *zone = NULL;
unsigned int i;
ipl_t ipl;
uint64_t total = 0;
 
ipl = interrupts_disable();
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
for (i = 0; i < zones.count; i++) {
zone = zones.info[i];
spinlock_lock(&zone->lock);
total += (uint64_t) FRAMES2SIZE(zone->count);
spinlock_unlock(&zone->lock);
}
uint64_t total = 0;
count_t i;
for (i = 0; i < zones.count; i++)
total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
1217,18 → 1205,14
/** Prints list of zones. */
void zone_print_list(void)
{
zone_t *zone = NULL;
unsigned int i;
ipl_t ipl;
 
#ifdef __32_BITS__
printf("# base address free frames busy frames\n");
printf("-- ------------ ------------ ------------\n");
#ifdef __32_BITS__
printf("# base address frames flags free frames busy frames\n");
printf("-- ------------ ------------ -------- ------------ ------------\n");
#endif
 
#ifdef __64_BITS__
printf("# base address free frames busy frames\n");
printf("-- -------------------- ------------ ------------\n");
printf("# base address frames flags free frames busy frames\n");
printf("-- -------------------- ------------ -------- ------------ ------------\n");
#endif
/*
1241,13 → 1225,10
* we may end up with inaccurate output (e.g. a zone being skipped from
* the listing).
*/
 
for (i = 0; ; i++) {
uintptr_t base;
count_t free_count;
count_t busy_count;
 
ipl = interrupts_disable();
count_t i;
for (i = 0;; i++) {
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
if (i >= zones.count) {
1255,56 → 1236,61
interrupts_restore(ipl);
break;
}
 
zone = zones.info[i];
spinlock_lock(&zone->lock);
 
base = PFN2ADDR(zone->base);
free_count = zone->free_count;
busy_count = zone->busy_count;
 
spinlock_unlock(&zone->lock);
uintptr_t base = PFN2ADDR(zones.info[i].base);
count_t count = zones.info[i].count;
zone_flags_t flags = zones.info[i].flags;
count_t free_count = zones.info[i].free_count;
count_t busy_count = zones.info[i].busy_count;
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
 
bool available = zone_flags_available(flags);
printf("%-2" PRIc, i);
#ifdef __32_BITS__
printf("%-2u %10p %12" PRIc " %12" PRIc "\n", i, base,
free_count, busy_count);
printf(" %10p", base);
#endif
 
#ifdef __64_BITS__
printf("%-2u %18p %12" PRIc " %12" PRIc "\n", i, base,
free_count, busy_count);
printf(" %18p", base);
#endif
printf(" %12" PRIc " %c%c%c ", count,
available ? 'A' : ' ',
(flags & ZONE_RESERVED) ? 'R' : ' ',
(flags & ZONE_FIRMWARE) ? 'F' : ' ');
if (available)
printf("%12" PRIc " %12" PRIc,
free_count, busy_count);
printf("\n");
}
}
 
/** Prints zone details.
*
* @param num Zone base address or zone number.
* @param num Zone base address or zone number.
*
*/
void zone_print_one(unsigned int num)
void zone_print_one(count_t num)
{
zone_t *zone = NULL;
ipl_t ipl;
unsigned int i;
uintptr_t base;
count_t count;
count_t busy_count;
count_t free_count;
 
ipl = interrupts_disable();
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
 
count_t znum = (count_t) -1;
count_t i;
for (i = 0; i < zones.count; i++) {
if ((i == num) || (PFN2ADDR(zones.info[i]->base) == num)) {
zone = zones.info[i];
if ((i == num) || (PFN2ADDR(zones.info[i].base) == num)) {
znum = i;
break;
}
}
if (!zone) {
if (znum == (count_t) -1) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
printf("Zone not found.\n");
1311,24 → 1297,33
return;
}
spinlock_lock(&zone->lock);
base = PFN2ADDR(zone->base);
count = zone->count;
busy_count = zone->busy_count;
free_count = zone->free_count;
spinlock_unlock(&zone->lock);
uintptr_t base = PFN2ADDR(zones.info[i].base);
zone_flags_t flags = zones.info[i].flags;
count_t count = zones.info[i].count;
count_t free_count = zones.info[i].free_count;
count_t busy_count = zones.info[i].busy_count;
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
 
bool available = zone_flags_available(flags);
printf("Zone number: %" PRIc "\n", znum);
printf("Zone base address: %p\n", base);
printf("Zone size: %" PRIc " frames (%" PRIs " KiB)\n", count,
printf("Zone size: %" PRIc " frames (%" PRIs " KiB)\n", count,
SIZE2KB(FRAMES2SIZE(count)));
printf("Allocated space: %" PRIc " frames (%" PRIs " KiB)\n",
busy_count, SIZE2KB(FRAMES2SIZE(busy_count)));
printf("Available space: %" PRIc " frames (%" PRIs " KiB)\n",
free_count, SIZE2KB(FRAMES2SIZE(free_count)));
printf("Zone flags: %c%c%c\n",
available ? 'A' : ' ',
(flags & ZONE_RESERVED) ? 'R' : ' ',
(flags & ZONE_FIRMWARE) ? 'F' : ' ');
if (available) {
printf("Allocated space: %" PRIc " frames (%" PRIs " KiB)\n",
busy_count, SIZE2KB(FRAMES2SIZE(busy_count)));
printf("Available space: %" PRIc " frames (%" PRIs " KiB)\n",
free_count, SIZE2KB(FRAMES2SIZE(free_count)));
}
}
 
/** @}
*/
 
/branches/dynload/kernel/generic/src/syscall/syscall.c
156,6 → 156,7
(syshandler_t) sys_thread_get_id,
(syshandler_t) sys_task_get_id,
(syshandler_t) sys_task_set_name,
(syshandler_t) sys_program_spawn_loader,
/* Synchronization related syscalls. */
/branches/dynload/kernel/generic/src/ipc/irq.c
44,8 → 44,28
* - ARG1: payload modified by a 'top-half' handler
* - ARG2: payload modified by a 'top-half' handler
* - ARG3: payload modified by a 'top-half' handler
* - ARG4: payload modified by a 'top-half' handler
* - ARG5: payload modified by a 'top-half' handler
* - in_phone_hash: interrupt counter (may be needed to assure correct order
* in multithreaded drivers)
*
* Note on synchronization for ipc_irq_register(), ipc_irq_unregister(),
* ipc_irq_cleanup() and IRQ handlers:
*
* By always taking all of the uspace IRQ hash table lock, IRQ structure lock
* and answerbox lock, we can rule out race conditions between the
* registration functions and also the cleanup function. Thus the observer can
* either see the IRQ structure present in both the hash table and the
* answerbox list or absent in both. Views in which the IRQ structure would be
* linked in the hash table but not in the answerbox list, or vice versa, are
* not possible.
*
* By always taking the hash table lock and the IRQ structure lock, we can
* rule out a scenario in which we would free up an IRQ structure, which is
* still referenced by, for example, an IRQ handler. The locking scheme forces
* us to lock the IRQ structure only after any progressing IRQs on that
* structure are finished. Because we hold the hash table lock, we prevent new
* IRQs from taking new references to the IRQ structure.
*/
 
#include <arch.h>
58,66 → 78,8
#include <console/console.h>
#include <print.h>
 
/** Execute code associated with IRQ notification.
/** Free the top-half pseudocode.
*
* @param call Notification call.
* @param code Top-half pseudocode.
*/
static void code_execute(call_t *call, irq_code_t *code)
{
unsigned int i;
unative_t dstval = 0;
if (!code)
return;
for (i = 0; i < code->cmdcount; i++) {
switch (code->cmds[i].cmd) {
case CMD_MEM_READ_1:
dstval = *((uint8_t *) code->cmds[i].addr);
break;
case CMD_MEM_READ_2:
dstval = *((uint16_t *) code->cmds[i].addr);
break;
case CMD_MEM_READ_4:
dstval = *((uint32_t *) code->cmds[i].addr);
break;
case CMD_MEM_READ_8:
dstval = *((uint64_t *) code->cmds[i].addr);
break;
case CMD_MEM_WRITE_1:
*((uint8_t *) code->cmds[i].addr) = code->cmds[i].value;
break;
case CMD_MEM_WRITE_2:
*((uint16_t *) code->cmds[i].addr) =
code->cmds[i].value;
break;
case CMD_MEM_WRITE_4:
*((uint32_t *) code->cmds[i].addr) =
code->cmds[i].value;
break;
case CMD_MEM_WRITE_8:
*((uint64_t *) code->cmds[i].addr) =
code->cmds[i].value;
break;
case CMD_PORT_READ_1:
dstval = pio_read_8((long) code->cmds[i].addr);
break;
case CMD_PORT_WRITE_1:
pio_write_8((long) code->cmds[i].addr, code->cmds[i].value);
break;
default:
break;
}
if (code->cmds[i].dstarg && code->cmds[i].dstarg <
IPC_CALL_LEN) {
call->data.args[code->cmds[i].dstarg] = dstval;
}
}
}
 
/** Free top-half pseudocode.
*
* @param code Pointer to the top-half pseudocode.
*/
static void code_free(irq_code_t *code)
128,7 → 90,7
}
}
 
/** Copy top-half pseudocode from userspace into the kernel.
/** Copy the top-half pseudocode from userspace into the kernel.
*
* @param ucode Userspace address of the top-half pseudocode.
*
164,38 → 126,6
return code;
}
 
/** Unregister task from IRQ notification.
*
* @param box Answerbox associated with the notification.
* @param inr IRQ number.
* @param devno Device number.
*/
void ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno)
{
ipl_t ipl;
irq_t *irq;
 
ipl = interrupts_disable();
irq = irq_find_and_lock(inr, devno);
if (irq) {
if (irq->notif_cfg.answerbox == box) {
code_free(irq->notif_cfg.code);
irq->notif_cfg.notify = false;
irq->notif_cfg.answerbox = NULL;
irq->notif_cfg.code = NULL;
irq->notif_cfg.method = 0;
irq->notif_cfg.counter = 0;
 
spinlock_lock(&box->irq_lock);
list_remove(&irq->notif_cfg.link);
spinlock_unlock(&box->irq_lock);
spinlock_unlock(&irq->lock);
}
}
interrupts_restore(ipl);
}
 
/** Register an answerbox as a receiving end for IRQ notifications.
*
* @param box Receiving answerbox.
212,6 → 142,10
ipl_t ipl;
irq_code_t *code;
irq_t *irq;
unative_t key[] = {
(unative_t) inr,
(unative_t) devno
};
 
if (ucode) {
code = code_from_uspace(ucode);
221,21 → 155,15
code = NULL;
}
 
ipl = interrupts_disable();
irq = irq_find_and_lock(inr, devno);
if (!irq) {
interrupts_restore(ipl);
code_free(code);
return ENOENT;
}
if (irq->notif_cfg.answerbox) {
spinlock_unlock(&irq->lock);
interrupts_restore(ipl);
code_free(code);
return EEXISTS;
}
/*
* Allocate and populate the IRQ structure.
*/
irq = malloc(sizeof(irq_t), 0);
irq_initialize(irq);
irq->devno = devno;
irq->inr = inr;
irq->claim = ipc_irq_top_half_claim;
irq->handler = ipc_irq_top_half_handler;
irq->notif_cfg.notify = true;
irq->notif_cfg.answerbox = box;
irq->notif_cfg.method = method;
242,14 → 170,140
irq->notif_cfg.code = code;
irq->notif_cfg.counter = 0;
 
/*
* Enlist the IRQ structure in the uspace IRQ hash table and the
* answerbox's list.
*/
ipl = interrupts_disable();
spinlock_lock(&irq_uspace_hash_table_lock);
spinlock_lock(&irq->lock);
spinlock_lock(&box->irq_lock);
if (hash_table_find(&irq_uspace_hash_table, key)) {
code_free(code);
spinlock_unlock(&box->irq_lock);
spinlock_unlock(&irq->lock);
spinlock_unlock(&irq_uspace_hash_table_lock);
free(irq);
interrupts_restore(ipl);
return EEXISTS;
}
hash_table_insert(&irq_uspace_hash_table, key, &irq->link);
list_append(&irq->notif_cfg.link, &box->irq_head);
spinlock_unlock(&box->irq_lock);
spinlock_unlock(&irq->lock);
spinlock_unlock(&irq_uspace_hash_table_lock);
 
interrupts_restore(ipl);
return EOK;
}
 
/** Unregister task from IRQ notification.
*
* @param box Answerbox associated with the notification.
* @param inr IRQ number.
* @param devno Device number.
*/
int ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno)
{
ipl_t ipl;
unative_t key[] = {
(unative_t) inr,
(unative_t) devno
};
link_t *lnk;
irq_t *irq;
 
ipl = interrupts_disable();
spinlock_lock(&irq_uspace_hash_table_lock);
lnk = hash_table_find(&irq_uspace_hash_table, key);
if (!lnk) {
spinlock_unlock(&irq_uspace_hash_table_lock);
interrupts_restore(ipl);
return ENOENT;
}
irq = hash_table_get_instance(lnk, irq_t, link);
spinlock_lock(&irq->lock);
spinlock_lock(&box->irq_lock);
ASSERT(irq->notif_cfg.answerbox == box);
/* Free up the pseudo code and associated structures. */
code_free(irq->notif_cfg.code);
 
/* Remove the IRQ from the answerbox's list. */
list_remove(&irq->notif_cfg.link);
 
/* Remove the IRQ from the uspace IRQ hash table. */
hash_table_remove(&irq_uspace_hash_table, key, 2);
spinlock_unlock(&irq_uspace_hash_table_lock);
spinlock_unlock(&irq->lock);
spinlock_unlock(&box->irq_lock);
/* Free up the IRQ structure. */
free(irq);
interrupts_restore(ipl);
return EOK;
}
 
return 0;
 
/** Disconnect all IRQ notifications from an answerbox.
*
* This function is effective because the answerbox contains
* list of all irq_t structures that are registered to
* send notifications to it.
*
* @param box Answerbox for which we want to carry out the cleanup.
*/
void ipc_irq_cleanup(answerbox_t *box)
{
ipl_t ipl;
loop:
ipl = interrupts_disable();
spinlock_lock(&irq_uspace_hash_table_lock);
spinlock_lock(&box->irq_lock);
while (box->irq_head.next != &box->irq_head) {
link_t *cur = box->irq_head.next;
irq_t *irq;
DEADLOCK_PROBE_INIT(p_irqlock);
unative_t key[2];
irq = list_get_instance(cur, irq_t, notif_cfg.link);
if (!spinlock_trylock(&irq->lock)) {
/*
* Avoid deadlock by trying again.
*/
spinlock_unlock(&box->irq_lock);
spinlock_unlock(&irq_uspace_hash_table_lock);
interrupts_restore(ipl);
DEADLOCK_PROBE(p_irqlock, DEADLOCK_THRESHOLD);
goto loop;
}
key[0] = irq->inr;
key[1] = irq->devno;
ASSERT(irq->notif_cfg.answerbox == box);
/* Unlist from the answerbox. */
list_remove(&irq->notif_cfg.link);
/* Remove from the hash table. */
hash_table_remove(&irq_uspace_hash_table, key, 2);
/* Free up the pseudo code and associated structures. */
code_free(irq->notif_cfg.code);
spinlock_unlock(&irq->lock);
free(irq);
}
spinlock_unlock(&box->irq_lock);
spinlock_unlock(&irq_uspace_hash_table_lock);
interrupts_restore(ipl);
}
 
/** Add a call to the proper answerbox queue.
268,125 → 322,158
waitq_wakeup(&irq->notif_cfg.answerbox->wq, WAKEUP_FIRST);
}
 
/** Send notification message.
/** Apply the top-half pseudo code to find out whether to accept the IRQ or not.
*
* @param irq IRQ structure.
* @param a1 Driver-specific payload argument.
* @param a2 Driver-specific payload argument.
* @param a3 Driver-specific payload argument.
* @param a4 Driver-specific payload argument.
* @param a5 Driver-specific payload argument.
*
* @return IRQ_ACCEPT if the interrupt is accepted by the
* pseudocode. IRQ_DECLINE otherwise.
*/
void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2, unative_t a3,
unative_t a4, unative_t a5)
irq_ownership_t ipc_irq_top_half_claim(irq_t *irq)
{
call_t *call;
unsigned int i;
unative_t dstval;
irq_code_t *code = irq->notif_cfg.code;
unative_t *scratch = irq->notif_cfg.scratch;
 
spinlock_lock(&irq->lock);
 
if (irq->notif_cfg.answerbox) {
call = ipc_call_alloc(FRAME_ATOMIC);
if (!call) {
spinlock_unlock(&irq->lock);
return;
if (!irq->notif_cfg.notify)
return IRQ_DECLINE;
if (!code)
return IRQ_DECLINE;
for (i = 0; i < code->cmdcount; i++) {
unsigned int srcarg = code->cmds[i].srcarg;
unsigned int dstarg = code->cmds[i].dstarg;
if (srcarg >= IPC_CALL_LEN)
break;
if (dstarg >= IPC_CALL_LEN)
break;
switch (code->cmds[i].cmd) {
case CMD_PIO_READ_8:
dstval = pio_read_8((ioport8_t *) code->cmds[i].addr);
if (dstarg)
scratch[dstarg] = dstval;
break;
case CMD_PIO_READ_16:
dstval = pio_read_16((ioport16_t *) code->cmds[i].addr);
if (dstarg)
scratch[dstarg] = dstval;
break;
case CMD_PIO_READ_32:
dstval = pio_read_32((ioport32_t *) code->cmds[i].addr);
if (dstarg)
scratch[dstarg] = dstval;
break;
case CMD_PIO_WRITE_8:
pio_write_8((ioport8_t *) code->cmds[i].addr,
(uint8_t) code->cmds[i].value);
break;
case CMD_PIO_WRITE_16:
pio_write_16((ioport16_t *) code->cmds[i].addr,
(uint16_t) code->cmds[i].value);
break;
case CMD_PIO_WRITE_32:
pio_write_32((ioport32_t *) code->cmds[i].addr,
(uint32_t) code->cmds[i].value);
break;
case CMD_BTEST:
if (srcarg && dstarg) {
dstval = scratch[srcarg] & code->cmds[i].value;
scratch[dstarg] = dstval;
}
break;
case CMD_PREDICATE:
if (srcarg && !scratch[srcarg]) {
i += code->cmds[i].value;
continue;
}
break;
case CMD_ACCEPT:
return IRQ_ACCEPT;
break;
case CMD_DECLINE:
default:
return IRQ_DECLINE;
}
call->flags |= IPC_CALL_NOTIF;
IPC_SET_METHOD(call->data, irq->notif_cfg.method);
IPC_SET_ARG1(call->data, a1);
IPC_SET_ARG2(call->data, a2);
IPC_SET_ARG3(call->data, a3);
IPC_SET_ARG4(call->data, a4);
IPC_SET_ARG5(call->data, a5);
/* Put a counter to the message */
call->priv = ++irq->notif_cfg.counter;
send_call(irq, call);
}
spinlock_unlock(&irq->lock);
return IRQ_DECLINE;
}
 
/** Notify a task that an IRQ had occurred.
 
/* IRQ top-half handler.
*
* We expect interrupts to be disabled and the irq->lock already held.
*
* @param irq IRQ structure.
*/
void ipc_irq_send_notif(irq_t *irq)
void ipc_irq_top_half_handler(irq_t *irq)
{
call_t *call;
 
ASSERT(irq);
 
if (irq->notif_cfg.answerbox) {
call_t *call;
 
call = ipc_call_alloc(FRAME_ATOMIC);
if (!call) {
if (!call)
return;
}
call->flags |= IPC_CALL_NOTIF;
/* Put a counter to the message */
call->priv = ++irq->notif_cfg.counter;
 
/* Set up args */
IPC_SET_METHOD(call->data, irq->notif_cfg.method);
IPC_SET_ARG1(call->data, irq->notif_cfg.scratch[1]);
IPC_SET_ARG2(call->data, irq->notif_cfg.scratch[2]);
IPC_SET_ARG3(call->data, irq->notif_cfg.scratch[3]);
IPC_SET_ARG4(call->data, irq->notif_cfg.scratch[4]);
IPC_SET_ARG5(call->data, irq->notif_cfg.scratch[5]);
 
/* Execute code to handle irq */
code_execute(call, irq->notif_cfg.code);
send_call(irq, call);
}
}
 
/** Disconnect all IRQ notifications from an answerbox.
/** Send notification message.
*
* This function is effective because the answerbox contains
* list of all irq_t structures that are registered to
* send notifications to it.
*
* @param box Answerbox for which we want to carry out the cleanup.
* @param irq IRQ structure.
* @param a1 Driver-specific payload argument.
* @param a2 Driver-specific payload argument.
* @param a3 Driver-specific payload argument.
* @param a4 Driver-specific payload argument.
* @param a5 Driver-specific payload argument.
*/
void ipc_irq_cleanup(answerbox_t *box)
void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2, unative_t a3,
unative_t a4, unative_t a5)
{
ipl_t ipl;
loop:
ipl = interrupts_disable();
spinlock_lock(&box->irq_lock);
while (box->irq_head.next != &box->irq_head) {
link_t *cur = box->irq_head.next;
irq_t *irq;
DEADLOCK_PROBE_INIT(p_irqlock);
irq = list_get_instance(cur, irq_t, notif_cfg.link);
if (!spinlock_trylock(&irq->lock)) {
/*
* Avoid deadlock by trying again.
*/
spinlock_unlock(&box->irq_lock);
interrupts_restore(ipl);
DEADLOCK_PROBE(p_irqlock, DEADLOCK_THRESHOLD);
goto loop;
call_t *call;
 
spinlock_lock(&irq->lock);
 
if (irq->notif_cfg.answerbox) {
call = ipc_call_alloc(FRAME_ATOMIC);
if (!call) {
spinlock_unlock(&irq->lock);
return;
}
call->flags |= IPC_CALL_NOTIF;
/* Put a counter to the message */
call->priv = ++irq->notif_cfg.counter;
 
IPC_SET_METHOD(call->data, irq->notif_cfg.method);
IPC_SET_ARG1(call->data, a1);
IPC_SET_ARG2(call->data, a2);
IPC_SET_ARG3(call->data, a3);
IPC_SET_ARG4(call->data, a4);
IPC_SET_ARG5(call->data, a5);
ASSERT(irq->notif_cfg.answerbox == box);
list_remove(&irq->notif_cfg.link);
/*
* Don't forget to free any top-half pseudocode.
*/
code_free(irq->notif_cfg.code);
irq->notif_cfg.notify = false;
irq->notif_cfg.answerbox = NULL;
irq->notif_cfg.code = NULL;
irq->notif_cfg.method = 0;
irq->notif_cfg.counter = 0;
 
spinlock_unlock(&irq->lock);
send_call(irq, call);
}
spinlock_unlock(&box->irq_lock);
interrupts_restore(ipl);
spinlock_unlock(&irq->lock);
}
 
/** @}
/branches/dynload/kernel/arch/sparc64/include/types.h
57,7 → 57,9
typedef uint64_t unative_t;
typedef int64_t native_t;
 
typedef uintptr_t ioport_t;
typedef volatile uint8_t ioport8_t;
typedef volatile uint16_t ioport16_t;
typedef volatile uint32_t ioport32_t;
 
typedef struct {
} fncptr_t;
/branches/dynload/kernel/arch/sparc64/include/asm.h
44,49 → 44,49
#include <arch/stack.h>
#include <arch/barrier.h>
 
static inline void pio_write_8(ioport_t port, uint8_t v)
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
*((volatile uint8_t *)(port)) = v;
*port = v;
memory_barrier();
}
 
static inline void pio_write_16(ioport_t port, uint16_t v)
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
*((volatile uint16_t *)(port)) = v;
*port = v;
memory_barrier();
}
 
static inline void pio_write_32(ioport_t port, uint32_t v)
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
*((volatile uint32_t *)(port)) = v;
*port = v;
memory_barrier();
}
 
static inline uint8_t pio_read_8(ioport_t port)
static inline uint8_t pio_read_8(ioport8_t *port)
{
uint8_t rv;
 
rv = *((volatile uint8_t *)(port));
rv = *port;
memory_barrier();
 
return rv;
}
 
static inline uint16_t pio_read_16(ioport_t port)
static inline uint16_t pio_read_16(ioport16_t *port)
{
uint16_t rv;
 
rv = *((volatile uint16_t *)(port));
rv = *port;
memory_barrier();
 
return rv;
}
 
static inline uint32_t pio_read_32(ioport_t port)
static inline uint32_t pio_read_32(ioport32_t *port)
{
uint32_t rv;
 
rv = *((volatile uint32_t *)(port));
rv = *port;
memory_barrier();
 
return rv;
/branches/dynload/kernel/arch/sparc64/include/mm/frame.h
73,7 → 73,6
typedef union frame_address frame_address_t;
 
extern uintptr_t last_frame;
extern uintptr_t end_frame;
extern void frame_arch_init(void);
#define physmem_print()
 
/branches/dynload/kernel/arch/sparc64/include/drivers/z8530.h
File deleted
/branches/dynload/kernel/arch/sparc64/src/console.c
162,16 → 162,6
scr_redraw();
#endif
switch (kbd_type) {
#ifdef CONFIG_Z8530
case KBD_Z8530:
z8530_grab();
break;
#endif
#ifdef CONFIG_NS16550
case KBD_NS16550:
ns16550_grab();
break;
#endif
#ifdef CONFIG_SGCN
case KBD_SGCN:
sgcn_grab();
188,16 → 178,6
void arch_release_console(void)
{
switch (kbd_type) {
#ifdef CONFIG_Z8530
case KBD_Z8530:
z8530_release();
break;
#endif
#ifdef CONFIG_NS16550
case KBD_NS16550:
ns16550_release();
break;
#endif
#ifdef CONFIG_SGCN
case KBD_SGCN:
sgcn_release();
/branches/dynload/kernel/arch/sparc64/src/mm/frame.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup sparc64mm
/** @addtogroup sparc64mm
* @{
*/
/** @file
41,7 → 41,6
#include <macros.h>
 
uintptr_t last_frame = NULL;
uintptr_t end_frame = NULL;
 
/** Create memory zones according to information stored in bootinfo.
*
80,8 → 79,6
*/
frame_mark_unavailable(ADDR2PFN(KA2PA(PFN2ADDR(0))), 1);
}
end_frame = last_frame;
}
 
/** @}
/branches/dynload/kernel/arch/sparc64/src/mm/page.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup sparc64mm
/** @addtogroup sparc64mm
* @{
*/
/** @file
164,11 → 164,5
return virtaddr;
}
 
void hw_area(uintptr_t *physaddr, pfn_t *frames)
{
*physaddr = end_frame;
*frames = ADDR2PFN(0x7ffffffffff - end_frame);
}
 
/** @}
*/
/branches/dynload/kernel/arch/sparc64/src/drivers/fhc.c
45,6 → 45,7
#include <mm/slab.h>
#include <arch/types.h>
#include <genarch/ofw/ofw_tree.h>
#include <sysinfo/sysinfo.h>
 
fhc_t *central_fhc = NULL;
 
86,6 → 87,13
 
fhc->uart_imap = (uint32_t *) hw_map(paddr, reg->size);
/*
* Set sysinfo data needed by the uspace FHC driver.
*/
sysinfo_set_item_val("fhc.uart.size", NULL, reg->size);
sysinfo_set_item_val("fhc.uart.physical", NULL, paddr);
sysinfo_set_item_val("kbd.cir.fhc", NULL, 1);
 
return fhc;
}
 
/branches/dynload/kernel/arch/sparc64/src/drivers/kbd.c
47,6 → 47,7
#include <align.h>
#include <func.h>
#include <print.h>
#include <sysinfo/sysinfo.h>
 
kbd_type_t kbd_type = KBD_UNKNOWN;
 
65,6 → 66,13
const char *name;
cir_t cir;
void *cir_arg;
 
#ifdef CONFIG_NS16550
ns16550_t *ns16550;
#endif
#ifdef CONFIG_Z8530
z8530_t *z8530;
#endif
name = ofw_tree_node_name(node);
99,6 → 107,7
uintptr_t pa;
size_t size;
devno_t devno;
inr_t inr;
switch (kbd_type) {
131,7 → 140,6
return;
};
break;
default:
panic("Unexpected keyboard type.");
}
148,14 → 156,42
switch (kbd_type) {
#ifdef CONFIG_Z8530
case KBD_Z8530:
z8530_init(device_assign_devno(),
hw_map(aligned_addr, offset + size) + offset, inr, cir, cir_arg);
devno = device_assign_devno();
z8530 = (z8530_t *) hw_map(aligned_addr, offset + size) +
offset;
(void) z8530_init(z8530, devno, inr, cir, cir_arg);
/*
* This is the necessary evil until the userspace drivers are
* entirely self-sufficient.
*/
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.type", NULL, KBD_Z8530);
sysinfo_set_item_val("kbd.devno", NULL, devno);
sysinfo_set_item_val("kbd.inr", NULL, inr);
sysinfo_set_item_val("kbd.address.virtual", NULL,
(uintptr_t) z8530);
sysinfo_set_item_val("kbd.address.physical", NULL, pa);
break;
#endif
#ifdef CONFIG_NS16550
case KBD_NS16550:
ns16550_init(device_assign_devno(),
(ioport_t) (hw_map(aligned_addr, offset + size) + offset), inr, cir, cir_arg);
devno = device_assign_devno();
ns16550 = (ns16550_t *) hw_map(aligned_addr, offset + size) +
offset;
(void) ns16550_init(ns16550, devno, inr, cir, cir_arg);
/*
* This is the necessary evil until the userspace driver is
* entirely self-sufficient.
*/
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550);
sysinfo_set_item_val("kbd.devno", NULL, devno);
sysinfo_set_item_val("kbd.inr", NULL, inr);
sysinfo_set_item_val("kbd.address.virtual", NULL,
(uintptr_t) ns16550);
sysinfo_set_item_val("kbd.address.physical", NULL, pa);
break;
#endif
default:
/branches/dynload/kernel/arch/sparc64/src/drivers/sgcn.c
310,7 → 310,7
/**
* The driver works in polled mode, so no interrupt should be handled by it.
*/
static irq_ownership_t sgcn_claim(void *instance)
static irq_ownership_t sgcn_claim(irq_t *irq)
{
return IRQ_DECLINE;
}
381,13 → 381,7
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;
}
/* XXX: send notification to userspace */
}
spinlock_unlock(&sgcn_irq.lock);
/branches/dynload/kernel/arch/sparc64/src/drivers/pci.c
44,6 → 44,7
#include <print.h>
#include <func.h>
#include <arch/asm.h>
#include <sysinfo/sysinfo.h>
 
#define SABRE_INTERNAL_REG 0
#define PSYCHO_INTERNAL_REG 2
108,6 → 109,12
pci->op = &pci_sabre_ops;
pci->reg = (uint64_t *) hw_map(paddr, reg[SABRE_INTERNAL_REG].size);
 
/*
* Set sysinfo data needed by the uspace OBIO driver.
*/
sysinfo_set_item_val("obio.base.physical", NULL, paddr);
sysinfo_set_item_val("kbd.cir.obio", NULL, 1);
 
return pci;
}
 
149,6 → 156,12
pci->op = &pci_psycho_ops;
pci->reg = (uint64_t *) hw_map(paddr, reg[PSYCHO_INTERNAL_REG].size);
 
/*
* Set sysinfo data needed by the uspace OBIO driver.
*/
sysinfo_set_item_val("obio.base.physical", NULL, paddr);
sysinfo_set_item_val("kbd.cir.obio", NULL, 1);
 
return pci;
}
 
/branches/dynload/kernel/arch/ia64/include/types.h
65,7 → 65,9
typedef uint64_t unative_t;
typedef int64_t native_t;
 
typedef uintptr_t ioport_t;
typedef volatile uint8_t ioport8_t;
typedef volatile uint16_t ioport16_t;
typedef volatile uint32_t ioport32_t;
 
typedef struct {
unative_t fnc;
/branches/dynload/kernel/arch/ia64/include/asm.h
41,52 → 41,64
 
#define IA64_IOSPACE_ADDRESS 0xE001000000000000ULL
 
static inline void pio_write_8(ioport_t port, uint8_t v)
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
uintptr_t prt = (uintptr_t) port;
 
*((uint8_t *)(IA64_IOSPACE_ADDRESS +
((port & 0xfff) | ((port >> 2) << 12)))) = v;
((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
static inline void pio_write_16(ioport_t port, uint16_t v)
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
uintptr_t prt = (uintptr_t) port;
 
*((uint16_t *)(IA64_IOSPACE_ADDRESS +
((port & 0xfff) | ((port >> 2) << 12)))) = v;
((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
static inline void pio_write_32(ioport_t port, uint32_t v)
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
uintptr_t prt = (uintptr_t) port;
 
*((uint32_t *)(IA64_IOSPACE_ADDRESS +
((port & 0xfff) | ((port >> 2) << 12)))) = v;
((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
static inline uint8_t pio_read_8(ioport_t port)
static inline uint8_t pio_read_8(ioport8_t *port)
{
uintptr_t prt = (uintptr_t) port;
 
asm volatile ("mf\n" ::: "memory");
 
return *((uint8_t *)(IA64_IOSPACE_ADDRESS +
((port & 0xfff) | ((port >> 2) << 12))));
((prt & 0xfff) | ((prt >> 2) << 12))));
}
 
static inline uint16_t pio_read_16(ioport_t port)
static inline uint16_t pio_read_16(ioport16_t *port)
{
uintptr_t prt = (uintptr_t) port;
 
asm volatile ("mf\n" ::: "memory");
 
return *((uint16_t *)(IA64_IOSPACE_ADDRESS +
((port & 0xffE) | ((port >> 2) << 12))));
((prt & 0xffE) | ((prt >> 2) << 12))));
}
 
static inline uint32_t pio_read_32(ioport_t port)
static inline uint32_t pio_read_32(ioport32_t *port)
{
uintptr_t prt = (uintptr_t) port;
 
asm volatile ("mf\n" ::: "memory");
 
return *((uint32_t *)(IA64_IOSPACE_ADDRESS +
((port & 0xfff) | ((port >> 2) << 12))));
((prt & 0xfff) | ((prt >> 2) << 12))));
}
 
/** Return base address of current stack
/branches/dynload/kernel/arch/ia64/include/mm/frame.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia64mm
/** @addtogroup ia64mm
* @{
*/
/** @file
35,8 → 35,8
#ifndef KERN_ia64_FRAME_H_
#define KERN_ia64_FRAME_H_
 
#define FRAME_WIDTH 14 /* 16K */
#define FRAME_SIZE (1 << FRAME_WIDTH)
#define FRAME_WIDTH 14 /* 16K */
#define FRAME_SIZE (1 << FRAME_WIDTH)
 
#ifdef KERNEL
#ifndef __ASM__
44,7 → 44,6
#include <arch/types.h>
 
extern uintptr_t last_frame;
extern uintptr_t end_frame;
 
extern void frame_arch_init(void);
#define physmem_print()
/branches/dynload/kernel/arch/ia64/include/mm/tlb.h
35,9 → 35,6
#ifndef KERN_ia64_TLB_H_
#define KERN_ia64_TLB_H_
 
#define tlb_arch_init()
#define tlb_print()
 
#include <arch/mm/page.h>
#include <arch/mm/asid.h>
#include <arch/interrupt.h>
/branches/dynload/kernel/arch/ia64/include/drivers/i8042.h
File deleted
/branches/dynload/kernel/arch/ia64/include/drivers/ega.h
File deleted
/branches/dynload/kernel/arch/ia64/src/smp/smp.c
51,7 → 51,6
#include <syscall/syscall.h>
#include <ddi/irq.h>
#include <ddi/device.h>
#include <arch/drivers/ega.h>
#include <arch/bootinfo.h>
#include <genarch/kbd/i8042.h>
#include <genarch/kbd/ns16550.h>
/branches/dynload/kernel/arch/ia64/src/ia64.c
52,7 → 52,7
#include <ddi/irq.h>
#include <ddi/device.h>
#include <arch/bootinfo.h>
#include <arch/drivers/ega.h>
#include <genarch/drivers/legacy/ia32/io.h>
#include <genarch/drivers/ega/ega.h>
#include <genarch/kbd/i8042.h>
#include <genarch/kbd/ns16550.h>
65,7 → 65,6
 
/* NS16550 as a COM 1 */
#define NS16550_IRQ (4 + LEGACY_INTERRUPT_BASE)
#define NS16550_PORT 0x3f8
 
bootinfo_t *bootinfo;
 
161,14 → 160,22
#endif
 
#ifdef I460GX
devno_t kbd = device_assign_devno();
devno_t devno = device_assign_devno();
inr_t inr;
 
#ifdef CONFIG_NS16550
ns16550_init(kbd, NS16550_PORT, NS16550_IRQ, NULL, NULL);
inr = NS16550_IRQ;
(void) ns16550_init((ns16550_t *)NS16550_BASE, devno, inr, NULL, NULL);
sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550);
sysinfo_set_item_val("kbd.port", NULL, (uintptr_t)NS16550_BASE);
#else
devno_t mouse = device_assign_devno();
i8042_init(kbd, IRQ_KBD, mouse, IRQ_MOUSE);
inr = IRQ_KBD;
(void) i8042_init((i8042_t *)I8042_BASE, devno, inr);
sysinfo_set_item_val("kbd.type", NULL, KBD_LEGACY);
#endif
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.devno", NULL, devno);
sysinfo_set_item_val("kbd.inr", NULL, inr);
#endif
 
sysinfo_set_item_val("ia64_iospace", NULL, true);
222,13 → 229,7
{
#ifdef SKI
ski_kbd_grab();
#else
#ifdef CONFIG_NS16550
ns16550_grab();
#else
i8042_grab();
#endif
#endif
}
 
/** Return console to userspace
238,18 → 239,12
{
#ifdef SKI
ski_kbd_release();
#else
#ifdef CONFIG_NS16550
ns16550_release();
#else
i8042_release();
#endif
#endif
}
 
void arch_reboot(void)
{
pio_write_8(0x64, 0xfe);
pio_write_8((ioport8_t *)0x64, 0xfe);
while (1)
;
}
/branches/dynload/kernel/arch/ia64/src/ski/ski.c
145,7 → 145,7
if (ski_kbd_irq.notif_cfg.notify &&
ski_kbd_irq.notif_cfg.answerbox) {
chardev_push_character(&ski_uconsole, ch);
ipc_irq_send_notif(&ski_kbd_irq);
/* XXX: send notification to userspace */
} else {
chardev_push_character(&ski_console, ch);
}
159,7 → 159,7
if (ski_kbd_irq.notif_cfg.notify &&
ski_kbd_irq.notif_cfg.answerbox) {
chardev_push_character(&ski_uconsole, 0);
ipc_irq_send_notif(&ski_kbd_irq);
/* XXX: send notification to userspace */
}
last = 0;
}
186,7 → 186,7
*
* @return Always IRQ_DECLINE.
*/
static irq_ownership_t ski_kbd_claim(void *instance)
static irq_ownership_t ski_kbd_claim(irq_t *irq)
{
return IRQ_DECLINE;
}
/branches/dynload/kernel/arch/ia64/src/mm/tlb.c
749,5 → 749,13
}
}
 
void tlb_arch_init(void)
{
}
 
void tlb_print(void)
{
}
 
/** @}
*/
/branches/dynload/kernel/arch/ia64/src/mm/frame.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia64mm
/** @addtogroup ia64mm
* @{
*/
/** @file
51,7 → 51,6
#define MINCONF 1
 
uintptr_t last_frame = 0;
uintptr_t end_frame = 0;
 
void frame_arch_init(void)
{
/branches/dynload/kernel/arch/ia64/src/mm/page.c
27,7 → 27,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia64mm
/** @addtogroup ia64mm
* @{
*/
/** @file
63,9 → 63,9
void set_environment(void)
{
region_register rr;
pta_register pta;
pta_register pta;
int i;
#ifdef CONFIG_VHPT
#ifdef CONFIG_VHPT
uintptr_t vhpt_base;
#endif
 
270,15 → 270,9
 
uintptr_t hw_map(uintptr_t physaddr, size_t size __attribute__ ((unused)))
{
/* This is a dirty hack. */
return PA2KA(physaddr);
/* THIS is a dirty hack. */
return (uintptr_t)((uint64_t)(PA2KA(physaddr)) + VIO_OFFSET);
}
 
void hw_area(uintptr_t *physaddr, pfn_t *frames)
{
*physaddr = end_frame;
*frames = ADDR2PFN(0x7fffffffffffffffUL - end_frame);
}
 
/** @}
*/
/branches/dynload/kernel/arch/ia64/src/drivers/it.c
56,8 → 56,8
 
static irq_t it_irq;
 
static irq_ownership_t it_claim(void *);
static void it_interrupt(irq_t *irq);
static irq_ownership_t it_claim(irq_t *);
static void it_interrupt(irq_t *);
 
/** Initialize Interval Timer. */
void it_init(void)
104,7 → 104,7
*
* @return Always IRQ_ACCEPT.
*/
irq_ownership_t it_claim(void *instance)
irq_ownership_t it_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
/branches/dynload/kernel/arch/arm32/include/types.h
64,7 → 64,9
typedef uint32_t unative_t;
typedef int32_t native_t;
 
typedef uintptr_t ioport_t;
typedef volatile uint8_t ioport8_t;
typedef volatile uint16_t ioport16_t;
typedef volatile uint32_t ioport32_t;
 
typedef struct {
} fncptr_t;
/branches/dynload/kernel/arch/arm32/include/machine.h
104,8 → 104,6
 
#ifdef MACHINE_gxemul
#define machine_console_init(devno) gxemul_console_init(devno)
#define machine_grab_console gxemul_grab_console
#define machine_release_console gxemul_release_console
#define machine_hw_map_init gxemul_hw_map_init
#define machine_timer_irq_start gxemul_timer_irq_start
#define machine_cpu_halt gxemul_cpu_halt
/branches/dynload/kernel/arch/arm32/include/asm.h
46,16 → 46,36
{
}
 
static inline void pio_write_8(ioport_t port, uint8_t v)
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
/* XXX */
*port = v;
}
 
static inline uint8_t pio_read_8(ioport_t port)
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
return 0; /* XXX */
*port = v;
}
 
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
*port = v;
}
 
static inline uint8_t pio_read_8(ioport8_t *port)
{
return *port;
}
 
static inline uint16_t pio_read_16(ioport16_t *port)
{
return *port;
}
 
static inline uint32_t pio_read_32(ioport32_t *port)
{
return *port;
}
 
/** Return base address of current stack.
*
* Return the base address of the current stack.
/branches/dynload/kernel/arch/arm32/include/mm/frame.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup arm32mm
/** @addtogroup arm32mm
* @{
*/
/** @file
36,8 → 36,8
#ifndef KERN_arm32_FRAME_H_
#define KERN_arm32_FRAME_H_
 
#define FRAME_WIDTH 12 /* 4KB frames */
#define FRAME_SIZE (1 << FRAME_WIDTH)
#define FRAME_WIDTH 12 /* 4KB frames */
#define FRAME_SIZE (1 << FRAME_WIDTH)
 
#ifdef KERNEL
#ifndef __ASM__
44,14 → 44,13
 
#include <arch/types.h>
 
#define BOOT_PAGE_TABLE_SIZE 0x4000
#define BOOT_PAGE_TABLE_ADDRESS 0x4000
#define BOOT_PAGE_TABLE_SIZE 0x4000
#define BOOT_PAGE_TABLE_ADDRESS 0x4000
 
#define BOOT_PAGE_TABLE_START_FRAME (BOOT_PAGE_TABLE_ADDRESS >> FRAME_WIDTH)
#define BOOT_PAGE_TABLE_SIZE_IN_FRAMES (BOOT_PAGE_TABLE_SIZE >> FRAME_WIDTH)
 
extern uintptr_t last_frame;
extern uintptr_t end_frame;
 
extern void frame_arch_init(void);
extern void boot_page_table_free(void);
/branches/dynload/kernel/arch/arm32/include/mm/tlb.h
36,9 → 36,6
#ifndef KERN_arm32_TLB_H_
#define KERN_arm32_TLB_H_
 
#define tlb_arch_init()
#define tlb_print()
 
#endif
 
/** @}
/branches/dynload/kernel/arch/arm32/src/console.c
50,13 → 50,11
#ifdef CONFIG_FB
fb_redraw();
#endif
machine_grab_console();
}
 
/** Return console to userspace. */
void arch_release_console(void)
{
machine_release_console();
}
 
/** @}
/branches/dynload/kernel/arch/arm32/src/mm/tlb.c
89,5 → 89,13
invalidate_page(page + i * PAGE_SIZE);
}
 
void tlb_arch_init(void)
{
}
 
void tlb_print(void)
{
}
 
/** @}
*/
/branches/dynload/kernel/arch/arm32/src/mm/frame.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup arm32mm
/** @addtogroup arm32mm
* @{
*/
/** @file
41,7 → 41,6
 
/** Address of the last frame in the memory. */
uintptr_t last_frame = 0;
uintptr_t end_frame = 0;
 
/** Creates memory zones. */
void frame_arch_init(void)
50,7 → 49,6
zone_create(0, ADDR2PFN(machine_get_memory_size()),
BOOT_PAGE_TABLE_START_FRAME + BOOT_PAGE_TABLE_SIZE_IN_FRAMES, 0);
last_frame = machine_get_memory_size();
end_frame = last_frame;
/* blacklist boot page table */
frame_mark_unavailable(BOOT_PAGE_TABLE_START_FRAME,
/branches/dynload/kernel/arch/arm32/src/mm/page.c
106,11 → 106,5
return virtaddr;
}
 
void hw_area(uintptr_t *physaddr, pfn_t *frames)
{
*physaddr = end_frame;
*frames = ADDR2PFN(0xffffffff - end_frame);
}
 
/** @}
*/
/branches/dynload/kernel/arch/arm32/src/drivers/gxemul.c
34,7 → 34,6
*/
 
#include <interrupt.h>
#include <ipc/irq.h>
#include <console/chardev.h>
#include <arch/drivers/gxemul.h>
#include <console/console.h>
187,50 → 186,23
*/
static void gxemul_irq_handler(irq_t *irq)
{
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) {
ipc_irq_send_notif(irq);
} else {
char ch = 0;
char ch = 0;
ch = *((char *) gxemul_hw_map.kbd);
if (ch == '\r') {
ch = '\n';
}
if (ch == 0x7f) {
ch = '\b';
}
chardev_push_character(&console, ch);
ch = *((char *) gxemul_hw_map.kbd);
if (ch == '\r') {
ch = '\n';
}
if (ch == 0x7f) {
ch = '\b';
}
chardev_push_character(&console, ch);
}
 
static irq_ownership_t gxemul_claim(void *instance)
static irq_ownership_t gxemul_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
 
 
/** Acquire console back for kernel. */
void gxemul_grab_console(void)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&gxemul_console_irq.lock);
gxemul_console_irq.notif_cfg.notify = false;
spinlock_unlock(&gxemul_console_irq.lock);
interrupts_restore(ipl);
}
 
/** Return console to userspace. */
void gxemul_release_console(void)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&gxemul_console_irq.lock);
if (gxemul_console_irq.notif_cfg.answerbox) {
gxemul_console_irq.notif_cfg.notify = true;
}
spinlock_unlock(&gxemul_console_irq.lock);
interrupts_restore(ipl);
}
 
/** Initializes console object representing gxemul console.
*
* @param devno device number.
265,7 → 237,7
*((uint32_t*) gxemul_hw_map.rtc_freq) = frequency;
}
 
static irq_ownership_t gxemul_timer_claim(void *instance)
static irq_ownership_t gxemul_timer_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
/branches/dynload/kernel/arch/ppc32/include/types.h
57,7 → 57,9
typedef uint32_t unative_t;
typedef int32_t native_t;
 
typedef uintptr_t ioport_t;
typedef volatile uint8_t ioport8_t;
typedef volatile uint16_t ioport16_t;
typedef volatile uint32_t ioport32_t;
 
typedef struct {
} fncptr_t;
/branches/dynload/kernel/arch/ppc32/include/asm.h
149,16 → 149,36
 
extern void userspace_asm(uintptr_t uspace_uarg, uintptr_t stack, uintptr_t entry);
 
static inline void pio_write_8(ioport_t port, uint8_t v)
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
/* XXX */
*port = v;
}
 
static inline uint8_t pio_read_8(ioport_t port)
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
return 0; /* XXX */
*port = v;
}
 
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
*port = v;
}
 
static inline uint8_t pio_read_8(ioport8_t *port)
{
return *port;
}
 
static inline uint16_t pio_read_16(ioport16_t *port)
{
return *port;
}
 
static inline uint32_t pio_read_32(ioport32_t *port)
{
return *port;
}
 
#endif
 
/** @}
/branches/dynload/kernel/arch/ppc32/include/mm/frame.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ppc32mm
/** @addtogroup ppc32mm
* @{
*/
/** @file
35,8 → 35,8
#ifndef KERN_ppc32_FRAME_H_
#define KERN_ppc32_FRAME_H_
 
#define FRAME_WIDTH 12 /* 4K */
#define FRAME_SIZE (1 << FRAME_WIDTH)
#define FRAME_WIDTH 12 /* 4K */
#define FRAME_SIZE (1 << FRAME_WIDTH)
 
#ifdef KERNEL
#ifndef __ASM__
44,7 → 44,6
#include <arch/types.h>
 
extern uintptr_t last_frame;
extern uintptr_t end_frame;
 
extern void frame_arch_init(void);
extern void physmem_print(void);
/branches/dynload/kernel/arch/ppc32/include/drivers/cuda.h
40,8 → 40,6
 
extern void cuda_init(devno_t devno, uintptr_t base, size_t size);
extern int cuda_get_scancode(void);
extern void cuda_grab(void);
extern void cuda_release(void);
 
#endif
 
/branches/dynload/kernel/arch/ppc32/src/ppc32.c
156,7 → 156,6
void arch_grab_console(void)
{
fb_redraw();
cuda_grab();
}
 
/** Return console to userspace
164,7 → 163,6
*/
void arch_release_console(void)
{
cuda_release();
}
 
/** Construct function pointer
/branches/dynload/kernel/arch/ppc32/src/mm/frame.c
40,7 → 40,6
#include <print.h>
 
uintptr_t last_frame = 0;
uintptr_t end_frame = 0;
 
void physmem_print(void)
{
76,8 → 75,6
last_frame = ALIGN_UP(bootinfo.memmap.zones[i].start + bootinfo.memmap.zones[i].size, FRAME_SIZE);
}
end_frame = last_frame;
/* First is exception vector, second is 'implementation specific',
third and fourth is reserved, other contain real mode code */
frame_mark_unavailable(0, 8);
/branches/dynload/kernel/arch/ppc32/src/mm/page.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ppc32mm
/** @addtogroup ppc32mm
* @{
*/
/** @file
63,11 → 63,5
return virtaddr;
}
 
void hw_area(uintptr_t *physaddr, pfn_t *frames)
{
*physaddr = end_frame;
*frames = ADDR2PFN(0xffffffff - end_frame);
}
 
/** @}
*/
/branches/dynload/kernel/arch/ppc32/src/drivers/cuda.c
33,7 → 33,6
*/
 
#include <arch/drivers/cuda.h>
#include <ipc/irq.h>
#include <arch/asm.h>
#include <console/console.h>
#include <console/chardev.h>
251,52 → 250,20
 
static void cuda_irq_handler(irq_t *irq)
{
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox))
ipc_irq_send_notif(irq);
else {
int scan_code = cuda_get_scancode();
int scan_code = cuda_get_scancode();
if (scan_code != -1) {
uint8_t scancode = (uint8_t) scan_code;
if ((scancode & 0x80) != 0x80)
chardev_push_character(&kbrd, lchars[scancode & 0x7f]);
}
if (scan_code != -1) {
uint8_t scancode = (uint8_t) scan_code;
if ((scancode & 0x80) != 0x80)
chardev_push_character(&kbrd, lchars[scancode & 0x7f]);
}
}
 
static irq_ownership_t cuda_claim(void *instance)
static irq_ownership_t cuda_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
 
 
/** Initialize keyboard and service interrupts using kernel routine */
void cuda_grab(void)
{
if (cuda) {
ipl_t ipl = interrupts_disable();
spinlock_lock(&cuda_irq.lock);
cuda_irq.notif_cfg.notify = false;
spinlock_unlock(&cuda_irq.lock);
interrupts_restore(ipl);
}
}
 
 
/** Resume the former interrupt vector */
void cuda_release(void)
{
if (cuda) {
ipl_t ipl = interrupts_disable();
spinlock_lock(&cuda_irq.lock);
if (cuda_irq.notif_cfg.answerbox)
cuda_irq.notif_cfg.notify = true;
spinlock_unlock(&cuda_irq.unlock);
interrupts_restore(ipl);
}
}
 
 
void cuda_init(devno_t devno, uintptr_t base, size_t size)
{
cuda = (uint8_t *) hw_map(base, size);
/branches/dynload/kernel/arch/amd64/include/types.h
57,7 → 57,9
typedef uint64_t unative_t;
typedef int64_t native_t;
 
typedef uintptr_t ioport_t;
typedef volatile uint8_t ioport8_t;
typedef volatile uint16_t ioport16_t;
typedef volatile uint32_t ioport32_t;
 
typedef struct {
} fncptr_t;
/branches/dynload/kernel/arch/amd64/include/asm.h
73,7 → 73,7
* @param port Port to read from
* @return Value read
*/
static inline uint8_t pio_read_8(uint16_t port)
static inline uint8_t pio_read_8(ioport8_t *port)
{
uint8_t val;
 
81,6 → 81,36
return val;
}
 
/** Word from port
*
* Get word from port
*
* @param port Port to read from
* @return Value read
*/
static inline uint16_t pio_read_16(ioport16_t *port)
{
uint16_t val;
asm volatile ("inw %w1, %w0 \n" : "=a" (val) : "d" (port));
return val;
}
 
/** Double word from port
*
* Get double word from port
*
* @param port Port to read from
* @return Value read
*/
static inline uint32_t pio_read_32(ioport32_t *port)
{
uint32_t val;
asm volatile ("inl %w1, %0 \n" : "=a" (val) : "d" (port));
return val;
}
 
/** Byte to port
*
* Output byte to port
88,11 → 118,35
* @param port Port to write to
* @param val Value to write
*/
static inline void pio_write_8(uint16_t port, uint8_t val)
static inline void pio_write_8(ioport8_t *port, uint8_t val)
{
asm volatile ("outb %b0, %w1\n" : : "a" (val), "d" (port));
}
 
/** Word to port
*
* Output word to port
*
* @param port Port to write to
* @param val Value to write
*/
static inline void pio_write_16(ioport16_t *port, uint16_t val)
{
asm volatile ("outw %w0, %w1\n" : : "a" (val), "d" (port));
}
 
/** Double word to port
*
* Output double word to port
*
* @param port Port to write to
* @param val Value to write
*/
static inline void pio_write_32(ioport32_t *port, uint32_t val)
{
asm volatile ("outl %0, %w1\n" : : "a" (val), "d" (port));
}
 
/** Swap Hidden part of GS register with visible one */
static inline void swapgs(void)
{
/branches/dynload/kernel/arch/amd64/include/mm/frame.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup amd64mm
/** @addtogroup amd64mm
* @{
*/
/** @file
39,12 → 39,11
#include <arch/types.h>
#endif /* __ASM__ */
 
#define FRAME_WIDTH 12 /* 4K */
#define FRAME_SIZE (1 << FRAME_WIDTH)
#define FRAME_WIDTH 12 /* 4K */
#define FRAME_SIZE (1 << FRAME_WIDTH)
 
#ifndef __ASM__
extern uintptr_t last_frame;
extern uintptr_t end_frame;
extern void frame_arch_init(void);
extern void physmem_print(void);
#endif /* __ASM__ */
/branches/dynload/kernel/arch/amd64/include/mm/tlb.h
35,9 → 35,6
#ifndef KERN_amd64_TLB_H_
#define KERN_amd64_TLB_H_
 
#define tlb_arch_init()
#define tlb_print()
 
#endif
 
/** @}
/branches/dynload/kernel/arch/amd64/src/amd64.c
39,7 → 39,7
#include <config.h>
 
#include <proc/thread.h>
#include <arch/drivers/ega.h>
#include <genarch/drivers/legacy/ia32/io.h>
#include <genarch/drivers/ega/ega.h>
#include <arch/drivers/vesa.h>
#include <genarch/kbd/i8042.h>
63,6 → 63,7
#include <console/console.h>
#include <ddi/irq.h>
#include <ddi/device.h>
#include <sysinfo/sysinfo.h>
 
 
/** Disable I/O on non-privileged levels
173,8 → 174,17
 
void arch_post_smp_init(void)
{
devno_t devno = device_assign_devno();
/* keyboard controller */
i8042_init(device_assign_devno(), IRQ_KBD, device_assign_devno(), IRQ_MOUSE);
(void) i8042_init((i8042_t *) I8042_BASE, devno, IRQ_KBD);
 
/*
* This is the necessary evil until the userspace driver is entirely
* self-sufficient.
*/
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.devno", NULL, devno);
sysinfo_set_item_val("kbd.inr", NULL, IRQ_KBD);
}
 
void calibrate_delay_loop(void)
214,8 → 224,6
#else
ega_redraw();
#endif
i8042_grab();
}
 
/** Return console to userspace
223,7 → 231,6
*/
void arch_release_console(void)
{
i8042_release();
}
 
/** Construct function pointer
/branches/dynload/kernel/arch/amd64/src/boot/boot.S
223,7 → 223,7
movq %rdx, 16(%rdi)
addl $16, %esi
addq $16, %rdi
addq $48, %rdi
loop mods_loop
/branches/dynload/kernel/arch/amd64/src/mm/page.c
214,11 → 214,5
return virtaddr;
}
 
void hw_area(uintptr_t *physaddr, pfn_t *frames)
{
*physaddr = end_frame;
*frames = ADDR2PFN(0xfffffffffffff - end_frame);
}
 
/** @}
*/
/branches/dynload/kernel/arch/mips32/include/types.h
57,7 → 57,9
typedef uint32_t unative_t;
typedef int32_t native_t;
 
typedef uintptr_t ioport_t;
typedef volatile uint8_t ioport8_t;
typedef volatile uint16_t ioport16_t;
typedef volatile uint32_t ioport32_t;
 
typedef struct {
} fncptr_t;
/branches/dynload/kernel/arch/mips32/include/asm.h
75,16 → 75,36
extern ipl_t interrupts_read(void);
extern void asm_delay_loop(uint32_t t);
 
static inline void pio_write_8(ioport_t port, uint8_t v)
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
/* XXX */
*port = v;
}
 
static inline uint8_t pio_read_8(ioport_t port)
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
return 0; /* XXX */
*port = v;
}
 
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
*port = v;
}
 
static inline uint8_t pio_read_8(ioport8_t *port)
{
return *port;
}
 
static inline uint16_t pio_read_16(ioport16_t *port)
{
return *port;
}
 
static inline uint32_t pio_read_32(ioport32_t *port)
{
return *port;
}
 
#endif
 
/** @}
/branches/dynload/kernel/arch/mips32/include/mm/frame.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup mips32mm
/** @addtogroup mips32mm
* @{
*/
/** @file
46,8 → 46,6
extern void frame_arch_init(void);
extern void physmem_print(void);
 
extern uintptr_t end_frame;
 
#endif /* __ASM__ */
#endif /* KERNEL */
 
/branches/dynload/kernel/arch/mips32/src/mm/frame.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup mips32mm
/** @addtogroup mips32mm
* @{
*/
/** @file
65,9 → 65,7
static count_t phys_regions_count = 0;
static phys_region_t phys_regions[MAX_REGIONS];
 
uintptr_t end_frame = 0;
 
 
/** Check whether frame is available
*
* Returns true if given frame is generally available for use.
220,7 → 218,7
ZERO_PAGE_VALUE = 0xdeadbeef;
if (ZERO_PAGE_VALUE != 0xdeadbeef)
avail = false;
#if defined(lgxemul) || defined(bgxemul)
#if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)
else {
ZERO_PAGE_VALUE_KSEG1(frame) = 0xaabbccdd;
if (ZERO_PAGE_VALUE_KSEG1(frame) != 0xaabbccdd)
238,10 → 236,8
}
}
end_frame = frame;
frame_add_region(start_frame, frame);
frame_add_region(start_frame, end_frame);
/* Blacklist interrupt vector frame */
frame_mark_unavailable(0, 1);
/branches/dynload/kernel/arch/mips32/src/mm/page.c
51,11 → 51,5
return physaddr + 0xa0000000;
}
 
void hw_area(uintptr_t *physaddr, pfn_t *frames)
{
*physaddr = end_frame;
*frames = ADDR2PFN(0xffffffff - end_frame);
}
 
/** @}
*/
/branches/dynload/kernel/arch/mips32/src/interrupt.c
101,7 → 101,7
cp0_compare_write(nextcount);
}
 
static irq_ownership_t timer_claim(void *instance)
static irq_ownership_t timer_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
/branches/dynload/kernel/arch/mips32/src/drivers/serial.c
34,7 → 34,6
 
#include <interrupt.h>
#include <arch/cp0.h>
#include <ipc/irq.h>
#include <arch/drivers/serial.h>
#include <console/chardev.h>
#include <console/console.h>
114,13 → 113,10
/** Process keyboard interrupt. Does not work in simics? */
static void serial_irq_handler(irq_t *irq)
{
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox))
ipc_irq_send_notif(irq);
else
serial_handler();
serial_handler();
}
 
static irq_ownership_t serial_claim(void *instance)
static irq_ownership_t serial_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
/branches/dynload/kernel/arch/mips32/src/drivers/msim.c
33,7 → 33,6
*/
 
#include <interrupt.h>
#include <ipc/irq.h>
#include <console/chardev.h>
#include <arch/drivers/msim.h>
#include <arch/cp0.h>
95,21 → 94,17
/** Process keyboard interrupt. */
static void msim_irq_handler(irq_t *irq)
{
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox))
ipc_irq_send_notif(irq);
else {
char ch = 0;
char ch = 0;
ch = *((char *) MSIM_KBD_ADDRESS);
if (ch =='\r')
ch = '\n';
if (ch == 0x7f)
ch = '\b';
chardev_push_character(&console, ch);
}
ch = *((char *) MSIM_KBD_ADDRESS);
if (ch =='\r')
ch = '\n';
if (ch == 0x7f)
ch = '\b';
chardev_push_character(&console, ch);
}
 
static irq_ownership_t msim_claim(void *instance)
static irq_ownership_t msim_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
/branches/dynload/kernel/arch/ia32/include/types.h
57,7 → 57,9
typedef uint32_t unative_t;
typedef int32_t native_t;
 
typedef uintptr_t ioport_t;
typedef volatile uint8_t ioport8_t;
typedef volatile uint16_t ioport16_t;
typedef volatile uint32_t ioport32_t;
 
typedef struct {
} fncptr_t;
/branches/dynload/kernel/arch/ia32/include/boot/memmap.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/** @file
35,24 → 35,29
#ifndef KERN_ia32_MEMMAP_H_
#define KERN_ia32_MEMMAP_H_
 
/* E820h memory range types - other values*/
/* Free memory */
#define MEMMAP_MEMORY_AVAILABLE 1
/* Not available for OS */
#define MEMMAP_MEMORY_RESERVED 2
/* OS may use it after reading ACPI table */
#define MEMMAP_MEMORY_ACPI 3
/* Unusable, required to be saved and restored across an NVS sleep */
#define MEMMAP_MEMORY_NVS 4
/* Corrupted memory */
#define MEMMAP_MEMORY_UNUSABLE 5
/* E820h memory range types */
 
/* size of one entry */
#define MEMMAP_E820_RECORD_SIZE 20
/* maximum entries */
#define MEMMAP_E820_MAX_RECORDS 32
/* Free memory */
#define MEMMAP_MEMORY_AVAILABLE 1
 
/* Not available for OS */
#define MEMMAP_MEMORY_RESERVED 2
 
/* OS may use it after reading ACPI table */
#define MEMMAP_MEMORY_ACPI 3
 
/* Unusable, required to be saved and restored across an NVS sleep */
#define MEMMAP_MEMORY_NVS 4
 
/* Corrupted memory */
#define MEMMAP_MEMORY_UNUSABLE 5
 
/* Size of one entry */
#define MEMMAP_E820_RECORD_SIZE 20
 
/* Maximum entries */
#define MEMMAP_E820_MAX_RECORDS 32
 
#ifndef __ASM__
 
#include <arch/types.h>
/branches/dynload/kernel/arch/ia32/include/boot/cboot.h
0,0 → 1,91
/*
* Copyright (c) 2005 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
* @{
*/
/** @file
*/
 
#ifndef KERN_ia32_CBOOT_H__
#define KERN_ia32_CBOOT_H_
 
#include <arch/types.h>
#include <arch/boot/memmap.h>
 
/** Multiboot mod structure */
typedef struct {
uintptr_t start;
uintptr_t end;
char *string;
uint32_t reserved;
} __attribute__ ((packed)) mb_mod_t;
 
/** Multiboot mmap structure */
typedef struct {
uint32_t size;
e820memmap_t mm_info;
} __attribute__ ((packed)) mb_mmap_t;
 
/** Multiboot information structure */
typedef struct {
uint32_t flags;
uintptr_t mem_lower;
uintptr_t mem_upper;
 
uint32_t boot_device;
char *cmdline;
 
uint32_t mods_count;
mb_mod_t *mods_addr;
 
uint32_t syms[4];
 
uint32_t mmap_length;
mb_mmap_t *mmap_addr;
 
/* ... */
} __attribute__ ((packed)) mb_info_t;
 
enum mb_info_flags {
MBINFO_FLAGS_MEM = 0x01,
MBINFO_FLAGS_BOOT = 0x02,
MBINFO_FLAGS_CMDLINE = 0x04,
MBINFO_FLAGS_MODS = 0x08,
MBINFO_FLAGS_SYMS1 = 0x10,
MBINFO_FLAGS_SYMS2 = 0x20,
MBINFO_FLAGS_MMAP = 0x40
/* ... */
};
 
extern void ia32_cboot(uint32_t signature, const mb_info_t *mi);
 
#endif
 
/** @}
*/
/branches/dynload/kernel/arch/ia32/include/asm.h
105,9 → 105,9
* @param port Port to write to
* @param val Value to write
*/
static inline void pio_write_8(uint16_t port, uint8_t val)
static inline void pio_write_8(ioport8_t *port, uint8_t val)
{
asm volatile ("outb %b0, %w1\n" : : "a" (val), "d" (port) );
asm volatile ("outb %b0, %w1\n" : : "a" (val), "d" (port));
}
 
/** Word to port
117,9 → 117,9
* @param port Port to write to
* @param val Value to write
*/
static inline void pio_write_16(uint16_t port, uint16_t val)
static inline void pio_write_16(ioport16_t *port, uint16_t val)
{
asm volatile ("outw %w0, %w1\n" : : "a" (val), "d" (port) );
asm volatile ("outw %w0, %w1\n" : : "a" (val), "d" (port));
}
 
/** Double word to port
129,9 → 129,9
* @param port Port to write to
* @param val Value to write
*/
static inline void pio_write_32(uint16_t port, uint32_t val)
static inline void pio_write_32(ioport32_t *port, uint32_t val)
{
asm volatile ("outl %l0, %w1\n" : : "a" (val), "d" (port) );
asm volatile ("outl %0, %w1\n" : : "a" (val), "d" (port));
}
 
/** Byte from port
141,11 → 141,11
* @param port Port to read from
* @return Value read
*/
static inline uint8_t pio_read_8(uint16_t port)
static inline uint8_t pio_read_8(ioport8_t *port)
{
uint8_t val;
asm volatile ("inb %w1, %b0 \n" : "=a" (val) : "d" (port) );
asm volatile ("inb %w1, %b0 \n" : "=a" (val) : "d" (port));
return val;
}
 
156,11 → 156,11
* @param port Port to read from
* @return Value read
*/
static inline uint16_t pio_read_16(uint16_t port)
static inline uint16_t pio_read_16(ioport16_t *port)
{
uint16_t val;
asm volatile ("inw %w1, %w0 \n" : "=a" (val) : "d" (port) );
asm volatile ("inw %w1, %w0 \n" : "=a" (val) : "d" (port));
return val;
}
 
171,11 → 171,11
* @param port Port to read from
* @return Value read
*/
static inline uint32_t pio_read_32(uint16_t port)
static inline uint32_t pio_read_32(ioport32_t *port)
{
uint32_t val;
asm volatile ("inl %w1, %l0 \n" : "=a" (val) : "d" (port) );
asm volatile ("inl %w1, %0 \n" : "=a" (val) : "d" (port));
return val;
}
 
/branches/dynload/kernel/arch/ia32/include/mm/frame.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32mm
/** @addtogroup ia32mm
* @{
*/
/** @file
35,8 → 35,8
#ifndef KERN_ia32_FRAME_H_
#define KERN_ia32_FRAME_H_
 
#define FRAME_WIDTH 12 /* 4K */
#define FRAME_SIZE (1 << FRAME_WIDTH)
#define FRAME_WIDTH 12 /* 4K */
#define FRAME_SIZE (1 << FRAME_WIDTH)
 
#ifdef KERNEL
#ifndef __ASM__
44,7 → 44,6
#include <arch/types.h>
 
extern uintptr_t last_frame;
extern uintptr_t end_frame;
 
extern void frame_arch_init(void);
extern void physmem_print(void);
/branches/dynload/kernel/arch/ia32/include/mm/tlb.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32mm
/** @addtogroup ia32mm
* @{
*/
/** @file
35,9 → 35,6
#ifndef KERN_ia32_TLB_H_
#define KERN_ia32_TLB_H_
 
#define tlb_arch_init()
#define tlb_print()
 
#endif
 
/** @}
/branches/dynload/kernel/arch/ia32/include/drivers/i8042.h
File deleted
/branches/dynload/kernel/arch/ia32/include/drivers/ega.h
File deleted
/branches/dynload/kernel/arch/ia32/include/drivers/i8259.h
38,10 → 38,10
#include <arch/types.h>
#include <arch/interrupt.h>
 
#define PIC_PIC0PORT1 0x20
#define PIC_PIC0PORT2 0x21
#define PIC_PIC1PORT1 0xa0
#define PIC_PIC1PORT2 0xa1
#define PIC_PIC0PORT1 ((ioport8_t *) 0x20)
#define PIC_PIC0PORT2 ((ioport8_t *) 0x21)
#define PIC_PIC1PORT1 ((ioport8_t *) 0xa0)
#define PIC_PIC1PORT2 ((ioport8_t *) 0xa1)
 
#define PIC_NEEDICW4 (1<<0)
#define PIC_ICW1 (1<<4)
/branches/dynload/kernel/arch/ia32/Makefile.inc
45,11 → 45,11
## Accepted CPUs
#
 
ifeq ($(MACHINE),athlon-xp)
ifeq ($(MACHINE),athlon_xp)
CMN2 = -march=athlon-xp
SUNCC_CFLAGS += -xarch=ssea
endif
ifeq ($(MACHINE),athlon-mp)
ifeq ($(MACHINE),athlon_mp)
CMN2 = -march=athlon-mp
SUNCC_CFLAGS += xarch=ssea
endif
99,6 → 99,7
arch/$(KARCH)/src/drivers/i8259.c \
arch/$(KARCH)/src/drivers/vesa.c \
arch/$(KARCH)/src/boot/boot.S \
arch/$(KARCH)/src/boot/cboot.c \
arch/$(KARCH)/src/boot/memmap.c \
arch/$(KARCH)/src/fpu_context.c \
arch/$(KARCH)/src/debugger.c \
/branches/dynload/kernel/arch/ia32/src/ia32.c
38,7 → 38,7
 
#include <arch/pm.h>
 
#include <arch/drivers/ega.h>
#include <genarch/drivers/legacy/ia32/io.h>
#include <genarch/drivers/ega/ega.h>
#include <arch/drivers/vesa.h>
#include <genarch/kbd/i8042.h>
62,6 → 62,7
#include <syscall/syscall.h>
#include <console/console.h>
#include <ddi/device.h>
#include <sysinfo/sysinfo.h>
 
#ifdef CONFIG_SMP
#include <arch/smp/apic.h>
124,10 → 125,17
 
void arch_post_smp_init(void)
{
devno_t kbd = device_assign_devno();
devno_t mouse = device_assign_devno();
devno_t devno = device_assign_devno();
/* keyboard controller */
i8042_init(kbd, IRQ_KBD, mouse, IRQ_MOUSE);
(void) i8042_init((i8042_t *) I8042_BASE, devno, IRQ_KBD);
 
/*
* This is the necessary evil until the userspace driver is entirely
* self-sufficient.
*/
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.devno", NULL, devno);
sysinfo_set_item_val("kbd.inr", NULL, IRQ_KBD);
}
 
void calibrate_delay_loop(void)
165,8 → 173,6
#else
ega_redraw();
#endif
i8042_grab();
}
 
/** Return console to userspace
174,7 → 180,6
*/
void arch_release_console(void)
{
i8042_release();
}
 
/** Construct function pointer
/branches/dynload/kernel/arch/ia32/src/smp/smp.c
122,8 → 122,8
* Save 0xa to address 0xf of the CMOS RAM.
* BIOS will not do the POST after the INIT signal.
*/
pio_write_8(0x70, 0xf);
pio_write_8(0x71, 0xa);
pio_write_8((ioport8_t *)0x70, 0xf);
pio_write_8((ioport8_t *)0x71, 0xa);
 
pic_disable_irqs(0xffff);
apic_init();
154,8 → 154,13
/*
* Prepare new GDT for CPU in question.
*/
/* XXX Flag FRAME_LOW_4_GiB was removed temporarily,
* it needs to be replaced by a generic fuctionality of
* the memory subsystem
*/
gdt_new = (struct descriptor *) malloc(GDT_ITEMS *
sizeof(struct descriptor), FRAME_ATOMIC | FRAME_LOW_4_GiB);
sizeof(struct descriptor), FRAME_ATOMIC);
if (!gdt_new)
panic("Cannot allocate memory for GDT.");
 
/branches/dynload/kernel/arch/ia32/src/smp/apic.c
132,7 → 132,7
#endif
}
 
static irq_ownership_t l_apic_timer_claim(void *instance)
static irq_ownership_t l_apic_timer_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
/branches/dynload/kernel/arch/ia32/src/boot/boot.S
101,117 → 101,16
shr $16, %ebx
mov %bx, KA2PA(vesa_bpp)
#endif
 
call map_kernel # map kernel and turn paging on
movl grub_eax, %eax
movl grub_ebx, %ebx
cmpl $MULTIBOOT_LOADER_MAGIC, %eax # compare GRUB signature
je valid_boot
xorl %ecx, %ecx # no memory map available
movl %ecx, e820counter
jmp invalid_boot
valid_boot:
movl (%ebx), %eax # ebx = physical address of struct multiboot_info
bt $3, %eax # mbi->flags[3] (mods_count, mods_addr valid)
jc mods_valid
xorl %ecx, %ecx
movl %ecx, init
jmp mods_end
mods_valid:
movl 20(%ebx), %ecx # mbi->mods_count
movl %ecx, init
cmpl $0, %ecx
je mods_end
movl 24(%ebx), %esi # mbi->mods_addr
movl $init, %edi
mods_loop:
movl 0(%esi), %edx # mods->mod_start
addl $0x80000000, %edx
movl %edx, 4(%edi)
movl 4(%esi), %edx
subl 0(%esi), %edx # mods->mod_end - mods->mod_start
movl %edx, 8(%edi)
addl $16, %esi
addl $8 , %edi
loop mods_loop
mods_end:
bt $6, %eax # mbi->flags[6] (mmap_length, mmap_addr valid)
jc mmap_valid
xorl %edx, %edx
jmp mmap_invalid
mmap_valid:
movl 44(%ebx), %ecx # mbi->mmap_length
movl 48(%ebx), %esi # mbi->mmap_addr
movl $e820table, %edi
xorl %edx, %edx
mmap_loop:
cmpl $0, %ecx
jle mmap_end
movl 4(%esi), %eax # mmap->base_addr_low
movl %eax, (%edi)
movl 8(%esi), %eax # mmap->base_addr_high
movl %eax, 4(%edi)
movl 12(%esi), %eax # mmap->length_low
movl %eax, 8(%edi)
movl 16(%esi), %eax # mmap->length_high
movl %eax, 12(%edi)
movl 20(%esi), %eax # mmap->type
movl %eax, 16(%edi)
movl (%esi), %eax # mmap->size
addl $0x4, %eax
addl %eax, %esi
subl %eax, %ecx
addl $MEMMAP_E820_RECORD_SIZE, %edi
incl %edx
jmp mmap_loop
mmap_end:
mmap_invalid:
movl %edx, e820counter
invalid_boot:
#ifdef CONFIG_SMP
# copy AP bootstrap routines below 1 MB
movl $BOOT_OFFSET, %esi
movl $AP_BOOT_OFFSET, %edi
movl $_hardcoded_unmapped_size, %ecx
rep movsb
#endif
 
call main_bsp # never returns
# ia32_cboot(grub_eax, grub_ebx)
pushl grub_ebx
pushl grub_eax
call ia32_cboot # Does not return.
 
# Not reached.
 
cli
hlt
 
/branches/dynload/kernel/arch/ia32/src/boot/cboot.c
0,0 → 1,123
/*
* Copyright (c) 2009 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
* @{
*/
/** @file
*/
 
#include <main/main.h>
#include <arch/boot/boot.h>
#include <arch/boot/cboot.h>
#include <arch/boot/memmap.h>
#include <config.h>
#include <memstr.h>
#include <func.h>
 
/* This is a symbol so the type is only dummy. Obtain the value using &. */
extern int _hardcoded_unmapped_size;
 
/** C part of ia32 boot sequence.
* @param signature Should contain the multiboot signature.
* @param mi Pointer to the multiboot information structure.
*/
void ia32_cboot(uint32_t signature, const mb_info_t *mi)
{
uint32_t flags;
mb_mod_t *mods;
uint32_t i;
 
if (signature == MULTIBOOT_LOADER_MAGIC) {
flags = mi->flags;
} else {
/* No multiboot info available. */
flags = 0;
}
 
/* Copy module information. */
 
if ((flags & MBINFO_FLAGS_MODS) != 0) {
init.cnt = mi->mods_count;
mods = mi->mods_addr;
 
for (i = 0; i < init.cnt; i++) {
init.tasks[i].addr = mods[i].start + 0x80000000;
init.tasks[i].size = mods[i].end - mods[i].start;
 
/* Copy command line, if available. */
if (mods[i].string) {
strncpy(init.tasks[i].name, mods[i].string,
CONFIG_TASK_NAME_BUFLEN - 1);
init.tasks[i].name[CONFIG_TASK_NAME_BUFLEN - 1]
= '\0';
} else {
init.tasks[i].name[0] = '\0';
}
}
} else {
init.cnt = 0;
}
 
/* Copy memory map. */
 
int32_t mmap_length;
mb_mmap_t *mme;
uint32_t size;
 
if ((flags & MBINFO_FLAGS_MMAP) != 0) {
mmap_length = mi->mmap_length;
mme = mi->mmap_addr;
e820counter = 0;
 
i = 0;
while (mmap_length > 0) {
e820table[i++] = mme->mm_info;
 
/* Compute address of next structure. */
size = sizeof(mme->size) + mme->size;
mme = ((void *) mme) + size;
mmap_length -= size;
}
 
e820counter = i;
} else {
e820counter = 0;
}
 
#ifdef CONFIG_SMP
/* Copy AP bootstrap routines below 1 MB. */
memcpy((void *) AP_BOOT_OFFSET, (void *) BOOT_OFFSET,
(size_t) &_hardcoded_unmapped_size);
#endif
 
main_bsp();
}
 
/** @}
*/
/branches/dynload/kernel/arch/ia32/src/mm/tlb.c
67,5 → 67,13
invlpg(page + i * PAGE_SIZE);
}
 
void tlb_arch_init(void)
{
}
 
void tlb_print(void)
{
}
 
/** @}
*/
/branches/dynload/kernel/arch/ia32/src/mm/frame.c
50,34 → 50,62
size_t hardcoded_unmapped_kdata_size = 0;
 
uintptr_t last_frame = 0;
uintptr_t end_frame = 0;
 
static void init_e820_memory(pfn_t minconf)
{
unsigned int i;
pfn_t start, conf;
size_t size;
 
for (i = 0; i < e820counter; i++) {
uint64_t base = e820table[i].base_address;
uint64_t size = e820table[i].size;
#ifdef __32_BITS__
/* Ignore physical memory above 4 GB */
if ((base >> 32) != 0)
continue;
/* Clip regions above 4 GB */
if (((base + size) >> 32) != 0)
size = 0xffffffff - base;
#endif
pfn_t pfn;
count_t count;
if (e820table[i].type == MEMMAP_MEMORY_AVAILABLE) {
start = ADDR2PFN(ALIGN_UP(e820table[i].base_address, FRAME_SIZE));
size = SIZE2FRAMES(ALIGN_DOWN(e820table[i].size, FRAME_SIZE));
/* To be safe, make available zone possibly smaller */
pfn = ADDR2PFN(ALIGN_UP(base, FRAME_SIZE));
count = SIZE2FRAMES(ALIGN_DOWN(size, FRAME_SIZE));
if ((minconf < start) || (minconf >= start + size))
conf = start;
pfn_t conf;
if ((minconf < pfn) || (minconf >= pfn + count))
conf = pfn;
else
conf = minconf;
zone_create(start, size, conf, 0);
zone_create(pfn, count, conf, ZONE_AVAILABLE);
if (last_frame < ALIGN_UP(e820table[i].base_address +
e820table[i].size, FRAME_SIZE))
last_frame =
ALIGN_UP(e820table[i].base_address + e820table[i].size, FRAME_SIZE);
// XXX this has to be removed
if (last_frame < ALIGN_UP(base + size, FRAME_SIZE))
last_frame = ALIGN_UP(base + size, FRAME_SIZE);
}
if (e820table[i].type == MEMMAP_MEMORY_RESERVED) {
/* To be safe, make reserved zone possibly larger */
pfn = ADDR2PFN(ALIGN_DOWN(base, FRAME_SIZE));
count = SIZE2FRAMES(ALIGN_UP(size, FRAME_SIZE));
zone_create(pfn, count, 0, ZONE_RESERVED);
}
if (e820table[i].type == MEMMAP_MEMORY_ACPI) {
/* To be safe, make firmware zone possibly larger */
pfn = ADDR2PFN(ALIGN_DOWN(base, (uintptr_t) FRAME_SIZE));
count = SIZE2FRAMES(ALIGN_UP(size, (uintptr_t) FRAME_SIZE));
zone_create(pfn, count, 0, ZONE_FIRMWARE);
}
}
end_frame = last_frame;
}
 
static char *e820names[] = {
/branches/dynload/kernel/arch/ia32/src/mm/page.c
53,7 → 53,7
{
uintptr_t cur;
int flags;
 
if (config.cpu_active == 1) {
page_mapping_operations = &pt_mapping_operations;
66,12 → 66,12
flags |= PAGE_GLOBAL;
page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags);
}
 
exc_register(14, "page_fault", (iroutine) page_fault);
write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
} else
write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
 
paging_on();
}
 
93,12 → 93,6
return virtaddr;
}
 
void hw_area(uintptr_t *physaddr, pfn_t *frames)
{
*physaddr = end_frame;
*frames = ADDR2PFN(0xffffffff - end_frame);
}
 
void page_fault(int n __attribute__((unused)), istate_t *istate)
{
uintptr_t page;
/branches/dynload/kernel/arch/ia32/src/drivers/i8259.c
119,8 → 119,8
 
void pic_eoi(void)
{
pio_write_8(0x20, 0x20);
pio_write_8(0xa0, 0x20);
pio_write_8((ioport8_t *)0x20, 0x20);
pio_write_8((ioport8_t *)0xa0, 0x20);
}
 
void pic_spurious(int n __attribute__((unused)), istate_t *istate __attribute__((unused)))
/branches/dynload/kernel/arch/ia32/src/drivers/i8254.c
53,8 → 53,8
#include <ddi/irq.h>
#include <ddi/device.h>
 
#define CLK_PORT1 0x40
#define CLK_PORT4 0x43
#define CLK_PORT1 ((ioport8_t *)0x40)
#define CLK_PORT4 ((ioport8_t *)0x43)
 
#define CLK_CONST 1193180
#define MAGIC_NUMBER 1194
61,7 → 61,7
 
static irq_t i8254_irq;
 
static irq_ownership_t i8254_claim(void *instance)
static irq_ownership_t i8254_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}