Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4347 → Rev 4348

/branches/dynload/kernel/arch/sparc64/src/drivers/kbd.c
54,100 → 54,140
#include <print.h>
#include <sysinfo/sysinfo.h>
 
kbd_type_t kbd_type = KBD_UNKNOWN;
 
#ifdef CONFIG_SUN_KBD
 
/** Initialize keyboard.
*
* Traverse OpenFirmware device tree in order to find necessary
* info about the keyboard device.
*
* @param node Keyboard device node.
*/
void kbd_init(ofw_tree_node_t *node)
#ifdef CONFIG_Z8530
 
static bool kbd_z8530_init(ofw_tree_node_t *node)
{
size_t offset;
uintptr_t aligned_addr;
ofw_tree_property_t *prop;
const char *name;
const char *name = ofw_tree_node_name(node);
if (str_cmp(name, "zs") != 0)
return false;
/*
* Read 'interrupts' property.
*/
ofw_tree_property_t *prop = ofw_tree_getprop(node, "interrupts");
if ((!prop) || (!prop->value)) {
printf("z8530: Unable to find interrupts property\n");
return false;
}
uint32_t interrupts = *((uint32_t *) prop->value);
/*
* Read 'reg' property.
*/
prop = ofw_tree_getprop(node, "reg");
if ((!prop) || (!prop->value)) {
printf("z8530: Unable to find reg property\n");
return false;
}
size_t size = ((ofw_fhc_reg_t *) prop->value)->size;
uintptr_t pa;
if (!ofw_fhc_apply_ranges(node->parent,
((ofw_fhc_reg_t *) prop->value), &pa)) {
printf("z8530: Failed to determine address\n");
return false;
}
inr_t inr;
cir_t cir;
void *cir_arg;
if (!ofw_fhc_map_interrupt(node->parent,
((ofw_fhc_reg_t *) prop->value), interrupts, &inr, &cir,
&cir_arg)) {
printf("z8530: Failed to determine interrupt\n");
return false;
}
#ifdef CONFIG_NS16550
ns16550_t *ns16550;
#endif
#ifdef CONFIG_Z8530
z8530_t *z8530;
#endif
/*
* We need to pass aligned address to hw_map().
* However, the physical keyboard address can
* be pretty much unaligned, depending on the
* underlying controller.
*/
uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
size_t offset = pa - aligned_addr;
name = ofw_tree_node_name(node);
z8530_t *z8530 = (z8530_t *)
(hw_map(aligned_addr, offset + size) + offset);
z8530_instance_t *z8530_instance = z8530_init(z8530, inr, cir, cir_arg);
if (z8530_instance) {
kbrd_instance_t *kbrd_instance = kbrd_init();
if (kbrd_instance) {
indev_t *sink = stdin_wire();
indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
z8530_wire(z8530_instance, kbrd);
}
}
/*
* Determine keyboard serial controller type.
* This is the necessary evil until the userspace drivers are
* entirely self-sufficient.
*/
if (strcmp(name, "zs") == 0)
kbd_type = KBD_Z8530;
else if (strcmp(name, "su") == 0)
kbd_type = KBD_NS16550;
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.inr", NULL, inr);
sysinfo_set_item_val("kbd.address.kernel", NULL,
(uintptr_t) z8530);
sysinfo_set_item_val("kbd.address.physical", NULL, pa);
sysinfo_set_item_val("kbd.type.z8530", NULL, true);
if (kbd_type == KBD_UNKNOWN) {
printf("Unknown keyboard device.\n");
return;
}
return true;
}
 
#endif /* CONFIG_Z8530 */
 
#ifdef CONFIG_NS16550
 
static bool kbd_ns16550_init(ofw_tree_node_t *node)
{
const char *name = ofw_tree_node_name(node);
if (str_cmp(name, "su") != 0)
return false;
/*
* Read 'interrupts' property.
*/
uint32_t interrupts;
prop = ofw_tree_getprop(node, "interrupts");
if ((!prop) || (!prop->value))
panic("Cannot find 'interrupt' property.");
interrupts = *((uint32_t *) prop->value);
ofw_tree_property_t *prop = ofw_tree_getprop(node, "interrupts");
if ((!prop) || (!prop->value)) {
printf("ns16550: Unable to find interrupts property\n");
return false;
}
uint32_t interrupts = *((uint32_t *) prop->value);
/*
* Read 'reg' property.
*/
prop = ofw_tree_getprop(node, "reg");
if ((!prop) || (!prop->value))
panic("Cannot find 'reg' property.");
if ((!prop) || (!prop->value)) {
printf("ns16550: Unable to find reg property\n");
return false;
}
size_t size = ((ofw_ebus_reg_t *) prop->value)->size;
uintptr_t pa;
size_t size;
if (!ofw_ebus_apply_ranges(node->parent,
((ofw_ebus_reg_t *) prop->value), &pa)) {
printf("ns16550: Failed to determine address\n");
return false;
}
inr_t inr;
switch (kbd_type) {
case KBD_Z8530:
size = ((ofw_fhc_reg_t *) prop->value)->size;
if (!ofw_fhc_apply_ranges(node->parent,
((ofw_fhc_reg_t *) prop->value), &pa)) {
printf("Failed to determine keyboard address.\n");
return;
}
if (!ofw_fhc_map_interrupt(node->parent,
((ofw_fhc_reg_t *) prop->value), interrupts, &inr, &cir,
&cir_arg)) {
printf("Failed to determine keyboard interrupt.\n");
return;
}
break;
case KBD_NS16550:
size = ((ofw_ebus_reg_t *) prop->value)->size;
if (!ofw_ebus_apply_ranges(node->parent,
((ofw_ebus_reg_t *) prop->value), &pa)) {
printf("Failed to determine keyboard address.\n");
return;
}
if (!ofw_ebus_map_interrupt(node->parent,
((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir,
&cir_arg)) {
printf("Failed to determine keyboard interrupt.\n");
return;
};
break;
default:
panic("Unexpected keyboard type.");
cir_t cir;
void *cir_arg;
if (!ofw_ebus_map_interrupt(node->parent,
((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir,
&cir_arg)) {
printf("ns16550: Failed to determine interrupt\n");
return false;
}
/*
156,59 → 196,58
* be pretty much unaligned, depending on the
* underlying controller.
*/
aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
offset = pa - aligned_addr;
uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
size_t offset = pa - aligned_addr;
switch (kbd_type) {
ns16550_t *ns16550 = (ns16550_t *)
(hw_map(aligned_addr, offset + size) + offset);
ns16550_instance_t *ns16550_instance = ns16550_init(ns16550, inr, cir, cir_arg);
if (ns16550_instance) {
kbrd_instance_t *kbrd_instance = kbrd_init();
if (kbrd_instance) {
indev_t *sink = stdin_wire();
indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
ns16550_wire(ns16550_instance, kbrd);
}
}
/*
* 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.inr", NULL, inr);
sysinfo_set_item_val("kbd.address.kernel", NULL,
(uintptr_t) ns16550);
sysinfo_set_item_val("kbd.address.physical", NULL, pa);
sysinfo_set_item_val("kbd.type.ns16550", NULL, true);
return true;
}
 
#endif /* CONFIG_NS16550 */
 
/** Initialize keyboard.
*
* Traverse OpenFirmware device tree in order to find necessary
* info about the keyboard device.
*
* @param node Keyboard device node.
*
*/
void kbd_init(ofw_tree_node_t *node)
{
#ifdef CONFIG_Z8530
case KBD_Z8530:
z8530 = (z8530_t *) hw_map(aligned_addr, offset + size) +
offset;
indev_t *kbrdin_z8530 = z8530_init(z8530, inr, cir, cir_arg);
if (kbrdin_z8530)
kbrd_init(kbrdin_z8530);
/*
* 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.inr", NULL, inr);
sysinfo_set_item_val("kbd.address.kernel", NULL,
(uintptr_t) z8530);
sysinfo_set_item_val("kbd.address.physical", NULL, pa);
break;
kbd_z8530_init(node);
#endif
#ifdef CONFIG_NS16550
case KBD_NS16550:
ns16550 = (ns16550_t *) hw_map(aligned_addr, offset + size) +
offset;
indev_t *kbrdin_ns16550 = ns16550_init(ns16550, inr, cir, cir_arg);
if (kbrdin_ns16550)
kbrd_init(kbrdin_ns16550);
/*
* 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.inr", NULL, inr);
sysinfo_set_item_val("kbd.address.kernel", NULL,
(uintptr_t) ns16550);
sysinfo_set_item_val("kbd.address.physical", NULL, pa);
break;
kbd_ns16550_init(node);
#endif
default:
printf("Kernel is not compiled with the necessary keyboard "
"driver this machine requires.\n");
}
}
 
#endif
#endif /* CONFIG_SUN_KBD */
 
/** @}
*/
/branches/dynload/kernel/arch/sparc64/src/drivers/scr.c
63,13 → 63,13
name = ofw_tree_node_name(node);
if (strcmp(name, "SUNW,m64B") == 0)
if (str_cmp(name, "SUNW,m64B") == 0)
scr_type = SCR_ATYFB;
else if (strcmp(name, "SUNW,XVR-100") == 0)
else if (str_cmp(name, "SUNW,XVR-100") == 0)
scr_type = SCR_XVR;
else if (strcmp(name, "SUNW,ffb") == 0)
else if (str_cmp(name, "SUNW,ffb") == 0)
scr_type = SCR_FFB;
else if (strcmp(name, "cgsix") == 0)
else if (str_cmp(name, "cgsix") == 0)
scr_type = SCR_CGSIX;
if (scr_type == SCR_UNKNOWN) {
/branches/dynload/kernel/arch/sparc64/src/drivers/sgcn.c
31,7 → 31,7
*/
/**
* @file
* @brief SGCN driver.
* @brief SGCN driver.
*/
 
#include <arch.h>
101,9 → 101,6
/** Returns a pointer to the console buffer header. */
#define SGCN_BUFFER_HEADER (SGCN_BUFFER(sgcn_buffer_header_t, 0))
 
/** defined in drivers/kbd.c */
extern kbd_type_t kbd_type;
 
/** starting address of SRAM, will be set by the init_sram_begin function */
static uintptr_t sram_begin;
 
130,7 → 127,7
 
 
/* functions referenced from definitions of I/O operations structures */
static void sgcn_putchar(outdev_t *, const char, bool);
static void sgcn_putchar(outdev_t *, const wchar_t, bool);
 
/** SGCN output device operations */
static outdev_operations_t sgcnout_ops = {
137,12 → 134,6
.write = sgcn_putchar
};
 
/** SGCN input device operations */
static indev_operations_t sgcnin_ops = {
.poll = NULL
};
 
static indev_t sgcnin; /**< SGCN input device. */
static outdev_t sgcnout; /**< SGCN output device. */
 
/**
207,12 → 198,12
 
init_sram_begin();
ASSERT(strcmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0);
ASSERT(str_cmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0);
/* lookup TOC entry with the correct key */
uint32_t i;
for (i = 0; i < MAX_TOC_ENTRIES; i++) {
if (strcmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0)
if (str_cmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0)
break;
}
ASSERT(i < MAX_TOC_ENTRIES);
264,18 → 255,20
}
 
/**
* SGCN output operation. Prints a single character to the SGCN. If the line
* feed character is written ('\n'), the carriage return character ('\r') is
* written straight away.
* SGCN output operation. Prints a single character to the SGCN. Newline
* character is converted to CRLF.
*/
static void sgcn_putchar(outdev_t *od, const char c, bool silent)
static void sgcn_putchar(outdev_t *od, const wchar_t ch, bool silent)
{
if (!silent) {
spinlock_lock(&sgcn_output_lock);
sgcn_do_putchar(c);
if (c == '\n')
sgcn_do_putchar('\r');
if (ascii_check(ch)) {
if (ch == '\n')
sgcn_do_putchar('\r');
sgcn_do_putchar(ch);
} else
sgcn_do_putchar(U_SPECIAL);
spinlock_unlock(&sgcn_output_lock);
}
286,7 → 279,7
*/
void sgcn_grab(void)
{
kbd_disabled = true;
kbd_disabled = false;
}
 
/**
302,7 → 295,7
* there are some unread characters in the input queue. If so, it picks them up
* and sends them to the upper layers of HelenOS.
*/
static void sgcn_poll()
static void sgcn_poll(sgcn_instance_t *instance)
{
uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
uint32_t end = SGCN_BUFFER_HEADER->in_end;
320,13 → 313,12
volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
while (*in_rdptr_ptr != *in_wrptr_ptr) {
buf_ptr = (volatile char *)
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
char c = *buf_ptr;
*in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
indev_push_character(&sgcnin, c);
indev_push_character(instance->srlnin, c);
}
 
spinlock_unlock(&sgcn_input_lock);
335,11 → 327,10
/**
* Polling thread function.
*/
static void kkbdpoll(void *arg) {
static void ksgcnpoll(void *instance) {
while (1) {
if (!silent) {
sgcn_poll();
}
if (!silent)
sgcn_poll(instance);
thread_usleep(POLL_INTERVAL);
}
}
347,23 → 338,36
/**
* A public function which initializes input from the Serengeti console.
*/
indev_t *sgcnin_init(void)
sgcn_instance_t *sgcnin_init(void)
{
sgcn_buffer_begin_init();
sgcn_instance_t *instance =
malloc(sizeof(sgcn_instance_t), FRAME_ATOMIC);
if (instance) {
instance->srlnin = NULL;
instance->thread = thread_create(ksgcnpoll, instance, TASK, 0,
"ksgcnpoll", true);
if (!instance->thread) {
free(instance);
return NULL;
}
}
return instance;
}
 
kbd_type = KBD_SGCN;
void sgcnin_wire(sgcn_instance_t *instance, indev_t *srlnin)
{
ASSERT(instance);
ASSERT(srlnin);
 
instance->srlnin = srlnin;
thread_ready(instance->thread);
 
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.type", NULL, KBD_SGCN);
 
thread_t *t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true);
if (!t)
panic("Cannot create kkbdpoll.");
thread_ready(t);
indev_initialize("sgcnin", &sgcnin, &sgcnin_ops);
 
return &sgcnin;
}
 
/**
/branches/dynload/kernel/arch/sparc64/src/drivers/pci.c
183,7 → 183,7
/*
* First, verify this is a PCI node.
*/
ASSERT(strcmp(ofw_tree_node_name(node), "pci") == 0);
ASSERT(str_cmp(ofw_tree_node_name(node), "pci") == 0);
 
/*
* Determine PCI controller model.
192,13 → 192,13
if (!prop || !prop->value)
return NULL;
if (strcmp(prop->value, "SUNW,sabre") == 0) {
if (str_cmp(prop->value, "SUNW,sabre") == 0) {
/*
* PCI controller Sabre.
* This model is found on UltraSPARC IIi based machines.
*/
return pci_sabre_init(node);
} else if (strcmp(prop->value, "SUNW,psycho") == 0) {
} else if (str_cmp(prop->value, "SUNW,psycho") == 0) {
/*
* PCI controller Psycho.
* Used on UltraSPARC II based processors, for instance,