~galfy/helenos/bird-port-mainline

« back to all changes in this revision

Viewing changes to kernel/genarch/src/drivers/z8530/z8530.c

  • Committer: Martin Decky
  • Date: 2009-08-04 11:19:19 UTC
  • Revision ID: martin@uranus.dsrg.hide.ms.mff.cuni.cz-20090804111919-evyclddlr3v5lhmp
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2009 Jakub Jermar
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 *
 
9
 * - Redistributions of source code must retain the above copyright
 
10
 *   notice, this list of conditions and the following disclaimer.
 
11
 * - Redistributions in binary form must reproduce the above copyright
 
12
 *   notice, this list of conditions and the following disclaimer in the
 
13
 *   documentation and/or other materials provided with the distribution.
 
14
 * - The name of the author may not be used to endorse or promote products
 
15
 *   derived from this software without specific prior written permission.
 
16
 *
 
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
27
 */
 
28
 
 
29
/** @addtogroup genarch
 
30
 * @{
 
31
 */
 
32
/**
 
33
 * @file
 
34
 * @brief Zilog 8530 serial controller driver.
 
35
 */
 
36
 
 
37
#include <genarch/drivers/z8530/z8530.h>
 
38
#include <console/chardev.h>
 
39
#include <ddi/irq.h>
 
40
#include <arch/asm.h>
 
41
#include <mm/slab.h>
 
42
#include <ddi/device.h>
 
43
 
 
44
static inline void z8530_write(ioport8_t *ctl, uint8_t reg, uint8_t val)
 
45
{
 
46
        /*
 
47
         * Registers 8-15 will automatically issue the Point High
 
48
         * command as their bit 3 is 1.
 
49
         */
 
50
        pio_write_8(ctl, reg);  /* Select register */
 
51
        pio_write_8(ctl, val);  /* Write value */
 
52
}
 
53
 
 
54
static inline uint8_t z8530_read(ioport8_t *ctl, uint8_t reg) 
 
55
{
 
56
        /*
 
57
         * Registers 8-15 will automatically issue the Point High
 
58
         * command as their bit 3 is 1.
 
59
         */
 
60
        pio_write_8(ctl, reg);   /* Select register */
 
61
        return pio_read_8(ctl);
 
62
}
 
63
 
 
64
static irq_ownership_t z8530_claim(irq_t *irq)
 
65
{
 
66
        z8530_instance_t *instance = irq->instance;
 
67
        z8530_t *dev = instance->z8530;
 
68
        
 
69
        if (z8530_read(&dev->ctl_a, RR0) & RR0_RCA)
 
70
                return IRQ_ACCEPT;
 
71
        else
 
72
                return IRQ_DECLINE;
 
73
}
 
74
 
 
75
static void z8530_irq_handler(irq_t *irq)
 
76
{
 
77
        z8530_instance_t *instance = irq->instance;
 
78
        z8530_t *dev = instance->z8530;
 
79
        
 
80
        if (z8530_read(&dev->ctl_a, RR0) & RR0_RCA) {
 
81
                uint8_t data = z8530_read(&dev->ctl_a, RR8);
 
82
                indev_push_character(instance->kbrdin, data);
 
83
        }
 
84
}
 
85
 
 
86
/** Initialize z8530. */
 
87
z8530_instance_t *z8530_init(z8530_t *dev, inr_t inr, cir_t cir, void *cir_arg)
 
88
{
 
89
        z8530_instance_t *instance
 
90
            = malloc(sizeof(z8530_instance_t), FRAME_ATOMIC);
 
91
        if (instance) {
 
92
                instance->z8530 = dev;
 
93
                instance->kbrdin = NULL;
 
94
                
 
95
                irq_initialize(&instance->irq);
 
96
                instance->irq.devno = device_assign_devno();
 
97
                instance->irq.inr = inr;
 
98
                instance->irq.claim = z8530_claim;
 
99
                instance->irq.handler = z8530_irq_handler;
 
100
                instance->irq.instance = instance;
 
101
                instance->irq.cir = cir;
 
102
                instance->irq.cir_arg = cir_arg;
 
103
        }
 
104
        
 
105
        return instance;
 
106
}
 
107
 
 
108
void z8530_wire(z8530_instance_t *instance, indev_t *kbrdin)
 
109
{
 
110
        ASSERT(instance);
 
111
        ASSERT(kbrdin);
 
112
        
 
113
        instance->kbrdin = kbrdin;
 
114
        
 
115
        irq_register(&instance->irq);
 
116
        
 
117
        (void) z8530_read(&instance->z8530->ctl_a, RR8);
 
118
        
 
119
        /*
 
120
         * Clear any pending TX interrupts or we never manage
 
121
         * to set FHC UART interrupt state to idle.
 
122
         */
 
123
        z8530_write(&instance->z8530->ctl_a, WR0, WR0_TX_IP_RST);
 
124
        
 
125
        /* interrupt on all characters */
 
126
        z8530_write(&instance->z8530->ctl_a, WR1, WR1_IARCSC);
 
127
        
 
128
        /* 8 bits per character and enable receiver */
 
129
        z8530_write(&instance->z8530->ctl_a, WR3, WR3_RX8BITSCH | WR3_RX_ENABLE);
 
130
        
 
131
        /* Master Interrupt Enable. */
 
132
        z8530_write(&instance->z8530->ctl_a, WR9, WR9_MIE);
 
133
}
 
134
 
 
135
/** @}
 
136
 */