Changeset b446b02 in mainline for uspace/drv/intctl/apic/apic.c
- Timestamp:
- 2017-10-17T17:47:11Z (8 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- b1efe3e
- Parents:
- a416d070
- File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/intctl/apic/apic.c
ra416d070 rb446b02 40 40 #include <sysinfo.h> 41 41 #include <as.h> 42 #include <ddf/driver.h> 43 #include <ddf/log.h> 42 44 #include <ddi.h> 43 45 #include <stdbool.h> … … 45 47 #include <async.h> 46 48 #include <stdio.h> 49 50 #include "apic.h" 47 51 48 52 #define NAME "apic" … … 89 93 } __attribute__ ((packed)) io_redirection_reg_t; 90 94 91 // FIXME: get the address from the kernel92 #define IO_APIC_BASE 0xfec00000UL93 95 #define IO_APIC_SIZE 20 94 96 95 ioport32_t *io_apic = NULL;96 97 97 /** Read from IO APIC register. 98 98 * 99 * @param apic APIC 99 100 * @param address IO APIC register address. 100 101 * … … 102 103 * 103 104 */ 104 static uint32_t io_apic_read( uint8_t address)105 static uint32_t io_apic_read(apic_t *apic, uint8_t address) 105 106 { 106 107 io_regsel_t regsel; 107 108 108 regsel.value = io_apic[IOREGSEL];109 regsel.value = pio_read_32(&apic->regs[IOREGSEL]); 109 110 regsel.reg_addr = address; 110 io_apic[IOREGSEL] = regsel.value;111 return io_apic[IOWIN];111 pio_write_32(&apic->regs[IOREGSEL], regsel.value); 112 return pio_read_32(&apic->regs[IOWIN]); 112 113 } 113 114 114 115 /** Write to IO APIC register. 115 116 * 117 * @param apic APIC 116 118 * @param address IO APIC register address. 117 119 * @param val Content to be written to the addressed IO APIC register. 118 120 * 119 121 */ 120 static void io_apic_write( uint8_t address, uint32_t val)122 static void io_apic_write(apic_t *apic, uint8_t address, uint32_t val) 121 123 { 122 124 io_regsel_t regsel; 123 125 124 regsel.value = io_apic[IOREGSEL];126 regsel.value = pio_read_32(&apic->regs[IOREGSEL]); 125 127 regsel.reg_addr = address; 126 io_apic[IOREGSEL] = regsel.value;127 io_apic[IOWIN] = val;128 pio_write_32(&apic->regs[IOREGSEL], regsel.value); 129 pio_write_32(&apic->regs[IOWIN], val); 128 130 } 129 131 … … 137 139 } 138 140 139 static int apic_enable_irq( sysarg_t irq)141 static int apic_enable_irq(apic_t *apic, sysarg_t irq) 140 142 { 141 143 io_redirection_reg_t reg; … … 148 150 return ENOENT; 149 151 150 reg.lo = io_apic_read( (uint8_t) (IOREDTBL + pin * 2));152 reg.lo = io_apic_read(apic, (uint8_t) (IOREDTBL + pin * 2)); 151 153 reg.masked = false; 152 io_apic_write( (uint8_t) (IOREDTBL + pin * 2), reg.lo);154 io_apic_write(apic, (uint8_t) (IOREDTBL + pin * 2), reg.lo); 153 155 154 156 return EOK; … … 165 167 ipc_callid_t callid; 166 168 ipc_call_t call; 169 apic_t *apic; 167 170 168 171 /* … … 170 173 */ 171 174 async_answer_0(iid, EOK); 175 176 apic = (apic_t *)ddf_dev_data_get(ddf_fun_get_dev((ddf_fun_t *)arg)); 172 177 173 178 while (true) { … … 182 187 switch (IPC_GET_IMETHOD(call)) { 183 188 case IRC_ENABLE_INTERRUPT: 184 async_answer_0(callid, apic_enable_irq(IPC_GET_ARG1(call))); 189 async_answer_0(callid, apic_enable_irq(apic, 190 IPC_GET_ARG1(call))); 185 191 break; 186 192 case IRC_DISABLE_INTERRUPT: … … 199 205 } 200 206 201 /** Initialize the APIC driver. 202 * 203 */ 204 static bool apic_init(void) 205 { 206 sysarg_t apic; 207 category_id_t irc_cat; 208 service_id_t svc_id; 209 210 if ((sysinfo_get_value("apic", &apic) != EOK) || (!apic)) { 207 /** Add APIC device. */ 208 int apic_add(apic_t *apic, apic_res_t *res) 209 { 210 sysarg_t have_apic; 211 ddf_fun_t *fun_a = NULL; 212 void *regs; 213 int rc; 214 215 if ((sysinfo_get_value("apic", &have_apic) != EOK) || (!have_apic)) { 211 216 printf("%s: No APIC found\n", NAME); 212 return false; 213 } 214 215 int rc = pio_enable((void *) IO_APIC_BASE, IO_APIC_SIZE, 216 (void **) &io_apic); 217 return ENOTSUP; 218 } 219 220 rc = pio_enable((void *) res->base, IO_APIC_SIZE, ®s); 217 221 if (rc != EOK) { 218 222 printf("%s: Failed to enable PIO for APIC: %d\n", NAME, rc); 219 return false; 220 } 221 222 async_set_fallback_port_handler(apic_connection, NULL); 223 224 rc = loc_server_register(NAME); 223 return EIO; 224 } 225 226 apic->regs = (ioport32_t *)regs; 227 228 fun_a = ddf_fun_create(apic->dev, fun_exposed, "a"); 229 if (fun_a == NULL) { 230 ddf_msg(LVL_ERROR, "Failed creating function 'a'."); 231 rc = ENOMEM; 232 goto error; 233 } 234 235 ddf_fun_set_conn_handler(fun_a, apic_connection); 236 237 rc = ddf_fun_bind(fun_a); 225 238 if (rc != EOK) { 226 printf("%s: Failed registering server. (%d)\n", NAME, rc); 227 return false; 228 } 229 230 rc = loc_service_register("irc/" NAME, &svc_id); 231 if (rc != EOK) { 232 printf("%s: Failed registering service. (%d)\n", NAME, rc); 233 return false; 234 } 235 236 rc = loc_category_get_id("irc", &irc_cat, IPC_FLAG_BLOCKING); 237 if (rc != EOK) { 238 printf("%s: Failed resolving category 'iplink' (%d).\n", NAME, 239 rc); 240 return false; 241 } 242 243 rc = loc_service_add_to_cat(svc_id, irc_cat); 244 if (rc != EOK) { 245 printf("%s: Failed adding service to category (%d).\n", NAME, 246 rc); 247 return false; 248 } 249 250 return true; 251 } 252 253 int main(int argc, char **argv) 254 { 255 printf("%s: HelenOS APIC driver\n", NAME); 256 257 if (!apic_init()) 258 return -1; 259 260 printf("%s: Accepting connections\n", NAME); 261 task_retval(0); 262 async_manager(); 263 264 /* Never reached */ 265 return 0; 239 ddf_msg(LVL_ERROR, "Failed binding function 'a'. (%d)", rc); 240 goto error; 241 } 242 243 rc = ddf_fun_add_to_category(fun_a, "irc"); 244 if (rc != EOK) 245 goto error; 246 247 return EOK; 248 error: 249 if (fun_a != NULL) 250 ddf_fun_destroy(fun_a); 251 return rc; 252 } 253 254 /** Remove APIC device */ 255 int apic_remove(apic_t *apic) 256 { 257 return ENOTSUP; 258 } 259 260 /** APIC device gone */ 261 int apic_gone(apic_t *apic) 262 { 263 return ENOTSUP; 266 264 } 267 265
Note:
See TracChangeset
for help on using the changeset viewer.