Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4311 → Rev 4610

/trunk/kernel/genarch/src/drivers/via-cuda/cuda.c
1,5 → 1,6
/*
* Copyright (c) 2006 Martin Decky
* Copyright (c) 2009 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
38,16 → 39,89
#include <arch/asm.h>
#include <mm/slab.h>
#include <ddi/device.h>
#include <synch/spinlock.h>
 
static void cuda_packet_handle(cuda_instance_t *instance, size_t len);
 
/** B register fields */
enum {
TREQ = 0x08,
TACK = 0x10,
TIP = 0x20
};
 
/** IER register fields */
enum {
IER_SET = 0x80,
SR_INT = 0x04
};
 
static irq_ownership_t cuda_claim(irq_t *irq)
{
return IRQ_DECLINE;
cuda_instance_t *instance = irq->instance;
cuda_t *dev = instance->cuda;
uint8_t ifr;
 
ifr = pio_read_8(&dev->ifr);
 
if ((ifr & SR_INT) != 0)
return IRQ_ACCEPT;
else
return IRQ_DECLINE;
}
 
static void cuda_irq_handler(irq_t *irq)
{
cuda_instance_t *instance = irq->instance;
cuda_t *dev = instance->cuda;
uint8_t b, data;
size_t pos;
 
spinlock_lock(&instance->dev_lock);
 
/* We have received one or more CUDA packets. Process them all. */
while (true) {
b = pio_read_8(&dev->b);
 
if ((b & TREQ) != 0)
break; /* No data */
 
pio_write_8(&dev->b, b & ~TIP);
 
/* Read one packet. */
 
pos = 0;
do {
data = pio_read_8(&dev->sr);
b = pio_read_8(&dev->b);
pio_write_8(&dev->b, b ^ TACK);
 
if (pos < CUDA_RCV_BUF_SIZE)
instance->rcv_buf[pos++] = data;
} while ((b & TREQ) == 0);
 
pio_write_8(&dev->b, b | TACK | TIP);
 
cuda_packet_handle(instance, pos);
}
 
spinlock_unlock(&instance->dev_lock);
}
 
static void cuda_packet_handle(cuda_instance_t *instance, size_t len)
{
uint8_t *data = instance->rcv_buf;
 
if (data[0] != 0x00 || data[1] != 0x40 || data[2] != 0x2c)
return;
 
/* The packet contains one or two scancodes. */
if (data[3] != 0xff)
indev_push_character(instance->kbrdin, data[3]);
if (data[4] != 0xff)
indev_push_character(instance->kbrdin, data[4]);
}
 
cuda_instance_t *cuda_init(cuda_t *dev, inr_t inr, cir_t cir, void *cir_arg)
{
cuda_instance_t *instance
55,7 → 129,9
if (instance) {
instance->cuda = dev;
instance->kbrdin = NULL;
 
spinlock_initialize(&instance->dev_lock, "cuda_dev");
 
irq_initialize(&instance->irq);
instance->irq.devno = device_assign_devno();
instance->irq.inr = inr;
71,8 → 147,15
 
void cuda_wire(cuda_instance_t *instance, indev_t *kbrdin)
{
ASSERT(instance);
ASSERT(kbrdin);
 
instance->kbrdin = kbrdin;
irq_register(&instance->irq);
 
/* Enable SR interrupt. */
pio_write_8(&instance->cuda->ier, IER_SET | SR_INT);
}
 
 
/** @}
*/