Changeset c2417bc in mainline for kernel/arch/sparc64/src/drivers/kbd.c
- Timestamp:
- 2009-04-21T12:46:26Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f2d2c7ba
- Parents:
- 44b7783
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/sparc64/src/drivers/kbd.c
r44b7783 rc2417bc 55 55 #include <sysinfo/sysinfo.h> 56 56 57 kbd_type_t kbd_type = KBD_UNKNOWN;58 59 57 #ifdef CONFIG_SUN_KBD 60 58 61 /** Initialize keyboard. 62 * 63 * Traverse OpenFirmware device tree in order to find necessary 64 * info about the keyboard device. 65 * 66 * @param node Keyboard device node. 67 */ 68 void kbd_init(ofw_tree_node_t *node) 59 #ifdef CONFIG_Z8530 60 61 static bool kbd_z8530_init(ofw_tree_node_t *node) 69 62 { 70 size_t offset; 71 uintptr_t aligned_addr; 72 ofw_tree_property_t *prop; 73 const char *name; 63 const char *name = ofw_tree_node_name(node); 64 65 if (str_cmp(name, "zs") != 0) 66 return false; 67 68 /* 69 * Read 'interrupts' property. 70 */ 71 ofw_tree_property_t *prop = ofw_tree_getprop(node, "interrupts"); 72 if ((!prop) || (!prop->value)) { 73 printf("z8530: Unable to find interrupts property\n"); 74 return false; 75 } 76 77 uint32_t interrupts = *((uint32_t *) prop->value); 78 79 /* 80 * Read 'reg' property. 81 */ 82 prop = ofw_tree_getprop(node, "reg"); 83 if ((!prop) || (!prop->value)) { 84 printf("z8530: Unable to find reg property\n"); 85 return false; 86 } 87 88 size_t size = ((ofw_fhc_reg_t *) prop->value)->size; 89 90 uintptr_t pa; 91 if (!ofw_fhc_apply_ranges(node->parent, 92 ((ofw_fhc_reg_t *) prop->value), &pa)) { 93 printf("z8530: Failed to determine address\n"); 94 return false; 95 } 96 97 inr_t inr; 74 98 cir_t cir; 75 99 void *cir_arg; 76 77 #ifdef CONFIG_NS16550 78 ns16550_t *ns16550; 79 #endif 80 #ifdef CONFIG_Z8530 81 z8530_t *z8530; 82 #endif 83 84 name = ofw_tree_node_name(node); 85 86 /* 87 * Determine keyboard serial controller type. 88 */ 89 if (str_cmp(name, "zs") == 0) 90 kbd_type = KBD_Z8530; 91 else if (str_cmp(name, "su") == 0) 92 kbd_type = KBD_NS16550; 93 94 if (kbd_type == KBD_UNKNOWN) { 95 printf("Unknown keyboard device.\n"); 96 return; 97 } 98 99 /* 100 * Read 'interrupts' property. 101 */ 102 uint32_t interrupts; 103 prop = ofw_tree_getprop(node, "interrupts"); 104 if ((!prop) || (!prop->value)) 105 panic("Cannot find 'interrupt' property."); 106 interrupts = *((uint32_t *) prop->value); 107 108 /* 109 * Read 'reg' property. 110 */ 111 prop = ofw_tree_getprop(node, "reg"); 112 if ((!prop) || (!prop->value)) 113 panic("Cannot find 'reg' property."); 114 115 uintptr_t pa; 116 size_t size; 117 inr_t inr; 118 119 switch (kbd_type) { 120 case KBD_Z8530: 121 size = ((ofw_fhc_reg_t *) prop->value)->size; 122 if (!ofw_fhc_apply_ranges(node->parent, 123 ((ofw_fhc_reg_t *) prop->value), &pa)) { 124 printf("Failed to determine keyboard address.\n"); 125 return; 126 } 127 if (!ofw_fhc_map_interrupt(node->parent, 128 ((ofw_fhc_reg_t *) prop->value), interrupts, &inr, &cir, 129 &cir_arg)) { 130 printf("Failed to determine keyboard interrupt.\n"); 131 return; 132 } 133 break; 134 135 case KBD_NS16550: 136 size = ((ofw_ebus_reg_t *) prop->value)->size; 137 if (!ofw_ebus_apply_ranges(node->parent, 138 ((ofw_ebus_reg_t *) prop->value), &pa)) { 139 printf("Failed to determine keyboard address.\n"); 140 return; 141 } 142 if (!ofw_ebus_map_interrupt(node->parent, 143 ((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir, 144 &cir_arg)) { 145 printf("Failed to determine keyboard interrupt.\n"); 146 return; 147 }; 148 break; 149 default: 150 panic("Unexpected keyboard type."); 100 if (!ofw_fhc_map_interrupt(node->parent, 101 ((ofw_fhc_reg_t *) prop->value), interrupts, &inr, &cir, 102 &cir_arg)) { 103 printf("z8530: Failed to determine interrupt\n"); 104 return false; 151 105 } 152 106 … … 157 111 * underlying controller. 158 112 */ 159 aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE); 160 offset = pa - aligned_addr; 161 162 switch (kbd_type) { 113 uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE); 114 size_t offset = pa - aligned_addr; 115 116 z8530_t *z8530 = (z8530_t *) 117 (hw_map(aligned_addr, offset + size) + offset); 118 119 z8530_instance_t *z8530_instance = z8530_init(z8530, inr, cir, cir_arg); 120 if (z8530_instance) { 121 kbrd_instance_t *kbrd_instance = kbrd_init(); 122 if (kbrd_instance) { 123 indev_t *sink = stdin_wire(); 124 indev_t *kbrd = kbrd_wire(kbrd_instance, sink); 125 z8530_wire(z8530_instance, kbrd); 126 } 127 } 128 129 /* 130 * This is the necessary evil until the userspace drivers are 131 * entirely self-sufficient. 132 */ 133 sysinfo_set_item_val("kbd", NULL, true); 134 sysinfo_set_item_val("kbd.inr", NULL, inr); 135 sysinfo_set_item_val("kbd.address.kernel", NULL, 136 (uintptr_t) z8530); 137 sysinfo_set_item_val("kbd.address.physical", NULL, pa); 138 sysinfo_set_item_val("kbd.type.z8530", NULL, true); 139 140 return true; 141 } 142 143 #endif /* CONFIG_Z8530 */ 144 145 #ifdef CONFIG_NS16550 146 147 static bool kbd_ns16550_init(ofw_tree_node_t *node) 148 { 149 const char *name = ofw_tree_node_name(node); 150 151 if (str_cmp(name, "su") != 0) 152 return false; 153 154 /* 155 * Read 'interrupts' property. 156 */ 157 ofw_tree_property_t *prop = ofw_tree_getprop(node, "interrupts"); 158 if ((!prop) || (!prop->value)) { 159 printf("ns16550: Unable to find interrupts property\n"); 160 return false; 161 } 162 163 uint32_t interrupts = *((uint32_t *) prop->value); 164 165 /* 166 * Read 'reg' property. 167 */ 168 prop = ofw_tree_getprop(node, "reg"); 169 if ((!prop) || (!prop->value)) { 170 printf("ns16550: Unable to find reg property\n"); 171 return false; 172 } 173 174 size_t size = ((ofw_ebus_reg_t *) prop->value)->size; 175 176 uintptr_t pa; 177 if (!ofw_ebus_apply_ranges(node->parent, 178 ((ofw_ebus_reg_t *) prop->value), &pa)) { 179 printf("ns16550: Failed to determine address\n"); 180 return false; 181 } 182 183 inr_t inr; 184 cir_t cir; 185 void *cir_arg; 186 if (!ofw_ebus_map_interrupt(node->parent, 187 ((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir, 188 &cir_arg)) { 189 printf("ns16550: Failed to determine interrupt\n"); 190 return false; 191 } 192 193 /* 194 * We need to pass aligned address to hw_map(). 195 * However, the physical keyboard address can 196 * be pretty much unaligned, depending on the 197 * underlying controller. 198 */ 199 uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE); 200 size_t offset = pa - aligned_addr; 201 202 ns16550_t *ns16550 = (ns16550_t *) 203 (hw_map(aligned_addr, offset + size) + offset); 204 205 ns16550_instance_t *ns16550_instance = ns16550_init(ns16550, inr, cir, cir_arg); 206 if (ns16550_instance) { 207 kbrd_instance_t *kbrd_instance = kbrd_init(); 208 if (kbrd_instance) { 209 indev_t *sink = stdin_wire(); 210 indev_t *kbrd = kbrd_wire(kbrd_instance, sink); 211 ns16550_wire(ns16550_instance, kbrd); 212 } 213 } 214 215 /* 216 * This is the necessary evil until the userspace drivers are 217 * entirely self-sufficient. 218 */ 219 sysinfo_set_item_val("kbd", NULL, true); 220 sysinfo_set_item_val("kbd.inr", NULL, inr); 221 sysinfo_set_item_val("kbd.address.kernel", NULL, 222 (uintptr_t) ns16550); 223 sysinfo_set_item_val("kbd.address.physical", NULL, pa); 224 sysinfo_set_item_val("kbd.type.ns16550", NULL, true); 225 226 return true; 227 } 228 229 #endif /* CONFIG_NS16550 */ 230 231 /** Initialize keyboard. 232 * 233 * Traverse OpenFirmware device tree in order to find necessary 234 * info about the keyboard device. 235 * 236 * @param node Keyboard device node. 237 * 238 */ 239 void kbd_init(ofw_tree_node_t *node) 240 { 163 241 #ifdef CONFIG_Z8530 164 case KBD_Z8530: 165 z8530 = (z8530_t *) 166 (hw_map(aligned_addr, offset + size) + offset); 167 168 indev_t *kbrdin_z8530 = z8530_init(z8530, inr, cir, cir_arg); 169 if (kbrdin_z8530) 170 kbrd_init(kbrdin_z8530); 171 172 /* 173 * This is the necessary evil until the userspace drivers are 174 * entirely self-sufficient. 175 */ 176 sysinfo_set_item_val("kbd", NULL, true); 177 sysinfo_set_item_val("kbd.type", NULL, KBD_Z8530); 178 sysinfo_set_item_val("kbd.inr", NULL, inr); 179 sysinfo_set_item_val("kbd.address.kernel", NULL, 180 (uintptr_t) z8530); 181 sysinfo_set_item_val("kbd.address.physical", NULL, pa); 182 break; 183 #endif 242 kbd_z8530_init(node); 243 #endif 244 184 245 #ifdef CONFIG_NS16550 185 case KBD_NS16550: 186 ns16550 = (ns16550_t *) 187 (hw_map(aligned_addr, offset + size) + offset); 188 189 indev_t *kbrdin_ns16550 = ns16550_init(ns16550, inr, cir, cir_arg); 190 if (kbrdin_ns16550) 191 kbrd_init(kbrdin_ns16550); 192 193 /* 194 * This is the necessary evil until the userspace driver is 195 * entirely self-sufficient. 196 */ 197 sysinfo_set_item_val("kbd", NULL, true); 198 sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550); 199 sysinfo_set_item_val("kbd.inr", NULL, inr); 200 sysinfo_set_item_val("kbd.address.kernel", NULL, 201 (uintptr_t) ns16550); 202 sysinfo_set_item_val("kbd.address.physical", NULL, pa); 203 break; 204 #endif 205 default: 206 printf("Kernel is not compiled with the necessary keyboard " 207 "driver this machine requires.\n"); 208 } 246 kbd_ns16550_init(node); 247 #endif 209 248 } 210 249 211 #endif 250 #endif /* CONFIG_SUN_KBD */ 212 251 213 252 /** @}
Note:
See TracChangeset
for help on using the changeset viewer.