Subversion Repositories HelenOS

Rev

Rev 4055 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4055 Rev 4156
Line 24... Line 24...
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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
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.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/** @addtogroup genarch
29
/** @addtogroup genarch
30
 * @{
30
 * @{
31
 */
31
 */
32
/**
32
/**
33
 * @file
33
 * @file
34
 * @brief   NS 16550 serial controller driver.
34
 * @brief NS 16550 serial controller driver.
35
 */
35
 */
36
 
36
 
37
#include <genarch/drivers/ns16550/ns16550.h>
37
#include <genarch/drivers/ns16550/ns16550.h>
38
#include <ddi/irq.h>
38
#include <ddi/irq.h>
39
#include <arch/asm.h>
39
#include <arch/asm.h>
40
#include <console/chardev.h>
40
#include <console/chardev.h>
41
#include <mm/slab.h>
41
#include <mm/slab.h>
-
 
42
#include <ddi/device.h>
42
 
43
 
43
#define LSR_DATA_READY  0x01
44
#define LSR_DATA_READY  0x01
-
 
45
 
-
 
46
static indev_operations_t kbrdin_ops = {
-
 
47
    .poll = NULL
-
 
48
};
-
 
49
 
-
 
50
static irq_ownership_t ns16550_claim(irq_t *irq)
-
 
51
{
-
 
52
    ns16550_instance_t *instance = irq->instance;
-
 
53
    ns16550_t *dev = instance->ns16550;
-
 
54
   
-
 
55
    if (pio_read_8(&dev->lsr) & LSR_DATA_READY)
-
 
56
        return IRQ_ACCEPT;
-
 
57
    else
-
 
58
        return IRQ_DECLINE;
-
 
59
}
-
 
60
 
-
 
61
static void ns16550_irq_handler(irq_t *irq)
-
 
62
{
-
 
63
    ns16550_instance_t *instance = irq->instance;
-
 
64
    ns16550_t *dev = instance->ns16550;
-
 
65
   
-
 
66
    if (pio_read_8(&dev->lsr) & LSR_DATA_READY) {
-
 
67
        uint8_t x = pio_read_8(&dev->rbr);
-
 
68
        indev_push_character(&instance->kbrdin, x);
-
 
69
    }
-
 
70
}
44
 
71
 
45
/** Initialize ns16550.
72
/** Initialize ns16550.
46
 *
73
 *
47
 * @param dev       Addrress of the beginning of the device in I/O space.
74
 * @param dev      Addrress of the beginning of the device in I/O space.
48
 * @param devno     Device number.
75
 * @param devno    Device number.
49
 * @param inr       Interrupt number.
76
 * @param inr      Interrupt number.
50
 * @param cir       Clear interrupt function.
77
 * @param cir      Clear interrupt function.
51
 * @param cir_arg   First argument to cir.
78
 * @param cir_arg  First argument to cir.
-
 
79
 *
52
 * @param devout    Output character device.
80
 * @return Keyboard device pointer or NULL on failure.
53
 *
81
 *
54
 * @return      True on success, false on failure.
-
 
55
 */
82
 */
56
bool
-
 
57
ns16550_init(ns16550_t *dev, devno_t devno, inr_t inr, cir_t cir, void *cir_arg,
83
indev_t *ns16550_init(ns16550_t *dev, inr_t inr, cir_t cir, void *cir_arg)
58
    chardev_t *devout)
-
 
59
{
84
{
60
    ns16550_instance_t *instance;
85
    ns16550_instance_t *instance
61
   
-
 
62
    instance = malloc(sizeof(ns16550_instance_t), FRAME_ATOMIC);
86
        = malloc(sizeof(ns16550_instance_t), FRAME_ATOMIC);
63
    if (!instance)
87
    if (!instance)
64
        return false;
88
        return NULL;
65
 
89
   
66
    instance->devno = devno;
90
    indev_initialize("ns16550", &instance->kbrdin, &kbrdin_ops);
-
 
91
   
67
    instance->ns16550 = dev;
92
    instance->ns16550 = dev;
68
    instance->devout = devout;
-
 
69
   
93
   
70
    irq_initialize(&instance->irq);
94
    irq_initialize(&instance->irq);
71
    instance->irq.devno = devno;
95
    instance->irq.devno = device_assign_devno();
72
    instance->irq.inr = inr;
96
    instance->irq.inr = inr;
73
    instance->irq.claim = ns16550_claim;
97
    instance->irq.claim = ns16550_claim;
74
    instance->irq.handler = ns16550_irq_handler;
98
    instance->irq.handler = ns16550_irq_handler;
75
    instance->irq.instance = instance;
99
    instance->irq.instance = instance;
76
    instance->irq.cir = cir;
100
    instance->irq.cir = cir;
77
    instance->irq.cir_arg = cir_arg;
101
    instance->irq.cir_arg = cir_arg;
78
    irq_register(&instance->irq);
102
    irq_register(&instance->irq);
79
 
103
   
80
    while ((pio_read_8(&dev->lsr) & LSR_DATA_READY))
104
    while ((pio_read_8(&dev->lsr) & LSR_DATA_READY))
81
        (void) pio_read_8(&dev->rbr);
105
        (void) pio_read_8(&dev->rbr);
82
   
106
   
83
    /* Enable interrupts */
107
    /* Enable interrupts */
84
    pio_write_8(&dev->ier, IER_ERBFI);
108
    pio_write_8(&dev->ier, IER_ERBFI);
85
    pio_write_8(&dev->mcr, MCR_OUT2);
109
    pio_write_8(&dev->mcr, MCR_OUT2);
86
   
110
   
87
    return true;
-
 
88
}
-
 
89
 
-
 
90
irq_ownership_t ns16550_claim(irq_t *irq)
-
 
91
{
-
 
92
    ns16550_instance_t *instance = irq->instance;
-
 
93
    ns16550_t *dev = instance->ns16550;
-
 
94
 
-
 
95
    if (pio_read_8(&dev->lsr) & LSR_DATA_READY)
-
 
96
        return IRQ_ACCEPT;
-
 
97
    else
-
 
98
        return IRQ_DECLINE;
-
 
99
}
-
 
100
 
-
 
101
void ns16550_irq_handler(irq_t *irq)
-
 
102
{
-
 
103
    ns16550_instance_t *instance = irq->instance;
-
 
104
    ns16550_t *dev = instance->ns16550;
-
 
105
 
-
 
106
    if (pio_read_8(&dev->lsr) & LSR_DATA_READY) {
-
 
107
        uint8_t x;
-
 
108
       
-
 
109
        x = pio_read_8(&dev->rbr);
-
 
110
        if (instance->devout)
111
    return &instance->kbrdin;
111
            chardev_push_character(instance->devout, x);
-
 
112
    }
-
 
113
}
112
}
114
 
113
 
115
/** @}
114
/** @}
116
 */
115
 */