Changeset 013c4d6 in mainline for kernel/genarch/src/kbd/ns16550.c
- Timestamp:
- 2009-02-19T23:55:23Z (16 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f32d90b
- Parents:
- d1eece6
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/genarch/src/kbd/ns16550.c
rd1eece6 r013c4d6 51 51 #include <sysinfo/sysinfo.h> 52 52 #include <synch/spinlock.h> 53 #include <mm/slab.h> 53 54 54 55 #define LSR_DATA_READY 0x01 55 56 56 /** Structure representing the ns16550. */ 57 static ns16550_t ns16550; 58 59 /** Structure for ns16550's IRQ. */ 60 static irq_t ns16550_irq; 57 static irq_t *ns16550_irq; 61 58 62 59 /* … … 71 68 .suspend = ns16550_suspend, 72 69 .resume = ns16550_resume, 73 .read = ns16550_key_read74 70 }; 75 76 void ns16550_interrupt(void);77 71 78 72 /** Initialize keyboard and service interrupts using kernel routine */ … … 80 74 { 81 75 ipl_t ipl = interrupts_disable(); 82 83 ns16550_ier_write(&ns16550, IER_ERBFI); /* enable receiver interrupt */ 84 85 while (ns16550_lsr_read(&ns16550) & LSR_DATA_READY) 86 (void) ns16550_rbr_read(&ns16550); 87 88 spinlock_lock(&ns16550_irq.lock); 89 ns16550_irq.notif_cfg.notify = false; 90 spinlock_unlock(&ns16550_irq.lock); 76 spinlock_lock(&ns16550_irq->lock); 77 ns16550_irq->notif_cfg.notify = false; 78 spinlock_unlock(&ns16550_irq->lock); 91 79 interrupts_restore(ipl); 92 80 } … … 96 84 { 97 85 ipl_t ipl = interrupts_disable(); 98 spinlock_lock(&ns16550_irq .lock);99 if (ns16550_irq .notif_cfg.answerbox)100 ns16550_irq .notif_cfg.notify = true;101 spinlock_unlock(&ns16550_irq .lock);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); 102 90 interrupts_restore(ipl); 103 91 } … … 105 93 /** Initialize ns16550. 106 94 * 95 * @param dev Addrress of the beginning of the device in I/O space. 107 96 * @param devno Device number. 108 * @param port Virtual/IO address of device's registers.109 97 * @param inr Interrupt number. 110 98 * @param cir Clear interrupt function. 111 99 * @param cir_arg First argument to cir. 112 */ 113 void 114 ns16550_init(devno_t devno, ioport_t port, inr_t inr, cir_t cir, void *cir_arg) 115 { 100 * 101 * @return True on success, false on failure. 102 */ 103 bool 104 ns16550_init(ns16550_t *dev, devno_t devno, inr_t inr, cir_t cir, void *cir_arg) 105 { 106 ns16550_instance_t *instance; 107 irq_t *irq; 108 116 109 chardev_initialize("ns16550_kbd", &kbrd, &ops); 117 110 stdin = &kbrd; 118 111 119 ns16550.devno = devno; 120 ns16550.io_port = port; 121 122 irq_initialize(&ns16550_irq); 123 ns16550_irq.devno = devno; 124 ns16550_irq.inr = inr; 125 ns16550_irq.claim = ns16550_claim; 126 ns16550_irq.handler = ns16550_irq_handler; 127 ns16550_irq.cir = cir; 128 ns16550_irq.cir_arg = cir_arg; 129 irq_register(&ns16550_irq); 130 131 while ((ns16550_lsr_read(&ns16550) & LSR_DATA_READY)) 132 ns16550_rbr_read(&ns16550); 112 instance = malloc(sizeof(ns16550_instance_t), FRAME_ATOMIC); 113 if (!instance) 114 return false; 115 116 irq = malloc(sizeof(irq_t), FRAME_ATOMIC); 117 if (!irq) { 118 free(instance); 119 return false; 120 } 121 122 instance->devno = devno; 123 instance->ns16550 = dev; 124 instance->irq = irq; 125 126 irq_initialize(irq); 127 irq->devno = devno; 128 irq->inr = inr; 129 irq->claim = ns16550_claim; 130 irq->handler = ns16550_irq_handler; 131 irq->instance = instance; 132 irq->cir = cir; 133 irq->cir_arg = cir_arg; 134 irq_register(irq); 135 136 ns16550_irq = irq; /* TODO: remove me soon */ 137 138 while ((pio_read_8(&dev->lsr) & LSR_DATA_READY)) 139 (void) pio_read_8(&dev->rbr); 133 140 134 141 sysinfo_set_item_val("kbd", NULL, true); … … 136 143 sysinfo_set_item_val("kbd.devno", NULL, devno); 137 144 sysinfo_set_item_val("kbd.inr", NULL, inr); 138 sysinfo_set_item_val("kbd.address.virtual", NULL, port);139 sysinfo_set_item_val("kbd.port", NULL, port);145 sysinfo_set_item_val("kbd.address.virtual", NULL, (uintptr_t) dev); 146 sysinfo_set_item_val("kbd.port", NULL, (uintptr_t) dev); 140 147 141 148 /* Enable interrupts */ 142 ns16550_ier_write(&ns16550, IER_ERBFI); 143 ns16550_mcr_write(&ns16550, MCR_OUT2); 144 145 uint8_t c; 146 // This switches rbr & ier to mode when accept baudrate constant 147 c = ns16550_lcr_read(&ns16550); 148 ns16550_lcr_write(&ns16550, 0x80 | c); 149 ns16550_rbr_write(&ns16550, 0x0c); 150 ns16550_ier_write(&ns16550, 0x00); 151 ns16550_lcr_write(&ns16550, c); 149 pio_write_8(&dev->ier, IER_ERBFI); 150 pio_write_8(&dev->mcr, MCR_OUT2); 152 151 153 152 ns16550_grab(); 154 } 155 156 /** Process ns16550 interrupt. */ 157 void ns16550_interrupt(void) 158 { 159 ns16550_poll(); 153 154 return true; 160 155 } 161 156 … … 170 165 } 171 166 172 173 char ns16550_key_read(chardev_t *d) 174 { 175 char ch; 176 177 while(!(ch = active_read_buff_read())) { 178 uint8_t x; 179 while (!(ns16550_lsr_read(&ns16550) & LSR_DATA_READY)); 180 181 x = ns16550_rbr_read(&ns16550); 182 183 if (x != IGNORE_CODE) { 184 if (x & KEY_RELEASE) 185 key_released(x ^ KEY_RELEASE); 186 else 187 active_read_key_pressed(x); 188 } 167 irq_ownership_t ns16550_claim(void *instance) 168 { 169 ns16550_instance_t *ns16550_instance = instance; 170 ns16550_t *dev = ns16550_instance->ns16550; 171 172 if (pio_read_8(&dev->lsr) & LSR_DATA_READY) 173 return IRQ_ACCEPT; 174 else 175 return IRQ_DECLINE; 176 } 177 178 void ns16550_irq_handler(irq_t *irq) 179 { 180 if (irq->notif_cfg.notify && irq->notif_cfg.answerbox) { 181 /* 182 * This will hopefully go to the IRQ dispatch code soon. 183 */ 184 ipc_irq_send_notif(irq); 185 return; 189 186 } 190 return ch; 191 } 192 193 /** Poll for key press and release events. 194 * 195 * This function can be used to implement keyboard polling. 196 */ 197 void ns16550_poll(void) 198 { 199 while (ns16550_lsr_read(&ns16550) & LSR_DATA_READY) { 187 188 ns16550_instance_t *ns16550_instance = irq->instance; 189 ns16550_t *dev = ns16550_instance->ns16550; 190 191 if (pio_read_8(&dev->lsr) & LSR_DATA_READY) { 200 192 uint8_t x; 201 193 202 x = ns16550_rbr_read(&ns16550);194 x = pio_read_8(&dev->rbr); 203 195 204 196 if (x != IGNORE_CODE) { … … 209 201 } 210 202 } 211 } 212 213 irq_ownership_t ns16550_claim(void *instance) 214 { 215 return (ns16550_lsr_read(&ns16550) & LSR_DATA_READY); 216 } 217 218 void ns16550_irq_handler(irq_t *irq) 219 { 220 if (irq->notif_cfg.notify && irq->notif_cfg.answerbox) 221 ipc_irq_send_notif(irq); 222 else 223 ns16550_interrupt(); 203 224 204 } 225 205
Note:
See TracChangeset
for help on using the changeset viewer.