/trunk/kernel/genarch/include/kbd/z8530.h |
---|
37,8 → 37,8 |
#ifndef KERN_Z8530_H_ |
#define KERN_Z8530_H_ |
#include <irq.h> |
#include <typedefs.h> |
#include <ddi/irq.h> |
extern bool z8530_belongs_to_kernel; |
/trunk/kernel/genarch/include/kbd/ns16550.h |
---|
38,7 → 38,7 |
#define KERN_NS16550_H_ |
#include <typedefs.h> |
#include <irq.h> |
#include <ddi/irq.h> |
extern void ns16550_init(void); |
extern void ns16550_poll(void); |
/trunk/kernel/genarch/src/kbd/ns16550.c |
---|
39,7 → 39,7 |
#include <genarch/kbd/scanc.h> |
#include <genarch/kbd/scanc_sun.h> |
#include <arch/drivers/ns16550.h> |
#include <irq.h> |
#include <ddi/irq.h> |
#include <arch/interrupt.h> |
#include <cpu.h> |
#include <arch/asm.h> |
/trunk/kernel/genarch/src/kbd/z8530.c |
---|
39,7 → 39,7 |
#include <genarch/kbd/scanc.h> |
#include <genarch/kbd/scanc_sun.h> |
#include <arch/drivers/z8530.h> |
#include <irq.h> |
#include <ddi/irq.h> |
#include <arch/interrupt.h> |
#include <arch/drivers/kbd.h> |
#include <arch/drivers/fhc.h> |
/trunk/kernel/generic/include/irq.h |
---|
File deleted |
/trunk/kernel/generic/include/ddi/irq.h |
---|
0,0 → 1,90 |
/* |
* 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 genericddi |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_IRQ_H_ |
#define KERN_IRQ_H_ |
#include <arch/types.h> |
#include <adt/list.h> |
typedef enum { |
IRQ_DECLINE, /**< Decline to service. */ |
IRQ_ACCEPT /**< Accept to service. */ |
} irq_ownership_t; |
typedef enum { |
IRQ_TRIGGER_LEVEL = 1, |
IRQ_TRIGGER_EDGE |
} irq_trigger_t; |
typedef struct irq irq_t; |
typedef void (* irq_handler_t)(irq_t *irq, void *arg, ...); |
/** Structure representing one device IRQ. |
* |
* If one device has multiple interrupts, there will |
* be multiple irq_t instantions with the same |
* devno. |
*/ |
struct irq { |
/** Hash table link. */ |
link_t link; |
/** Unique device number. -1 if not yet assigned. */ |
devno_t devno; |
/** Actual IRQ number. -1 if not yet assigned. */ |
inr_t inr; |
/** Task ID of the task to be notified about the IRQ or 0. */ |
task_id_t notif; |
/** Trigger level of the IRQ.*/ |
irq_trigger_t trigger; |
/** Claim ownership of the IRQ. */ |
irq_ownership_t (* claim)(void); |
/** Handler for this IRQ and device. */ |
irq_handler_t handler; |
/** Argument for the handler. */ |
void *arg; |
}; |
extern void irq_init(count_t inrs, count_t chains); |
extern void irq_initialize(irq_t *irq); |
extern void irq_register(irq_t *irq); |
extern irq_t *irq_dispatch(inr_t inr); |
#endif |
/** @} |
*/ |
/trunk/kernel/generic/include/ddi/device.h |
---|
0,0 → 1,45 |
/* |
* 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 genericddi |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_DEVICE_H_ |
#define KERN_DEVICE_H_ |
#include <typedefs.h> |
extern devno_t device_assign_devno(void); |
#endif |
/** @} |
*/ |
/trunk/kernel/generic/include/typedefs.h |
---|
95,6 → 95,9 |
typedef struct btree_node btree_node_t; |
typedef struct btree btree_t; |
typedef signed int inr_t; |
typedef signed int devno_t; |
#endif |
/** @} |
/trunk/kernel/generic/src/interrupt/irq.c |
---|
File deleted |
/trunk/kernel/generic/src/ddi/device.c |
---|
0,0 → 1,59 |
/* |
* 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 genericddi |
* @{ |
*/ |
/** |
* @file |
* @brief Device numbers. |
*/ |
#include <ddi/device.h> |
#include <atomic.h> |
#include <debug.h> |
#include <typedefs.h> |
static atomic_t last; |
/** Assign new device number. |
* |
* @return Unique device number. |
*/ |
devno_t device_assign_devno(void) |
{ |
devno_t devno; |
devno = (devno_t) atomic_postinc(&last); |
ASSERT(devno >= 0); |
return devno; |
} |
/** @} |
*/ |
/trunk/kernel/generic/src/ddi/irq.c |
---|
0,0 → 1,267 |
/* |
* 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 genericddi |
* @{ |
*/ |
/** |
* @file |
* @brief IRQ redirector. |
* |
* This file provides means of connecting IRQs with particular |
* devices and logic for dispatching interrupts to IRQ handlers |
* defined by those devices. |
* |
* This code is designed to support: |
* - multiple devices sharing single IRQ |
* - multiple IRQs per signle device |
* |
* |
* Note about architectures. |
* |
* Some architectures has the term IRQ well defined. Examples |
* of such architectures include amd64, ia32 and mips32. Some |
* other architectures, such as sparc64, don't use the term |
* at all. In those cases, we boldly step forward and define what |
* an IRQ is. |
* |
* The implementation is generic enough and still allows the |
* architectures to use the hardware layout effectively. |
* For instance, on amd64 and ia32, where there is only 16 |
* IRQs, the irq_hash_table can be optimized to a one-dimensional |
* array. Next, when it is known that the IRQ numbers (aka INR's) |
* are unique, the claim functions can always return IRQ_ACCEPT. |
*/ |
#include <ddi/irq.h> |
#include <adt/hash_table.h> |
#include <arch/types.h> |
#include <typedefs.h> |
#include <synch/spinlock.h> |
#include <arch.h> |
/** |
* Spinlock protecting the hash table. |
* This lock must be taken only when interrupts are disabled. |
*/ |
SPINLOCK_INITIALIZE(irq_hash_table_lock); |
static hash_table_t irq_hash_table; |
/** |
* Hash table operations for cases when we know that |
* there will be collisions between different keys. |
*/ |
static index_t irq_ht_hash(unative_t *key); |
static bool irq_ht_compare(unative_t *key, count_t keys, link_t *item); |
static hash_table_operations_t irq_ht_ops = { |
.hash = irq_ht_hash, |
.compare = irq_ht_compare, |
.remove_callback = NULL /* not used */ |
}; |
/** |
* Hash table operations for cases when we know that |
* there will be no collisions between different keys. |
* However, there might be still collisions among |
* elements with single key (sharing of one IRQ). |
*/ |
static index_t irq_lin_hash(unative_t *key); |
static bool irq_lin_compare(unative_t *key, count_t keys, link_t *item); |
static hash_table_operations_t irq_lin_ops = { |
.hash = irq_lin_hash, |
.compare = irq_lin_compare, |
.remove_callback = NULL /* not used */ |
}; |
/** Initialize IRQ subsystem. |
* |
* @param inrs Numbers of unique IRQ numbers or INRs. |
* @param chains Number of chains in the hash table. |
*/ |
void irq_init(count_t inrs, count_t chains) |
{ |
/* |
* Be smart about the choice of the hash table operations. |
* In cases in which inrs equals the requested number of |
* chains (i.e. where there is no collision between |
* different keys), we can use optimized set of operations. |
*/ |
if (inrs == chains) |
hash_table_create(&irq_hash_table, chains, 1, &irq_lin_ops); |
else |
hash_table_create(&irq_hash_table, chains, 1, &irq_ht_ops); |
} |
/** Initialize one IRQ structure. |
* |
* @param irq Pointer to the IRQ structure to be initialized. |
* |
*/ |
void irq_initialize(irq_t *irq) |
{ |
link_initialize(&irq->link); |
irq->inr = -1; |
irq->devno = -1; |
irq->notif = 0; |
irq->trigger = 0; |
irq->claim = NULL; |
irq->handler = NULL; |
irq->arg = NULL; |
} |
/** Register IRQ for device. |
* |
* The irq structure must be filled with information |
* about the interrupt source and with the claim() |
* function pointer and irq_handler() function pointer. |
* |
* @param irq IRQ structure belonging to a device. |
*/ |
void irq_register(irq_t *irq) |
{ |
ipl_t ipl; |
ipl = interrupts_disable(); |
spinlock_lock(&irq_hash_table_lock); |
hash_table_insert(&irq_hash_table, (void *) &irq->inr, &irq->link); |
spinlock_unlock(&irq_hash_table_lock); |
interrupts_restore(ipl); |
} |
/** Dispatch the IRQ. |
* |
* @param inr Interrupt number (aka inr or irq). |
* |
* @return IRQ structure of the respective device or NULL. |
*/ |
irq_t *irq_dispatch(inr_t inr) |
{ |
ipl_t ipl; |
link_t *lnk; |
ipl = interrupts_disable(); |
spinlock_lock(&irq_hash_table_lock); |
lnk = hash_table_find(&irq_hash_table, (void *) &inr); |
if (lnk) { |
irq_t *irq; |
irq = hash_table_get_instance(lnk, irq_t, link); |
spinlock_unlock(&irq_hash_table_lock); |
interrupts_restore(ipl); |
return irq; |
} |
spinlock_unlock(&irq_hash_table_lock); |
interrupts_restore(ipl); |
return NULL; |
} |
/** Compute hash index for the key. |
* |
* This function computes hash index into |
* the IRQ hash table for which there |
* can be collisions between different |
* INRs. |
* |
* @param key Pointer to INR. |
* |
* @return Index into the hash table. |
*/ |
index_t irq_ht_hash(unative_t *key) |
{ |
inr_t *inr = (inr_t *) key; |
return *inr % irq_hash_table.entries; |
} |
/** Compare hash table element with a key. |
* |
* As usually, we do sort of a hack here. |
* Even when the key matches the inr member, |
* we ask the device to either accept |
* or decline to service the interrupt. |
* |
* @param key Pointer to key (i.e. inr). |
* @param keys This is 1. |
* @param item The item to compare the key with. |
* |
* @return True on match or false otherwise. |
*/ |
bool irq_ht_compare(unative_t *key, count_t keys, link_t *item) |
{ |
irq_t *irq = hash_table_get_instance(item, irq_t, link); |
inr_t *inr = (inr_t *) key; |
return ((irq->inr == *inr) && (irq->claim() == IRQ_ACCEPT)); |
} |
/** Compute hash index for the key. |
* |
* This function computes hash index into |
* the IRQ hash table for which there |
* are no collisions between different |
* INRs. |
* |
* @param key INR. |
* |
* @return Index into the hash table. |
*/ |
index_t irq_lin_hash(unative_t *key) |
{ |
inr_t *inr = (inr_t *) key; |
return *inr; |
} |
/** Compare hash table element with a key. |
* |
* As usually, we do sort of a hack here. |
* We don't compare the inr member with |
* the key because we know that there are |
* no collision between different keys. |
* We only ask the device to either accept |
* or decline to service the interrupt. |
* |
* @param key Pointer to key (i.e. inr). |
* @param keys This is 1. |
* @param item The item to compare the key with. |
* |
* @return True on match or false otherwise. |
*/ |
bool irq_lin_compare(unative_t *key, count_t keys, link_t *item) |
{ |
irq_t *irq = list_get_instance(item, irq_t, link); |
return (irq->claim() == IRQ_ACCEPT); |
} |
/** @} |
*/ |
/trunk/kernel/Makefile |
---|
147,8 → 147,9 |
generic/src/console/cmd.c \ |
generic/src/cpu/cpu.c \ |
generic/src/ddi/ddi.c \ |
generic/src/ddi/irq.c \ |
generic/src/ddi/device.c \ |
generic/src/interrupt/interrupt.c \ |
generic/src/interrupt/irq.c \ |
generic/src/main/main.c \ |
generic/src/main/kinit.c \ |
generic/src/main/uinit.c \ |
/trunk/kernel/arch/sparc64/src/sparc64.c |
---|
46,7 → 46,7 |
#include <arch/stack.h> |
#include <genarch/ofw/ofw_tree.h> |
#include <userspace.h> |
#include <irq.h> |
#include <ddi/irq.h> |
bootinfo_t bootinfo; |
/trunk/kernel/arch/sparc64/src/trap/interrupt.c |
---|
35,7 → 35,7 |
#include <arch/interrupt.h> |
#include <arch/trap/interrupt.h> |
#include <interrupt.h> |
#include <irq.h> |
#include <ddi/irq.h> |
#include <typedefs.h> |
#include <arch/types.h> |
#include <debug.h> |
/trunk/kernel/arch/sparc64/src/drivers/kbd.c |
---|
40,7 → 40,8 |
#ifdef CONFIG_NS16550 |
#include <genarch/kbd/ns16550.h> |
#endif |
#include <irq.h> |
#include <ddi/device.h> |
#include <ddi/irq.h> |
#include <arch/mm/page.h> |
#include <arch/types.h> |
#include <typedefs.h> |
117,7 → 118,7 |
return; |
} else { |
kbd_irq.inr = inr; |
kbd_irq.devno = 0; /* FIXME: assign unique devno */ |
kbd_irq.devno = device_assign_devno(); |
kbd_irq.trigger = IRQ_TRIGGER_LEVEL; |
kbd_irq.claim = z8530_claim; |
kbd_irq.handler = z8530_irq_handler; |
136,7 → 137,7 |
return; |
} else { |
kbd_irq.inr = inr; |
kbd_irq.devno = 0; /* FIXME: assign unique devno */ |
kbd_irq.devno = device_assign_devno(); |
kbd_irq.trigger = IRQ_TRIGGER_LEVEL; |
kbd_irq.claim = ns16550_claim; |
kbd_irq.handler = ns16550_irq_handler; |