Changeset b446b02 in mainline for uspace/drv/intctl/apic/apic.c


Ignore:
Timestamp:
2017-10-17T17:47:11Z (7 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b1efe3e
Parents:
a416d070
Message:

Enumerate APIC and i8259 via DDF.

File:
1 moved

Legend:

Unmodified
Added
Removed
  • uspace/drv/intctl/apic/apic.c

    ra416d070 rb446b02  
    4040#include <sysinfo.h>
    4141#include <as.h>
     42#include <ddf/driver.h>
     43#include <ddf/log.h>
    4244#include <ddi.h>
    4345#include <stdbool.h>
     
    4547#include <async.h>
    4648#include <stdio.h>
     49
     50#include "apic.h"
    4751
    4852#define NAME  "apic"
     
    8993} __attribute__ ((packed)) io_redirection_reg_t;
    9094
    91 // FIXME: get the address from the kernel
    92 #define IO_APIC_BASE    0xfec00000UL
    9395#define IO_APIC_SIZE    20
    9496
    95 ioport32_t *io_apic = NULL;
    96 
    9797/** Read from IO APIC register.
    9898 *
     99 * @param apic APIC
    99100 * @param address IO APIC register address.
    100101 *
     
    102103 *
    103104 */
    104 static uint32_t io_apic_read(uint8_t address)
     105static uint32_t io_apic_read(apic_t *apic, uint8_t address)
    105106{
    106107        io_regsel_t regsel;
    107108
    108         regsel.value = io_apic[IOREGSEL];
     109        regsel.value = pio_read_32(&apic->regs[IOREGSEL]);
    109110        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]);
    112113}
    113114
    114115/** Write to IO APIC register.
    115116 *
     117 * @param apic    APIC
    116118 * @param address IO APIC register address.
    117119 * @param val     Content to be written to the addressed IO APIC register.
    118120 *
    119121 */
    120 static void io_apic_write(uint8_t address, uint32_t val)
     122static void io_apic_write(apic_t *apic, uint8_t address, uint32_t val)
    121123{
    122124        io_regsel_t regsel;
    123125
    124         regsel.value = io_apic[IOREGSEL];
     126        regsel.value = pio_read_32(&apic->regs[IOREGSEL]);
    125127        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);
    128130}
    129131
     
    137139}
    138140
    139 static int apic_enable_irq(sysarg_t irq)
     141static int apic_enable_irq(apic_t *apic, sysarg_t irq)
    140142{
    141143        io_redirection_reg_t reg;
     
    148150                return ENOENT;
    149151
    150         reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2));
     152        reg.lo = io_apic_read(apic, (uint8_t) (IOREDTBL + pin * 2));
    151153        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);
    153155
    154156        return EOK;
     
    165167        ipc_callid_t callid;
    166168        ipc_call_t call;
     169        apic_t *apic;
    167170       
    168171        /*
     
    170173         */
    171174        async_answer_0(iid, EOK);
     175       
     176        apic = (apic_t *)ddf_dev_data_get(ddf_fun_get_dev((ddf_fun_t *)arg));
    172177       
    173178        while (true) {
     
    182187                switch (IPC_GET_IMETHOD(call)) {
    183188                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)));
    185191                        break;
    186192                case IRC_DISABLE_INTERRUPT:
     
    199205}
    200206
    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. */
     208int 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)) {
    211216                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, &regs);
    217221        if (rc != EOK) {
    218222                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);
    225238        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;
     248error:
     249        if (fun_a != NULL)
     250                ddf_fun_destroy(fun_a);
     251        return rc;
     252}
     253
     254/** Remove APIC device */
     255int apic_remove(apic_t *apic)
     256{
     257        return ENOTSUP;
     258}
     259
     260/** APIC device gone */
     261int apic_gone(apic_t *apic)
     262{
     263        return ENOTSUP;
    266264}
    267265
Note: See TracChangeset for help on using the changeset viewer.