Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4153 → Rev 3386

/branches/network/kernel/arch/ia32/src/drivers/ega.c
0,0 → 1,155
/*
* 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 EGA driver.
*/
 
#include <arch/drivers/ega.h>
#include <putchar.h>
#include <mm/page.h>
#include <mm/as.h>
#include <arch/mm/page.h>
#include <synch/spinlock.h>
#include <arch/types.h>
#include <arch/asm.h>
#include <memstr.h>
#include <console/chardev.h>
#include <console/console.h>
#include <sysinfo/sysinfo.h>
#include <ddi/ddi.h>
 
/*
* The EGA driver.
* Simple and short. Function for displaying characters and "scrolling".
*/
 
static parea_t ega_parea; /**< Physical memory area for EGA video RAM. */
 
SPINLOCK_INITIALIZE(egalock);
static uint32_t ega_cursor;
static uint8_t *videoram;
 
static void ega_putchar(chardev_t *d, const char ch);
 
chardev_t ega_console;
static chardev_operations_t ega_ops = {
.write = ega_putchar
};
 
static void ega_move_cursor(void);
 
void ega_init(void)
{
uint8_t hi, lo;
videoram = (uint8_t *) hw_map(VIDEORAM, SCREEN * 2);
outb(0x3d4, 0xe);
hi = inb(0x3d5);
outb(0x3d4, 0xf);
lo = inb(0x3d5);
ega_cursor = (hi << 8) | lo;
 
chardev_initialize("ega_out", &ega_console, &ega_ops);
stdout = &ega_console;
ega_parea.pbase = VIDEORAM;
ega_parea.vbase = (uintptr_t) videoram;
ega_parea.frames = 1;
ega_parea.cacheable = false;
ddi_parea_register(&ega_parea);
 
sysinfo_set_item_val("fb", NULL, true);
sysinfo_set_item_val("fb.kind", NULL, 2);
sysinfo_set_item_val("fb.width", NULL, ROW);
sysinfo_set_item_val("fb.height", NULL, ROWS);
sysinfo_set_item_val("fb.address.physical", NULL, VIDEORAM);
}
 
static void ega_display_char(char ch)
{
videoram[ega_cursor * 2] = ch;
}
 
/*
* This function takes care of scrolling.
*/
static void ega_check_cursor(void)
{
if (ega_cursor < SCREEN)
return;
 
memcpy((void *) videoram, (void *) (videoram + ROW * 2), (SCREEN - ROW) * 2);
memsetw(videoram + (SCREEN - ROW) * 2, ROW, 0x0720);
ega_cursor = ega_cursor - ROW;
}
 
void ega_putchar(chardev_t *d __attribute__((unused)), const char ch)
{
ipl_t ipl;
 
ipl = interrupts_disable();
spinlock_lock(&egalock);
 
switch (ch) {
case '\n':
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 % ROW)
ega_cursor--;
break;
default:
ega_display_char(ch);
ega_cursor++;
break;
}
ega_check_cursor();
ega_move_cursor();
 
spinlock_unlock(&egalock);
interrupts_restore(ipl);
}
 
void ega_move_cursor(void)
{
outb(0x3d4, 0xe);
outb(0x3d5, (uint8_t) ((ega_cursor >> 8) & 0xff));
outb(0x3d4, 0xf);
outb(0x3d5, (uint8_t) (ega_cursor & 0xff));
}
 
/** @}
*/
/branches/network/kernel/arch/ia32/src/drivers/i8259.c
49,28 → 49,28
void i8259_init(void)
{
/* ICW1: this is ICW1, ICW4 to follow */
pio_write_8(PIC_PIC0PORT1, PIC_ICW1 | PIC_NEEDICW4);
outb(PIC_PIC0PORT1, PIC_ICW1 | PIC_NEEDICW4);
 
/* ICW2: IRQ 0 maps to INT IRQBASE */
pio_write_8(PIC_PIC0PORT2, IVT_IRQBASE);
outb(PIC_PIC0PORT2, IVT_IRQBASE);
 
/* ICW3: pic1 using IRQ IRQ_PIC1 */
pio_write_8(PIC_PIC0PORT2, 1 << IRQ_PIC1);
outb(PIC_PIC0PORT2, 1 << IRQ_PIC1);
 
/* ICW4: i8086 mode */
pio_write_8(PIC_PIC0PORT2, 1);
outb(PIC_PIC0PORT2, 1);
 
/* ICW1: ICW1, ICW4 to follow */
pio_write_8(PIC_PIC1PORT1, PIC_ICW1 | PIC_NEEDICW4);
outb(PIC_PIC1PORT1, PIC_ICW1 | PIC_NEEDICW4);
 
/* ICW2: IRQ 8 maps to INT (IVT_IRQBASE + 8) */
pio_write_8(PIC_PIC1PORT2, IVT_IRQBASE + 8);
outb(PIC_PIC1PORT2, IVT_IRQBASE + 8);
 
/* ICW3: pic1 is known as IRQ_PIC1 */
pio_write_8(PIC_PIC1PORT2, IRQ_PIC1);
outb(PIC_PIC1PORT2, IRQ_PIC1);
 
/* ICW4: i8086 mode */
pio_write_8(PIC_PIC1PORT2, 1);
outb(PIC_PIC1PORT2, 1);
 
/*
* Register interrupt handler for the PIC spurious interrupt.
94,12 → 94,12
uint8_t x;
 
if (irqmask & 0xff) {
x = pio_read_8(PIC_PIC0PORT2);
pio_write_8(PIC_PIC0PORT2, (uint8_t) (x & (~(irqmask & 0xff))));
x = inb(PIC_PIC0PORT2);
outb(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))));
x = inb(PIC_PIC1PORT2);
outb(PIC_PIC1PORT2, (uint8_t) (x & (~(irqmask >> 8))));
}
}
 
108,19 → 108,19
uint8_t x;
 
if (irqmask & 0xff) {
x = pio_read_8(PIC_PIC0PORT2);
pio_write_8(PIC_PIC0PORT2, (uint8_t) (x | (irqmask & 0xff)));
x = inb(PIC_PIC0PORT2);
outb(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)));
x = inb(PIC_PIC1PORT2);
outb(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);
outb(0x20, 0x20);
outb(0xa0, 0x20);
}
 
void pic_spurious(int n __attribute__((unused)), istate_t *istate __attribute__((unused)))
/branches/network/kernel/arch/ia32/src/drivers/i8254.c
26,12 → 26,12
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/**
* @file
* @brief i8254 chip driver.
* @brief i8254 chip driver.
*
* Low level time functions.
*/
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,12 → 61,12
 
static irq_t i8254_irq;
 
static irq_ownership_t i8254_claim(irq_t *irq)
static irq_ownership_t i8254_claim(void)
{
return IRQ_ACCEPT;
}
 
static void i8254_irq_handler(irq_t *irq)
static void i8254_irq_handler(irq_t *irq, void *arg __attribute__((unused)), ...)
{
/*
* This IRQ is responsible for kernel preemption.
94,10 → 94,10
 
void i8254_normal_operation(void)
{
pio_write_8(CLK_PORT4, 0x36);
outb(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);
outb(CLK_PORT1, (CLK_CONST / HZ) & 0xf);
outb(CLK_PORT1, (CLK_CONST / HZ) >> 8);
pic_enable_irqs(1 << IRQ_CLK);
}
 
114,36 → 114,36
* 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);
outb(CLK_PORT4, 0x30);
outb(CLK_PORT1, 0xff);
outb(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;
outb(CLK_PORT4, 0xc2);
not_ok = (uint8_t) ((inb(CLK_PORT1) >> 6) & 1);
t1 = inb(CLK_PORT1);
t1 |= inb(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;
outb(CLK_PORT4, 0xd2);
t2 = inb(CLK_PORT1);
t2 |= inb(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;
outb(CLK_PORT4, 0xd2);
o1 = inb(CLK_PORT1);
o1 |= inb(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;
outb(CLK_PORT4, 0xd2);
o2 = inb(CLK_PORT1);
o2 |= inb(CLK_PORT1) << 8;
 
CPU->delay_loop_const =
((MAGIC_NUMBER * LOOPS) / 1000) / ((t1 - t2) - (o1 - o2)) +
/branches/network/kernel/arch/ia32/src/drivers/vesa.c
56,20 → 56,12
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))
if (vesa_width != 0xffff)
return true;
if (vesa_height != 0xffff)
return true;
return false;
}
 
82,12 → 74,7
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;
else
visual = VISUAL_RGB_5_6_5;
visual = VISUAL_RGB_5_6_5;
break;
case 24:
visual = VISUAL_RGB_8_8_8;
96,25 → 83,12
visual = VISUAL_RGB_0_8_8_8;
break;
default:
panic("Unsupported bits per pixel.");
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);
fb_init(vesa_ph_addr, vesa_width, vesa_height, vesa_scanline, visual);
}
 
void vesa_redraw(void)
{
fb_redraw();
}
 
#endif
 
/** @}