Beispiel #1
0
static int cuda_init(void)
{
	if (sysinfo_get_value("cuda.address.physical", &(instance->cuda_physical)) != EOK)
		return -1;
	
	void *vaddr;
	if (pio_enable((void *) instance->cuda_physical, sizeof(cuda_t), &vaddr) != 0)
		return -1;
	
	dev = vaddr;

	instance->cuda = dev;
	instance->xstate = cx_listen;
	instance->bidx = 0;
	instance->snd_bytes = 0;

	fibril_mutex_initialize(&instance->dev_lock);

	/* Disable all interrupts from CUDA. */
	pio_write_8(&dev->ier, IER_CLR | ALL_INT);

	cuda_irq_code.ranges[0].base = (uintptr_t) instance->cuda_physical;
	cuda_irq_code.cmds[0].addr = (void *) &((cuda_t *) instance->cuda_physical)->ifr;
	async_set_interrupt_received(cuda_irq_handler);
	irq_register(10, device_assign_devno(), 0, &cuda_irq_code);

	/* Enable SR interrupt. */
	pio_write_8(&dev->ier, TIP | TREQ);
	pio_write_8(&dev->ier, IER_SET | SR_INT);

	/* Enable ADB autopolling. */
	cuda_autopoll_set(true);

	return 0;
}
Beispiel #2
0
static inline void set_timer(UINT32 hz)
{
	UINT32 div = CLK_CONST / hz;
	pio_write_8(CLK_PORT4, PIT_SET);
	pio_write_8(CLK_PORT1, div & PIT_MASK);
	pio_write_8(CLK_PORT1, (div >> 8) & PIT_MASK);
}
Beispiel #3
0
void arch_irq_eoi(UINT16 irqmask)
{
    if (irqmask & 0xff00)
    {
        pio_write_8(PIC_PIC1PORT1, 0x20);
    }
    pio_write_8(PIC_PIC0PORT1, 0x20);
}
Beispiel #4
0
void ns16550_wire(ns16550_instance_t *instance, indev_t *input)
{
	ASSERT(instance);
	ASSERT(input);
	
	instance->input = input;
	irq_register(&instance->irq);
	
	ns16550_clear_buffer(instance->ns16550);
	
	/* Enable interrupts */
	pio_write_8(&instance->ns16550->ier, IER_ERBFI);
	pio_write_8(&instance->ns16550->mcr, MCR_OUT2);
}
Beispiel #5
0
cuda_instance_t *cuda_init(cuda_t *dev, inr_t inr, cir_t cir, void *cir_arg)
{
	cuda_instance_t *instance
	    = malloc(sizeof(cuda_instance_t), FRAME_ATOMIC);
	if (instance) {
		instance->cuda = dev;
		instance->kbrdin = NULL;
		instance->xstate = cx_listen;
		instance->bidx = 0;
		instance->snd_bytes = 0;

		spinlock_initialize(&instance->dev_lock, "cuda.instance.dev_lock");

		/* Disable all interrupts from CUDA. */
		pio_write_8(&dev->ier, IER_CLR | ALL_INT);

		irq_initialize(&instance->irq);
		instance->irq.devno = device_assign_devno();
		instance->irq.inr = inr;
		instance->irq.claim = cuda_claim;
		instance->irq.handler = cuda_irq_handler;
		instance->irq.instance = instance;
		instance->irq.cir = cir;
		instance->irq.cir_arg = cir_arg;
		instance->irq.preack = true;
	}
	
	return instance;
}
Beispiel #6
0
static void cuda_irq_handler(irq_t *irq)
{
	cuda_instance_t *instance = irq->instance;
	uint8_t rbuf[CUDA_RCV_BUF_SIZE];
	size_t len;
	bool handle;

	handle = false;
	len = 0;

	spinlock_lock(&instance->dev_lock);

	/* Lower IFR.SR_INT so that CUDA can generate next int by raising it. */
	pio_write_8(&instance->cuda->ifr, SR_INT);

	switch (instance->xstate) {
	case cx_listen: cuda_irq_listen(irq); break;
	case cx_receive: cuda_irq_receive(irq); break;
	case cx_rcv_end: cuda_irq_rcv_end(irq, rbuf, &len);
	    handle = true; break;
	case cx_send_start: cuda_irq_send_start(irq); break;
	case cx_send: cuda_irq_send(irq); break;
	}

	spinlock_unlock(&instance->dev_lock);

	/* Handle an incoming packet. */
	if (handle)
		cuda_packet_handle(instance, rbuf, len);
}
Beispiel #7
0
static void cuda_irq_handler(ipc_callid_t iid, ipc_call_t *call)
{
	uint8_t rbuf[CUDA_RCV_BUF_SIZE];
	size_t len;
	bool handle;

	handle = false;
	len = 0;

	fibril_mutex_lock(&instance->dev_lock);

	/* Lower IFR.SR_INT so that CUDA can generate next int by raising it. */
	pio_write_8(&instance->cuda->ifr, SR_INT);

	switch (instance->xstate) {
	case cx_listen: cuda_irq_listen(); break;
	case cx_receive: cuda_irq_receive(); break;
	case cx_rcv_end: cuda_irq_rcv_end(rbuf, &len);
	    handle = true; break;
	case cx_send_start: cuda_irq_send_start(); break;
	case cx_send: cuda_irq_send(); break;
	}

	fibril_mutex_unlock(&instance->dev_lock);

	/* Handle an incoming packet. */
	if (handle)
		cuda_packet_handle(rbuf, len);
}
Beispiel #8
0
void cuda_wire(cuda_instance_t *instance, indev_t *kbrdin)
{
	cuda_t *dev = instance->cuda;

	ASSERT(instance);
	ASSERT(kbrdin);

	instance->kbrdin = kbrdin;
	irq_register(&instance->irq);

	/* Enable SR interrupt. */
	pio_write_8(&dev->ier, TIP | TREQ);
	pio_write_8(&dev->ier, IER_SET | SR_INT);

	/* Enable ADB autopolling. */
	cuda_autopoll_set(instance, true);
}
Beispiel #9
0
/** Interrupt in receive state.
 *
 * Receive next byte of packet.
 */
static void cuda_irq_receive(void)
{
	uint8_t b, data;

	data = pio_read_8(&dev->sr);
	if (instance->bidx < CUDA_RCV_BUF_SIZE)
		instance->rcv_buf[instance->bidx++] = data;

	b = pio_read_8(&dev->b);

	if ((b & TREQ) == 0) {
		pio_write_8(&dev->b, b ^ TACK);
	} else {
		pio_write_8(&dev->b, b | TACK | TIP);
		instance->xstate = cx_rcv_end;
	}
}
Beispiel #10
0
/** Write data to i8042 port.
 *
 * @param fun    DDF function.
 * @param buffer Data source.
 * @param size   Data size.
 *
 * @return Bytes written.
 *
 */
static int i8042_write(ddf_fun_t *fun, char *buffer, size_t size)
{
    i8042_t *controller = dev_i8042(ddf_fun_get_dev(fun));
    fibril_mutex_lock(&controller->write_guard);

    for (size_t i = 0; i < size; ++i) {
        if (controller->aux_fun == fun) {
            wait_ready(controller);
            pio_write_8(&controller->regs->status,
                        i8042_CMD_WRITE_AUX);
        }

        wait_ready(controller);
        pio_write_8(&controller->regs->data, buffer[i]);
    }

    fibril_mutex_unlock(&controller->write_guard);
    return size;
}
Beispiel #11
0
static void cuda_send_start(void)
{
	cuda_t *dev = instance->cuda;

	assert(instance->xstate == cx_listen);

	if (instance->snd_bytes == 0)
		return;

	/* Check for incoming data. */
	if ((pio_read_8(&dev->b) & TREQ) == 0)
		return;

	pio_write_8(&dev->acr, pio_read_8(&dev->acr) | SR_OUT);
	pio_write_8(&dev->sr, instance->snd_buf[0]);
	pio_write_8(&dev->b, pio_read_8(&dev->b) & ~TIP);

	instance->xstate = cx_send_start;
}
Beispiel #12
0
/** Interrupt in send state.
 *
 * Send next byte or terminate transmission.
 */
static void cuda_irq_send(void)
{
	if (instance->bidx < instance->snd_bytes) {
		/* Send next byte. */
		pio_write_8(&dev->sr, instance->snd_buf[instance->bidx++]);
		pio_write_8(&dev->b, pio_read_8(&dev->b) ^ TACK);
		return;
	}

	/* End transfer. */
	instance->snd_bytes = 0;
	instance->bidx = 0;

	pio_write_8(&dev->acr, pio_read_8(&dev->acr) & ~SR_OUT);
	pio_read_8(&dev->sr);
	pio_write_8(&dev->b, pio_read_8(&dev->b) | TACK | TIP);

	instance->xstate = cx_listen;
	/* TODO: Match reply with request. */
}
Beispiel #13
0
/** Interrupt in send_start state.
 *
 * Process result of sending first byte (and send second on success).
 */
static void cuda_irq_send_start(void)
{
	uint8_t b;

	b = pio_read_8(&dev->b);

	if ((b & TREQ) == 0) {
		/* Collision */
		pio_write_8(&dev->acr, pio_read_8(&dev->acr) & ~SR_OUT);
		pio_read_8(&dev->sr);
		pio_write_8(&dev->b, pio_read_8(&dev->b) | TIP | TACK);
		instance->xstate = cx_listen;
		return;
	}

	pio_write_8(&dev->sr, instance->snd_buf[1]);
	pio_write_8(&dev->b, pio_read_8(&dev->b) ^ TACK);
	instance->bidx = 2;

	instance->xstate = cx_send;
}
Beispiel #14
0
/** Interrupt in listen state.
 *
 * Start packet reception.
 */
static void cuda_irq_listen(void)
{
	uint8_t b;

	b = pio_read_8(&dev->b);

	if ((b & TREQ) != 0) {
		printf("cuda_irq_listen: no TREQ?!\n");
		return;
	}

	pio_read_8(&dev->sr);
	pio_write_8(&dev->b, pio_read_8(&dev->b) & ~TIP);
	instance->xstate = cx_receive;
}
Beispiel #15
0
/** Interrupt in listen state.
 *
 * Start packet reception.
 */
static void cuda_irq_listen(irq_t *irq)
{
	cuda_instance_t *instance = irq->instance;
	cuda_t *dev = instance->cuda;
	uint8_t b;

	b = pio_read_8(&dev->b);

	if ((b & TREQ) != 0) {
		log(LF_OTHER, LVL_ERROR, "cuda_irq_listen: no TREQ?!");
		return;
	}

	pio_read_8(&dev->sr);
	pio_write_8(&dev->b, pio_read_8(&dev->b) & ~TIP);
	instance->xstate = cx_receive;
}
Beispiel #16
0
/** Interrupt in rcv_end state.
 *
 * Terminate packet reception. Either go back to listen state or start
 * receiving another packet if CUDA has one for us.
 */
static void cuda_irq_rcv_end(void *buf, size_t *len)
{
	uint8_t b;
	
	b = pio_read_8(&dev->b);
	pio_read_8(&dev->sr);
	
	if ((b & TREQ) == 0) {
		instance->xstate = cx_receive;
		pio_write_8(&dev->b, b & ~TIP);
	} else {
		instance->xstate = cx_listen;
		cuda_send_start();
	}
	
	memcpy(buf, instance->rcv_buf, instance->bidx);
	*len = instance->bidx;
	instance->bidx = 0;
}
Beispiel #17
0
static void ega_cursor_update(outdev_t *dev, sysarg_t prev_col,
    sysarg_t prev_row, sysarg_t col, sysarg_t row, bool visible)
{
	/* Cursor position */
	uint16_t cursor = row * ega.cols + col;
	
	pio_write_8(EGA_IO_BASE, 0x0e);
	pio_write_8(EGA_IO_BASE + 1, (cursor >> 8) & 0xff);
	pio_write_8(EGA_IO_BASE, 0x0f);
	pio_write_8(EGA_IO_BASE + 1, cursor & 0xff);
	
	/* Cursor visibility */
	pio_write_8(EGA_IO_BASE, 0x0a);
	uint8_t stat = pio_read_8(EGA_IO_BASE + 1);
	
	pio_write_8(EGA_IO_BASE, 0x0a);
	
	if (visible)
		pio_write_8(EGA_IO_BASE + 1, stat & (~(1 << 5)));
	else
		pio_write_8(EGA_IO_BASE + 1, stat | (1 << 5));
}
Beispiel #18
0
/** Initialize UHCI hc hw resources.
 *
 * @param[in] instance UHCI structure to use.
 * For magic values see UHCI Design Guide
 */
void hc_init_hw(const hc_t *instance)
{
	assert(instance);
	uhci_regs_t *registers = instance->registers;

	/* Reset everything, who knows what touched it before us */
	pio_write_16(&registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
	async_usleep(50000); /* 50ms according to USB spec(root hub reset) */
	pio_write_16(&registers->usbcmd, 0);

	/* Reset hc, all states and counters. Hope that hw is not broken */
	pio_write_16(&registers->usbcmd, UHCI_CMD_HCRESET);
	do { async_usleep(10); }
	while ((pio_read_16(&registers->usbcmd) & UHCI_CMD_HCRESET) != 0);

	/* Set frame to exactly 1ms */
	pio_write_8(&registers->sofmod, 64);

	/* Set frame list pointer */
	const uint32_t pa = addr_to_phys(instance->frame_list);
	pio_write_32(&registers->flbaseadd, pa);

	if (instance->hw_interrupts) {
		/* Enable all interrupts, but resume interrupt */
		pio_write_16(&instance->registers->usbintr,
		    UHCI_INTR_ALLOW_INTERRUPTS);
	}

	const uint16_t cmd = pio_read_16(&registers->usbcmd);
	if (cmd != 0)
		usb_log_warning("Previous command value: %x.\n", cmd);

	/* Start the hc with large(64B) packet FSBR */
	pio_write_16(&registers->usbcmd,
	    UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE);
}
Beispiel #19
0
void hda_reg8_write(uint8_t *r, uint8_t val)
{
	pio_write_8(r, val);
}
Beispiel #20
0
/** Initialize i8042 driver structure.
 *
 * @param dev       Driver structure to initialize.
 * @param regs      I/O address of registers.
 * @param reg_size  size of the reserved I/O address space.
 * @param irq_kbd   IRQ for primary port.
 * @param irq_mouse IRQ for aux port.
 * @param ddf_dev   DDF device structure of the device.
 *
 * @return Error code.
 *
 */
int i8042_init(i8042_t *dev, void *regs, size_t reg_size, int irq_kbd,
               int irq_mouse, ddf_dev_t *ddf_dev)
{
    const size_t range_count = sizeof(i8042_ranges) /
                               sizeof(irq_pio_range_t);
    irq_pio_range_t ranges[range_count];
    const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t);
    irq_cmd_t cmds[cmd_count];

    int rc;
    bool kbd_bound = false;
    bool aux_bound = false;

    dev->kbd_fun = NULL;
    dev->aux_fun = NULL;

    if (reg_size < sizeof(i8042_regs_t)) {
        rc = EINVAL;
        goto error;
    }

    if (pio_enable(regs, sizeof(i8042_regs_t), (void **) &dev->regs) != 0) {
        rc = EIO;
        goto error;
    }

    dev->kbd_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2a");
    if (dev->kbd_fun == NULL) {
        rc = ENOMEM;
        goto error;
    };

    rc = ddf_fun_add_match_id(dev->kbd_fun, "char/xtkbd", 90);
    if (rc != EOK)
        goto error;

    dev->aux_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b");
    if (dev->aux_fun == NULL) {
        rc = ENOMEM;
        goto error;
    }

    rc = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90);
    if (rc != EOK)
        goto error;

    ddf_fun_set_ops(dev->kbd_fun, &ops);
    ddf_fun_set_ops(dev->aux_fun, &ops);

    buffer_init(&dev->kbd_buffer, dev->kbd_data, BUFFER_SIZE);
    buffer_init(&dev->aux_buffer, dev->aux_data, BUFFER_SIZE);
    fibril_mutex_initialize(&dev->write_guard);

    rc = ddf_fun_bind(dev->kbd_fun);
    if (rc != EOK) {
        ddf_msg(LVL_ERROR, "Failed to bind keyboard function: %s.",
                ddf_fun_get_name(dev->kbd_fun));
        goto error;
    }
    kbd_bound = true;

    rc = ddf_fun_bind(dev->aux_fun);
    if (rc != EOK) {
        ddf_msg(LVL_ERROR, "Failed to bind aux function: %s.",
                ddf_fun_get_name(dev->aux_fun));
        goto error;
    }
    aux_bound = true;

    /* Disable kbd and aux */
    wait_ready(dev);
    pio_write_8(&dev->regs->status, i8042_CMD_WRITE_CMDB);
    wait_ready(dev);
    pio_write_8(&dev->regs->data, i8042_KBD_DISABLE | i8042_AUX_DISABLE);

    /* Flush all current IO */
    while (pio_read_8(&dev->regs->status) & i8042_OUTPUT_FULL)
        (void) pio_read_8(&dev->regs->data);

    memcpy(ranges, i8042_ranges, sizeof(i8042_ranges));
    ranges[0].base = (uintptr_t) regs;

    memcpy(cmds, i8042_cmds, sizeof(i8042_cmds));
    cmds[0].addr = (void *) &(((i8042_regs_t *) regs)->status);
    cmds[3].addr = (void *) &(((i8042_regs_t *) regs)->data);

    irq_code_t irq_code = {
        .rangecount = range_count,
        .ranges = ranges,
        .cmdcount = cmd_count,
        .cmds = cmds
    };

    rc = register_interrupt_handler(ddf_dev, irq_kbd, i8042_irq_handler,
                                    &irq_code);
    if (rc != EOK) {
        ddf_msg(LVL_ERROR, "Failed set handler for kbd: %s.",
                ddf_dev_get_name(ddf_dev));
        goto error;
    }

    rc = register_interrupt_handler(ddf_dev, irq_mouse, i8042_irq_handler,
                                    &irq_code);
    if (rc != EOK) {
        ddf_msg(LVL_ERROR, "Failed set handler for mouse: %s.",
                ddf_dev_get_name(ddf_dev));
        goto error;
    }

    /* Enable interrupts */
    async_sess_t *parent_sess = ddf_dev_parent_sess_get(ddf_dev);
    assert(parent_sess != NULL);

    const bool enabled = hw_res_enable_interrupt(parent_sess);
    if (!enabled) {
        log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to enable interrupts: %s.",
                ddf_dev_get_name(ddf_dev));
        rc = EIO;
        goto error;
    }

    /* Enable port interrupts. */
    wait_ready(dev);
    pio_write_8(&dev->regs->status, i8042_CMD_WRITE_CMDB);
    wait_ready(dev);
    pio_write_8(&dev->regs->data, i8042_KBD_IE | i8042_KBD_TRANSLATE |
                i8042_AUX_IE);

    return EOK;
error:
    if (kbd_bound)
        ddf_fun_unbind(dev->kbd_fun);
    if (aux_bound)
        ddf_fun_unbind(dev->aux_fun);
    if (dev->kbd_fun != NULL)
        ddf_fun_destroy(dev->kbd_fun);
    if (dev->aux_fun != NULL)
        ddf_fun_destroy(dev->aux_fun);

    return rc;
}
Beispiel #21
0
static void ns16550_sendb(ns16550_t *dev, uint8_t byte)
{
	while (!(pio_read_8(&dev->lsr) & LSR_TH_READY))
		;
	pio_write_8(&dev->thr, byte);
}