Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4685 → Rev 4687

/tags/0.4.1/kernel/arch/ia32/src/drivers/vesa.c
0,0 → 1,121
/*
* Copyright (c) 2006 Jakub Vana
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
* @{
*/
/**
* @file
* @brief VESA frame buffer driver.
*/
 
#ifdef CONFIG_FB
 
#include <genarch/fb/fb.h>
#include <genarch/fb/visuals.h>
#include <arch/drivers/vesa.h>
#include <putchar.h>
#include <mm/page.h>
#include <mm/frame.h>
#include <mm/as.h>
#include <arch/mm/page.h>
#include <synch/spinlock.h>
#include <arch/asm.h>
#include <arch/types.h>
#include <memstr.h>
#include <bitops.h>
 
uint32_t vesa_ph_addr;
uint16_t vesa_width;
uint16_t vesa_height;
uint16_t vesa_bpp;
uint16_t vesa_scanline;
 
uint8_t vesa_red_mask;
uint8_t vesa_red_pos;
 
uint8_t vesa_green_mask;
uint8_t vesa_green_pos;
 
uint8_t vesa_blue_mask;
uint8_t vesa_blue_pos;
 
int vesa_present(void)
{
if ((vesa_width != 0xffff) && (vesa_height != 0xffff))
return true;
return false;
}
 
void vesa_init(void)
{
unsigned int visual;
switch (vesa_bpp) {
case 8:
visual = VISUAL_INDIRECT_8;
break;
case 16:
if ((vesa_red_mask == 5) && (vesa_red_pos == 10)
&& (vesa_green_mask == 5) && (vesa_green_pos == 5)
&& (vesa_blue_mask == 5) && (vesa_blue_pos == 0))
visual = VISUAL_RGB_5_5_5_LE;
else
visual = VISUAL_RGB_5_6_5_LE;
break;
case 24:
visual = VISUAL_BGR_8_8_8;
break;
case 32:
visual = VISUAL_BGR_8_8_8_0;
break;
default:
panic("Unsupported bits per pixel.");
}
fb_properties_t vesa_props = {
.addr = vesa_ph_addr,
.offset = 0,
.x = vesa_width,
.y = vesa_height,
.scan = vesa_scanline,
.visual = visual,
};
fb_init(&vesa_props);
}
 
void vesa_redraw(void)
{
fb_redraw();
}
 
#endif
 
/** @}
*/
/tags/0.4.1/kernel/arch/ia32/src/drivers/i8254.c
0,0 → 1,162
/*
* Copyright (c) 2001-2004 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
* @{
*/
/**
* @file
* @brief i8254 chip driver.
*
* Low level time functions.
*/
 
#include <arch/types.h>
#include <time/clock.h>
#include <time/delay.h>
#include <arch/cycle.h>
#include <arch/interrupt.h>
#include <arch/drivers/i8259.h>
#include <arch/drivers/i8254.h>
#include <cpu.h>
#include <config.h>
#include <arch/pm.h>
#include <arch/asm.h>
#include <arch/cpuid.h>
#include <arch.h>
#include <time/delay.h>
#include <ddi/irq.h>
#include <ddi/device.h>
 
#define CLK_PORT1 ((ioport8_t *)0x40)
#define CLK_PORT4 ((ioport8_t *)0x43)
 
#define CLK_CONST 1193180
#define MAGIC_NUMBER 1194
 
static irq_t i8254_irq;
 
static irq_ownership_t i8254_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
 
static void i8254_irq_handler(irq_t *irq)
{
/*
* This IRQ is responsible for kernel preemption.
* Nevertheless, we are now holding a spinlock which prevents
* preemption. For this particular IRQ, we don't need the
* lock. We just release it, call clock() and then reacquire it again.
*/
spinlock_unlock(&irq->lock);
clock();
spinlock_lock(&irq->lock);
}
 
void i8254_init(void)
{
irq_initialize(&i8254_irq);
i8254_irq.preack = true;
i8254_irq.devno = device_assign_devno();
i8254_irq.inr = IRQ_CLK;
i8254_irq.claim = i8254_claim;
i8254_irq.handler = i8254_irq_handler;
irq_register(&i8254_irq);
i8254_normal_operation();
}
 
void i8254_normal_operation(void)
{
pio_write_8(CLK_PORT4, 0x36);
pic_disable_irqs(1 << IRQ_CLK);
pio_write_8(CLK_PORT1, (CLK_CONST / HZ) & 0xf);
pio_write_8(CLK_PORT1, (CLK_CONST / HZ) >> 8);
pic_enable_irqs(1 << IRQ_CLK);
}
 
#define LOOPS 150000
#define SHIFT 11
void i8254_calibrate_delay_loop(void)
{
uint64_t clk1, clk2;
uint32_t t1, t2, o1, o2;
uint8_t not_ok;
 
 
/*
* One-shot timer. Count-down from 0xffff at 1193180Hz
* MAGIC_NUMBER is the magic value for 1ms.
*/
pio_write_8(CLK_PORT4, 0x30);
pio_write_8(CLK_PORT1, 0xff);
pio_write_8(CLK_PORT1, 0xff);
 
do {
/* will read both status and count */
pio_write_8(CLK_PORT4, 0xc2);
not_ok = (uint8_t) ((pio_read_8(CLK_PORT1) >> 6) & 1);
t1 = pio_read_8(CLK_PORT1);
t1 |= pio_read_8(CLK_PORT1) << 8;
} while (not_ok);
 
asm_delay_loop(LOOPS);
 
pio_write_8(CLK_PORT4, 0xd2);
t2 = pio_read_8(CLK_PORT1);
t2 |= pio_read_8(CLK_PORT1) << 8;
 
/*
* We want to determine the overhead of the calibrating mechanism.
*/
pio_write_8(CLK_PORT4, 0xd2);
o1 = pio_read_8(CLK_PORT1);
o1 |= pio_read_8(CLK_PORT1) << 8;
 
asm_fake_loop(LOOPS);
 
pio_write_8(CLK_PORT4, 0xd2);
o2 = pio_read_8(CLK_PORT1);
o2 |= pio_read_8(CLK_PORT1) << 8;
 
CPU->delay_loop_const =
((MAGIC_NUMBER * LOOPS) / 1000) / ((t1 - t2) - (o1 - o2)) +
(((MAGIC_NUMBER * LOOPS) / 1000) % ((t1 - t2) - (o1 - o2)) ? 1 : 0);
 
clk1 = get_cycle();
delay(1 << SHIFT);
clk2 = get_cycle();
CPU->frequency_mhz = (clk2 - clk1) >> SHIFT;
 
return;
}
 
/** @}
*/
/tags/0.4.1/kernel/arch/ia32/src/drivers/i8259.c
0,0 → 1,134
/*
* Copyright (c) 2001-2004 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
* @{
*/
/**
* @file
* @brief PIC driver.
*
* Programmable Interrupt Controller for UP systems based on i8259 chip.
*/
 
#include <arch/drivers/i8259.h>
#include <cpu.h>
#include <arch/types.h>
#include <arch/asm.h>
#include <arch.h>
#include <print.h>
#include <interrupt.h>
 
static void pic_spurious(int n, istate_t *istate);
 
void i8259_init(void)
{
/* ICW1: this is ICW1, ICW4 to follow */
pio_write_8(PIC_PIC0PORT1, PIC_ICW1 | PIC_NEEDICW4);
 
/* ICW2: IRQ 0 maps to INT IRQBASE */
pio_write_8(PIC_PIC0PORT2, IVT_IRQBASE);
 
/* ICW3: pic1 using IRQ IRQ_PIC1 */
pio_write_8(PIC_PIC0PORT2, 1 << IRQ_PIC1);
 
/* ICW4: i8086 mode */
pio_write_8(PIC_PIC0PORT2, 1);
 
/* ICW1: ICW1, ICW4 to follow */
pio_write_8(PIC_PIC1PORT1, PIC_ICW1 | PIC_NEEDICW4);
 
/* ICW2: IRQ 8 maps to INT (IVT_IRQBASE + 8) */
pio_write_8(PIC_PIC1PORT2, IVT_IRQBASE + 8);
 
/* ICW3: pic1 is known as IRQ_PIC1 */
pio_write_8(PIC_PIC1PORT2, IRQ_PIC1);
 
/* ICW4: i8086 mode */
pio_write_8(PIC_PIC1PORT2, 1);
 
/*
* Register interrupt handler for the PIC spurious interrupt.
*/
exc_register(VECTOR_PIC_SPUR, "pic_spurious", (iroutine) pic_spurious);
 
/*
* Set the enable/disable IRQs handlers.
* Set the End-of-Interrupt handler.
*/
enable_irqs_function = pic_enable_irqs;
disable_irqs_function = pic_disable_irqs;
eoi_function = pic_eoi;
 
pic_disable_irqs(0xffff); /* disable all irq's */
pic_enable_irqs(1 << IRQ_PIC1); /* but enable pic1 */
}
 
void pic_enable_irqs(uint16_t irqmask)
{
uint8_t x;
 
if (irqmask & 0xff) {
x = pio_read_8(PIC_PIC0PORT2);
pio_write_8(PIC_PIC0PORT2, (uint8_t) (x & (~(irqmask & 0xff))));
}
if (irqmask >> 8) {
x = pio_read_8(PIC_PIC1PORT2);
pio_write_8(PIC_PIC1PORT2, (uint8_t) (x & (~(irqmask >> 8))));
}
}
 
void pic_disable_irqs(uint16_t irqmask)
{
uint8_t x;
 
if (irqmask & 0xff) {
x = pio_read_8(PIC_PIC0PORT2);
pio_write_8(PIC_PIC0PORT2, (uint8_t) (x | (irqmask & 0xff)));
}
if (irqmask >> 8) {
x = pio_read_8(PIC_PIC1PORT2);
pio_write_8(PIC_PIC1PORT2, (uint8_t) (x | (irqmask >> 8)));
}
}
 
void pic_eoi(void)
{
pio_write_8((ioport8_t *)0x20, 0x20);
pio_write_8((ioport8_t *)0xa0, 0x20);
}
 
void pic_spurious(int n __attribute__((unused)), istate_t *istate __attribute__((unused)))
{
#ifdef CONFIG_DEBUG
printf("cpu%u: PIC spurious interrupt\n", CPU->id);
#endif
}
 
/** @}
*/