/branches/dynload/kernel/genarch/include/kbd/z8530.h |
---|
37,90 → 37,19 |
#ifndef KERN_Z8530_H_ |
#define KERN_Z8530_H_ |
#include <console/chardev.h> |
#include <ipc/irq.h> |
#include <ddi/irq.h> |
#include <arch/types.h> |
#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 bool z8530_belongs_to_kernel; |
#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_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 *); |
extern void z8530_irq_handler(irq_t *); |
#endif |
/branches/dynload/kernel/genarch/include/kbd/ns16550.h |
---|
37,10 → 37,30 |
#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. */ |
47,31 → 67,67 |
#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 ns16550_instance { |
typedef struct { |
devno_t devno; |
ns16550_t *ns16550; |
irq_t irq; |
} ns16550_instance_t; |
/** Memory mapped registers of the ns16550. */ |
volatile ioport_t io_port; |
} ns16550_t; |
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_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); |
} |
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,25 → 35,15 |
#ifndef KERN_I8042_H_ |
#define KERN_I8042_H_ |
#include <ddi/irq.h> |
#include <arch/types.h> |
#include <typedefs.h> |
#include <console/chardev.h> |
struct i8042 { |
ioport8_t data; |
uint8_t pad[3]; |
ioport8_t status; |
} __attribute__ ((packed)); |
typedef struct i8042 i8042_t; |
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); |
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 |
---|
File deleted |
/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,17 → 37,16 |
#include <arch/types.h> |
#define EGA_COLS 80 |
#define EGA_ROWS 25 |
#define EGA_SCREEN (EGA_COLS * EGA_ROWS) |
#define EGA_VRAM_SIZE (2 * EGA_SCREEN) |
#define ROW 80 |
#define ROWS 25 |
#define SCREEN (ROW * ROWS) |
/* 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(ioport8_t *, uintptr_t); |
extern void ega_init(ioport_t, uintptr_t); |
#endif |
/branches/dynload/kernel/genarch/src/kbd/ns16550.c |
---|
1,5 → 1,5 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* Copyright (c) 2001-2006 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
40,6 → 40,7 |
#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> |
47,11 → 48,17 |
#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. |
*/ |
63,53 → 70,95 |
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. |
*/ |
bool |
ns16550_init(ns16550_t *dev, devno_t devno, inr_t inr, cir_t cir, void *cir_arg) |
void |
ns16550_init(devno_t devno, ioport_t port, inr_t inr, cir_t cir, void *cir_arg) |
{ |
ns16550_instance_t *instance; |
chardev_initialize("ns16550_kbd", &kbrd, &ops); |
stdin = &kbrd; |
instance = malloc(sizeof(ns16550_instance_t), FRAME_ATOMIC); |
if (!instance) |
return false; |
instance->devno = devno; |
instance->ns16550 = dev; |
ns16550.devno = devno; |
ns16550.io_port = port; |
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); |
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); |
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 */ |
pio_write_8(&dev->ier, IER_ERBFI); |
pio_write_8(&dev->mcr, MCR_OUT2); |
ns16550_ier_write(&ns16550, IER_ERBFI); |
ns16550_mcr_write(&ns16550, MCR_OUT2); |
return true; |
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(); |
} |
/** Process ns16550 interrupt. */ |
void ns16550_interrupt(void) |
{ |
ns16550_poll(); |
} |
/* Called from getc(). */ |
void ns16550_resume(chardev_t *d) |
{ |
120,26 → 169,37 |
{ |
} |
irq_ownership_t ns16550_claim(irq_t *irq) |
char ns16550_key_read(chardev_t *d) |
{ |
ns16550_instance_t *ns16550_instance = irq->instance; |
ns16550_t *dev = ns16550_instance->ns16550; |
char ch; |
if (pio_read_8(&dev->lsr) & LSR_DATA_READY) |
return IRQ_ACCEPT; |
else |
return IRQ_DECLINE; |
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; |
} |
void ns16550_irq_handler(irq_t *irq) |
/** Poll for key press and release events. |
* |
* This function can be used to implement keyboard polling. |
*/ |
void ns16550_poll(void) |
{ |
ns16550_instance_t *ns16550_instance = irq->instance; |
ns16550_t *dev = ns16550_instance->ns16550; |
if (pio_read_8(&dev->lsr) & LSR_DATA_READY) { |
while (ns16550_lsr_read(&ns16550) & LSR_DATA_READY) { |
uint8_t x; |
x = pio_read_8(&dev->rbr); |
x = ns16550_rbr_read(&ns16550); |
if (x != IGNORE_CODE) { |
if (x & KEY_RELEASE) |
148,8 → 208,20 |
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) 2009 Jakub Jermar |
* Copyright (c) 2001-2004 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 <genarch/drivers/legacy/ia32/io.h> |
#include <arch/drivers/i8042.h> |
#include <cpu.h> |
#include <arch/asm.h> |
#include <arch.h> |
48,6 → 48,8 |
#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 |
73,8 → 75,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 *); |
82,72 → 84,115 |
static chardev_operations_t ops = { |
.suspend = i8042_suspend, |
.resume = i8042_resume, |
.read = i8042_key_read |
}; |
static irq_ownership_t i8042_claim(irq_t *irq) |
/** Structure for i8042's IRQ. */ |
static irq_t i8042_kbd_irq; |
static irq_t i8042_mouse_irq; |
void i8042_grab(void) |
{ |
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; |
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); |
} |
void i8042_release(void) |
{ |
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); |
} |
static irq_ownership_t i8042_claim(void *instance) |
{ |
return IRQ_ACCEPT; |
} |
static void i8042_irq_handler(irq_t *irq) |
{ |
i8042_instance_t *instance = irq->instance; |
i8042_t *dev = instance->i8042; |
uint8_t data; |
uint8_t status; |
if (irq->notif_cfg.notify && irq->notif_cfg.answerbox) |
ipc_irq_send_notif(irq); |
else { |
uint8_t data; |
uint8_t status; |
if (((status = pio_read_8(&dev->status)) & i8042_BUFFER_FULL_MASK)) { |
data = pio_read_8(&dev->data); |
while (((status = i8042_status_read()) & i8042_BUFFER_FULL_MASK)) { |
data = i8042_data_read(); |
if ((status & i8042_MOUSE_DATA)) |
return; |
if ((status & i8042_MOUSE_DATA)) |
continue; |
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. */ |
bool |
i8042_init(i8042_t *dev, devno_t devno, inr_t inr) |
void i8042_init(devno_t kbd_devno, inr_t kbd_inr, devno_t mouse_devno, inr_t mouse_inr) |
{ |
i8042_instance_t *instance; |
chardev_initialize("i8042_kbd", &kbrd, &ops); |
stdin = &kbrd; |
instance = malloc(sizeof(i8042_instance_t), FRAME_ATOMIC); |
if (!instance) |
return false; |
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->devno = devno; |
instance->i8042 = dev; |
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); |
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 << kbd_inr); |
trap_virtual_enable_irqs(1 << mouse_inr); |
trap_virtual_enable_irqs(1 << inr); |
/* |
* Clear input buffer. |
* Number of iterations is limited to prevent infinite looping. |
*/ |
while (pio_read_8(&dev->status) & i8042_BUFFER_FULL_MASK) |
(void) pio_read_8(&dev->data); |
int i; |
for (i = 0; (i8042_status_read() & i8042_BUFFER_FULL_MASK) && i < 100; i++) { |
i8042_data_read(); |
} |
return true; |
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(); |
} |
/* Called from getc(). */ |
160,5 → 205,40 |
{ |
} |
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) 2009 Jakub Jermar |
* Copyright (c) 2001-2004 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 driver. |
* @brief Zilog 8530 serial port / keyboard driver. |
*/ |
#include <genarch/kbd/z8530.h> |
38,38 → 38,28 |
#include <genarch/kbd/key.h> |
#include <genarch/kbd/scanc.h> |
#include <genarch/kbd/scanc_sun.h> |
#include <arch/drivers/z8530.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 <console/chardev.h> |
#include <ddi/irq.h> |
#include <arch/asm.h> |
#include <mm/slab.h> |
#include <interrupt.h> |
#include <sysinfo/sysinfo.h> |
#include <print.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 *); |
76,54 → 66,86 |
static chardev_operations_t ops = { |
.suspend = z8530_suspend, |
.resume = z8530_resume, |
.read = z8530_key_read |
}; |
/** Initialize z8530. */ |
bool |
z8530_init(z8530_t *dev, devno_t devno, inr_t inr, cir_t cir, void *cir_arg) |
/** Initialize keyboard and service interrupts using kernel routine. */ |
void z8530_grab(void) |
{ |
z8530_instance_t *instance; |
ipl_t ipl = interrupts_disable(); |
chardev_initialize("z8530_kbd", &kbrd, &ops); |
stdin = &kbrd; |
(void) z8530_read_a(&z8530, RR8); |
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(&dev->ctl_a, WR0, WR0_TX_IP_RST); |
z8530_write_a(&z8530, WR0, WR0_TX_IP_RST); |
/* interrupt on all characters */ |
z8530_write(&dev->ctl_a, WR1, WR1_IARCSC); |
z8530_write_a(&z8530, WR1, WR1_IARCSC); |
/* 8 bits per character and enable receiver */ |
z8530_write(&dev->ctl_a, WR3, WR3_RX8BITSCH | WR3_RX_ENABLE); |
z8530_write_a(&z8530, WR3, WR3_RX8BITSCH | WR3_RX_ENABLE); |
/* Master Interrupt Enable. */ |
z8530_write(&dev->ctl_a, WR9, WR9_MIE); |
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); |
} |
return true; |
/** 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); |
} |
/** 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) |
{ |
134,22 → 156,35 |
{ |
} |
irq_ownership_t z8530_claim(irq_t *irq) |
char z8530_key_read(chardev_t *d) |
{ |
z8530_instance_t *instance = irq->instance; |
z8530_t *dev = instance->z8530; |
char ch; |
return (z8530_read(&dev->ctl_a, RR0) & RR0_RCA); |
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; |
} |
void z8530_irq_handler(irq_t *irq) |
/** Poll for key press and release events. |
* |
* This function can be used to implement keyboard polling. |
*/ |
void z8530_poll(void) |
{ |
z8530_instance_t *instance = irq->instance; |
z8530_t *dev = instance->z8530; |
uint8_t x; |
if (z8530_read(&dev->ctl_a, RR0) & RR0_RCA) { |
x = z8530_read(&dev->ctl_a, RR8); |
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); |
159,5 → 194,18 |
} |
} |
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 ioport8_t *ega_base; |
static ioport_t ega_base; |
chardev_t ega_console; |
67,50 → 67,26 |
*/ |
static void ega_check_cursor(void) |
{ |
if (ega_cursor < EGA_SCREEN) |
if (ega_cursor < SCREEN) |
return; |
memmove((void *) videoram, (void *) (videoram + EGA_COLS * 2), |
(EGA_SCREEN - EGA_COLS) * 2); |
memmove((void *) backbuf, (void *) (backbuf + EGA_COLS * 2), |
(EGA_SCREEN - EGA_COLS) * 2); |
memsetw(videoram + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, 0x0720); |
memsetw(backbuf + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, 0x0720); |
ega_cursor = ega_cursor - EGA_COLS; |
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; |
} |
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, 0x0e); |
pio_write_8(ega_base + EGA_INDEX_REG, 0xe); |
pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) ((ega_cursor >> 8) & 0xff)); |
pio_write_8(ega_base + EGA_INDEX_REG, 0x0f); |
pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) (ega_cursor & 0xff)); |
pio_write_8(ega_base + EGA_INDEX_REG, 0xf); |
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; |
128,13 → 104,13 |
switch (ch) { |
case '\n': |
ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS; |
ega_cursor = (ega_cursor + ROW) - ega_cursor % ROW; |
break; |
case '\t': |
ega_cursor = (ega_cursor + 8) - ega_cursor % 8; |
break; |
case '\b': |
if (ega_cursor % EGA_COLS) |
if (ega_cursor % ROW) |
ega_cursor--; |
break; |
default: |
155,20 → 131,21 |
.write = ega_putchar |
}; |
void ega_init(ioport8_t *base, uintptr_t videoram_phys) |
void ega_init(ioport_t base, uintptr_t videoram_phys) |
{ |
/* Initialize the software structure. */ |
/* Initialize the software structure. */ |
ega_base = base; |
backbuf = (uint8_t *) malloc(EGA_VRAM_SIZE, 0); |
backbuf = (uint8_t *) malloc(SCREEN * 2, 0); |
if (!backbuf) |
panic("Unable to allocate backbuffer."); |
videoram = (uint8_t *) hw_map(videoram_phys, EGA_VRAM_SIZE); |
videoram = (uint8_t *) hw_map(videoram_phys, SCREEN * 2); |
/* Synchronize the back buffer and cursor position. */ |
memcpy(backbuf, videoram, EGA_VRAM_SIZE); |
ega_sync_cursor(); |
/* Clear the screen and set the cursor position. */ |
memsetw(videoram, SCREEN, 0x0720); |
memsetw(backbuf, SCREEN, 0x0720); |
ega_move_cursor(); |
chardev_initialize("ega_out", &ega_console, &ega_ops); |
stdout = &ega_console; |
175,8 → 152,8 |
sysinfo_set_item_val("fb", NULL, true); |
sysinfo_set_item_val("fb.kind", NULL, 2); |
sysinfo_set_item_val("fb.width", NULL, EGA_COLS); |
sysinfo_set_item_val("fb.height", NULL, EGA_ROWS); |
sysinfo_set_item_val("fb.width", NULL, ROW); |
sysinfo_set_item_val("fb.height", NULL, ROWS); |
sysinfo_set_item_val("fb.blinking", NULL, true); |
sysinfo_set_item_val("fb.address.physical", NULL, videoram_phys); |
} |
183,9 → 160,8 |
void ega_redraw(void) |
{ |
memcpy(videoram, backbuf, EGA_VRAM_SIZE); |
memcpy(videoram, backbuf, SCREEN * 2); |
ega_move_cursor(); |
ega_show_cursor(); |
} |
/** @} |
/branches/dynload/kernel/generic/include/config.h |
---|
40,14 → 40,11 |
#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,7 → 144,6 |
#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/ddi/irq.h |
---|
36,16 → 36,16 |
#define KERN_IRQ_H_ |
typedef enum { |
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_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_LAST |
} irq_cmd_type; |
52,9 → 52,8 |
typedef struct { |
irq_cmd_type cmd; |
void *addr; |
unsigned long long value; |
unsigned int srcarg; |
unsigned int dstarg; |
unsigned long long value; |
int dstarg; |
} irq_cmd_t; |
typedef struct { |
66,10 → 65,8 |
#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. */ |
99,8 → 96,6 |
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. */ |
144,7 → 139,7 |
/** Trigger level of the IRQ. */ |
irq_trigger_t trigger; |
/** Claim ownership of the IRQ. */ |
irq_ownership_t (* claim)(struct irq *); |
irq_ownership_t (* claim)(void *); |
/** Handler for this IRQ and device. */ |
irq_handler_t handler; |
/** Instance argument for the handler and the claim function. */ |
159,13 → 154,11 |
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/mm/page.h |
---|
61,6 → 61,7 |
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/frame.h |
---|
38,82 → 38,34 |
#include <arch/types.h> |
#include <adt/list.h> |
#include <synch/spinlock.h> |
#include <mm/buddy.h> |
#include <synch/spinlock.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 the system. */ |
#define ZONES_MAX 32 |
/** Maximum number of zones in system. */ |
#define ZONES_MAX 16 |
typedef uint8_t frame_flags_t; |
/** Convert the frame address to kernel VA. */ |
#define FRAME_KA 0x01 |
/** Convert the frame address to kernel va. */ |
#define FRAME_KA 0x1 |
/** Do not panic and do not sleep on failure. */ |
#define FRAME_ATOMIC 0x02 |
#define FRAME_ATOMIC 0x2 |
/** Do not start reclaiming when no free memory. */ |
#define FRAME_NO_RECLAIM 0x04 |
#define FRAME_NO_RECLAIM 0x4 |
/** Do not allocate above 4 GiB. */ |
#define FRAME_LOW_4_GiB 0x8 |
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); |
136,37 → 88,31 |
return (size_t) (frames << FRAME_WIDTH); |
} |
static inline bool zone_flags_available(zone_flags_t flags) |
{ |
return ((flags & (ZONE_RESERVED | ZONE_FIRMWARE)) == 0); |
} |
#define IS_BUDDY_ORDER_OK(index, order) \ |
#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) & 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 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 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, frame_flags_t, count_t *); |
extern void *frame_alloc_generic(uint8_t, int, unsigned int *); |
extern void frame_free(uintptr_t); |
extern void frame_reference_add(pfn_t); |
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 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 void frame_mark_unavailable(pfn_t, count_t); |
extern uintptr_t zone_conf_size(count_t); |
extern bool zone_merge(count_t, count_t); |
extern void zone_merge(unsigned int, unsigned int); |
extern void zone_merge_all(void); |
extern uint64_t zone_total_size(void); |
174,7 → 120,7 |
* Console functions |
*/ |
extern void zone_print_list(void); |
extern void zone_print_one(count_t); |
extern void zone_print_one(unsigned int); |
#endif |
/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(size_t); |
extern size_t buddy_conf_size(int); |
extern link_t *buddy_system_alloc_block(buddy_system_t *, link_t *); |
#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 0x01 |
#define SLAB_RECLAIM_ALL 0x1 |
/* cache_create flags */ |
/branches/dynload/kernel/generic/include/console/console.h |
---|
41,8 → 41,6 |
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/syscall/syscall.h |
---|
44,7 → 44,6 |
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 20 |
#define IRQ_MAX_PROG_SIZE 10 |
#include <ipc/ipc.h> |
#include <ddi/irq.h> |
43,15 → 43,12 |
#include <arch/types.h> |
#include <adt/list.h> |
extern int ipc_irq_register(answerbox_t *, inr_t, devno_t, unative_t, |
irq_code_t *); |
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 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. |
69,8 → 66,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 *, unative_t, unative_t, unative_t, unative_t, |
unative_t); |
extern void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2, |
unative_t a3, unative_t a4, unative_t a5); |
#endif |
/branches/dynload/kernel/generic/include/main/main.h |
---|
35,13 → 35,8 |
#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/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/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/btree.h> |
#include <adt/list.h> |
#include <arch.h> |
#include <align.h> |
#include <errno.h> |
55,13 → 55,17 |
/** This lock protects the parea_btree. */ |
SPINLOCK_INITIALIZE(parea_lock); |
/** B+tree with enabled physical memory areas. */ |
static btree_t parea_btree; |
/** List with enabled physical memory areas. */ |
static LIST_INITIALIZE(parea_head); |
/** Physical memory area for devices. */ |
static parea_t dev_area; |
/** Initialize DDI. */ |
void ddi_init(void) |
{ |
btree_create(&parea_btree); |
hw_area(&dev_area.pbase, &dev_area.frames); |
ddi_parea_register(&dev_area); |
} |
/** Enable piece of physical memory for mapping by physmem_map(). |
68,16 → 72,22 |
* |
* @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 = interrupts_disable(); |
ipl_t ipl; |
ipl = interrupts_disable(); |
spinlock_lock(&parea_lock); |
/* |
* We don't check for overlaps here as the kernel is pretty sane. |
* TODO: we should really check for overlaps here. |
* However, we should be safe because the kernel is pretty sane. |
*/ |
btree_insert(&parea_btree, (btree_key_t) parea->pbase, parea, NULL); |
link_initialize(&parea->link); |
list_append(&parea->link, &parea_head); |
spinlock_unlock(&parea_lock); |
interrupts_restore(ipl); |
85,83 → 95,64 |
/** 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, 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. |
* |
* 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. |
*/ |
static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, count_t pages, int flags) |
static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, pfn_t pages, int flags) |
{ |
ASSERT(TASK); |
ASSERT((pf % FRAME_SIZE) == 0); |
ASSERT((vp % PAGE_SIZE) == 0); |
ipl_t ipl; |
cap_t caps; |
mem_backend_data_t backend_data; |
backend_data.base = pf; |
backend_data.frames = pages; |
/* |
* Make sure the caller is authorised to make this syscall. |
*/ |
cap_t caps = cap_get(TASK); |
caps = cap_get(TASK); |
if (!(caps & CAP_MEM_MANAGER)) |
return EPERM; |
mem_backend_data_t backend_data; |
backend_data.base = pf; |
backend_data.frames = pages; |
ipl = interrupts_disable(); |
ipl_t ipl = interrupts_disable(); |
/* |
* Check if the physical memory area is enabled for mapping. |
*/ |
spinlock_lock(&parea_lock); |
/* Find the zone of the physical memory */ |
spinlock_lock(&zones.lock); |
count_t znum = find_zone(ADDR2PFN(pf), pages, 0); |
bool fnd = false; |
link_t *cur; |
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; |
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 (zones.info[znum].flags & ZONE_FIRMWARE) { |
/* Frames are part of firmware */ |
spinlock_unlock(&zones.lock); |
goto map; |
} |
spinlock_unlock(&parea_lock); |
if (zone_flags_available(zones.info[znum].flags)) { |
/* Frames are part of physical memory, check if the memory |
* region is enabled for mapping. |
if (!fnd) { |
/* |
* Physical memory area cannot be mapped. |
*/ |
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; |
interrupts_restore(ipl); |
return ENOENT; |
} |
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. |
187,24 → 178,28 |
* @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. |
*/ |
cap_t caps = cap_get(TASK); |
caps = cap_get(TASK); |
if (!(caps & CAP_IO_MANAGER)) |
return EPERM; |
ipl_t ipl = interrupts_disable(); |
ipl = interrupts_disable(); |
spinlock_lock(&tasks_lock); |
task_t *task = task_find_by_id(id); |
t = task_find_by_id(id); |
if ((!task) || (!context_check(CONTEXT, task->context))) { |
if ((!t) || (!context_check(CONTEXT, t->context))) { |
/* |
* There is no task with the specified ID |
* or the task belongs to a different security |
214,16 → 209,15 |
interrupts_restore(ipl); |
return ENOENT; |
} |
/* Lock the task and release the lock protecting tasks_btree. */ |
spinlock_lock(&task->lock); |
spinlock_lock(&t->lock); |
spinlock_unlock(&tasks_lock); |
rc = ddi_iospace_enable_arch(t, ioaddr, size); |
int rc = ddi_iospace_enable_arch(task, ioaddr, size); |
spinlock_unlock(&task->lock); |
spinlock_unlock(&t->lock); |
interrupts_restore(ipl); |
return rc; |
} |
235,14 → 229,13 |
* @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), |
(count_t) pages, (int) flags); |
(pfn_t) pages, (int) flags); |
} |
/** Wrapper for SYS_ENABLE_IOSPACE syscall. |
250,15 → 243,16 |
* @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 = copy_from_uspace(&arg, uspace_io_arg, sizeof(ddi_ioarg_t)); |
int rc; |
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); |
} |
266,23 → 260,19 |
/** 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,11 → 69,8 |
#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 |
80,22 → 77,13 |
#define KEY_DEVNO 1 |
/** |
* Spinlock protecting the kernel IRQ hash table. |
* Spinlock protecting the hash table. |
* This lock must be taken only when interrupts are disabled. |
*/ |
SPINLOCK_INITIALIZE(irq_kernel_hash_table_lock); |
/** The kernel IRQ hash table. */ |
static hash_table_t irq_kernel_hash_table; |
SPINLOCK_INITIALIZE(irq_hash_table_lock); |
static hash_table_t irq_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. |
*/ |
123,9 → 111,6 |
.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. |
133,7 → 118,6 |
*/ |
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 |
140,17 → 124,10 |
* 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_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); |
} |
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); |
} |
/** Initialize one IRQ structure. |
160,12 → 137,23 |
*/ |
void irq_initialize(irq_t *irq) |
{ |
memsetb(irq, sizeof(irq_t), 0); |
link_initialize(&irq->link); |
spinlock_initialize(&irq->lock, "irq.lock"); |
link_initialize(&irq->notif_cfg.link); |
irq->preack = false; |
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. |
172,10 → 160,9 |
* |
* The irq structure must be filled with information |
* about the interrupt source and with the claim() |
* function pointer and handler() function pointer. |
* function pointer and irq_handler() function pointer. |
* |
* @param irq IRQ structure belonging to a device. |
* @return True on success, false on failure. |
* @param irq IRQ structure belonging to a device. |
*/ |
void irq_register(irq_t *irq) |
{ |
186,101 → 173,88 |
}; |
ipl = interrupts_disable(); |
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); |
spinlock_lock(&irq_hash_table_lock); |
hash_table_insert(&irq_hash_table, key, &irq->link); |
spinlock_unlock(&irq_hash_table_lock); |
interrupts_restore(ipl); |
} |
/** Search and lock the uspace IRQ hash table. |
/** 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. |
*/ |
static irq_t *irq_dispatch_and_lock_uspace(inr_t inr) |
irq_t *irq_dispatch_and_lock(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_uspace_hash_table_lock); |
lnk = hash_table_find(&irq_uspace_hash_table, key); |
spinlock_lock(&irq_hash_table_lock); |
lnk = hash_table_find(&irq_hash_table, key); |
if (lnk) { |
irq_t *irq; |
irq = hash_table_get_instance(lnk, irq_t, link); |
spinlock_unlock(&irq_uspace_hash_table_lock); |
spinlock_unlock(&irq_hash_table_lock); |
return irq; |
} |
spinlock_unlock(&irq_uspace_hash_table_lock); |
return NULL; |
spinlock_unlock(&irq_hash_table_lock); |
return NULL; |
} |
/** Search and lock the kernel IRQ hash table. |
/** Find the IRQ structure corresponding to inr and devno. |
* |
* 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. |
*/ |
static irq_t *irq_dispatch_and_lock_kernel(inr_t inr) |
irq_t *irq_find_and_lock(inr_t inr, devno_t devno) |
{ |
link_t *lnk; |
unative_t key[] = { |
unative_t keys[] = { |
(unative_t) inr, |
(unative_t) -1 /* search will use claim() instead of devno */ |
(unative_t) devno |
}; |
spinlock_lock(&irq_kernel_hash_table_lock); |
lnk = hash_table_find(&irq_kernel_hash_table, key); |
spinlock_lock(&irq_hash_table_lock); |
lnk = hash_table_find(&irq_hash_table, keys); |
if (lnk) { |
irq_t *irq; |
irq = hash_table_get_instance(lnk, irq_t, link); |
spinlock_unlock(&irq_kernel_hash_table_lock); |
spinlock_unlock(&irq_hash_table_lock); |
return irq; |
} |
spinlock_unlock(&irq_kernel_hash_table_lock); |
return NULL; |
} |
spinlock_unlock(&irq_hash_table_lock); |
/** 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); |
return NULL; |
} |
/** Compute hash index for the key. |
299,7 → 273,7 |
index_t irq_ht_hash(unative_t key[]) |
{ |
inr_t inr = (inr_t) key[KEY_INR]; |
return inr % buckets; |
return inr % irq_hash_table.entries; |
} |
/** Compare hash table element with a key. |
334,7 → 308,7 |
if (devno == -1) { |
/* Invoked by irq_dispatch_and_lock(). */ |
rv = ((irq->inr == inr) && |
(irq->claim(irq) == IRQ_ACCEPT)); |
(irq->claim(irq->instance) == IRQ_ACCEPT)); |
} else { |
/* Invoked by irq_find_and_lock(). */ |
rv = ((irq->inr == inr) && (irq->devno == devno)); |
393,7 → 367,7 |
spinlock_lock(&irq->lock); |
if (devno == -1) { |
/* Invoked by irq_dispatch_and_lock() */ |
rv = (irq->claim(irq) == IRQ_ACCEPT); |
rv = (irq->claim(irq->instance) == 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; |
/** Silence output */ |
bool silent = false; |
/**< Silent output */ |
static 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(irq_t *irq) |
static irq_ownership_t klog_claim(void *instance) |
{ |
return IRQ_DECLINE; |
} |
/branches/dynload/kernel/generic/src/console/cmd.c |
---|
514,31 → 514,23 |
*/ |
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", len, hlp->name, hlp->description); |
printf("%s - %s\n", hlp->name, hlp->description); |
spinlock_unlock(&hlp->lock); |
} |
spinlock_unlock(&cmd_lock); |
return 1; |
} |
956,23 → 948,18 |
*/ |
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("%-*s %s%s\n", len, test->name, test->desc, (test->safe ? "" : " (unsafe)")); |
printf("%-10s %s%s\n", test->name, test->desc, (test->safe ? "" : " (unsafe)")); |
printf("%-*s Run all safe tests\n", len, "*"); |
printf("%-10s Run all safe tests\n", "*"); |
return 1; |
} |
static bool run_test(const test_t *test) |
{ |
printf("%s (%s)\n", test->name, test->desc); |
printf("%s\t\t%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(irq_t *irq) |
static irq_ownership_t kconsole_claim(void *instance) |
{ |
return IRQ_DECLINE; |
} |
/branches/dynload/kernel/generic/src/proc/task.c |
---|
249,35 → 249,6 |
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 |
396,13 → 367,13 |
order(task_get_accounting(t), &cycles, &suffix); |
#ifdef __32_BITS__ |
printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %10p %10p %9" PRIu64 |
printf("%-6" PRIu64 " %-10s %-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 " %-12s %-3" PRIu32 " %18p %18p %9" PRIu64 |
printf("%-6" PRIu64 " %-10s %-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 |
427,16 → 398,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 > TASK_NAME_BUFLEN - 1) |
name_len = TASK_NAME_BUFLEN - 1; |
if (name_len > THREAD_NAME_BUFLEN - 1) |
name_len = THREAD_NAME_BUFLEN - 1; |
rc = copy_from_uspace(namebuf, uspace_name, name_len); |
if (rc != 0) |
/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(size_t max_order) |
size_t buddy_conf_size(int max_order) |
{ |
return sizeof(buddy_system_t) + (max_order + 1) * sizeof(link_t); |
} |
/branches/dynload/kernel/generic/src/mm/frame.c |
---|
1,7 → 1,6 |
/* |
* 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 |
34,7 → 33,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. |
42,6 → 41,16 |
* @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> |
48,6 → 57,7 |
#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> |
59,16 → 69,50 |
#include <macros.h> |
#include <config.h> |
zones_t zones; |
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 { |
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; |
count_t mem_avail_req = 0; /**< Number of frames requested. */ |
count_t mem_avail_gen = 0; /**< Generation counter. */ |
unsigned long mem_avail_frames = 0; /**< Number of available frames. */ |
unsigned long mem_avail_gen = 0; /**< Generation counter. */ |
/********************/ |
/* Helper functions */ |
84,12 → 128,13 |
return (index_t) (frame - zone->frames) + zone->base; |
} |
static inline bool frame_index_valid(zone_t *zone, index_t index) |
static inline int frame_index_valid(zone_t *zone, index_t index) |
{ |
return (index < zone->count); |
} |
static inline index_t make_frame_index(zone_t *zone, frame_t *frame) |
/** Compute pfn_t from frame_t pointer & zone pointer */ |
static index_t make_frame_index(zone_t *zone, frame_t *frame) |
{ |
return (frame - zone->frames); |
} |
96,8 → 141,7 |
/** Initialize frame structure. |
* |
* @param frame Frame structure to be initialized. |
* |
* @param frame Frame structure to be initialized. |
*/ |
static void frame_initialize(frame_t *frame) |
{ |
105,143 → 149,153 |
frame->buddy_order = 0; |
} |
/*******************/ |
/* Zones functions */ |
/*******************/ |
/**********************/ |
/* Zoneinfo functions */ |
/**********************/ |
/** Insert-sort zone into zones list. |
* |
* 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. |
* |
* @param newzone New zone to be inserted into zone list. |
* @return Zone number on success, -1 on error. |
*/ |
static count_t zones_insert_zone(pfn_t base, count_t count) |
static int zones_add_zone(zone_t *newzone) |
{ |
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); |
return (count_t) -1; |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
return -1; |
} |
count_t i; |
for (i = 0; i < zones.count; i++) { |
/* Check for overlap */ |
if (overlaps(base, count, |
zones.info[i].base, zones.info[i].count)) { |
/* Check for overflow */ |
z = zones.info[i]; |
if (overlaps(newzone->base, newzone->count, z->base, |
z->count)) { |
printf("Zones overlap!\n"); |
return (count_t) -1; |
return -1; |
} |
if (base < zones.info[i].base) |
if (newzone->base < z->base) |
break; |
} |
/* Move other zones up */ |
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]; |
} |
for (j = i; j < zones.count; j++) |
zones.info[j + 1] = zones.info[j]; |
zones.info[i] = newzone; |
zones.count++; |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
return i; |
} |
/** Get total available frames. |
/** Try to find a zone where can we find the frame. |
* |
* Assume interrupts are disabled and zones lock is |
* locked. |
* Assume interrupts are disabled. |
* |
* @return Total number of available frames. |
* |
* @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. |
*/ |
static count_t total_frames_free(void) |
static zone_t *find_zone_and_lock(pfn_t frame, unsigned int *pzone) |
{ |
count_t total = 0; |
count_t i; |
for (i = 0; i < zones.count; i++) |
total += zones.info[i].free_count; |
unsigned int i; |
unsigned int hint = pzone ? *pzone : 0; |
zone_t *z; |
return total; |
} |
spinlock_lock(&zones.lock); |
/** 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; |
count_t i = hint; |
i = hint; |
do { |
if ((zones.info[i].base <= frame) |
&& (zones.info[i].base + zones.info[i].count >= frame + count)) |
return i; |
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); |
i++; |
if (i >= zones.count) |
i = 0; |
} while (i != hint); |
return (count_t) -1; |
spinlock_unlock(&zones.lock); |
return NULL; |
} |
/** @return True if zone can allocate specified order */ |
static bool zone_can_alloc(zone_t *zone, uint8_t order) |
static int zone_can_alloc(zone_t *z, uint8_t order) |
{ |
return (zone_flags_available(zone->flags) |
&& buddy_system_can_alloc(zone->buddy_system, order)); |
return buddy_system_can_alloc(z->buddy_system, order); |
} |
/** Find a zone that can allocate order frames. |
/** Find and lock zone that can allocate order frames. |
* |
* Assume interrupts are disabled and zones lock is |
* locked. |
* Assume interrupts are disabled. |
* |
* @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. |
* |
* @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. |
*/ |
static count_t find_free_zone(uint8_t order, zone_flags_t flags, count_t hint) |
static zone_t * |
find_free_zone_and_lock(uint8_t order, int flags, unsigned int *pzone) |
{ |
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; |
count_t i = hint; |
i = hint; |
do { |
z = zones.info[i]; |
spinlock_lock(&z->lock); |
/* |
* Check whether the zone meets the search criteria. |
*/ |
if ((zones.info[i].flags & flags) == flags) { |
if ((z->flags & flags) == flags) { |
/* |
* Check if the zone has 2^order frames area available. |
*/ |
if (zone_can_alloc(&zones.info[i], order)) |
return i; |
if (zone_can_alloc(z, order)) { |
spinlock_unlock(&zones.lock); |
if (pzone) |
*pzone = i; |
return z; |
} |
} |
i++; |
if (i >= zones.count) |
spinlock_unlock(&z->lock); |
if (++i >= zones.count) |
i = 0; |
} while (i != hint); |
return (count_t) -1; |
spinlock_unlock(&zones.lock); |
return NULL; |
} |
/**************************/ |
253,76 → 307,82 |
* 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 *buddy, link_t *child, |
static link_t *zone_buddy_find_block(buddy_system_t *b, link_t *child, |
uint8_t order) |
{ |
frame_t *frame = list_get_instance(child, frame_t, buddy_link); |
zone_t *zone = (zone_t *) buddy->data; |
frame_t *frame; |
zone_t *zone; |
index_t index; |
index_t index = frame_index(zone, frame); |
frame = list_get_instance(child, frame_t, buddy_link); |
zone = (zone_t *) b->data; |
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 buddy Buddy system. |
* @param block Block for which buddy should be found. |
* @param b 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 *buddy, link_t *block) |
static link_t *zone_buddy_find_buddy(buddy_system_t *b, link_t *block) |
{ |
frame_t *frame = list_get_instance(block, frame_t, buddy_link); |
zone_t *zone = (zone_t *) buddy->data; |
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; |
ASSERT(IS_BUDDY_ORDER_OK(frame_index_abs(zone, frame), |
frame->buddy_order)); |
bool is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame); |
bool is_right = IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame); |
is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame); |
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 buddy Buddy system. |
* @param block Block to bisect. |
* @param b Buddy system. |
* @param block Block to bisect. |
* |
* @return Right block. |
* |
* @return Right block. |
*/ |
static link_t *zone_buddy_bisect(buddy_system_t *buddy, link_t *block) |
static link_t *zone_buddy_bisect(buddy_system_t *b, link_t *block) |
{ |
frame_t *frame_l = list_get_instance(block, frame_t, buddy_link); |
frame_t *frame_r = (frame_l + (1 << (frame_l->buddy_order - 1))); |
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))); |
return &frame_r->buddy_link; |
} |
329,68 → 389,75 |
/** Buddy system coalesce implementation. |
* |
* @param buddy Buddy system. |
* @param block_1 First block. |
* @param block_2 First block's buddy. |
* @param b 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 *buddy, link_t *block_1, |
link_t *block_2) |
static link_t *zone_buddy_coalesce(buddy_system_t *b, link_t *block_1, |
link_t *block_2) |
{ |
frame_t *frame1 = list_get_instance(block_1, frame_t, buddy_link); |
frame_t *frame2 = list_get_instance(block_2, frame_t, buddy_link); |
frame_t *frame1, *frame2; |
return ((frame1 < frame2) ? block_1 : block_2); |
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; |
} |
/** Buddy system set_order implementation. |
* |
* @param buddy Buddy system. |
* @param block Buddy system block. |
* @param order Order to set. |
* |
* @param b Buddy system. |
* @param block Buddy system block. |
* @param order Order to set. |
*/ |
static void zone_buddy_set_order(buddy_system_t *buddy, link_t *block, |
static void zone_buddy_set_order(buddy_system_t *b, link_t *block, |
uint8_t order) |
{ |
list_get_instance(block, frame_t, buddy_link)->buddy_order = order; |
frame_t *frame; |
frame = list_get_instance(block, frame_t, buddy_link); |
frame->buddy_order = order; |
} |
/** Buddy system get_order implementation. |
* |
* @param buddy Buddy system. |
* @param block Buddy system block. |
* @param b 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 *buddy, link_t *block) |
static uint8_t zone_buddy_get_order(buddy_system_t *b, link_t *block) |
{ |
return list_get_instance(block, frame_t, buddy_link)->buddy_order; |
frame_t *frame; |
frame = list_get_instance(block, frame_t, buddy_link); |
return frame->buddy_order; |
} |
/** Buddy system mark_busy implementation. |
* |
* @param buddy Buddy system. |
* @param block Buddy system block. |
* |
* @param b Buddy system. |
* @param block Buddy system block. |
*/ |
static void zone_buddy_mark_busy(buddy_system_t *buddy, link_t * block) |
static void zone_buddy_mark_busy(buddy_system_t *b, link_t * block) |
{ |
list_get_instance(block, frame_t, buddy_link)->refcount = 1; |
frame_t * frame; |
frame = list_get_instance(block, frame_t, buddy_link); |
frame->refcount = 1; |
} |
/** Buddy system mark_available implementation. |
* |
* @param buddy Buddy system. |
* @param block Buddy system block. |
* @param b Buddy system. |
* @param block Buddy system block. |
*/ |
static void zone_buddy_mark_available(buddy_system_t *buddy, link_t *block) |
static void zone_buddy_mark_available(buddy_system_t *b, link_t *block) |
{ |
list_get_instance(block, frame_t, buddy_link)->refcount = 0; |
frame_t *frame; |
frame = list_get_instance(block, frame_t, buddy_link); |
frame->refcount = 0; |
} |
static buddy_system_operations_t zone_buddy_system_operations = { |
410,57 → 477,60 |
/** Allocate frame in particular zone. |
* |
* Assume zone is locked and is available for allocation. |
* Assume zone is locked. |
* 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) |
{ |
ASSERT(zone_flags_available(zone->flags)); |
pfn_t v; |
link_t *tmp; |
frame_t *frame; |
/* Allocate frames from zone buddy system */ |
link_t *link = buddy_system_alloc(zone->buddy_system, order); |
tmp = buddy_system_alloc(zone->buddy_system, order); |
ASSERT(link); |
ASSERT(tmp); |
/* Update zone information. */ |
zone->free_count -= (1 << order); |
zone->busy_count += (1 << order); |
/* Frame will be actually a first frame of the block. */ |
frame_t *frame = list_get_instance(link, frame_t, buddy_link); |
frame = list_get_instance(tmp, frame_t, buddy_link); |
/* Get frame address */ |
return make_frame_index(zone, frame); |
/* get frame address */ |
v = make_frame_index(zone, frame); |
return v; |
} |
/** Free frame from zone. |
* |
* Assume zone is locked and is available for deallocation. |
* Assume zone is locked. |
* |
* @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) |
{ |
ASSERT(zone_flags_available(zone->flags)); |
frame_t *frame; |
uint8_t order; |
frame = &zone->frames[frame_idx]; |
frame_t *frame = &zone->frames[frame_idx]; |
/* Remember frame order */ |
uint8_t order = frame->buddy_order; |
/* remember frame order */ |
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); |
477,630 → 547,567 |
/** Mark frame in zone unavailable to allocation. */ |
static void zone_mark_unavailable(zone_t *zone, index_t frame_idx) |
{ |
ASSERT(zone_flags_available(zone->flags)); |
frame_t *frame = zone_get_frame(zone, frame_idx); |
frame_t *frame; |
link_t *link; |
frame = zone_get_frame(zone, frame_idx); |
if (frame->refcount) |
return; |
link_t *link = buddy_system_alloc_block(zone->buddy_system, |
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); |
} |
/** Merge two zones. |
/** Join two zones. |
* |
* Expect buddy to point to space at least zone_conf_size large. |
* Assume z1 & z2 are locked and compatible and zones lock is |
* locked. |
* Expect zone_t *z to point to space at least zone_conf_size large. |
* |
* @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. |
* Assume z1 & z2 are locked. |
* |
* @param z Target zone structure pointer. |
* @param z1 Zone to merge. |
* @param z2 Zone to merge. |
*/ |
static void zone_merge_internal(count_t z1, count_t z2, zone_t *old_z1, buddy_system_t *buddy) |
static void _zone_merge(zone_t *z, zone_t *z1, zone_t *z2) |
{ |
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)); |
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; |
/* 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]); |
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]); |
} |
/* 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, clearing |
* 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, clear |
* 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 < 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]; |
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]; |
} |
i = 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; |
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; |
i++; |
} |
} |
/* 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]; |
/* 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]; |
frame->refcount = 0; |
buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link); |
buddy_system_free(z->buddy_system, &frame->buddy_link); |
} |
/* 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]; |
while (zone_can_alloc(z2, 0)) { |
frame_idx = zone_frame_alloc(z2, 0); |
frame = &z->frames[frame_idx + (z2->base - z1->base)]; |
frame->refcount = 0; |
buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link); |
buddy_system_free(z->buddy_system, &frame->buddy_link); |
} |
} |
/** Return old configuration frames into the zone. |
* |
* 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 |
* 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 |
* |
* @param znum The actual zone where freeing should occur. |
* @param pfn Old zone configuration frame. |
* @param count Old zone frame count. |
* |
* @param newzone The actual zone where freeing should occur. |
* @param oldzone Pointer to old zone configuration data that should |
* be freed from new zone. |
*/ |
static void return_config_frames(count_t znum, pfn_t pfn, count_t count) |
static void return_config_frames(zone_t *newzone, zone_t *oldzone) |
{ |
ASSERT(zone_flags_available(zones.info[znum].flags)); |
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)); |
count_t cframes = SIZE2FRAMES(zone_conf_size(count)); |
if ((pfn < zones.info[znum].base) |
|| (pfn >= zones.info[znum].base + zones.info[znum].count)) |
if (pfn < newzone->base || pfn >= newzone->base + newzone->count) |
return; |
frame_t *frame |
= &zones.info[znum].frames[pfn - zones.info[znum].base]; |
frame = &newzone->frames[pfn - newzone->base]; |
ASSERT(!frame->buddy_order); |
count_t i; |
for (i = 0; i < cframes; i++) { |
zones.info[znum].busy_count++; |
zone_frame_free(&zones.info[znum], |
pfn - zones.info[znum].base + i); |
newzone->busy_count++; |
zone_frame_free(newzone, pfn+i-newzone->base); |
} |
} |
/** Reduce allocated block to count of order 0 frames. |
* |
* 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, |
* 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, |
* you have to free every frame. |
* |
* @param znum Zone. |
* @param frame_idx Index the first frame of the block. |
* @param count Allocated frames in block. |
* |
* @param zone |
* @param frame_idx Index to block. |
* @param count Allocated space in block. |
*/ |
static void zone_reduce_region(count_t znum, pfn_t frame_idx, count_t count) |
static void zone_reduce_region(zone_t *zone, pfn_t frame_idx, count_t count) |
{ |
ASSERT(zone_flags_available(zones.info[znum].flags)); |
ASSERT(frame_idx + count < zones.info[znum].count); |
count_t i; |
uint8_t order; |
frame_t *frame; |
uint8_t order = zones.info[znum].frames[frame_idx].buddy_order; |
ASSERT(frame_idx + count < zone->count); |
order = zone->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_t *frame = &zones.info[znum].frames[i + frame_idx]; |
frame = &zone->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(&zones.info[znum], i + frame_idx); |
for (i = count; i < (count_t) (1 << order); i++) { |
zone_frame_free(zone, i + frame_idx); |
} |
} |
/** Merge zones z1 and z2. |
* |
* 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. |
* - the zones must be 2 zones with no zone existing in between, |
* which means that z2 = z1+1 |
* |
* 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 |
* |
* - 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 :-/ |
*/ |
bool zone_merge(count_t z1, count_t z2) |
void zone_merge(unsigned int z1, unsigned int z2) |
{ |
ipl_t ipl = interrupts_disable(); |
ipl_t ipl; |
zone_t *zone1, *zone2, *newzone; |
unsigned int cframes; |
uint8_t order; |
unsigned int i; |
pfn_t pfn; |
ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
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; |
if ((z1 >= zones.count) || (z2 >= zones.count)) |
goto errout; |
} |
pfn_t cframes = SIZE2FRAMES(zone_conf_size( |
zones.info[z2].base - zones.info[z1].base |
+ zones.info[z2].count)); |
uint8_t order; |
/* 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)); |
if (cframes == 1) |
order = 0; |
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 |
order = fnzb(cframes - 1) + 1; |
/* 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); |
goto errout2; |
newzone = (zone_t *) PA2KA(PFN2ADDR(pfn)); |
_zone_merge(newzone, zone1, zone2); |
/* Free unneeded config frames */ |
zone_reduce_region(z1, pfn - zones.info[z1].base, cframes); |
zone_reduce_region(newzone, pfn - newzone->base, cframes); |
/* Subtract zone information from busy frames */ |
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++) { |
newzone->busy_count -= cframes; |
/* Replace existing zones in zoneinfo list */ |
zones.info[z1] = newzone; |
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 mergeable zones into one big zone. |
/** Merge all zones into one big zone. |
* |
* It is reasonable to do this on systems where |
* BIOS reports parts in chunks, so that we could |
* have 1 zone (it's faster). |
* |
* It is reasonable to do this on systems whose bios reports parts in chunks, |
* so that we could have 1 zone (it's faster). |
*/ |
void zone_merge_all(void) |
{ |
count_t i = 0; |
while (i < zones.count) { |
if (!zone_merge(i, i + 1)) |
i++; |
int count = zones.count; |
while (zones.count > 1 && --count) { |
zone_merge(0, 1); |
break; |
} |
} |
/** Create new frame zone. |
* |
* @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. |
* @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. |
* |
* @return Initialized zone. |
* |
* @return Initialized zone. |
*/ |
static void zone_construct(zone_t *zone, buddy_system_t *buddy, pfn_t start, count_t count, zone_flags_t flags) |
static void zone_construct(pfn_t start, count_t count, zone_t *z, int flags) |
{ |
zone->base = start; |
zone->count = count; |
zone->flags = flags; |
zone->free_count = count; |
zone->busy_count = 0; |
zone->buddy_system = buddy; |
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]; |
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; |
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); |
} |
} |
/** 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) |
{ |
return (count * sizeof(frame_t) + buddy_conf_size(fnzb(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; |
} |
/** 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. |
*/ |
count_t zone_create(pfn_t start, count_t count, pfn_t confframe, zone_flags_t flags) |
int zone_create(pfn_t start, count_t count, pfn_t confframe, int flags) |
{ |
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); |
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++) |
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++) |
if (overlaps(addr, PFN2ADDR(confcount), |
KA2PA(init.tasks[i].addr), |
init.tasks[i].size)) { |
overlap = true; |
break; |
} |
if (overlap) |
continue; |
break; |
} |
KA2PA(init.tasks[i].addr), |
init.tasks[i].size)) { |
overlap = true; |
break; |
} |
if (overlap) |
continue; |
if (confframe >= start + count) |
panic("Cannot find configuration data for zone."); |
break; |
} |
count_t znum = zones_insert_zone(start, count); |
if (znum == (count_t) -1) { |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
return (count_t) -1; |
if (confframe >= start + count) |
panic("Cannot find configuration data for zone."); |
} |
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); |
} |
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; |
} |
/* 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, count_t hint) |
void frame_set_parent(pfn_t pfn, void *data, unsigned int hint) |
{ |
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); |
zone_t *zone = find_zone_and_lock(pfn, &hint); |
ASSERT(zone); |
zone_get_frame(zone, pfn - zone->base)->parent = data; |
spinlock_unlock(&zone->lock); |
} |
void *frame_get_parent(pfn_t pfn, count_t hint) |
void *frame_get_parent(pfn_t pfn, unsigned int hint) |
{ |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
zone_t *zone = find_zone_and_lock(pfn, &hint); |
void *res; |
ASSERT(zone); |
res = zone_get_frame(zone, pfn - zone->base)->parent; |
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); |
spinlock_unlock(&zone->lock); |
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, frame_flags_t flags, count_t *pzone) |
void *frame_alloc_generic(uint8_t order, int flags, unsigned int *pzone) |
{ |
count_t size = ((count_t) 1) << order; |
ipl_t ipl; |
count_t hint = pzone ? (*pzone) : 0; |
int freed; |
pfn_t v; |
zone_t *zone; |
unsigned long gen = 0; |
loop: |
ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
/* |
* First, find suitable frame zone. |
*/ |
count_t znum = find_free_zone(order, |
FRAME_TO_ZONE_FLAGS(flags), hint); |
zone = find_free_zone_and_lock(order, flags, pzone); |
/* If no memory, reclaim some slab memory, |
if it does not help, reclaim all */ |
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) { |
if (!zone && !(flags & FRAME_NO_RECLAIM)) { |
freed = slab_reclaim(0); |
if (freed) |
zone = find_free_zone_and_lock(order, flags, pzone); |
if (!zone) { |
freed = slab_reclaim(SLAB_RECLAIM_ALL); |
if (freed > 0) |
znum = find_free_zone(order, |
FRAME_TO_ZONE_FLAGS(flags), hint); |
if (freed) |
zone = find_free_zone_and_lock(order, flags, |
pzone); |
} |
} |
if (znum == (count_t) -1) { |
if (!zone) { |
/* |
* Sleep until some frames are available again. |
*/ |
if (flags & FRAME_ATOMIC) { |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
return NULL; |
return 0; |
} |
#ifdef CONFIG_DEBUG |
count_t avail = total_frames_free(); |
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); |
#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); |
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) |
while ((mem_avail_frames < (1ULL << order)) || |
gen == mem_avail_gen) |
condvar_wait(&mem_avail_cv, &mem_avail_mtx); |
gen = mem_avail_gen; |
mutex_unlock(&mem_avail_mtx); |
#ifdef CONFIG_DEBUG |
printf("Thread %" PRIu64 " woken up.\n", THREAD->tid); |
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); |
#endif |
interrupts_restore(ipl); |
goto loop; |
} |
pfn_t pfn = zone_frame_alloc(&zones.info[znum], order) |
+ zones.info[znum].base; |
v = zone_frame_alloc(zone, order); |
v += zone->base; |
spinlock_unlock(&zone->lock); |
spinlock_unlock(&zones.lock); |
mutex_lock(&mem_avail_mtx); |
mem_avail_frames -= (1ULL << order); |
mutex_unlock(&mem_avail_mtx); |
interrupts_restore(ipl); |
if (pzone) |
*pzone = znum; |
if (flags & FRAME_KA) |
return (void *) PA2KA(PFN2ADDR(pfn)); |
return (void *) PFN2ADDR(pfn); |
return (void *)PA2KA(PFN2ADDR(v)); |
return (void *)PFN2ADDR(v); |
} |
/** 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 = interrupts_disable(); |
spinlock_lock(&zones.lock); |
ipl_t ipl; |
zone_t *zone; |
pfn_t pfn = ADDR2PFN(frame); |
ipl = interrupts_disable(); |
/* |
* First, find host frame zone for addr. |
*/ |
pfn_t pfn = ADDR2PFN(frame); |
count_t znum = find_zone(pfn, 1, NULL); |
zone = find_zone_and_lock(pfn, NULL); |
ASSERT(zone); |
ASSERT(znum != (count_t) -1); |
zone_frame_free(zone, pfn - zone->base); |
zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base); |
spinlock_unlock(&zone->lock); |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
/* |
* Signal that some memory has been freed. |
*/ |
mutex_lock(&mem_avail_mtx); |
if (mem_avail_req > 0) |
mem_avail_req--; |
if (mem_avail_req == 0) { |
mem_avail_gen++; |
condvar_broadcast(&mem_avail_cv); |
} |
mem_avail_frames++; |
mem_avail_gen++; |
condvar_broadcast(&mem_avail_cv); |
mutex_unlock(&mem_avail_mtx); |
interrupts_restore(ipl); |
} |
/** Add reference to frame. |
1108,24 → 1115,26 |
* 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 = interrupts_disable(); |
spinlock_lock(&zones.lock); |
ipl_t ipl; |
zone_t *zone; |
frame_t *frame; |
ipl = interrupts_disable(); |
/* |
* First, find host frame zone for addr. |
*/ |
count_t znum = find_zone(pfn, 1, NULL); |
zone = find_zone_and_lock(pfn, NULL); |
ASSERT(zone); |
ASSERT(znum != (count_t) -1); |
frame = &zone->frames[pfn - zone->base]; |
frame->refcount++; |
zones.info[znum].frames[pfn - zones.info[znum].base].refcount++; |
spinlock_unlock(&zones.lock); |
spinlock_unlock(&zone->lock); |
interrupts_restore(ipl); |
} |
1132,21 → 1141,18 |
/** Mark given range unavailable in frame zones. */ |
void frame_mark_unavailable(pfn_t start, count_t count) |
{ |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
unsigned int i; |
zone_t *zone; |
unsigned int prefzone = 0; |
count_t i; |
for (i = 0; i < count; i++) { |
count_t znum = find_zone(start + i, 1, 0); |
if (znum == (count_t) -1) /* PFN not found */ |
zone = find_zone_and_lock(start + i, &prefzone); |
if (!zone) /* PFN not found */ |
continue; |
zone_mark_unavailable(&zones.info[znum], |
start + i - zones.info[znum].base); |
zone_mark_unavailable(zone, start + i - zone->base); |
spinlock_unlock(&zone->lock); |
} |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
} |
/** Initialize physical memory management. */ |
1158,7 → 1164,6 |
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) { |
1173,28 → 1178,35 |
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) |
{ |
ipl_t ipl = interrupts_disable(); |
zone_t *zone = NULL; |
unsigned int i; |
ipl_t ipl; |
uint64_t total = 0; |
ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
uint64_t total = 0; |
count_t i; |
for (i = 0; i < zones.count; i++) |
total += (uint64_t) FRAMES2SIZE(zones.info[i].count); |
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); |
} |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
1205,14 → 1217,18 |
/** Prints list of zones. */ |
void zone_print_list(void) |
{ |
#ifdef __32_BITS__ |
printf("# base address frames flags free frames busy frames\n"); |
printf("-- ------------ ------------ -------- ------------ ------------\n"); |
zone_t *zone = NULL; |
unsigned int i; |
ipl_t ipl; |
#ifdef __32_BITS__ |
printf("# base address free frames busy frames\n"); |
printf("-- ------------ ------------ ------------\n"); |
#endif |
#ifdef __64_BITS__ |
printf("# base address frames flags free frames busy frames\n"); |
printf("-- -------------------- ------------ -------- ------------ ------------\n"); |
printf("# base address free frames busy frames\n"); |
printf("-- -------------------- ------------ ------------\n"); |
#endif |
/* |
1225,10 → 1241,13 |
* we may end up with inaccurate output (e.g. a zone being skipped from |
* the listing). |
*/ |
count_t i; |
for (i = 0;; i++) { |
ipl_t ipl = interrupts_disable(); |
for (i = 0; ; i++) { |
uintptr_t base; |
count_t free_count; |
count_t busy_count; |
ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
if (i >= zones.count) { |
1236,61 → 1255,56 |
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(" %10p", base); |
printf("%-2u %10p %12" PRIc " %12" PRIc "\n", i, base, |
free_count, busy_count); |
#endif |
#ifdef __64_BITS__ |
printf(" %18p", base); |
printf("%-2u %18p %12" PRIc " %12" PRIc "\n", i, base, |
free_count, busy_count); |
#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(count_t num) |
void zone_print_one(unsigned int num) |
{ |
ipl_t ipl = interrupts_disable(); |
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(); |
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)) { |
znum = i; |
if ((i == num) || (PFN2ADDR(zones.info[i]->base) == num)) { |
zone = zones.info[i]; |
break; |
} |
} |
if (znum == (count_t) -1) { |
if (!zone) { |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
printf("Zone not found.\n"); |
1297,33 → 1311,24 |
return; |
} |
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_lock(&zone->lock); |
base = PFN2ADDR(zone->base); |
count = zone->count; |
busy_count = zone->busy_count; |
free_count = zone->free_count; |
spinlock_unlock(&zone->lock); |
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("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))); |
} |
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/mm/slab.c |
---|
173,7 → 173,7 |
slab_t *slab; |
size_t fsize; |
unsigned int i; |
count_t zone = 0; |
unsigned int zone = 0; |
data = frame_alloc_generic(cache->order, FRAME_KA | flags, &zone); |
if (!data) { |
/branches/dynload/kernel/generic/src/ipc/irq.c |
---|
44,28 → 44,8 |
* - 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> |
78,8 → 58,66 |
#include <console/console.h> |
#include <print.h> |
/** Free the top-half pseudocode. |
/** Execute code associated with IRQ notification. |
* |
* @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) |
90,7 → 128,7 |
} |
} |
/** Copy the top-half pseudocode from userspace into the kernel. |
/** Copy top-half pseudocode from userspace into the kernel. |
* |
* @param ucode Userspace address of the top-half pseudocode. |
* |
126,6 → 164,38 |
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. |
142,10 → 212,6 |
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); |
155,15 → 221,21 |
code = NULL; |
} |
/* |
* 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; |
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; |
} |
irq->notif_cfg.notify = true; |
irq->notif_cfg.answerbox = box; |
irq->notif_cfg.method = method; |
170,140 → 242,14 |
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; |
} |
/** 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); |
return 0; |
} |
/** Add a call to the proper answerbox queue. |
322,158 → 268,125 |
waitq_wakeup(&irq->notif_cfg.answerbox->wq, WAKEUP_FIRST); |
} |
/** Apply the top-half pseudo code to find out whether to accept the IRQ or not. |
/** Send notification message. |
* |
* @param irq IRQ structure. |
* |
* @return IRQ_ACCEPT if the interrupt is accepted by the |
* pseudocode. IRQ_DECLINE otherwise. |
* @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. |
*/ |
irq_ownership_t ipc_irq_top_half_claim(irq_t *irq) |
void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2, unative_t a3, |
unative_t a4, unative_t a5) |
{ |
unsigned int i; |
unative_t dstval; |
irq_code_t *code = irq->notif_cfg.code; |
unative_t *scratch = irq->notif_cfg.scratch; |
call_t *call; |
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; |
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; |
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; |
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; |
} |
send_call(irq, call); |
} |
return IRQ_DECLINE; |
spinlock_unlock(&irq->lock); |
} |
/* IRQ top-half handler. |
/** Notify a task that an IRQ had occurred. |
* |
* We expect interrupts to be disabled and the irq->lock already held. |
* |
* @param irq IRQ structure. |
*/ |
void ipc_irq_top_half_handler(irq_t *irq) |
void ipc_irq_send_notif(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); |
} |
} |
/** Send notification message. |
/** Disconnect all IRQ notifications from an answerbox. |
* |
* @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. |
* 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_send_msg(irq_t *irq, unative_t a1, unative_t a2, unative_t a3, |
unative_t a4, unative_t a5) |
void ipc_irq_cleanup(answerbox_t *box) |
{ |
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; |
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->flags |= IPC_CALL_NOTIF; |
/* Put a counter to the message */ |
call->priv = ++irq->notif_cfg.counter; |
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; |
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); |
send_call(irq, call); |
spinlock_unlock(&irq->lock); |
} |
spinlock_unlock(&irq->lock); |
spinlock_unlock(&box->irq_lock); |
interrupts_restore(ipl); |
} |
/** @} |
/branches/dynload/kernel/generic/src/main/kinit.c |
---|
174,12 → 174,9 |
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, |
name, &programs[i]); |
"init-bin", &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,15 → 105,18 |
* 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/syscall/syscall.c |
---|
156,7 → 156,6 |
(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/arch/sparc64/include/asm.h |
---|
44,49 → 44,49 |
#include <arch/stack.h> |
#include <arch/barrier.h> |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
static inline void pio_write_8(ioport_t port, uint8_t v) |
{ |
*port = v; |
*((volatile uint8_t *)(port)) = v; |
memory_barrier(); |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
static inline void pio_write_16(ioport_t port, uint16_t v) |
{ |
*port = v; |
*((volatile uint16_t *)(port)) = v; |
memory_barrier(); |
} |
static inline void pio_write_32(ioport32_t *port, uint32_t v) |
static inline void pio_write_32(ioport_t port, uint32_t v) |
{ |
*port = v; |
*((volatile uint32_t *)(port)) = v; |
memory_barrier(); |
} |
static inline uint8_t pio_read_8(ioport8_t *port) |
static inline uint8_t pio_read_8(ioport_t port) |
{ |
uint8_t rv; |
rv = *port; |
rv = *((volatile uint8_t *)(port)); |
memory_barrier(); |
return rv; |
} |
static inline uint16_t pio_read_16(ioport16_t *port) |
static inline uint16_t pio_read_16(ioport_t port) |
{ |
uint16_t rv; |
rv = *port; |
rv = *((volatile uint16_t *)(port)); |
memory_barrier(); |
return rv; |
} |
static inline uint32_t pio_read_32(ioport32_t *port) |
static inline uint32_t pio_read_32(ioport_t port) |
{ |
uint32_t rv; |
rv = *port; |
rv = *((volatile uint32_t *)(port)); |
memory_barrier(); |
return rv; |
/branches/dynload/kernel/arch/sparc64/include/mm/frame.h |
---|
73,6 → 73,7 |
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/types.h |
---|
57,9 → 57,7 |
typedef uint64_t unative_t; |
typedef int64_t native_t; |
typedef volatile uint8_t ioport8_t; |
typedef volatile uint16_t ioport16_t; |
typedef volatile uint32_t ioport32_t; |
typedef uintptr_t ioport_t; |
typedef struct { |
} fncptr_t; |
/branches/dynload/kernel/arch/sparc64/include/drivers/z8530.h |
---|
0,0 → 1,140 |
/* |
* Copyright (c) 2006 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 sparc64 |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_sparc64_Z8530_H_ |
#define KERN_sparc64_Z8530_H_ |
#include <arch/types.h> |
#include <arch/drivers/kbd.h> |
#define Z8530_CHAN_A 4 |
#define Z8530_CHAN_B 0 |
#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 |
#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 |
/* Write Register 0 */ |
#define WR0_TX_IP_RST (0x5<<3) /** Reset pending TX interrupt. */ |
#define WR0_ERR_RST (0x6<<3) |
/* Write Register 1 */ |
#define WR1_RID (0x0<<3) /** Receive Interrupts Disabled. */ |
#define WR1_RIFCSC (0x1<<3) /** Receive Interrupt on First Character or Special Condition. */ |
#define WR1_IARCSC (0x2<<3) /** Interrupt on All Receive Characters or Special Conditions. */ |
#define WR1_RISC (0x3<<3) /** Receive Interrupt on Special Condition. */ |
#define WR1_PISC (0x1<<2) /** Parity Is Special Condition. */ |
/* Write Register 3 */ |
#define WR3_RX_ENABLE (0x1<<0) /** Rx Enable. */ |
#define WR3_RX8BITSCH (0x3<<6) /** 8-bits per character. */ |
/* Write Register 9 */ |
#define WR9_MIE (0x1<<3) /** Master Interrupt Enable. */ |
/* Read Register 0 */ |
#define RR0_RCA (0x1<<0) /** Receive Character Available. */ |
/** Structure representing the z8530 device. */ |
typedef struct { |
devno_t devno; |
volatile uint8_t *reg; /** Memory mapped registers of the z8530. */ |
} z8530_t; |
static inline void z8530_write(z8530_t *dev, index_t chan, uint8_t reg, uint8_t val) |
{ |
/* |
* Registers 8-15 will automatically issue the Point High |
* command as their bit 3 is 1. |
*/ |
dev->reg[WR0+chan] = reg; /* select register */ |
dev->reg[WR0+chan] = val; /* write value */ |
} |
static inline void z8530_write_a(z8530_t *dev, uint8_t reg, uint8_t val) |
{ |
z8530_write(dev, Z8530_CHAN_A, reg, val); |
} |
static inline void z8530_write_b(z8530_t *dev, uint8_t reg, uint8_t val) |
{ |
z8530_write(dev, Z8530_CHAN_B, reg, val); |
} |
static inline uint8_t z8530_read(z8530_t *dev, index_t chan, uint8_t reg) |
{ |
/* |
* Registers 8-15 will automatically issue the Point High |
* command as their bit 3 is 1. |
*/ |
dev->reg[WR0+chan] = reg; /* select register */ |
return dev->reg[WR0+chan]; |
} |
static inline uint8_t z8530_read_a(z8530_t *dev, uint8_t reg) |
{ |
return z8530_read(dev, Z8530_CHAN_A, reg); |
} |
static inline uint8_t z8530_read_b(z8530_t *dev, uint8_t reg) |
{ |
return z8530_read(dev, Z8530_CHAN_B, reg); |
} |
#endif |
/** @} |
*/ |
/branches/dynload/kernel/arch/sparc64/src/console.c |
---|
162,6 → 162,16 |
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(); |
178,6 → 188,16 |
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,6 → 41,7 |
#include <macros.h> |
uintptr_t last_frame = NULL; |
uintptr_t end_frame = NULL; |
/** Create memory zones according to information stored in bootinfo. |
* |
79,6 → 80,8 |
*/ |
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,5 → 164,11 |
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/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(irq_t *irq) |
static irq_ownership_t sgcn_claim(void *instance) |
{ |
return IRQ_DECLINE; |
} |
381,7 → 381,13 |
volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr); |
if (*in_rdptr_ptr != *in_wrptr_ptr) { |
/* XXX: send notification to userspace */ |
if (sgcn_irq.notif_cfg.notify && sgcn_irq.notif_cfg.answerbox) { |
ipc_irq_send_notif(&sgcn_irq); |
spinlock_unlock(&sgcn_irq.lock); |
interrupts_restore(ipl); |
spinlock_unlock(&sgcn_input_lock); |
return; |
} |
} |
spinlock_unlock(&sgcn_irq.lock); |
/branches/dynload/kernel/arch/sparc64/src/drivers/fhc.c |
---|
45,7 → 45,6 |
#include <mm/slab.h> |
#include <arch/types.h> |
#include <genarch/ofw/ofw_tree.h> |
#include <sysinfo/sysinfo.h> |
fhc_t *central_fhc = NULL; |
87,13 → 86,6 |
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,7 → 47,6 |
#include <align.h> |
#include <func.h> |
#include <print.h> |
#include <sysinfo/sysinfo.h> |
kbd_type_t kbd_type = KBD_UNKNOWN; |
66,13 → 65,6 |
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); |
107,7 → 99,6 |
uintptr_t pa; |
size_t size; |
devno_t devno; |
inr_t inr; |
switch (kbd_type) { |
140,6 → 131,7 |
return; |
}; |
break; |
default: |
panic("Unexpected keyboard type."); |
} |
156,42 → 148,14 |
switch (kbd_type) { |
#ifdef CONFIG_Z8530 |
case KBD_Z8530: |
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); |
z8530_init(device_assign_devno(), |
hw_map(aligned_addr, offset + size) + offset, inr, cir, cir_arg); |
break; |
#endif |
#ifdef CONFIG_NS16550 |
case KBD_NS16550: |
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); |
ns16550_init(device_assign_devno(), |
(ioport_t) (hw_map(aligned_addr, offset + size) + offset), inr, cir, cir_arg); |
break; |
#endif |
default: |
/branches/dynload/kernel/arch/sparc64/src/drivers/pci.c |
---|
44,7 → 44,6 |
#include <print.h> |
#include <func.h> |
#include <arch/asm.h> |
#include <sysinfo/sysinfo.h> |
#define SABRE_INTERNAL_REG 0 |
#define PSYCHO_INTERNAL_REG 2 |
109,12 → 108,6 |
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; |
} |
156,12 → 149,6 |
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/asm.h |
---|
41,64 → 41,52 |
#define IA64_IOSPACE_ADDRESS 0xE001000000000000ULL |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
static inline void pio_write_8(ioport_t port, uint8_t v) |
{ |
uintptr_t prt = (uintptr_t) port; |
*((uint8_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
((port & 0xfff) | ((port >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
static inline void pio_write_16(ioport_t port, uint16_t v) |
{ |
uintptr_t prt = (uintptr_t) port; |
*((uint16_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
((port & 0xfff) | ((port >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
} |
static inline void pio_write_32(ioport32_t *port, uint32_t v) |
static inline void pio_write_32(ioport_t port, uint32_t v) |
{ |
uintptr_t prt = (uintptr_t) port; |
*((uint32_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
((port & 0xfff) | ((port >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
} |
static inline uint8_t pio_read_8(ioport8_t *port) |
static inline uint8_t pio_read_8(ioport_t port) |
{ |
uintptr_t prt = (uintptr_t) port; |
asm volatile ("mf\n" ::: "memory"); |
return *((uint8_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
((port & 0xfff) | ((port >> 2) << 12)))); |
} |
static inline uint16_t pio_read_16(ioport16_t *port) |
static inline uint16_t pio_read_16(ioport_t port) |
{ |
uintptr_t prt = (uintptr_t) port; |
asm volatile ("mf\n" ::: "memory"); |
return *((uint16_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xffE) | ((prt >> 2) << 12)))); |
((port & 0xffE) | ((port >> 2) << 12)))); |
} |
static inline uint32_t pio_read_32(ioport32_t *port) |
static inline uint32_t pio_read_32(ioport_t port) |
{ |
uintptr_t prt = (uintptr_t) port; |
asm volatile ("mf\n" ::: "memory"); |
return *((uint32_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
((port & 0xfff) | ((port >> 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,6 → 44,7 |
#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,6 → 35,9 |
#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 |
---|
0,0 → 1,71 |
/* |
* Copyright (c) 2006 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 |
*/ |
/** |
* This file implements ia32 specific access to i8042 registers. |
*/ |
#ifndef KERN_ia64_I8042_H_ |
#define KERN_ia64_I8042_H_ |
#include <arch/asm.h> |
#include <arch/types.h> |
#define i8042_DATA 0x60 |
#define i8042_STATUS 0x64 |
static inline void i8042_data_write(uint8_t data) |
{ |
pio_write_8(i8042_DATA, data); |
} |
static inline uint8_t i8042_data_read(void) |
{ |
return pio_read_8(i8042_DATA); |
} |
static inline uint8_t i8042_status_read(void) |
{ |
return pio_read_8(i8042_STATUS); |
} |
static inline void i8042_command_write(uint8_t command) |
{ |
pio_write_8(i8042_STATUS, command); |
} |
#endif |
/** @} |
*/ |
/branches/dynload/kernel/arch/ia64/include/drivers/ega.h |
---|
0,0 → 1,44 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup ia64 |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_ia64_EGA_H |
#define KERN_ia64_EGA_H |
#define EGA_VIDEORAM 0xb8000 |
#define EGA_BASE 0x3d4 |
#endif |
/** @} |
*/ |
/branches/dynload/kernel/arch/ia64/include/types.h |
---|
65,9 → 65,7 |
typedef uint64_t unative_t; |
typedef int64_t native_t; |
typedef volatile uint8_t ioport8_t; |
typedef volatile uint16_t ioport16_t; |
typedef volatile uint32_t ioport32_t; |
typedef uintptr_t ioport_t; |
typedef struct { |
unative_t fnc; |
/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 <genarch/drivers/legacy/ia32/io.h> |
#include <arch/drivers/ega.h> |
#include <genarch/drivers/ega/ega.h> |
#include <genarch/kbd/i8042.h> |
#include <genarch/kbd/ns16550.h> |
65,6 → 65,7 |
/* NS16550 as a COM 1 */ |
#define NS16550_IRQ (4 + LEGACY_INTERRUPT_BASE) |
#define NS16550_PORT 0x3f8 |
bootinfo_t *bootinfo; |
160,22 → 161,14 |
#endif |
#ifdef I460GX |
devno_t devno = device_assign_devno(); |
inr_t inr; |
devno_t kbd = device_assign_devno(); |
#ifdef CONFIG_NS16550 |
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); |
ns16550_init(kbd, NS16550_PORT, NS16550_IRQ, NULL, NULL); |
#else |
inr = IRQ_KBD; |
(void) i8042_init((i8042_t *)I8042_BASE, devno, inr); |
sysinfo_set_item_val("kbd.type", NULL, KBD_LEGACY); |
devno_t mouse = device_assign_devno(); |
i8042_init(kbd, IRQ_KBD, mouse, IRQ_MOUSE); |
#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); |
229,7 → 222,13 |
{ |
#ifdef SKI |
ski_kbd_grab(); |
#else |
#ifdef CONFIG_NS16550 |
ns16550_grab(); |
#else |
i8042_grab(); |
#endif |
#endif |
} |
/** Return console to userspace |
239,12 → 238,18 |
{ |
#ifdef SKI |
ski_kbd_release(); |
#else |
#ifdef CONFIG_NS16550 |
ns16550_release(); |
#else |
i8042_release(); |
#endif |
#endif |
} |
void arch_reboot(void) |
{ |
pio_write_8((ioport8_t *)0x64, 0xfe); |
pio_write_8(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); |
/* XXX: send notification to userspace */ |
ipc_irq_send_notif(&ski_kbd_irq); |
} 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); |
/* XXX: send notification to userspace */ |
ipc_irq_send_notif(&ski_kbd_irq); |
} |
last = 0; |
} |
186,7 → 186,7 |
* |
* @return Always IRQ_DECLINE. |
*/ |
static irq_ownership_t ski_kbd_claim(irq_t *irq) |
static irq_ownership_t ski_kbd_claim(void *instance) |
{ |
return IRQ_DECLINE; |
} |
/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,6 → 51,7 |
#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,9 → 270,15 |
uintptr_t hw_map(uintptr_t physaddr, size_t size __attribute__ ((unused))) |
{ |
/* THIS is a dirty hack. */ |
return (uintptr_t)((uint64_t)(PA2KA(physaddr)) + VIO_OFFSET); |
/* This is a dirty hack. */ |
return PA2KA(physaddr); |
} |
void hw_area(uintptr_t *physaddr, pfn_t *frames) |
{ |
*physaddr = end_frame; |
*frames = ADDR2PFN(0x7fffffffffffffffUL - end_frame); |
} |
/** @} |
*/ |
/branches/dynload/kernel/arch/ia64/src/mm/tlb.c |
---|
749,13 → 749,5 |
} |
} |
void tlb_arch_init(void) |
{ |
} |
void tlb_print(void) |
{ |
} |
/** @} |
*/ |
/branches/dynload/kernel/arch/ia64/src/drivers/it.c |
---|
56,8 → 56,8 |
static irq_t it_irq; |
static irq_ownership_t it_claim(irq_t *); |
static void it_interrupt(irq_t *); |
static irq_ownership_t it_claim(void *); |
static void it_interrupt(irq_t *irq); |
/** Initialize Interval Timer. */ |
void it_init(void) |
104,7 → 104,7 |
* |
* @return Always IRQ_ACCEPT. |
*/ |
irq_ownership_t it_claim(irq_t *irq) |
irq_ownership_t it_claim(void *instance) |
{ |
return IRQ_ACCEPT; |
} |
/branches/dynload/kernel/arch/ia64/src/smp/smp.c |
---|
51,6 → 51,7 |
#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/arm32/include/machine.h |
---|
104,6 → 104,8 |
#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,36 → 46,16 |
{ |
} |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
static inline void pio_write_8(ioport_t port, uint8_t v) |
{ |
*port = v; |
/* XXX */ |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
static inline uint8_t pio_read_8(ioport_t port) |
{ |
*port = v; |
return 0; /* XXX */ |
} |
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,13 → 44,14 |
#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,6 → 36,9 |
#ifndef KERN_arm32_TLB_H_ |
#define KERN_arm32_TLB_H_ |
#define tlb_arch_init() |
#define tlb_print() |
#endif |
/** @} |
/branches/dynload/kernel/arch/arm32/include/types.h |
---|
64,9 → 64,7 |
typedef uint32_t unative_t; |
typedef int32_t native_t; |
typedef volatile uint8_t ioport8_t; |
typedef volatile uint16_t ioport16_t; |
typedef volatile uint32_t ioport32_t; |
typedef uintptr_t ioport_t; |
typedef struct { |
} fncptr_t; |
/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,6 → 41,7 |
/** 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) |
49,6 → 50,7 |
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,5 → 106,11 |
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/mm/tlb.c |
---|
89,13 → 89,5 |
invalidate_page(page + i * PAGE_SIZE); |
} |
void tlb_arch_init(void) |
{ |
} |
void tlb_print(void) |
{ |
} |
/** @} |
*/ |
/branches/dynload/kernel/arch/arm32/src/drivers/gxemul.c |
---|
34,6 → 34,7 |
*/ |
#include <interrupt.h> |
#include <ipc/irq.h> |
#include <console/chardev.h> |
#include <arch/drivers/gxemul.h> |
#include <console/console.h> |
186,23 → 187,50 |
*/ |
static void gxemul_irq_handler(irq_t *irq) |
{ |
char ch = 0; |
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) { |
ipc_irq_send_notif(irq); |
} else { |
char ch = 0; |
ch = *((char *) gxemul_hw_map.kbd); |
if (ch == '\r') { |
ch = '\n'; |
ch = *((char *) gxemul_hw_map.kbd); |
if (ch == '\r') { |
ch = '\n'; |
} |
if (ch == 0x7f) { |
ch = '\b'; |
} |
chardev_push_character(&console, ch); |
} |
if (ch == 0x7f) { |
ch = '\b'; |
} |
chardev_push_character(&console, ch); |
} |
static irq_ownership_t gxemul_claim(irq_t *irq) |
static irq_ownership_t gxemul_claim(void *instance) |
{ |
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. |
237,7 → 265,7 |
*((uint32_t*) gxemul_hw_map.rtc_freq) = frequency; |
} |
static irq_ownership_t gxemul_timer_claim(irq_t *irq) |
static irq_ownership_t gxemul_timer_claim(void *instance) |
{ |
return IRQ_ACCEPT; |
} |
/branches/dynload/kernel/arch/arm32/src/console.c |
---|
50,11 → 50,13 |
#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/ppc32/include/asm.h |
---|
149,36 → 149,16 |
extern void userspace_asm(uintptr_t uspace_uarg, uintptr_t stack, uintptr_t entry); |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
static inline void pio_write_8(ioport_t port, uint8_t v) |
{ |
*port = v; |
/* XXX */ |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
static inline uint8_t pio_read_8(ioport_t port) |
{ |
*port = v; |
return 0; /* XXX */ |
} |
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,6 → 44,7 |
#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/types.h |
---|
57,9 → 57,7 |
typedef uint32_t unative_t; |
typedef int32_t native_t; |
typedef volatile uint8_t ioport8_t; |
typedef volatile uint16_t ioport16_t; |
typedef volatile uint32_t ioport32_t; |
typedef uintptr_t ioport_t; |
typedef struct { |
} fncptr_t; |
/branches/dynload/kernel/arch/ppc32/include/drivers/cuda.h |
---|
40,6 → 40,8 |
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,6 → 156,7 |
void arch_grab_console(void) |
{ |
fb_redraw(); |
cuda_grab(); |
} |
/** Return console to userspace |
163,6 → 164,7 |
*/ |
void arch_release_console(void) |
{ |
cuda_release(); |
} |
/** Construct function pointer |
/branches/dynload/kernel/arch/ppc32/src/mm/frame.c |
---|
40,6 → 40,7 |
#include <print.h> |
uintptr_t last_frame = 0; |
uintptr_t end_frame = 0; |
void physmem_print(void) |
{ |
75,6 → 76,8 |
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,5 → 63,11 |
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,6 → 33,7 |
*/ |
#include <arch/drivers/cuda.h> |
#include <ipc/irq.h> |
#include <arch/asm.h> |
#include <console/console.h> |
#include <console/chardev.h> |
250,20 → 251,52 |
static void cuda_irq_handler(irq_t *irq) |
{ |
int scan_code = cuda_get_scancode(); |
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) |
ipc_irq_send_notif(irq); |
else { |
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(irq_t *irq) |
static irq_ownership_t cuda_claim(void *instance) |
{ |
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/asm.h |
---|
73,7 → 73,7 |
* @param port Port to read from |
* @return Value read |
*/ |
static inline uint8_t pio_read_8(ioport8_t *port) |
static inline uint8_t pio_read_8(uint16_t port) |
{ |
uint8_t val; |
81,36 → 81,6 |
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 |
118,35 → 88,11 |
* @param port Port to write to |
* @param val Value to write |
*/ |
static inline void pio_write_8(ioport8_t *port, uint8_t val) |
static inline void pio_write_8(uint16_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,11 → 39,12 |
#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,6 → 35,9 |
#ifndef KERN_amd64_TLB_H_ |
#define KERN_amd64_TLB_H_ |
#define tlb_arch_init() |
#define tlb_print() |
#endif |
/** @} |
/branches/dynload/kernel/arch/amd64/include/types.h |
---|
57,9 → 57,7 |
typedef uint64_t unative_t; |
typedef int64_t native_t; |
typedef volatile uint8_t ioport8_t; |
typedef volatile uint16_t ioport16_t; |
typedef volatile uint32_t ioport32_t; |
typedef uintptr_t ioport_t; |
typedef struct { |
} fncptr_t; |
/branches/dynload/kernel/arch/amd64/src/mm/page.c |
---|
214,5 → 214,11 |
return virtaddr; |
} |
void hw_area(uintptr_t *physaddr, pfn_t *frames) |
{ |
*physaddr = end_frame; |
*frames = ADDR2PFN(0xfffffffffffff - end_frame); |
} |
/** @} |
*/ |
/branches/dynload/kernel/arch/amd64/src/amd64.c |
---|
39,7 → 39,7 |
#include <config.h> |
#include <proc/thread.h> |
#include <genarch/drivers/legacy/ia32/io.h> |
#include <arch/drivers/ega.h> |
#include <genarch/drivers/ega/ega.h> |
#include <arch/drivers/vesa.h> |
#include <genarch/kbd/i8042.h> |
63,7 → 63,6 |
#include <console/console.h> |
#include <ddi/irq.h> |
#include <ddi/device.h> |
#include <sysinfo/sysinfo.h> |
/** Disable I/O on non-privileged levels |
174,17 → 173,8 |
void arch_post_smp_init(void) |
{ |
devno_t devno = device_assign_devno(); |
/* keyboard controller */ |
(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); |
i8042_init(device_assign_devno(), IRQ_KBD, device_assign_devno(), IRQ_MOUSE); |
} |
void calibrate_delay_loop(void) |
224,6 → 214,8 |
#else |
ega_redraw(); |
#endif |
i8042_grab(); |
} |
/** Return console to userspace |
231,6 → 223,7 |
*/ |
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 $48, %rdi |
addq $16, %rdi |
loop mods_loop |
/branches/dynload/kernel/arch/mips32/include/asm.h |
---|
75,36 → 75,16 |
extern ipl_t interrupts_read(void); |
extern void asm_delay_loop(uint32_t t); |
static inline void pio_write_8(ioport8_t *port, uint8_t v) |
static inline void pio_write_8(ioport_t port, uint8_t v) |
{ |
*port = v; |
/* XXX */ |
} |
static inline void pio_write_16(ioport16_t *port, uint16_t v) |
static inline uint8_t pio_read_8(ioport_t port) |
{ |
*port = v; |
return 0; /* XXX */ |
} |
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,6 → 46,8 |
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/include/types.h |
---|
57,9 → 57,7 |
typedef uint32_t unative_t; |
typedef int32_t native_t; |
typedef volatile uint8_t ioport8_t; |
typedef volatile uint16_t ioport16_t; |
typedef volatile uint32_t ioport32_t; |
typedef uintptr_t ioport_t; |
typedef struct { |
} fncptr_t; |
/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,7 → 65,9 |
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. |
218,7 → 220,7 |
ZERO_PAGE_VALUE = 0xdeadbeef; |
if (ZERO_PAGE_VALUE != 0xdeadbeef) |
avail = false; |
#if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul) |
#if defined(lgxemul) || defined(bgxemul) |
else { |
ZERO_PAGE_VALUE_KSEG1(frame) = 0xaabbccdd; |
if (ZERO_PAGE_VALUE_KSEG1(frame) != 0xaabbccdd) |
236,8 → 238,10 |
} |
} |
frame_add_region(start_frame, frame); |
end_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,5 → 51,11 |
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(irq_t *irq) |
static irq_ownership_t timer_claim(void *instance) |
{ |
return IRQ_ACCEPT; |
} |
/branches/dynload/kernel/arch/mips32/src/drivers/serial.c |
---|
34,6 → 34,7 |
#include <interrupt.h> |
#include <arch/cp0.h> |
#include <ipc/irq.h> |
#include <arch/drivers/serial.h> |
#include <console/chardev.h> |
#include <console/console.h> |
113,10 → 114,13 |
/** Process keyboard interrupt. Does not work in simics? */ |
static void serial_irq_handler(irq_t *irq) |
{ |
serial_handler(); |
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) |
ipc_irq_send_notif(irq); |
else |
serial_handler(); |
} |
static irq_ownership_t serial_claim(irq_t *irq) |
static irq_ownership_t serial_claim(void *instance) |
{ |
return IRQ_ACCEPT; |
} |
/branches/dynload/kernel/arch/mips32/src/drivers/msim.c |
---|
33,6 → 33,7 |
*/ |
#include <interrupt.h> |
#include <ipc/irq.h> |
#include <console/chardev.h> |
#include <arch/drivers/msim.h> |
#include <arch/cp0.h> |
94,17 → 95,21 |
/** Process keyboard interrupt. */ |
static void msim_irq_handler(irq_t *irq) |
{ |
char ch = 0; |
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) |
ipc_irq_send_notif(irq); |
else { |
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(irq_t *irq) |
static irq_ownership_t msim_claim(void *instance) |
{ |
return IRQ_ACCEPT; |
} |
/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(ioport8_t *port, uint8_t val) |
static inline void pio_write_8(uint16_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(ioport16_t *port, uint16_t val) |
static inline void pio_write_16(uint16_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(ioport32_t *port, uint32_t val) |
static inline void pio_write_32(uint16_t port, uint32_t val) |
{ |
asm volatile ("outl %0, %w1\n" : : "a" (val), "d" (port)); |
asm volatile ("outl %l0, %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(ioport8_t *port) |
static inline uint8_t pio_read_8(uint16_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(ioport16_t *port) |
static inline uint16_t pio_read_16(uint16_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(ioport32_t *port) |
static inline uint32_t pio_read_32(uint16_t port) |
{ |
uint32_t val; |
asm volatile ("inl %w1, %0 \n" : "=a" (val) : "d" (port)); |
asm volatile ("inl %w1, %l0 \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,6 → 44,7 |
#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,6 → 35,9 |
#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 |
---|
0,0 → 1,71 |
/* |
* Copyright (c) 2006 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 |
*/ |
/** |
* This file implements ia32 specific access to i8042 registers. |
*/ |
#ifndef KERN_ia32_I8042_H_ |
#define KERN_ia32_I8042_H_ |
#include <arch/asm.h> |
#include <arch/types.h> |
#define i8042_DATA 0x60 |
#define i8042_STATUS 0x64 |
static inline void i8042_data_write(uint8_t data) |
{ |
pio_write_8(i8042_DATA, data); |
} |
static inline uint8_t i8042_data_read(void) |
{ |
return pio_read_8(i8042_DATA); |
} |
static inline uint8_t i8042_status_read(void) |
{ |
return pio_read_8(i8042_STATUS); |
} |
static inline void i8042_command_write(uint8_t command) |
{ |
pio_write_8(i8042_STATUS, command); |
} |
#endif |
/** @} |
*/ |
/branches/dynload/kernel/arch/ia32/include/drivers/ega.h |
---|
0,0 → 1,44 |
/* |
* Copyright (c) 2008 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 |
*/ |
#ifndef KERN_ia32_EGA_H |
#define KERN_ia32_EGA_H |
#define EGA_VIDEORAM 0xb8000 |
#define EGA_BASE 0x3d4 |
#endif |
/** @} |
*/ |
/branches/dynload/kernel/arch/ia32/include/drivers/i8259.h |
---|
38,10 → 38,10 |
#include <arch/types.h> |
#include <arch/interrupt.h> |
#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_PIC0PORT1 0x20 |
#define PIC_PIC0PORT2 0x21 |
#define PIC_PIC1PORT1 0xa0 |
#define PIC_PIC1PORT2 0xa1 |
#define PIC_NEEDICW4 (1<<0) |
#define PIC_ICW1 (1<<4) |
/branches/dynload/kernel/arch/ia32/include/types.h |
---|
57,9 → 57,7 |
typedef uint32_t unative_t; |
typedef int32_t native_t; |
typedef volatile uint8_t ioport8_t; |
typedef volatile uint16_t ioport16_t; |
typedef volatile uint32_t ioport32_t; |
typedef uintptr_t ioport_t; |
typedef struct { |
} fncptr_t; |
/branches/dynload/kernel/arch/ia32/include/boot/cboot.h |
---|
File deleted |
/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,29 → 35,24 |
#ifndef KERN_ia32_MEMMAP_H_ |
#define KERN_ia32_MEMMAP_H_ |
/* E820h memory range types */ |
/* 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 |
/* Free memory */ |
#define MEMMAP_MEMORY_AVAILABLE 1 |
/* size of one entry */ |
#define MEMMAP_E820_RECORD_SIZE 20 |
/* maximum entries */ |
#define MEMMAP_E820_MAX_RECORDS 32 |
/* 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/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((ioport8_t *)0x70, 0xf); |
pio_write_8((ioport8_t *)0x71, 0xa); |
pio_write_8(0x70, 0xf); |
pio_write_8(0x71, 0xa); |
pic_disable_irqs(0xffff); |
apic_init(); |
154,13 → 154,8 |
/* |
* 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); |
sizeof(struct descriptor), FRAME_ATOMIC | FRAME_LOW_4_GiB); |
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(irq_t *irq) |
static irq_ownership_t l_apic_timer_claim(void *instance) |
{ |
return IRQ_ACCEPT; |
} |
/branches/dynload/kernel/arch/ia32/src/mm/frame.c |
---|
50,62 → 50,34 |
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) { |
/* To be safe, make available zone possibly smaller */ |
pfn = ADDR2PFN(ALIGN_UP(base, FRAME_SIZE)); |
count = SIZE2FRAMES(ALIGN_DOWN(size, FRAME_SIZE)); |
start = ADDR2PFN(ALIGN_UP(e820table[i].base_address, FRAME_SIZE)); |
size = SIZE2FRAMES(ALIGN_DOWN(e820table[i].size, FRAME_SIZE)); |
pfn_t conf; |
if ((minconf < pfn) || (minconf >= pfn + count)) |
conf = pfn; |
if ((minconf < start) || (minconf >= start + size)) |
conf = start; |
else |
conf = minconf; |
zone_create(pfn, count, conf, ZONE_AVAILABLE); |
zone_create(start, size, conf, 0); |
// XXX this has to be removed |
if (last_frame < ALIGN_UP(base + size, FRAME_SIZE)) |
last_frame = ALIGN_UP(base + size, FRAME_SIZE); |
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); |
} |
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,6 → 93,12 |
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/mm/tlb.c |
---|
67,13 → 67,5 |
invlpg(page + i * PAGE_SIZE); |
} |
void tlb_arch_init(void) |
{ |
} |
void tlb_print(void) |
{ |
} |
/** @} |
*/ |
/branches/dynload/kernel/arch/ia32/src/drivers/i8259.c |
---|
119,8 → 119,8 |
void pic_eoi(void) |
{ |
pio_write_8((ioport8_t *)0x20, 0x20); |
pio_write_8((ioport8_t *)0xa0, 0x20); |
pio_write_8(0x20, 0x20); |
pio_write_8(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 ((ioport8_t *)0x40) |
#define CLK_PORT4 ((ioport8_t *)0x43) |
#define CLK_PORT1 0x40 |
#define CLK_PORT4 0x43 |
#define CLK_CONST 1193180 |
#define MAGIC_NUMBER 1194 |
61,7 → 61,7 |
static irq_t i8254_irq; |
static irq_ownership_t i8254_claim(irq_t *irq) |
static irq_ownership_t i8254_claim(void *instance) |
{ |
return IRQ_ACCEPT; |
} |
/branches/dynload/kernel/arch/ia32/src/ia32.c |
---|
38,7 → 38,7 |
#include <arch/pm.h> |
#include <genarch/drivers/legacy/ia32/io.h> |
#include <arch/drivers/ega.h> |
#include <genarch/drivers/ega/ega.h> |
#include <arch/drivers/vesa.h> |
#include <genarch/kbd/i8042.h> |
62,7 → 62,6 |
#include <syscall/syscall.h> |
#include <console/console.h> |
#include <ddi/device.h> |
#include <sysinfo/sysinfo.h> |
#ifdef CONFIG_SMP |
#include <arch/smp/apic.h> |
125,17 → 124,10 |
void arch_post_smp_init(void) |
{ |
devno_t devno = device_assign_devno(); |
devno_t kbd = device_assign_devno(); |
devno_t mouse = device_assign_devno(); |
/* keyboard controller */ |
(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); |
i8042_init(kbd, IRQ_KBD, mouse, IRQ_MOUSE); |
} |
void calibrate_delay_loop(void) |
173,6 → 165,8 |
#else |
ega_redraw(); |
#endif |
i8042_grab(); |
} |
/** Return console to userspace |
180,6 → 174,7 |
*/ |
void arch_release_console(void) |
{ |
i8042_release(); |
} |
/** Construct function pointer |
/branches/dynload/kernel/arch/ia32/src/boot/cboot.c |
---|
File deleted |
/branches/dynload/kernel/arch/ia32/src/boot/boot.S |
---|
101,16 → 101,117 |
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 |
# ia32_cboot(grub_eax, grub_ebx) |
pushl grub_ebx |
pushl grub_eax |
call ia32_cboot # Does not return. |
call main_bsp # never returns |
# Not reached. |
cli |
hlt |
/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,7 → 99,6 |
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/tools/config.py |
---|
103,8 → 103,6 |
varval = '' |
else: |
varval = defaults[condname] |
if (varval == '*'): |
varval = 'y' |
if (ctype == 'cnf'): |
if (oper == '=') and (condval == varval): |
251,8 → 249,6 |
default = '' |
else: |
default = defaults[varname] |
if (default == '*'): |
default = 'y' |
outmk.write('# %s\n%s = %s\n\n' % (name, varname, default)) |
306,7 → 302,7 |
# Cancel out all defaults which have to be deduced |
for varname, vartype, name, choices, cond in ask_names: |
if ((vartype == 'y') and (defaults.has_key(varname)) and (defaults[varname] == '*')): |
if (vartype == 'y'): |
defaults[varname] = None |
options = [] |
339,7 → 335,7 |
options.append(" %s [%s] --> " % (name, default)) |
elif (vartype == 'y'): |
defaults[varname] = '*' |
defaults[varname] = 'y' |
continue |
elif (vartype == 'y/n'): |
if (default == None): |
/branches/dynload/uspace/app/bdsh/input.c |
---|
94,6 → 94,7 |
return rc; |
} |
/* Borrowed from Jiri Svoboda's 'cli' uspace app */ |
static void read_line(char *buffer, int n) |
{ |
char c; |
113,10 → 114,8 |
} |
continue; |
} |
if (c >= ' ') { |
putchar(c); |
buffer[chars++] = c; |
} |
putchar(c); |
buffer[chars++] = c; |
} |
putchar('\n'); |
buffer[chars] = '\0'; |
/branches/dynload/uspace/app/bdsh/cmds/modules/ls/ls.c |
---|
114,7 → 114,7 |
ls_print_dir(dp->d_name); |
break; |
case LS_FILE: |
ls_print_file(dp->d_name, buff); |
ls_print_file(dp->d_name); |
break; |
case LS_BOGUS: |
/* Odd chance it was deleted from the time readdir() found |
143,9 → 143,9 |
return; |
} |
static void ls_print_file(const char *name, const char *pathname) |
static void ls_print_file(const char *f) |
{ |
printf("%-40s\t%llu\n", name, (long long) flen(pathname)); |
printf("%-40s\t%llu\n", f, (long long) flen(f)); |
return; |
} |
192,7 → 192,7 |
free(buff); |
return CMD_FAILURE; |
case LS_FILE: |
ls_print_file(buff, buff); |
ls_print_file(buff); |
break; |
case LS_DIR: |
dirp = opendir(buff); |
/branches/dynload/uspace/app/bdsh/cmds/modules/ls/ls.h |
---|
10,7 → 10,7 |
static unsigned int ls_scope(const char *); |
static void ls_scan_dir(const char *, DIR *); |
static void ls_print_dir(const char *); |
static void ls_print_file(const char *, const char *); |
static void ls_print_file(const char *); |
#endif /* LS_H */ |
/branches/dynload/uspace/app/init/init.c |
---|
112,8 → 112,6 |
spawn("/srv/fb"); |
spawn("/srv/kbd"); |
spawn("/srv/console"); |
spawn("/srv/fhc"); |
spawn("/srv/obio"); |
console_wait(); |
version_print(); |
/branches/dynload/uspace/lib/libc/include/kbd/keycode.h |
---|
199,19 → 199,9 |
} keycode_t; |
enum keymod { |
KM_LSHIFT = 0x001, |
KM_RSHIFT = 0x002, |
KM_LCTRL = 0x004, |
KM_RCTRL = 0x008, |
KM_LALT = 0x010, |
KM_RALT = 0x020, |
KM_CAPS_LOCK = 0x040, |
KM_NUM_LOCK = 0x080, |
KM_SCROLL_LOCK = 0x100, |
KM_SHIFT = KM_LSHIFT | KM_RSHIFT, |
KM_CTRL = KM_LCTRL | KM_RCTRL, |
KM_ALT = KM_LALT | KM_RALT |
KM_SHIFT = 0x01, |
KM_CTRL = 0x02, |
KM_ALT = 0x04 |
} keymod_t; |
#endif |
/branches/dynload/uspace/lib/libc/include/ipc/bus.h |
---|
File deleted |
/branches/dynload/uspace/lib/libc/include/ipc/services.h |
---|
44,9 → 44,7 |
SERVICE_VIDEO, |
SERVICE_CONSOLE, |
SERVICE_VFS, |
SERVICE_DEVMAP, |
SERVICE_FHC, |
SERVICE_OBIO |
SERVICE_DEVMAP |
} services_t; |
/* Memory area to be received from NS */ |
/branches/dynload/uspace/lib/libc/include/task.h |
---|
40,7 → 40,6 |
typedef uint64_t task_id_t; |
extern task_id_t task_get_id(void); |
extern int task_set_name(const char *name); |
extern task_id_t task_spawn(const char *path, char *const argv[]); |
#endif |
/branches/dynload/uspace/lib/libc/include/ddi.h |
---|
37,10 → 37,9 |
#include <task.h> |
extern int physmem_map(void *, void *, unsigned long, int); |
extern int iospace_enable(task_id_t, void *, unsigned long); |
extern int preemption_control(int); |
extern int pio_enable(void *, size_t, void **); |
extern int physmem_map(void *pf, void *vp, unsigned long pages, int flags); |
extern int iospace_enable(task_id_t id, void *ioaddr, unsigned long size); |
extern int preemption_control(int enable); |
#endif |
/branches/dynload/uspace/lib/libc/generic/task.c |
---|
38,7 → 38,6 |
#include <stdlib.h> |
#include <errno.h> |
#include <loader/loader.h> |
#include <string.h> |
task_id_t task_get_id(void) |
{ |
49,17 → 48,6 |
return task_id; |
} |
/** Set the task name. |
* |
* @param name The new name, typically the command used to execute the |
* program. |
* @return Zero on success or negative error code. |
*/ |
int task_set_name(const char *name) |
{ |
return __SYSCALL2(SYS_TASK_SET_NAME, (sysarg_t) name, strlen(name)); |
} |
/** Create a new task by running an executable from the filesystem. |
* |
* This is really just a convenience wrapper over the more complicated |
/branches/dynload/uspace/lib/libc/generic/ddi.c |
---|
35,9 → 35,6 |
#include <ddi.h> |
#include <libc.h> |
#include <task.h> |
#include <as.h> |
#include <align.h> |
#include <libarch/config.h> |
#include <kernel/ddi/ddi_arg.h> |
/** Map piece of physical memory to task. |
44,20 → 41,18 |
* |
* Caller of this function must have the CAP_MEM_MANAGER capability. |
* |
* @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 Flags for the new address space area. |
* @param pf Physical address of the starting frame. |
* @param vp Virtual address of the sterting page. |
* @param pages Number of pages to map. |
* @param flags Flags for the new address space area. |
* |
* @return 0 on success, EPERM if the caller lacks the |
* CAP_MEM_MANAGER capability, ENOENT if there is no task |
* with specified ID and ENOMEM if there was some problem |
* in creating address space area. |
* @return 0 on success, EPERM if the caller lacks the CAP_MEM_MANAGER capability, |
* ENOENT if there is no task with specified ID and ENOMEM if there |
* was some problem in creating address space area. |
*/ |
int physmem_map(void *pf, void *vp, unsigned long pages, int flags) |
{ |
return __SYSCALL4(SYS_PHYSMEM_MAP, (sysarg_t) pf, (sysarg_t) vp, pages, |
flags); |
return __SYSCALL4(SYS_PHYSMEM_MAP, (sysarg_t) pf, (sysarg_t) vp, pages, flags); |
} |
/** Enable I/O space range to task. |
64,14 → 59,13 |
* |
* Caller of this function must have the IO_MEM_MANAGER capability. |
* |
* @param id Task ID. |
* @param ioaddr Starting address of the I/O range. |
* @param size Size of the range. |
* @param id Task ID. |
* @param ioaddr Starting address of the I/O range. |
* @param size Size of the range. |
* |
* @return 0 on success, EPERM if the caller lacks the |
* CAP_IO_MANAGER capability, ENOENT if there is no task |
* with specified ID and ENOMEM if there was some problem |
* in allocating memory. |
* @return 0 on success, EPERM if the caller lacks the CAP_IO_MANAGER capability, |
* ENOENT if there is no task with specified ID and ENOMEM if there |
* was some problem in allocating memory. |
*/ |
int iospace_enable(task_id_t id, void *ioaddr, unsigned long size) |
{ |
86,7 → 80,7 |
/** Interrupt control |
* |
* @param enable 1 - enable interrupts, 0 - disable interrupts |
* @param enable 1 - enable interrupts, 0 - disable interrupts |
*/ |
int preemption_control(int enable) |
{ |
93,36 → 87,5 |
return __SYSCALL1(SYS_PREEMPT_CONTROL, (sysarg_t) enable); |
} |
/** Enable PIO for specified I/O range. |
* |
* @param pio_addr I/O start address. |
* @param size Size of the I/O region. |
* @param use_addr Address where the final address for application's PIO |
* will be stored. |
* |
* @return Zero on success or negative error code. |
*/ |
int pio_enable(void *pio_addr, size_t size, void **use_addr) |
{ |
void *phys; |
void *virt; |
size_t offset; |
unsigned int pages; |
#ifdef IO_SPACE_BOUNDARY |
if (pio_addr < IO_SPACE_BOUNDARY) { |
*use_addr = pio_addr; |
return iospace_enable(task_get_id(), pio_addr, size); |
} |
#endif |
phys = ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE); |
offset = pio_addr - phys; |
pages = ALIGN_UP(offset + size, PAGE_SIZE) >> PAGE_WIDTH; |
virt = as_get_mappable_page(pages); |
*use_addr = virt + offset; |
return physmem_map(phys, virt, pages, AS_AREA_READ | AS_AREA_WRITE); |
} |
/** @} |
*/ |
/branches/dynload/uspace/lib/libc/arch/ia32/include/ddi.h |
---|
33,8 → 33,6 |
#ifndef LIBC_ia32_DDI_H_ |
#define LIBC_ia32_DDI_H_ |
#define IO_SPACE_BOUNDARY ((void *) (64 * 1024)) |
static inline void outb(int16_t port, uint8_t b) |
{ |
asm volatile ("outb %0, %1\n" :: "a" (b), "d" (port)); |
/branches/dynload/uspace/srv/fhc/Makefile |
---|
File deleted |
/branches/dynload/uspace/srv/fhc/fhc.c |
---|
File deleted |
/branches/dynload/uspace/srv/obio/obio.c |
---|
File deleted |
Property changes: |
Deleted: svn:mergeinfo |
/branches/dynload/uspace/srv/obio/Makefile |
---|
File deleted |
/branches/dynload/uspace/srv/obio |
---|
Property changes: |
Deleted: svn:mergeinfo |
/branches/dynload/uspace/srv/kbd/ctl/pc.c |
---|
40,15 → 40,30 |
#include <kbd/keycode.h> |
#include <kbd_ctl.h> |
enum dec_state { |
ds_s, |
ds_e |
}; |
static int scanmap_simple[]; |
static enum dec_state ds = ds_s; |
void kbd_ctl_parse_scancode(int scancode) |
{ |
kbd_ev_type_t type; |
unsigned int key; |
static int scanmap_simple[] = { |
if (scancode < 0 || scancode >= 0x100) |
return; |
if (scancode & 0x80) { |
scancode &= ~0x80; |
type = KE_RELEASE; |
} else { |
type = KE_PRESS; |
} |
key = scanmap_simple[scancode]; |
if (key != 0) |
kbd_push_ev(type, key, 0); |
} |
static int scanmap_simple[128] = { |
[0x29] = KC_BACKTICK, |
[0x02] = KC_1, |
135,91 → 150,15 |
[0x57] = KC_F11, |
[0x58] = KC_F12, |
[0x46] = KC_SCROLL_LOCK, |
[0x1c] = KC_ENTER |
[0x1c] = KC_ENTER, |
[0x45] = KC_NUM_LOCK, |
[0x37] = KC_NTIMES, |
[0x4a] = KC_NMINUS, |
[0x4e] = KC_NPLUS, |
[0x47] = KC_N7, |
[0x48] = KC_N8, |
[0x49] = KC_N9, |
[0x4b] = KC_N4, |
[0x4c] = KC_N5, |
[0x4d] = KC_N6, |
[0x4f] = KC_N1, |
[0x50] = KC_N2, |
[0x51] = KC_N3, |
[0x52] = KC_N0, |
[0x53] = KC_NPERIOD |
/* |
[0x1] = KC_PRNSCR, |
[0x1] = KC_SCROLL_LOCK, |
[0x1] = KC_PAUSE, |
*/ |
}; |
static int scanmap_e0[] = { |
[0x38] = KC_RALT, |
[0x1d] = KC_RSHIFT, |
[0x37] = KC_PRTSCR, |
[0x52] = KC_INSERT, |
[0x47] = KC_HOME, |
[0x49] = KC_PAGE_UP, |
[0x53] = KC_DELETE, |
[0x4f] = KC_END, |
[0x51] = KC_PAGE_DOWN, |
[0x48] = KC_UP, |
[0x4b] = KC_LEFT, |
[0x50] = KC_DOWN, |
[0x4d] = KC_RIGHT, |
[0x35] = KC_NSLASH, |
[0x1c] = KC_NENTER |
}; |
void kbd_ctl_parse_scancode(int scancode) |
{ |
kbd_ev_type_t type; |
unsigned int key; |
int *map; |
size_t map_length; |
if (scancode == 0xe0) { |
ds = ds_e; |
return; |
} |
switch (ds) { |
case ds_s: |
map = scanmap_simple; |
map_length = sizeof(scanmap_simple) / sizeof(int); |
break; |
case ds_e: |
map = scanmap_e0; |
map_length = sizeof(scanmap_e0) / sizeof(int); |
break; |
} |
ds = ds_s; |
if (scancode & 0x80) { |
scancode &= ~0x80; |
type = KE_RELEASE; |
} else { |
type = KE_PRESS; |
} |
if (scancode < 0 || scancode >= map_length) |
return; |
key = map[scancode]; |
if (key != 0) |
kbd_push_ev(type, key); |
} |
/** |
* @} |
*/ |
/branches/dynload/uspace/srv/kbd/ctl/stty.c |
---|
47,7 → 47,7 |
static void parse_ds_e2a(int scancode); |
static void parse_ds_e2b(int scancode); |
static void parse_leaf(int scancode, int (*map)[2], size_t map_length); |
static void parse_leaf(int scancode, int *map, size_t map_length); |
enum dec_state { |
ds_start, |
58,169 → 58,121 |
ds_e2b |
}; |
static int map_start[][2] = { |
static int map_start[] = { |
[0x60] = { 0, KC_BACKTICK }, |
[0x60] = KC_BACKTICK, |
[0x31] = { 0, KC_1 }, |
[0x32] = { 0, KC_2 }, |
[0x33] = { 0, KC_3 }, |
[0x34] = { 0, KC_4 }, |
[0x35] = { 0, KC_5 }, |
[0x36] = { 0, KC_6 }, |
[0x37] = { 0, KC_7 }, |
[0x38] = { 0, KC_8 }, |
[0x39] = { 0, KC_9 }, |
[0x30] = { 0, KC_0 }, |
[0x31] = KC_1, |
[0x32] = KC_2, |
[0x33] = KC_3, |
[0x34] = KC_4, |
[0x35] = KC_5, |
[0x36] = KC_6, |
[0x37] = KC_7, |
[0x38] = KC_8, |
[0x39] = KC_9, |
[0x30] = KC_0, |
[0x2d] = { 0, KC_MINUS }, |
[0x3d] = { 0, KC_EQUALS }, |
[0x08] = { 0, KC_BACKSPACE }, |
[0x2d] = KC_MINUS, |
[0x3d] = KC_EQUALS, |
[0x08] = KC_BACKSPACE, |
[0x0f] = { 0, KC_TAB }, |
[0x0f] = KC_TAB, |
[0x71] = { 0, KC_Q }, |
[0x77] = { 0, KC_W }, |
[0x65] = { 0, KC_E }, |
[0x72] = { 0, KC_R }, |
[0x74] = { 0, KC_T }, |
[0x79] = { 0, KC_Y }, |
[0x75] = { 0, KC_U }, |
[0x69] = { 0, KC_I }, |
[0x6f] = { 0, KC_O }, |
[0x70] = { 0, KC_P }, |
[0x71] = KC_Q, |
[0x77] = KC_W, |
[0x65] = KC_E, |
[0x72] = KC_R, |
[0x74] = KC_T, |
[0x79] = KC_Y, |
[0x75] = KC_U, |
[0x69] = KC_I, |
[0x6f] = KC_O, |
[0x70] = KC_P, |
[0x5b] = { 0, KC_LBRACKET }, |
[0x5d] = { 0, KC_RBRACKET }, |
[0x5b] = KC_LBRACKET, |
[0x5d] = KC_RBRACKET, |
[0x61] = { 0, KC_A }, |
[0x73] = { 0, KC_S }, |
[0x64] = { 0, KC_D }, |
[0x66] = { 0, KC_F }, |
[0x67] = { 0, KC_G }, |
[0x68] = { 0, KC_H }, |
[0x6a] = { 0, KC_J }, |
[0x6b] = { 0, KC_K }, |
[0x6c] = { 0, KC_L }, |
// [0x3a] = KC_CAPS_LOCK, |
[0x3b] = { 0, KC_SEMICOLON }, |
[0x27] = { 0, KC_QUOTE }, |
[0x5c] = { 0, KC_BACKSLASH }, |
[0x61] = KC_A, |
[0x73] = KC_S, |
[0x64] = KC_D, |
[0x66] = KC_F, |
[0x67] = KC_G, |
[0x68] = KC_H, |
[0x6a] = KC_J, |
[0x6b] = KC_K, |
[0x6c] = KC_L, |
[0x7a] = { 0, KC_Z }, |
[0x78] = { 0, KC_X }, |
[0x63] = { 0, KC_C }, |
[0x76] = { 0, KC_V }, |
[0x62] = { 0, KC_B }, |
[0x6e] = { 0, KC_N }, |
[0x6d] = { 0, KC_M }, |
[0x3b] = KC_SEMICOLON, |
[0x27] = KC_QUOTE, |
[0x5c] = KC_BACKSLASH, |
[0x2c] = { 0, KC_COMMA }, |
[0x2e] = { 0, KC_PERIOD }, |
[0x2f] = { 0, KC_SLASH }, |
// [0x2a] = KC_LSHIFT, |
[0x20] = { 0, KC_SPACE }, |
[0x7a] = KC_Z, |
[0x78] = KC_X, |
[0x63] = KC_C, |
[0x76] = KC_V, |
[0x62] = KC_B, |
[0x6e] = KC_N, |
[0x6d] = KC_M, |
[0x1b] = { 0, KC_ESCAPE }, |
[0x2c] = KC_COMMA, |
[0x2e] = KC_PERIOD, |
[0x2f] = KC_SLASH, |
[0x0a] = { 0, KC_ENTER }, |
[0x0d] = { 0, KC_ENTER }, |
// [0x36] = KC_RSHIFT, |
/* with Shift pressed */ |
// [0x1d] = KC_LCTRL, |
// [0x38] = KC_LALT, |
[0x20] = KC_SPACE, |
[0x7e] = { KM_LSHIFT, KC_BACKTICK }, |
[0x1b] = KC_ESCAPE, |
[0x21] = { KM_LSHIFT, KC_1 }, |
[0x40] = { KM_LSHIFT, KC_2 }, |
[0x23] = { KM_LSHIFT, KC_3 }, |
[0x24] = { KM_LSHIFT, KC_4 }, |
[0x25] = { KM_LSHIFT, KC_5 }, |
[0x5e] = { KM_LSHIFT, KC_6 }, |
[0x26] = { KM_LSHIFT, KC_7 }, |
[0x2a] = { KM_LSHIFT, KC_8 }, |
[0x28] = { KM_LSHIFT, KC_9 }, |
[0x29] = { KM_LSHIFT, KC_0 }, |
[0x0a] = KC_ENTER, |
[0x0d] = KC_ENTER |
[0x5f] = { KM_LSHIFT, KC_MINUS }, |
[0x2b] = { KM_LSHIFT, KC_EQUALS }, |
[0x51] = { KM_LSHIFT, KC_Q }, |
[0x57] = { KM_LSHIFT, KC_W }, |
[0x45] = { KM_LSHIFT, KC_E }, |
[0x52] = { KM_LSHIFT, KC_R }, |
[0x54] = { KM_LSHIFT, KC_T }, |
[0x59] = { KM_LSHIFT, KC_Y }, |
[0x55] = { KM_LSHIFT, KC_U }, |
[0x49] = { KM_LSHIFT, KC_I }, |
[0x4f] = { KM_LSHIFT, KC_O }, |
[0x50] = { KM_LSHIFT, KC_P }, |
[0x7b] = { KM_LSHIFT, KC_LBRACKET }, |
[0x7d] = { KM_LSHIFT, KC_RBRACKET }, |
[0x41] = { KM_LSHIFT, KC_A }, |
[0x53] = { KM_LSHIFT, KC_S }, |
[0x44] = { KM_LSHIFT, KC_D }, |
[0x46] = { KM_LSHIFT, KC_F }, |
[0x47] = { KM_LSHIFT, KC_G }, |
[0x48] = { KM_LSHIFT, KC_H }, |
[0x4a] = { KM_LSHIFT, KC_J }, |
[0x4b] = { KM_LSHIFT, KC_K }, |
[0x4c] = { KM_LSHIFT, KC_L }, |
[0x3a] = { KM_LSHIFT, KC_SEMICOLON }, |
[0x22] = { KM_LSHIFT, KC_QUOTE }, |
[0x7c] = { KM_LSHIFT, KC_BACKSLASH }, |
[0x5a] = { KM_LSHIFT, KC_Z }, |
[0x58] = { KM_LSHIFT, KC_X }, |
[0x43] = { KM_LSHIFT, KC_C }, |
[0x56] = { KM_LSHIFT, KC_V }, |
[0x42] = { KM_LSHIFT, KC_B }, |
[0x4e] = { KM_LSHIFT, KC_N }, |
[0x4d] = { KM_LSHIFT, KC_M }, |
[0x3c] = { KM_LSHIFT, KC_COMMA }, |
[0x3e] = { KM_LSHIFT, KC_PERIOD }, |
[0x3f] = { KM_LSHIFT, KC_SLASH } |
/* |
[0x1] = KC_PRNSCR, |
[0x1] = KC_SCROLL_LOCK, |
[0x1] = KC_PAUSE, |
*/ |
}; |
static int map_e1[][2] = |
static int map_e1[] = |
{ |
[0x50] = { 0, KC_F1 }, |
[0x51] = { 0, KC_F2 }, |
[0x52] = { 0, KC_F3 }, |
[0x53] = { 0, KC_F4 }, |
[0x50] = KC_F1, |
[0x51] = KC_F2, |
[0x52] = KC_F3, |
[0x53] = KC_F4, |
}; |
static int map_e2[][2] = |
static int map_e2[] = |
{ |
[0x41] = { 0, KC_UP }, |
[0x42] = { 0, KC_DOWN }, |
[0x44] = { 0, KC_LEFT }, |
[0x43] = { 0, KC_RIGHT }, |
[0x41] = KC_UP, |
[0x42] = KC_DOWN, |
[0x44] = KC_LEFT, |
[0x43] = KC_RIGHT, |
}; |
static int map_e2a[][2] = |
static int map_e2a[] = |
{ |
[0x35] = { 0, KC_F5 }, |
[0x37] = { 0, KC_F6 }, |
[0x38] = { 0, KC_F7 }, |
[0x39] = { 0, KC_F8 }, |
[0x35] = KC_F5, |
[0x37] = KC_F6, |
[0x38] = KC_F7, |
[0x39] = KC_F8, |
}; |
static int map_e2b[][2] = |
static int map_e2b[] = |
{ |
[0x30] = { 0, KC_F9 }, |
[0x31] = { 0, KC_F10 }, |
[0x32] = { 0, KC_F11 }, |
[0x33] = { 0, KC_F12 }, |
[0x30] = KC_F9, |
[0x31] = KC_F10, |
[0x32] = KC_F11, |
[0x33] = KC_F12, |
}; |
static unsigned int mods_keys[][2] = { |
{ KM_LSHIFT, KC_LSHIFT }, |
{ 0, 0 } |
}; |
static enum dec_state ds; |
238,12 → 190,15 |
static void parse_ds_start(int scancode) |
{ |
if (scancode < 0 || scancode >= sizeof(map_start) / sizeof(int)) |
return; |
if (scancode == 0x1b) { |
ds = ds_e; |
return; |
} |
parse_leaf(scancode, map_start, sizeof(map_start) / (2 * sizeof(int))); |
parse_leaf(scancode, map_start, sizeof(map_start) / sizeof(int)); |
} |
static void parse_ds_e(int scancode) |
257,12 → 212,12 |
default: ds = ds_start; return; |
} |
kbd_push_ev(KE_PRESS, KC_ESCAPE); |
kbd_push_ev(KE_PRESS, KC_ESCAPE, 0); |
} |
static void parse_ds_e1(int scancode) |
{ |
parse_leaf(scancode, map_e1, sizeof(map_e1) / (2 * sizeof(int))); |
parse_leaf(scancode, map_e1, sizeof(map_e1) / sizeof(int)); |
} |
static void parse_ds_e2(int scancode) |
273,23 → 228,22 |
default: ds = ds_start; break; |
} |
parse_leaf(scancode, map_e2, sizeof(map_e2) / (2 * sizeof(int))); |
parse_leaf(scancode, map_e2, sizeof(map_e2) / sizeof(int)); |
} |
static void parse_ds_e2a(int scancode) |
{ |
parse_leaf(scancode, map_e2a, sizeof(map_e2a) / (2 * sizeof(int))); |
parse_leaf(scancode, map_e2a, sizeof(map_e2a) / sizeof(int)); |
} |
static void parse_ds_e2b(int scancode) |
{ |
parse_leaf(scancode, map_e2b, sizeof(map_e2b) / (2 * sizeof(int))); |
parse_leaf(scancode, map_e2b, sizeof(map_e2b) / sizeof(int)); |
} |
static void parse_leaf(int scancode, int (*map)[2], size_t map_length) |
static void parse_leaf(int scancode, int *map, size_t map_length) |
{ |
unsigned int key, mod; |
int i; |
unsigned int key; |
ds = ds_start; |
296,31 → 250,9 |
if (scancode < 0 || scancode >= map_length) |
return; |
mod = map[scancode][0]; |
key = map[scancode][1]; |
/* Simulate modifier pressing. */ |
i = 0; |
while (mods_keys[i][0] != 0) { |
if (mod & mods_keys[i][0]) { |
kbd_push_ev(KE_PRESS, mods_keys[i][1]); |
} |
++i; |
} |
if (key != 0) { |
kbd_push_ev(KE_PRESS, key); |
kbd_push_ev(KE_RELEASE, key); |
} |
/* Simulate modifier releasing. */ |
i = 0; |
while (mods_keys[i][0] != 0) { |
if (mod & mods_keys[i][0]) { |
kbd_push_ev(KE_RELEASE, mods_keys[i][1]); |
} |
++i; |
} |
key = map[scancode]; |
if (key != 0) |
kbd_push_ev(KE_PRESS, key, 0); |
} |
/branches/dynload/uspace/srv/kbd/ctl/sun.c |
---|
65,7 → 65,7 |
key = scanmap_simple[scancode]; |
if (key != 0) |
kbd_push_ev(type, key); |
kbd_push_ev(type, key, 0); |
} |
/** Primary meaning of scancodes. */ |
/branches/dynload/uspace/srv/kbd/ctl/gxe_fb.c |
---|
47,7 → 47,7 |
static void parse_ds_e1b(int scancode); |
static void parse_ds_e1c(int scancode); |
static void parse_leaf(int scancode, int (*map)[2], size_t map_length); |
static void parse_leaf(int scancode, int *map, size_t map_length); |
enum dec_state { |
ds_start, |
58,165 → 58,117 |
ds_e1c |
}; |
static int map_start[][2] = { |
static int map_start[] = { |
[0x60] = { 0, KC_BACKTICK }, |
[0x60] = KC_BACKTICK, |
[0x31] = { 0, KC_1 }, |
[0x32] = { 0, KC_2 }, |
[0x33] = { 0, KC_3 }, |
[0x34] = { 0, KC_4 }, |
[0x35] = { 0, KC_5 }, |
[0x36] = { 0, KC_6 }, |
[0x37] = { 0, KC_7 }, |
[0x38] = { 0, KC_8 }, |
[0x39] = { 0, KC_9 }, |
[0x30] = { 0, KC_0 }, |
[0x31] = KC_1, |
[0x32] = KC_2, |
[0x33] = KC_3, |
[0x34] = KC_4, |
[0x35] = KC_5, |
[0x36] = KC_6, |
[0x37] = KC_7, |
[0x38] = KC_8, |
[0x39] = KC_9, |
[0x30] = KC_0, |
[0x2d] = { 0, KC_MINUS }, |
[0x3d] = { 0, KC_EQUALS }, |
[0x08] = { 0, KC_BACKSPACE }, |
[0x2d] = KC_MINUS, |
[0x3d] = KC_EQUALS, |
[0x08] = KC_BACKSPACE, |
[0x0f] = { 0, KC_TAB }, |
[0x0f] = KC_TAB, |
[0x71] = { 0, KC_Q }, |
[0x77] = { 0, KC_W }, |
[0x65] = { 0, KC_E }, |
[0x72] = { 0, KC_R }, |
[0x74] = { 0, KC_T }, |
[0x79] = { 0, KC_Y }, |
[0x75] = { 0, KC_U }, |
[0x69] = { 0, KC_I }, |
[0x6f] = { 0, KC_O }, |
[0x70] = { 0, KC_P }, |
[0x71] = KC_Q, |
[0x77] = KC_W, |
[0x65] = KC_E, |
[0x72] = KC_R, |
[0x74] = KC_T, |
[0x79] = KC_Y, |
[0x75] = KC_U, |
[0x69] = KC_I, |
[0x6f] = KC_O, |
[0x70] = KC_P, |
[0x5b] = { 0, KC_LBRACKET }, |
[0x5d] = { 0, KC_RBRACKET }, |
[0x5b] = KC_LBRACKET, |
[0x5d] = KC_RBRACKET, |
[0x61] = { 0, KC_A }, |
[0x73] = { 0, KC_S }, |
[0x64] = { 0, KC_D }, |
[0x66] = { 0, KC_F }, |
[0x67] = { 0, KC_G }, |
[0x68] = { 0, KC_H }, |
[0x6a] = { 0, KC_J }, |
[0x6b] = { 0, KC_K }, |
[0x6c] = { 0, KC_L }, |
// [0x3a] = KC_CAPS_LOCK, |
[0x3b] = { 0, KC_SEMICOLON }, |
[0x27] = { 0, KC_QUOTE }, |
[0x5c] = { 0, KC_BACKSLASH }, |
[0x61] = KC_A, |
[0x73] = KC_S, |
[0x64] = KC_D, |
[0x66] = KC_F, |
[0x67] = KC_G, |
[0x68] = KC_H, |
[0x6a] = KC_J, |
[0x6b] = KC_K, |
[0x6c] = KC_L, |
[0x7a] = { 0, KC_Z }, |
[0x78] = { 0, KC_X }, |
[0x63] = { 0, KC_C }, |
[0x76] = { 0, KC_V }, |
[0x62] = { 0, KC_B }, |
[0x6e] = { 0, KC_N }, |
[0x6d] = { 0, KC_M }, |
[0x3b] = KC_SEMICOLON, |
[0x27] = KC_QUOTE, |
[0x5c] = KC_BACKSLASH, |
[0x2c] = { 0, KC_COMMA }, |
[0x2e] = { 0, KC_PERIOD }, |
[0x2f] = { 0, KC_SLASH }, |
// [0x2a] = KC_LSHIFT, |
[0x20] = { 0, KC_SPACE }, |
[0x7a] = KC_Z, |
[0x78] = KC_X, |
[0x63] = KC_C, |
[0x76] = KC_V, |
[0x62] = KC_B, |
[0x6e] = KC_N, |
[0x6d] = KC_M, |
[0x1b] = { 0, KC_ESCAPE }, |
[0x2c] = KC_COMMA, |
[0x2e] = KC_PERIOD, |
[0x2f] = KC_SLASH, |
[0x0a] = { 0, KC_ENTER }, |
[0x0d] = { 0, KC_ENTER }, |
// [0x36] = KC_RSHIFT, |
/* with Shift pressed */ |
// [0x1d] = KC_LCTRL, |
// [0x38] = KC_LALT, |
[0x20] = KC_SPACE, |
[0x7e] = { KM_LSHIFT, KC_BACKTICK }, |
[0x1b] = KC_ESCAPE, |
[0x21] = { KM_LSHIFT, KC_1 }, |
[0x40] = { KM_LSHIFT, KC_2 }, |
[0x23] = { KM_LSHIFT, KC_3 }, |
[0x24] = { KM_LSHIFT, KC_4 }, |
[0x25] = { KM_LSHIFT, KC_5 }, |
[0x5e] = { KM_LSHIFT, KC_6 }, |
[0x26] = { KM_LSHIFT, KC_7 }, |
[0x2a] = { KM_LSHIFT, KC_8 }, |
[0x28] = { KM_LSHIFT, KC_9 }, |
[0x29] = { KM_LSHIFT, KC_0 }, |
[0x0a] = KC_ENTER, |
[0x0d] = KC_ENTER |
[0x5f] = { KM_LSHIFT, KC_MINUS }, |
[0x2b] = { KM_LSHIFT, KC_EQUALS }, |
[0x51] = { KM_LSHIFT, KC_Q }, |
[0x57] = { KM_LSHIFT, KC_W }, |
[0x45] = { KM_LSHIFT, KC_E }, |
[0x52] = { KM_LSHIFT, KC_R }, |
[0x54] = { KM_LSHIFT, KC_T }, |
[0x59] = { KM_LSHIFT, KC_Y }, |
[0x55] = { KM_LSHIFT, KC_U }, |
[0x49] = { KM_LSHIFT, KC_I }, |
[0x4f] = { KM_LSHIFT, KC_O }, |
[0x50] = { KM_LSHIFT, KC_P }, |
[0x7b] = { KM_LSHIFT, KC_LBRACKET }, |
[0x7d] = { KM_LSHIFT, KC_RBRACKET }, |
[0x41] = { KM_LSHIFT, KC_A }, |
[0x53] = { KM_LSHIFT, KC_S }, |
[0x44] = { KM_LSHIFT, KC_D }, |
[0x46] = { KM_LSHIFT, KC_F }, |
[0x47] = { KM_LSHIFT, KC_G }, |
[0x48] = { KM_LSHIFT, KC_H }, |
[0x4a] = { KM_LSHIFT, KC_J }, |
[0x4b] = { KM_LSHIFT, KC_K }, |
[0x4c] = { KM_LSHIFT, KC_L }, |
[0x3a] = { KM_LSHIFT, KC_SEMICOLON }, |
[0x22] = { KM_LSHIFT, KC_QUOTE }, |
[0x7c] = { KM_LSHIFT, KC_BACKSLASH }, |
[0x5a] = { KM_LSHIFT, KC_Z }, |
[0x58] = { KM_LSHIFT, KC_X }, |
[0x43] = { KM_LSHIFT, KC_C }, |
[0x56] = { KM_LSHIFT, KC_V }, |
[0x42] = { KM_LSHIFT, KC_B }, |
[0x4e] = { KM_LSHIFT, KC_N }, |
[0x4d] = { KM_LSHIFT, KC_M }, |
[0x3c] = { KM_LSHIFT, KC_COMMA }, |
[0x3e] = { KM_LSHIFT, KC_PERIOD }, |
[0x3f] = { KM_LSHIFT, KC_SLASH } |
/* |
[0x1] = KC_PRNSCR, |
[0x1] = KC_SCROLL_LOCK, |
[0x1] = KC_PAUSE, |
*/ |
}; |
static int map_e1[][2] = |
static int map_e1[] = |
{ |
}; |
static int map_e1a[][2] = |
static int map_e1a[] = |
{ |
[0x50] = { 0, KC_F1 }, |
[0x51] = { 0, KC_F2 }, |
[0x52] = { 0, KC_F3 }, |
[0x53] = { 0, KC_F4 }, |
[0x50] = KC_F1, |
[0x51] = KC_F2, |
[0x52] = KC_F3, |
[0x53] = KC_F4, |
}; |
static int map_e1b[][2] = |
static int map_e1b[] = |
{ |
[0x33] = { 0, KC_F5 }, |
[0x37] = { 0, KC_F6 }, |
[0x38] = { 0, KC_F7 }, |
[0x39] = { 0, KC_F8 }, |
[0x33] = KC_F5, |
[0x37] = KC_F6, |
[0x38] = KC_F7, |
[0x39] = KC_F8, |
}; |
static int map_e1c[][2] = |
static int map_e1c[] = |
{ |
[0x38] = { 0, KC_F9 }, |
[0x39] = { 0, KC_F10 }, |
[0x33] = { 0, KC_F11 }, |
[0x34] = { 0, KC_F12 }, |
[0x38] = KC_F9, |
[0x39] = KC_F10, |
[0x33] = KC_F11, |
[0x34] = KC_F12, |
}; |
static unsigned int mods_keys[][2] = { |
{ KM_LSHIFT, KC_LSHIFT }, |
{ 0, 0 } |
}; |
static enum dec_state ds = ds_start; |
239,7 → 191,7 |
return; |
} |
parse_leaf(scancode, map_start, sizeof(map_start) / (2 * sizeof(int))); |
parse_leaf(scancode, map_start, sizeof(map_start) / sizeof(int)); |
} |
static void parse_ds_e(int scancode) |
250,7 → 202,7 |
default: ds = ds_start; return; |
} |
kbd_push_ev(KE_PRESS, KC_ESCAPE); |
kbd_push_ev(KE_PRESS, KC_ESCAPE, 0); |
} |
static void parse_ds_e1(int scancode) |
262,28 → 214,27 |
default: ds = ds_start; break; |
} |
parse_leaf(scancode, map_e1, sizeof(map_e1) / (2 * sizeof(int))); |
parse_leaf(scancode, map_e1, sizeof(map_e1) / sizeof(int)); |
} |
static void parse_ds_e1a(int scancode) |
{ |
parse_leaf(scancode, map_e1a, sizeof(map_e1a) / (2 * sizeof(int))); |
parse_leaf(scancode, map_e1a, sizeof(map_e1a) / sizeof(int)); |
} |
static void parse_ds_e1b(int scancode) |
{ |
parse_leaf(scancode, map_e1b, sizeof(map_e1b) / (2 * sizeof(int))); |
parse_leaf(scancode, map_e1b, sizeof(map_e1b) / sizeof(int)); |
} |
static void parse_ds_e1c(int scancode) |
{ |
parse_leaf(scancode, map_e1c, sizeof(map_e1c) / (2 * sizeof(int))); |
parse_leaf(scancode, map_e1c, sizeof(map_e1c) / sizeof(int)); |
} |
static void parse_leaf(int scancode, int (*map)[2], size_t map_length) |
static void parse_leaf(int scancode, int *map, size_t map_length) |
{ |
unsigned int key, mod; |
int i; |
unsigned int key; |
ds = ds_start; |
290,33 → 241,12 |
if (scancode < 0 || scancode >= map_length) |
return; |
mod = map[scancode][0]; |
key = map[scancode][1]; |
key = map[scancode]; |
if (key != 0) |
kbd_push_ev(KE_PRESS, key, 0); |
} |
/* Simulate modifier pressing. */ |
i = 0; |
while (mods_keys[i][0] != 0) { |
if (mod & mods_keys[i][0]) { |
kbd_push_ev(KE_PRESS, mods_keys[i][1]); |
} |
++i; |
} |
if (key != 0) { |
kbd_push_ev(KE_PRESS, key); |
kbd_push_ev(KE_RELEASE, key); |
} |
/* Simulate modifier releasing. */ |
i = 0; |
while (mods_keys[i][0] != 0) { |
if (mod & mods_keys[i][0]) { |
kbd_push_ev(KE_RELEASE, mods_keys[i][1]); |
} |
++i; |
} |
} |
/** |
* @} |
*/ |
/branches/dynload/uspace/srv/kbd/include/kbd.h |
---|
45,11 → 45,8 |
#define KBD_MS_MIDDLE 1027 |
#define KBD_MS_MOVE 1028 |
extern int cir_service; |
extern int cir_phone; |
extern void kbd_push_scancode(int); |
extern void kbd_push_ev(int, unsigned int); |
extern void kbd_push_ev(int, unsigned int, unsigned int); |
#endif |
/branches/dynload/uspace/srv/kbd/port/z8530.c |
---|
35,7 → 35,6 |
*/ |
#include <ipc/ipc.h> |
#include <ipc/bus.h> |
#include <async.h> |
#include <sysinfo.h> |
#include <kbd.h> |
42,40 → 41,19 |
#include <kbd_port.h> |
#include <sys/types.h> |
#define CHAN_A_STATUS 4 |
#define CHAN_A_DATA 6 |
#define RR0_RCA 1 |
static irq_cmd_t z8530_cmds[] = { |
/** Top-half pseudocode for z8530. */ |
irq_cmd_t z8530_cmds[] = { |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0, /* will be patched in run-time */ |
.dstarg = 1 |
}, |
{ |
.cmd = CMD_BTEST, |
.value = RR0_RCA, |
.srcarg = 1, |
.dstarg = 3 |
}, |
{ |
.cmd = CMD_PREDICATE, |
.value = 2, |
.srcarg = 3 |
}, |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0, /* will be patched in run-time */ |
.dstarg = 2 |
}, |
{ |
.cmd = CMD_ACCEPT |
CMD_MEM_READ_1, |
0, /**< Address. Will be patched in run-time. */ |
0, /**< Value. Not used. */ |
1 /**< Arg 1 will contain the result. */ |
} |
}; |
irq_code_t z8530_kbd = { |
sizeof(z8530_cmds) / sizeof(irq_cmd_t), |
1, |
z8530_cmds |
}; |
84,23 → 62,16 |
int kbd_port_init(void) |
{ |
async_set_interrupt_received(z8530_irq_handler); |
z8530_cmds[0].addr = (void *) sysinfo_value("kbd.address.virtual") + |
CHAN_A_STATUS; |
z8530_cmds[3].addr = (void *) sysinfo_value("kbd.address.virtual") + |
CHAN_A_DATA; |
z8530_cmds[0].addr = (void *) sysinfo_value("kbd.address.virtual") + 6; |
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), |
sysinfo_value("kbd.inr"), &z8530_kbd); |
0, &z8530_kbd); |
return 0; |
} |
static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call) |
{ |
int scan_code = IPC_GET_ARG2(*call); |
int scan_code = IPC_GET_ARG1(*call); |
kbd_push_scancode(scan_code); |
if (cir_service) |
async_msg_1(cir_phone, BUS_CLEAR_INTERRUPT, |
IPC_GET_METHOD(*call)); |
} |
/** @} |
/branches/dynload/uspace/srv/kbd/port/gxemul.c |
---|
42,17 → 42,15 |
static irq_cmd_t gxemul_cmds[] = { |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0, /* will be patched in run-time */ |
.dstarg = 2, |
}, |
{ |
.cmd = CMD_ACCEPT |
CMD_MEM_READ_1, |
(void *) 0, |
0, |
2 |
} |
}; |
static irq_code_t gxemul_kbd = { |
sizeof(gxemul_cmds) / sizeof(irq_cmd_t), |
1, |
gxemul_cmds |
}; |
/branches/dynload/uspace/srv/kbd/port/ns16550.c |
---|
50,37 → 50,12 |
#define MCR_REG 4 /** Modem Control Register. */ |
#define LSR_REG 5 /** Line Status Register. */ |
#define LSR_DATA_READY 0x01 |
static irq_cmd_t ns16550_cmds[] = { |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0, /* will be patched in run-time */ |
.dstarg = 1 |
}, |
{ |
.cmd = CMD_BTEST, |
.value = LSR_DATA_READY, |
.srcarg = 1, |
.dstarg = 3 |
}, |
{ |
.cmd = CMD_PREDICATE, |
.value = 2, |
.srcarg = 3 |
}, |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0, /* will be patched in run-time */ |
.dstarg = 2 |
}, |
{ |
.cmd = CMD_ACCEPT |
} |
irq_cmd_t ns16550_cmds[1] = { |
{ CMD_PORT_READ_1, 0, 0, 2 }, |
}; |
irq_code_t ns16550_kbd = { |
sizeof(ns16550_cmds) / sizeof(irq_cmd_t), |
1, |
ns16550_cmds |
}; |
93,8 → 68,7 |
async_set_interrupt_received(ns16550_irq_handler); |
ns16550_port = sysinfo_value("kbd.port"); |
ns16550_kbd.cmds[0].addr = (void *) (ns16550_port + LSR_REG); |
ns16550_kbd.cmds[3].addr = (void *) (ns16550_port + RBR_REG); |
ns16550_kbd.cmds[0].addr = (void *) (ns16550_port + RBR_REG); |
ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), |
0, &ns16550_kbd); |
iospace_enable(task_get_id(), ns16550_port, 8); |
102,6 → 76,8 |
return 0; |
} |
#define LSR_DATA_READY 0x01 |
static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call) |
{ |
int scan_code = IPC_GET_ARG2(*call); |
/branches/dynload/uspace/srv/kbd/port/msim.c |
---|
40,20 → 40,12 |
#include <kbd_port.h> |
#include <kbd.h> |
irq_cmd_t msim_cmds[] = { |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0, /* will be patched in run-time */ |
.dstarg = 2 |
}, |
{ |
.cmd = CMD_ACCEPT |
} |
irq_cmd_t msim_cmds[1] = { |
{ CMD_MEM_READ_1, (void *) 0, 0, 2 } |
}; |
irq_code_t msim_kbd = { |
sizeof(msim_cmds) / sizeof(irq_cmd_t), |
1, |
msim_cmds |
}; |
/branches/dynload/uspace/srv/kbd/port/i8042.c |
---|
63,35 → 63,13 |
#define MOUSE_OUT_INIT 0xf4 |
#define MOUSE_ACK 0xfa |
static irq_cmd_t i8042_cmds[] = { |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0x64, |
.dstarg = 1 |
}, |
{ |
.cmd = CMD_BTEST, |
.value = i8042_OUTPUT_FULL, |
.srcarg = 1, |
.dstarg = 3 |
}, |
{ |
.cmd = CMD_PREDICATE, |
.value = 2, |
.srcarg = 3 |
}, |
{ |
.cmd = CMD_PIO_READ_8, |
.addr = (void *) 0x60, |
.dstarg = 2 |
}, |
{ |
.cmd = CMD_ACCEPT |
} |
static irq_cmd_t i8042_cmds[2] = { |
{ CMD_PORT_READ_1, (void *) 0x64, 0, 1 }, |
{ CMD_PORT_READ_1, (void *) 0x60, 0, 2 } |
}; |
static irq_code_t i8042_kbd = { |
sizeof(i8042_cmds) / sizeof(irq_cmd_t), |
2, |
i8042_cmds |
}; |
/branches/dynload/uspace/srv/kbd/generic/kbd.c |
---|
37,7 → 37,6 |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <sysinfo.h> |
#include <stdio.h> |
#include <unistd.h> |
#include <stdlib.h> |
47,7 → 46,6 |
#include <errno.h> |
#include <libadt/fifo.h> |
#include <kbd/kbd.h> |
#include <kbd/keycode.h> |
#include <kbd.h> |
#include <key_buffer.h> |
59,70 → 57,23 |
int cons_connected = 0; |
int phone2cons = -1; |
keybuffer_t keybuffer; |
keybuffer_t keybuffer; |
/** Currently active modifiers. */ |
static unsigned mods = KM_NUM_LOCK; |
/** Currently pressed lock keys. We track these to tackle autorepeat. */ |
static unsigned lock_keys; |
int cir_service = 0; |
int cir_phone = -1; |
void kbd_push_scancode(int scancode) |
{ |
/* printf("scancode: 0x%x\n", scancode);*/ |
printf("scancode: 0x%x\n", scancode); |
kbd_ctl_parse_scancode(scancode); |
} |
void kbd_push_ev(int type, unsigned int key) |
#include <kbd/keycode.h> |
void kbd_push_ev(int type, unsigned int key, unsigned int mods) |
{ |
kbd_event_t ev; |
unsigned mod_mask; |
switch (key) { |
case KC_LCTRL: mod_mask = KM_LCTRL; break; |
case KC_RCTRL: mod_mask = KM_RCTRL; break; |
case KC_LSHIFT: mod_mask = KM_LSHIFT; break; |
case KC_RSHIFT: mod_mask = KM_RSHIFT; break; |
case KC_LALT: mod_mask = KM_LALT; break; |
case KC_RALT: mod_mask = KM_RALT; break; |
default: mod_mask = 0; break; |
} |
if (mod_mask != 0) { |
if (type == KE_PRESS) |
mods = mods | mod_mask; |
else |
mods = mods & ~mod_mask; |
} |
switch (key) { |
case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break; |
case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; break; |
case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; break; |
default: mod_mask = 0; break; |
} |
if (mod_mask != 0) { |
if (type == KE_PRESS) { |
/* |
* Only change lock state on transition from released |
* to pressed. This prevents autorepeat from messing |
* up the lock state. |
*/ |
mods = mods ^ (mod_mask & ~lock_keys); |
lock_keys = lock_keys | mod_mask; |
} else { |
lock_keys = lock_keys & ~mod_mask; |
} |
} |
/* |
printf("type: %d\n", type); |
printf("mods: 0x%x\n", mods); |
printf("keycode: %u\n", key); |
*/ |
ev.type = type; |
ev.key = key; |
ev.mods = mods; |
132,6 → 83,27 |
async_msg_4(phone2cons, KBD_EVENT, ev.type, ev.key, ev.mods, ev.c); |
} |
//static void irq_handler(ipc_callid_t iid, ipc_call_t *call) |
//{ |
// kbd_event_t ev; |
// |
// kbd_arch_process(&keybuffer, call); |
// |
// if (cons_connected && phone2cons != -1) { |
// /* |
// * One interrupt can produce more than one event so the result |
// * is stored in a FIFO. |
// */ |
// while (!keybuffer_empty(&keybuffer)) { |
// if (!keybuffer_pop(&keybuffer, &ev)) |
// break; |
// |
// async_msg_4(phone2cons, KBD_EVENT, ev.type, ev.key, |
// ev.mods, ev.c); |
// } |
// } |
//} |
static void console_connection(ipc_callid_t iid, ipc_call_t *icall) |
{ |
ipc_callid_t callid; |
170,6 → 142,7 |
} |
int main(int argc, char **argv) |
{ |
printf(NAME ": HelenOS Keyboard service\n"); |
176,18 → 149,6 |
ipcarg_t phonead; |
if (sysinfo_value("kbd.cir.fhc") == 1) |
cir_service = SERVICE_FHC; |
else if (sysinfo_value("kbd.cir.obio") == 1) |
cir_service = SERVICE_OBIO; |
if (cir_service) { |
while (cir_phone < 0) { |
cir_phone = ipc_connect_me_to(PHONE_NS, cir_service, |
0, 0); |
} |
} |
/* Initialize port driver. */ |
if (kbd_port_init()) |
return -1; |
/branches/dynload/uspace/srv/kbd/Makefile |
---|
79,8 → 79,8 |
endif |
ifeq ($(UARCH), ia64) |
GENARCH_SOURCES += \ |
port/i8042.c \ |
ctl/pc.c |
port/dummy.c \ |
ctl/stty.c |
endif |
ifeq ($(MACHINE), msim) |
GENARCH_SOURCES += \ |
/branches/dynload/uspace/srv/kbd/layout/us_qwerty.c |
---|
36,7 → 36,26 |
#include <kbd/keycode.h> |
#include <layout.h> |
static char map_lcase[] = { |
static int map_normal[] = { |
[KC_BACKTICK] = '`', |
[KC_1] = '1', |
[KC_2] = '2', |
[KC_3] = '3', |
[KC_4] = '4', |
[KC_5] = '5', |
[KC_6] = '6', |
[KC_7] = '7', |
[KC_8] = '8', |
[KC_9] = '9', |
[KC_0] = '0', |
[KC_MINUS] = '-', |
[KC_EQUALS] = '=', |
[KC_BACKSPACE] = '\b', |
[KC_TAB] = '\t', |
[KC_Q] = 'q', |
[KC_W] = 'w', |
[KC_E] = 'e', |
48,6 → 67,9 |
[KC_O] = 'o', |
[KC_P] = 'p', |
[KC_LBRACKET] = '[', |
[KC_RBRACKET] = ']', |
[KC_A] = 'a', |
[KC_S] = 's', |
[KC_D] = 'd', |
58,6 → 80,11 |
[KC_K] = 'k', |
[KC_L] = 'l', |
[KC_SEMICOLON] = ';', |
[KC_QUOTE] = '\'', |
[KC_BACKSLASH] = '\\', |
[KC_ENTER] = '\n', |
[KC_Z] = 'z', |
[KC_X] = 'x', |
[KC_C] = 'c', |
65,162 → 92,20 |
[KC_B] = 'b', |
[KC_N] = 'n', |
[KC_M] = 'm', |
}; |
static char map_ucase[] = { |
[KC_Q] = 'Q', |
[KC_W] = 'W', |
[KC_E] = 'E', |
[KC_R] = 'R', |
[KC_T] = 'T', |
[KC_Y] = 'Y', |
[KC_U] = 'U', |
[KC_I] = 'I', |
[KC_O] = 'O', |
[KC_P] = 'P', |
[KC_A] = 'A', |
[KC_S] = 'S', |
[KC_D] = 'D', |
[KC_F] = 'F', |
[KC_G] = 'G', |
[KC_H] = 'H', |
[KC_J] = 'J', |
[KC_K] = 'K', |
[KC_L] = 'L', |
[KC_Z] = 'Z', |
[KC_X] = 'X', |
[KC_C] = 'C', |
[KC_V] = 'V', |
[KC_B] = 'B', |
[KC_N] = 'N', |
[KC_M] = 'M', |
}; |
static char map_not_shifted[] = { |
[KC_BACKTICK] = '`', |
[KC_1] = '1', |
[KC_2] = '2', |
[KC_3] = '3', |
[KC_4] = '4', |
[KC_5] = '5', |
[KC_6] = '6', |
[KC_7] = '7', |
[KC_8] = '8', |
[KC_9] = '9', |
[KC_0] = '0', |
[KC_MINUS] = '-', |
[KC_EQUALS] = '=', |
[KC_LBRACKET] = '[', |
[KC_RBRACKET] = ']', |
[KC_SEMICOLON] = ';', |
[KC_QUOTE] = '\'', |
[KC_BACKSLASH] = '\\', |
[KC_COMMA] = ',', |
[KC_PERIOD] = '.', |
[KC_SLASH] = '/', |
}; |
static char map_shifted[] = { |
[KC_BACKTICK] = '~', |
[KC_1] = '!', |
[KC_2] = '@', |
[KC_3] = '#', |
[KC_4] = '$', |
[KC_5] = '%', |
[KC_6] = '^', |
[KC_7] = '&', |
[KC_8] = '*', |
[KC_9] = '(', |
[KC_0] = ')', |
[KC_MINUS] = '_', |
[KC_EQUALS] = '+', |
[KC_LBRACKET] = '{', |
[KC_RBRACKET] = '}', |
[KC_SEMICOLON] = ':', |
[KC_QUOTE] = '"', |
[KC_BACKSLASH] = '|', |
[KC_COMMA] = '<', |
[KC_PERIOD] = '>', |
[KC_SLASH] = '?', |
[KC_SPACE] = ' ' |
}; |
static char map_neutral[] = { |
[KC_BACKSPACE] = '\b', |
[KC_TAB] = '\t', |
[KC_ENTER] = '\n', |
[KC_SPACE] = ' ', |
[KC_NSLASH] = '/', |
[KC_NTIMES] = '*', |
[KC_NMINUS] = '-', |
[KC_NPLUS] = '+', |
[KC_NENTER] = '\n' |
}; |
static char map_numeric[] = { |
[KC_N7] = '7', |
[KC_N8] = '8', |
[KC_N9] = '9', |
[KC_N4] = '4', |
[KC_N5] = '5', |
[KC_N6] = '6', |
[KC_N1] = '1', |
[KC_N2] = '2', |
[KC_N3] = '3', |
[KC_N0] = '0', |
[KC_NPERIOD] = '.' |
}; |
static int translate(unsigned int key, char *map, size_t map_length) |
{ |
if (key >= map_length) return 0; |
return map[key]; |
} |
char layout_parse_ev(kbd_event_t *ev) |
{ |
char c; |
/* Produce no characters when Ctrl or Alt is pressed. */ |
if ((ev->mods & (KM_CTRL | KM_ALT)) != 0) |
if (ev->key >= sizeof(map_normal) / sizeof(int)) |
return 0; |
c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(char)); |
if (c != 0) return c; |
if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0)) |
c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(char)); |
else |
c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(char)); |
if (c != 0) return c; |
if ((ev->mods & KM_SHIFT) != 0) |
c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(char)); |
else |
c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(char)); |
if (c != 0) return c; |
if ((ev->mods & KM_NUM_LOCK) != 0) |
c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(char)); |
else |
c = 0; |
return c; |
return map_normal[ev->key]; |
} |
/** |
/branches/dynload/uspace/srv/kbd/layout/us_dvorak.c |
---|
36,7 → 36,29 |
#include <kbd/keycode.h> |
#include <layout.h> |
static char map_lcase[] = { |
static int map_normal[] = { |
[KC_BACKTICK] = '`', |
[KC_1] = '1', |
[KC_2] = '2', |
[KC_3] = '3', |
[KC_4] = '4', |
[KC_5] = '5', |
[KC_6] = '6', |
[KC_7] = '7', |
[KC_8] = '8', |
[KC_9] = '9', |
[KC_0] = '0', |
[KC_MINUS] = '[', |
[KC_EQUALS] = ']', |
[KC_BACKSPACE] = '\b', |
[KC_TAB] = '\t', |
[KC_Q] = '\'', |
[KC_W] = ',', |
[KC_E] = '.', |
[KC_R] = 'p', |
[KC_T] = 'y', |
[KC_Y] = 'f', |
45,6 → 67,9 |
[KC_O] = 'r', |
[KC_P] = 'l', |
[KC_LBRACKET] = '/', |
[KC_RBRACKET] = '=', |
[KC_A] = 'a', |
[KC_S] = 'o', |
[KC_D] = 'e', |
56,7 → 81,10 |
[KC_L] = 'n', |
[KC_SEMICOLON] = 's', |
[KC_QUOTE] = '-', |
[KC_BACKSLASH] = '\\', |
[KC_Z] = ';', |
[KC_X] = 'q', |
[KC_C] = 'j', |
[KC_V] = 'k', |
67,141 → 95,18 |
[KC_COMMA] = 'w', |
[KC_PERIOD] = 'v', |
[KC_SLASH] = 'z', |
}; |
static char map_ucase[] = { |
[KC_R] = 'P', |
[KC_T] = 'Y', |
[KC_Y] = 'F', |
[KC_U] = 'G', |
[KC_I] = 'C', |
[KC_O] = 'R', |
[KC_P] = 'L', |
[KC_A] = 'A', |
[KC_S] = 'O', |
[KC_D] = 'E', |
[KC_F] = 'U', |
[KC_G] = 'I', |
[KC_H] = 'D', |
[KC_J] = 'H', |
[KC_K] = 'T', |
[KC_L] = 'N', |
[KC_SEMICOLON] = 'S', |
[KC_X] = 'Q', |
[KC_C] = 'J', |
[KC_V] = 'K', |
[KC_B] = 'X', |
[KC_N] = 'B', |
[KC_M] = 'M', |
[KC_COMMA] = 'W', |
[KC_PERIOD] = 'V', |
[KC_SLASH] = 'Z', |
}; |
static char map_not_shifted[] = { |
[KC_BACKTICK] = '`', |
[KC_1] = '1', |
[KC_2] = '2', |
[KC_3] = '3', |
[KC_4] = '4', |
[KC_5] = '5', |
[KC_6] = '6', |
[KC_7] = '7', |
[KC_8] = '8', |
[KC_9] = '9', |
[KC_0] = '0', |
[KC_MINUS] = '[', |
[KC_EQUALS] = ']', |
[KC_Q] = '\'', |
[KC_W] = ',', |
[KC_E] = '.', |
[KC_LBRACKET] = '/', |
[KC_RBRACKET] = '=', |
[KC_QUOTE] = '-', |
[KC_BACKSLASH] = '\\', |
[KC_Z] = ';', |
}; |
static char map_shifted[] = { |
[KC_BACKTICK] = '~', |
[KC_1] = '!', |
[KC_2] = '@', |
[KC_3] = '#', |
[KC_4] = '$', |
[KC_5] = '%', |
[KC_6] = '^', |
[KC_7] = '&', |
[KC_8] = '*', |
[KC_9] = '(', |
[KC_0] = ')', |
[KC_MINUS] = '{', |
[KC_EQUALS] = '}', |
[KC_Q] = '"', |
[KC_W] = '<', |
[KC_E] = '>', |
[KC_LBRACKET] = '?', |
[KC_RBRACKET] = '+', |
[KC_QUOTE] = '_', |
[KC_BACKSLASH] = '|', |
[KC_Z] = ':', |
}; |
static char map_neutral[] = { |
[KC_BACKSPACE] = '\b', |
[KC_TAB] = '\t', |
[KC_ENTER] = '\n' |
}; |
static int translate(unsigned int key, char *map, size_t map_length) |
{ |
if (key >= map_length) return 0; |
return map[key]; |
} |
char layout_parse_ev(kbd_event_t *ev) |
{ |
char c; |
/* Produce no characters when Ctrl or Alt is pressed. */ |
if ((ev->mods & (KM_CTRL | KM_ALT)) != 0) |
if (ev->key >= sizeof(map_normal) / sizeof(int)) |
return 0; |
c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(char)); |
if (c != 0) return c; |
if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0)) |
c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(char)); |
else |
c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(char)); |
if (c != 0) return c; |
if ((ev->mods & KM_SHIFT) != 0) |
c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(char)); |
else |
c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(char)); |
if (c != 0 ) return c; |
return map_normal[ev->key]; |
} |
/** |
* @} |
*/ |
/branches/dynload/uspace/srv/loader/main.c |
---|
278,9 → 278,6 |
*/ |
static void loader_run(ipc_callid_t rid, ipc_call_t *request) |
{ |
/* Set the task name. */ |
task_set_name(pathname); |
if (is_dyn_linked == true) { |
/* Dynamically linked program */ |
DPRINTF("Run ELF interpreter.\n"); |
/branches/dynload/uspace/Makefile |
---|
68,12 → 68,6 |
DIRS += srv/pci |
endif |
ifeq ($(UARCH),sparc64) |
DIRS += \ |
srv/fhc \ |
srv/obio |
endif |
BUILDS := $(addsuffix .build,$(DIRS)) |
CLEANS := $(addsuffix .clean,$(DIRS)) |
/branches/dynload/HelenOS.config |
---|
60,8 → 60,8 |
@ "pentium4" Pentium 4 |
@ "pentium3" Pentium 3 |
@ "core" Core Solo/Duo |
@ "athlon_xp" Athlon XP |
@ "athlon_mp" Athlon MP |
@ "athlon-xp" Athlon XP |
@ "athlon-mp" Athlon MP |
! [PLATFORM=ia32] MACHINE (choice) |
% CPU type |
243,7 → 243,7 |
## Kernel configuration |
% Fences |
! [PLATFORM=ia32&(MACHINE=athlon_xp|MACHINE=athlon_mp|MACHINE=pentium3)] CONFIG_FENCES_P3 (y) |
! [PLATFORM=ia32&(MACHINE=athlon-xp|MACHINE=athlon-mp|MACHINE=pentium3)] CONFIG_FENCES_P3 (y) |
% Fences |
! [PLATFORM=ia32&(MACHINE=pentium4|MACHINE=core)] CONFIG_FENCES_P4 (y) |
291,13 → 291,13 |
## Kernel features options |
% Support for SMP |
! [(PLATFORM=ia32&MACHINE!=athlon_xp)|PLATFORM=amd64|PLATFORM=sparc64|PLATFORM=ia64|(PLATFORM=mips32&MACHINE=msim)] CONFIG_SMP (y/n) |
! [(PLATFORM=ia32&MACHINE!=athlon-xp)|PLATFORM=amd64|PLATFORM=sparc64|PLATFORM=ia64|(PLATFORM=mips32&MACHINE=msim)] CONFIG_SMP (y/n) |
% Improved support for hyperthreading |
! [PLATFORM=amd64&CONFIG_SMP=y] CONFIG_HT (y/n) |
% Improved support for hyperthreading |
! [PLATFORM=ia32&MACHINE!=athlon_xp&MACHINE!=athlon_mp&MACHINE!=pentium3&CONFIG_SMP=y] CONFIG_HT (y/n) |
! [PLATFORM=ia32&MACHINE!=athlon-xp&MACHINE!=athlon-mp&MACHINE!=pentium3&CONFIG_SMP=y] CONFIG_HT (y/n) |
% Lazy FPU context switching |
! [CONFIG_FPU=y] CONFIG_FPU_LAZY (y/n) |
/branches/dynload/boot/arch/sparc64/loader/Makefile |
---|
102,9 → 102,7 |
$(USPACEDIR)/srv/kbd/kbd \ |
$(USPACEDIR)/srv/console/console \ |
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \ |
$(USPACEDIR)/srv/fs/fat/fat \ |
$(USPACEDIR)/srv/fhc/fhc \ |
$(USPACEDIR)/srv/obio/obio |
$(USPACEDIR)/srv/fs/fat/fat |
RD_APPS = \ |
$(USPACEDIR)/app/tetris/tetris \ |