Rev 3941 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3941 | Rev 3959 | ||
---|---|---|---|
Line 38... | Line 38... | ||
38 | #include <genarch/kbd/key.h> |
38 | #include <genarch/kbd/key.h> |
39 | #include <genarch/kbd/scanc.h> |
39 | #include <genarch/kbd/scanc.h> |
40 | #include <genarch/kbd/scanc_sun.h> |
40 | #include <genarch/kbd/scanc_sun.h> |
41 | #include <arch/drivers/kbd.h> |
41 | #include <arch/drivers/kbd.h> |
42 | #include <ddi/irq.h> |
42 | #include <ddi/irq.h> |
43 | #include <ipc/irq.h> |
- | |
44 | #include <cpu.h> |
43 | #include <cpu.h> |
45 | #include <arch/asm.h> |
44 | #include <arch/asm.h> |
46 | #include <arch.h> |
45 | #include <arch.h> |
47 | #include <console/chardev.h> |
46 | #include <console/chardev.h> |
48 | #include <console/console.h> |
47 | #include <console/console.h> |
Line 52... | Line 51... | ||
52 | #include <synch/spinlock.h> |
51 | #include <synch/spinlock.h> |
53 | #include <mm/slab.h> |
52 | #include <mm/slab.h> |
54 | 53 | ||
55 | #define LSR_DATA_READY 0x01 |
54 | #define LSR_DATA_READY 0x01 |
56 | 55 | ||
57 | static irq_t *ns16550_irq; |
- | |
58 | - | ||
59 | /* |
56 | /* |
60 | * These codes read from ns16550 data register are silently ignored. |
57 | * These codes read from ns16550 data register are silently ignored. |
61 | */ |
58 | */ |
62 | #define IGNORE_CODE 0x7f /* all keys up */ |
59 | #define IGNORE_CODE 0x7f /* all keys up */ |
63 | 60 | ||
Line 67... | Line 64... | ||
67 | static chardev_operations_t ops = { |
64 | static chardev_operations_t ops = { |
68 | .suspend = ns16550_suspend, |
65 | .suspend = ns16550_suspend, |
69 | .resume = ns16550_resume, |
66 | .resume = ns16550_resume, |
70 | }; |
67 | }; |
71 | 68 | ||
72 | /** Initialize keyboard and service interrupts using kernel routine */ |
- | |
73 | void ns16550_grab(void) |
- | |
74 | { |
- | |
75 | ipl_t ipl = interrupts_disable(); |
- | |
76 | spinlock_lock(&ns16550_irq->lock); |
- | |
77 | ns16550_irq->notif_cfg.notify = false; |
- | |
78 | spinlock_unlock(&ns16550_irq->lock); |
- | |
79 | interrupts_restore(ipl); |
- | |
80 | } |
- | |
81 | - | ||
82 | /** Resume the former interrupt vector */ |
- | |
83 | void ns16550_release(void) |
- | |
84 | { |
- | |
85 | ipl_t ipl = interrupts_disable(); |
- | |
86 | spinlock_lock(&ns16550_irq->lock); |
- | |
87 | if (ns16550_irq->notif_cfg.answerbox) |
- | |
88 | ns16550_irq->notif_cfg.notify = true; |
- | |
89 | spinlock_unlock(&ns16550_irq->lock); |
- | |
90 | interrupts_restore(ipl); |
- | |
91 | } |
- | |
92 | - | ||
93 | /** Initialize ns16550. |
69 | /** Initialize ns16550. |
94 | * |
70 | * |
95 | * @param dev Addrress of the beginning of the device in I/O space. |
71 | * @param dev Addrress of the beginning of the device in I/O space. |
96 | * @param devno Device number. |
72 | * @param devno Device number. |
97 | * @param inr Interrupt number. |
73 | * @param inr Interrupt number. |
Line 123... | Line 99... | ||
123 | instance->irq.instance = instance; |
99 | instance->irq.instance = instance; |
124 | instance->irq.cir = cir; |
100 | instance->irq.cir = cir; |
125 | instance->irq.cir_arg = cir_arg; |
101 | instance->irq.cir_arg = cir_arg; |
126 | irq_register(&instance->irq); |
102 | irq_register(&instance->irq); |
127 | 103 | ||
128 | ns16550_irq = &instance->irq; /* TODO: remove me soon */ |
- | |
129 | - | ||
130 | while ((pio_read_8(&dev->lsr) & LSR_DATA_READY)) |
104 | while ((pio_read_8(&dev->lsr) & LSR_DATA_READY)) |
131 | (void) pio_read_8(&dev->rbr); |
105 | (void) pio_read_8(&dev->rbr); |
132 | 106 | ||
- | 107 | /* |
|
- | 108 | * This is the necessary evil until the userspace driver is entirely |
|
- | 109 | * self-sufficient. |
|
- | 110 | */ |
|
133 | sysinfo_set_item_val("kbd", NULL, true); |
111 | sysinfo_set_item_val("kbd", NULL, true); |
134 | sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550); |
112 | sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550); |
135 | sysinfo_set_item_val("kbd.devno", NULL, devno); |
113 | sysinfo_set_item_val("kbd.devno", NULL, devno); |
136 | sysinfo_set_item_val("kbd.inr", NULL, inr); |
114 | sysinfo_set_item_val("kbd.inr", NULL, inr); |
137 | sysinfo_set_item_val("kbd.address.virtual", NULL, (uintptr_t) dev); |
115 | sysinfo_set_item_val("kbd.address.virtual", NULL, (uintptr_t) dev); |
Line 139... | Line 117... | ||
139 | 117 | ||
140 | /* Enable interrupts */ |
118 | /* Enable interrupts */ |
141 | pio_write_8(&dev->ier, IER_ERBFI); |
119 | pio_write_8(&dev->ier, IER_ERBFI); |
142 | pio_write_8(&dev->mcr, MCR_OUT2); |
120 | pio_write_8(&dev->mcr, MCR_OUT2); |
143 | 121 | ||
144 | ns16550_grab(); |
- | |
145 | - | ||
146 | return true; |
122 | return true; |
147 | } |
123 | } |
148 | 124 | ||
149 | /* Called from getc(). */ |
125 | /* Called from getc(). */ |
150 | void ns16550_resume(chardev_t *d) |
126 | void ns16550_resume(chardev_t *d) |
Line 167... | Line 143... | ||
167 | return IRQ_DECLINE; |
143 | return IRQ_DECLINE; |
168 | } |
144 | } |
169 | 145 | ||
170 | void ns16550_irq_handler(irq_t *irq) |
146 | void ns16550_irq_handler(irq_t *irq) |
171 | { |
147 | { |
172 | if (irq->notif_cfg.notify && irq->notif_cfg.answerbox) { |
- | |
173 | /* |
- | |
174 | * This will hopefully go to the IRQ dispatch code soon. |
- | |
175 | */ |
- | |
176 | ipc_irq_send_notif(irq); |
- | |
177 | return; |
- | |
178 | } |
- | |
179 | - | ||
180 | ns16550_instance_t *ns16550_instance = irq->instance; |
148 | ns16550_instance_t *ns16550_instance = irq->instance; |
181 | ns16550_t *dev = ns16550_instance->ns16550; |
149 | ns16550_t *dev = ns16550_instance->ns16550; |
182 | 150 | ||
183 | if (pio_read_8(&dev->lsr) & LSR_DATA_READY) { |
151 | if (pio_read_8(&dev->lsr) & LSR_DATA_READY) { |
184 | uint8_t x; |
152 | uint8_t x; |