Fork us on GitHub Follow us on Facebook Follow us on Twitter

Ignore:
Timestamp:
2017-10-05T19:09:34Z (4 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master
Children:
82cbf8c6
Parents:
84eb4edd (diff), c188c62 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge CUDA DDF conversion.

File:
1 moved

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/adb/cuda_adb/cuda_adb.c

    r84eb4edd r81b9d3e  
    3737 */
    3838
     39#include <assert.h>
     40#include <ddf/driver.h>
     41#include <ddf/log.h>
     42#include <ddi.h>
     43#include <errno.h>
     44#include <ipc/adb.h>
     45#include <libarch/ddi.h>
     46#include <stdbool.h>
     47#include <stddef.h>
     48#include <sysinfo.h>
     49#include <stdint.h>
    3950#include <stdio.h>
    4051#include <stdlib.h>
    41 #include <stddef.h>
    42 #include <stdint.h>
    43 #include <stdbool.h>
    44 #include <ddi.h>
    45 #include <libarch/ddi.h>
    46 #include <loc.h>
    47 #include <sysinfo.h>
    48 #include <errno.h>
    49 #include <ipc/adb.h>
    50 #include <assert.h>
     52
    5153#include "cuda_adb.h"
    5254#include "cuda_hw.h"
     
    5456#define NAME  "cuda_adb"
    5557
    56 static void cuda_connection(ipc_callid_t, ipc_call_t *, void *);
    57 static int cuda_init(cuda_instance_t *);
     58static void cuda_dev_connection(ipc_callid_t, ipc_call_t *, void *);
     59static int cuda_init(cuda_t *);
    5860static void cuda_irq_handler(ipc_callid_t, ipc_call_t *, void *);
    5961
    60 static void cuda_irq_listen(cuda_instance_t *);
    61 static void cuda_irq_receive(cuda_instance_t *);
    62 static void cuda_irq_rcv_end(cuda_instance_t *, void *, size_t *);
    63 static void cuda_irq_send_start(cuda_instance_t *);
    64 static void cuda_irq_send(cuda_instance_t *);
    65 
    66 static void cuda_packet_handle(cuda_instance_t *, uint8_t *, size_t);
    67 static void cuda_send_start(cuda_instance_t *);
    68 static void cuda_autopoll_set(cuda_instance_t *, bool);
    69 
    70 static void adb_packet_handle(cuda_instance_t *, uint8_t *, size_t, bool);
     62static void cuda_irq_listen(cuda_t *);
     63static void cuda_irq_receive(cuda_t *);
     64static void cuda_irq_rcv_end(cuda_t *, void *, size_t *);
     65static void cuda_irq_send_start(cuda_t *);
     66static void cuda_irq_send(cuda_t *);
     67
     68static void cuda_packet_handle(cuda_t *, uint8_t *, size_t);
     69static void cuda_send_start(cuda_t *);
     70static void cuda_autopoll_set(cuda_t *, bool);
     71
     72static void adb_packet_handle(cuda_t *, uint8_t *, size_t, bool);
    7173
    7274static irq_pio_range_t cuda_ranges[] = {
    7375        {
    7476                .base = 0,
    75                 .size = sizeof(cuda_t)
     77                .size = sizeof(cuda_regs_t)
    7678        }
    7779};
     
    107109};
    108110
    109 int main(int argc, char *argv[])
    110 {
    111         service_id_t service_id;
    112         cuda_instance_t cinst;
     111static int cuda_dev_create(cuda_t *cuda, const char *name, adb_dev_t **rdev)
     112{
     113        adb_dev_t *dev = NULL;
     114        ddf_fun_t *fun;
    113115        int rc;
    114         int i;
    115 
    116         printf(NAME ": VIA-CUDA Apple Desktop Bus driver\n");
    117        
    118         for (i = 0; i < ADB_MAX_ADDR; ++i) {
    119                 cinst.adb_dev[i].client_sess = NULL;
    120                 cinst.adb_dev[i].service_id = 0;
    121         }
    122 
    123         async_set_fallback_port_handler(cuda_connection, &cinst);
    124         rc = loc_server_register(NAME);
    125         if (rc < 0) {
    126                 printf(NAME ": Unable to register server.\n");
     116
     117        fun = ddf_fun_create(cuda->dev, fun_exposed, name);
     118        if (fun == NULL) {
     119                ddf_msg(LVL_ERROR, "Failed creating function '%s'.", name);
     120                rc = ENOMEM;
     121                goto error;
     122        }
     123
     124        dev = ddf_fun_data_alloc(fun, sizeof(adb_dev_t));
     125        if (dev == NULL) {
     126                ddf_msg(LVL_ERROR, "Failed allocating memory for '%s'.", name);
     127                rc = ENOMEM;
     128                goto error;
     129        }
     130
     131        dev->fun = fun;
     132        list_append(&dev->lcuda, &cuda->devs);
     133
     134        ddf_fun_set_conn_handler(fun, cuda_dev_connection);
     135
     136        rc = ddf_fun_bind(fun);
     137        if (rc != EOK) {
     138                ddf_msg(LVL_ERROR, "Failed binding function '%s'.", name);
     139                goto error;
     140        }
     141
     142        *rdev = dev;
     143        return EOK;
     144error:
     145        if (fun != NULL)
     146                ddf_fun_destroy(fun);
     147        return rc;
     148}
     149
     150int cuda_add(cuda_t *cuda, cuda_res_t *res)
     151{
     152        adb_dev_t *kbd = NULL;
     153        adb_dev_t *mouse = NULL;
     154        int rc;
     155
     156        cuda->phys_base = res->base;
     157
     158        rc = cuda_dev_create(cuda, "kbd", &kbd);
     159        if (rc != EOK)
     160                goto error;
     161
     162        rc = cuda_dev_create(cuda, "mouse", &mouse);
     163        if (rc != EOK)
     164                goto error;
     165
     166        cuda->addr_dev[2] = kbd;
     167        cuda->addr_dev[8] = kbd;
     168
     169        cuda->addr_dev[9] = mouse;
     170
     171        rc = cuda_init(cuda);
     172        if (rc != EOK) {
     173                ddf_msg(LVL_ERROR, "Failed initializing CUDA hardware.");
    127174                return rc;
    128175        }
    129176
    130         rc = loc_service_register("adb/kbd", &service_id);
    131         if (rc != EOK) {
    132                 printf(NAME ": Unable to register service %s.\n", "adb/kbd");
    133                 return rc;
    134         }
    135 
    136         cinst.adb_dev[2].service_id = service_id;
    137         cinst.adb_dev[8].service_id = service_id;
    138 
    139         rc = loc_service_register("adb/mouse", &service_id);
    140         if (rc != EOK) {
    141                 printf(NAME ": Unable to register service %s.\n", "adb/mouse");
    142                 return rc;
    143         }
    144 
    145         cinst.adb_dev[9].service_id = service_id;
    146 
    147         if (cuda_init(&cinst) < 0) {
    148                 printf("cuda_init() failed\n");
    149                 return 1;
    150         }
    151 
    152         task_retval(0);
    153         async_manager();
    154 
    155         return 0;
    156 }
    157 
    158 /** Character device connection handler */
    159 static void cuda_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    160 {
     177        return EOK;
     178error:
     179        return rc;
     180}
     181
     182int cuda_remove(cuda_t *cuda)
     183{
     184        return ENOTSUP;
     185}
     186
     187int cuda_gone(cuda_t *cuda)
     188{
     189        return ENOTSUP;
     190}
     191
     192/** Device connection handler */
     193static void cuda_dev_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     194{
     195        adb_dev_t *dev = (adb_dev_t *) ddf_fun_data_get((ddf_fun_t *) arg);
    161196        ipc_callid_t callid;
    162197        ipc_call_t call;
    163198        sysarg_t method;
    164         service_id_t dsid;
    165         cuda_instance_t *cuda = (cuda_instance_t *) arg;
    166         int dev_addr, i;
    167 
    168         /* Get the device handle. */
    169         dsid = IPC_GET_ARG2(*icall);
    170 
    171         /* Determine which disk device is the client connecting to. */
    172         dev_addr = -1;
    173         for (i = 0; i < ADB_MAX_ADDR; i++) {
    174                 if (cuda->adb_dev[i].service_id == dsid)
    175                         dev_addr = i;
    176         }
    177 
    178         if (dev_addr < 0) {
    179                 async_answer_0(iid, EINVAL);
    180                 return;
    181         }
    182199
    183200        /* Answer the IPC_M_CONNECT_ME_TO call. */
     
    187204                callid = async_get_call(&call);
    188205                method = IPC_GET_IMETHOD(call);
    189                
     206
    190207                if (!method) {
    191208                        /* The other side has hung up. */
     
    193210                        return;
    194211                }
    195                
     212
    196213                async_sess_t *sess =
    197214                    async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
    198215                if (sess != NULL) {
    199                         if (cuda->adb_dev[dev_addr].client_sess == NULL) {
    200                                 cuda->adb_dev[dev_addr].client_sess = sess;
    201                                
    202                                 /*
    203                                  * A hack so that we send the data to the session
    204                                  * regardless of which address the device is on.
    205                                  */
    206                                 for (i = 0; i < ADB_MAX_ADDR; ++i) {
    207                                         if (cuda->adb_dev[i].service_id == dsid)
    208                                                 cuda->adb_dev[i].client_sess = sess;
    209                                 }
    210                                
    211                                 async_answer_0(callid, EOK);
    212                         } else
    213                                 async_answer_0(callid, ELIMIT);
    214                 } else
     216                        dev->client_sess = sess;
     217                        async_answer_0(callid, EOK);
     218                } else {
    215219                        async_answer_0(callid, EINVAL);
    216         }
    217 }
    218 
    219 static int cuda_init(cuda_instance_t *cuda)
    220 {
    221         if (sysinfo_get_value("cuda.address.physical", &(cuda->cuda_physical)) != EOK)
    222                 return -1;
    223        
     220                }
     221        }
     222}
     223
     224static int cuda_init(cuda_t *cuda)
     225{
     226        int rc;
     227
    224228        void *vaddr;
    225         if (pio_enable((void *) cuda->cuda_physical, sizeof(cuda_t), &vaddr) != 0)
    226                 return -1;
    227        
     229        rc = pio_enable((void *) cuda->phys_base, sizeof(cuda_regs_t),
     230            &vaddr);
     231        if (rc != EOK)
     232                return rc;
     233
    228234        cuda->regs = vaddr;
    229235        cuda->xstate = cx_listen;
     
    236242        pio_write_8(&cuda->regs->ier, IER_CLR | ALL_INT);
    237243
    238         cuda_irq_code.ranges[0].base = (uintptr_t) cuda->cuda_physical;
    239         cuda_irq_code.cmds[0].addr = (void *) &((cuda_t *) cuda->cuda_physical)->ifr;
     244        cuda_irq_code.ranges[0].base = (uintptr_t) cuda->phys_base;
     245        cuda_irq_code.cmds[0].addr = (void *) &((cuda_regs_t *)
     246            cuda->phys_base)->ifr;
    240247        async_irq_subscribe(10, cuda_irq_handler, cuda, &cuda_irq_code);
    241248
     
    247254        cuda_autopoll_set(cuda, true);
    248255
    249         return 0;
     256        return EOK;
    250257}
    251258
     
    253260{
    254261        uint8_t rbuf[CUDA_RCV_BUF_SIZE];
    255         cuda_instance_t *cuda = (cuda_instance_t *)arg;
     262        cuda_t *cuda = (cuda_t *)arg;
    256263        size_t len;
    257264        bool handle;
     
    280287                break;
    281288        }
    282        
     289
    283290        /* Lower IFR.SR_INT so that CUDA can generate next int by raising it. */
    284291        pio_write_8(&cuda->regs->ifr, SR_INT);
     
    297304 * @param cuda CUDA instance
    298305 */
    299 static void cuda_irq_listen(cuda_instance_t *cuda)
     306static void cuda_irq_listen(cuda_t *cuda)
    300307{
    301308        uint8_t b = pio_read_8(&cuda->regs->b);
    302        
     309
    303310        if ((b & TREQ) != 0) {
    304                 printf("cuda_irq_listen: no TREQ?!\n");
    305                 return;
    306         }
    307        
     311                ddf_msg(LVL_WARN, "cuda_irq_listen: no TREQ?!");
     312                return;
     313        }
     314
    308315        pio_write_8(&cuda->regs->b, b & ~TIP);
    309316        cuda->xstate = cx_receive;
     
    316323 * @param cuda CUDA instance
    317324 */
    318 static void cuda_irq_receive(cuda_instance_t *cuda)
     325static void cuda_irq_receive(cuda_t *cuda)
    319326{
    320327        uint8_t data = pio_read_8(&cuda->regs->sr);
    321328        if (cuda->bidx < CUDA_RCV_BUF_SIZE)
    322329                cuda->rcv_buf[cuda->bidx++] = data;
    323        
     330
    324331        uint8_t b = pio_read_8(&cuda->regs->b);
    325        
     332
    326333        if ((b & TREQ) == 0) {
    327334                pio_write_8(&cuda->regs->b, b ^ TACK);
     
    341348 * @param len Place to store length of received packet
    342349 */
    343 static void cuda_irq_rcv_end(cuda_instance_t *cuda, void *buf, size_t *len)
     350static void cuda_irq_rcv_end(cuda_t *cuda, void *buf, size_t *len)
    344351{
    345352        uint8_t b = pio_read_8(&cuda->regs->b);
    346        
     353
    347354        if ((b & TREQ) == 0) {
    348355                cuda->xstate = cx_receive;
     
    352359                cuda_send_start(cuda);
    353360        }
    354        
     361
    355362        memcpy(buf, cuda->rcv_buf, cuda->bidx);
    356363        *len = cuda->bidx;
     
    364371 * @param cuda CUDA instance
    365372 */
    366 static void cuda_irq_send_start(cuda_instance_t *cuda)
     373static void cuda_irq_send_start(cuda_t *cuda)
    367374{
    368375        uint8_t b;
     
    394401 * @param cuda CUDA instance
    395402 */
    396 static void cuda_irq_send(cuda_instance_t *cuda)
     403static void cuda_irq_send(cuda_t *cuda)
    397404{
    398405        if (cuda->bidx < cuda->snd_bytes) {
     
    416423}
    417424
    418 static void cuda_packet_handle(cuda_instance_t *cuda, uint8_t *data, size_t len)
     425static void cuda_packet_handle(cuda_t *cuda, uint8_t *data, size_t len)
    419426{
    420427        if (data[0] != PT_ADB)
     
    426433}
    427434
    428 static void adb_packet_handle(cuda_instance_t *cuda, uint8_t *data,
    429     size_t size, bool autopoll)
     435static void adb_packet_handle(cuda_t *cuda, uint8_t *data, size_t size,
     436    bool autopoll)
    430437{
    431438        uint8_t dev_addr;
    432439        uint8_t reg_no;
    433440        uint16_t reg_val;
     441        adb_dev_t *dev;
    434442        unsigned i;
    435443
     
    438446
    439447        if (size != 3) {
    440                 printf("unrecognized packet, size=%zu\n", size);
     448                ddf_msg(LVL_WARN, "Unrecognized packet, size=%zu", size);
    441449                for (i = 0; i < size; ++i) {
    442                         printf(" 0x%02x", data[i]);
     450                        ddf_msg(LVL_WARN, " 0x%02x", data[i]);
    443451                }
    444                 putchar('\n');
    445452                return;
    446453        }
    447454
    448455        if (reg_no != 0) {
    449                 printf("unrecognized packet, size=%zu\n", size);
     456                ddf_msg(LVL_WARN, "Unrecognized packet, size=%zu", size);
    450457                for (i = 0; i < size; ++i) {
    451                         printf(" 0x%02x", data[i]);
     458                        ddf_msg(LVL_WARN, " 0x%02x", data[i]);
    452459                }
    453                 putchar('\n');
    454460                return;
    455461        }
     
    457463        reg_val = ((uint16_t) data[1] << 8) | (uint16_t) data[2];
    458464
    459         if (cuda->adb_dev[dev_addr].client_sess == NULL)
    460                 return;
    461 
    462         async_exch_t *exch =
    463             async_exchange_begin(cuda->adb_dev[dev_addr].client_sess);
     465        ddf_msg(LVL_DEBUG, "Received ADB packet for device address %d",
     466            dev_addr);
     467        dev = cuda->addr_dev[dev_addr];
     468        if (dev == NULL)
     469                return;
     470
     471        async_exch_t *exch = async_exchange_begin(dev->client_sess);
    464472        async_msg_1(exch, ADB_REG_NOTIF, reg_val);
    465473        async_exchange_end(exch);
    466474}
    467475
    468 static void cuda_autopoll_set(cuda_instance_t *cuda, bool enable)
     476static void cuda_autopoll_set(cuda_t *cuda, bool enable)
    469477{
    470478        cuda->snd_buf[0] = PT_CUDA;
     
    477485}
    478486
    479 static void cuda_send_start(cuda_instance_t *cuda)
     487static void cuda_send_start(cuda_t *cuda)
    480488{
    481489        assert(cuda->xstate == cx_listen);
Note: See TracChangeset for help on using the changeset viewer.