Changeset 81b9d3e in mainline for uspace/drv/bus/adb/cuda_adb/cuda_adb.c
- Timestamp:
- 2017-10-05T19:09:34Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- 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. - File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/adb/cuda_adb/cuda_adb.c
r84eb4edd r81b9d3e 37 37 */ 38 38 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> 39 50 #include <stdio.h> 40 51 #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 51 53 #include "cuda_adb.h" 52 54 #include "cuda_hw.h" … … 54 56 #define NAME "cuda_adb" 55 57 56 static void cuda_ connection(ipc_callid_t, ipc_call_t *, void *);57 static int cuda_init(cuda_ instance_t *);58 static void cuda_dev_connection(ipc_callid_t, ipc_call_t *, void *); 59 static int cuda_init(cuda_t *); 58 60 static void cuda_irq_handler(ipc_callid_t, ipc_call_t *, void *); 59 61 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);62 static void cuda_irq_listen(cuda_t *); 63 static void cuda_irq_receive(cuda_t *); 64 static void cuda_irq_rcv_end(cuda_t *, void *, size_t *); 65 static void cuda_irq_send_start(cuda_t *); 66 static void cuda_irq_send(cuda_t *); 67 68 static void cuda_packet_handle(cuda_t *, uint8_t *, size_t); 69 static void cuda_send_start(cuda_t *); 70 static void cuda_autopoll_set(cuda_t *, bool); 71 72 static void adb_packet_handle(cuda_t *, uint8_t *, size_t, bool); 71 73 72 74 static irq_pio_range_t cuda_ranges[] = { 73 75 { 74 76 .base = 0, 75 .size = sizeof(cuda_ t)77 .size = sizeof(cuda_regs_t) 76 78 } 77 79 }; … … 107 109 }; 108 110 109 int main(int argc, char *argv[])110 { 111 service_id_t service_id;112 cuda_instance_t cinst;111 static 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; 113 115 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; 144 error: 145 if (fun != NULL) 146 ddf_fun_destroy(fun); 147 return rc; 148 } 149 150 int 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."); 127 174 return rc; 128 175 } 129 176 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; 178 error: 179 return rc; 180 } 181 182 int cuda_remove(cuda_t *cuda) 183 { 184 return ENOTSUP; 185 } 186 187 int cuda_gone(cuda_t *cuda) 188 { 189 return ENOTSUP; 190 } 191 192 /** Device connection handler */ 193 static 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); 161 196 ipc_callid_t callid; 162 197 ipc_call_t call; 163 198 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 }182 199 183 200 /* Answer the IPC_M_CONNECT_ME_TO call. */ … … 187 204 callid = async_get_call(&call); 188 205 method = IPC_GET_IMETHOD(call); 189 206 190 207 if (!method) { 191 208 /* The other side has hung up. */ … … 193 210 return; 194 211 } 195 212 196 213 async_sess_t *sess = 197 214 async_callback_receive_start(EXCHANGE_SERIALIZE, &call); 198 215 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 { 215 219 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 224 static int cuda_init(cuda_t *cuda) 225 { 226 int rc; 227 224 228 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 228 234 cuda->regs = vaddr; 229 235 cuda->xstate = cx_listen; … … 236 242 pio_write_8(&cuda->regs->ier, IER_CLR | ALL_INT); 237 243 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; 240 247 async_irq_subscribe(10, cuda_irq_handler, cuda, &cuda_irq_code); 241 248 … … 247 254 cuda_autopoll_set(cuda, true); 248 255 249 return 0;256 return EOK; 250 257 } 251 258 … … 253 260 { 254 261 uint8_t rbuf[CUDA_RCV_BUF_SIZE]; 255 cuda_ instance_t *cuda = (cuda_instance_t *)arg;262 cuda_t *cuda = (cuda_t *)arg; 256 263 size_t len; 257 264 bool handle; … … 280 287 break; 281 288 } 282 289 283 290 /* Lower IFR.SR_INT so that CUDA can generate next int by raising it. */ 284 291 pio_write_8(&cuda->regs->ifr, SR_INT); … … 297 304 * @param cuda CUDA instance 298 305 */ 299 static void cuda_irq_listen(cuda_ instance_t *cuda)306 static void cuda_irq_listen(cuda_t *cuda) 300 307 { 301 308 uint8_t b = pio_read_8(&cuda->regs->b); 302 309 303 310 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 308 315 pio_write_8(&cuda->regs->b, b & ~TIP); 309 316 cuda->xstate = cx_receive; … … 316 323 * @param cuda CUDA instance 317 324 */ 318 static void cuda_irq_receive(cuda_ instance_t *cuda)325 static void cuda_irq_receive(cuda_t *cuda) 319 326 { 320 327 uint8_t data = pio_read_8(&cuda->regs->sr); 321 328 if (cuda->bidx < CUDA_RCV_BUF_SIZE) 322 329 cuda->rcv_buf[cuda->bidx++] = data; 323 330 324 331 uint8_t b = pio_read_8(&cuda->regs->b); 325 332 326 333 if ((b & TREQ) == 0) { 327 334 pio_write_8(&cuda->regs->b, b ^ TACK); … … 341 348 * @param len Place to store length of received packet 342 349 */ 343 static void cuda_irq_rcv_end(cuda_ instance_t *cuda, void *buf, size_t *len)350 static void cuda_irq_rcv_end(cuda_t *cuda, void *buf, size_t *len) 344 351 { 345 352 uint8_t b = pio_read_8(&cuda->regs->b); 346 353 347 354 if ((b & TREQ) == 0) { 348 355 cuda->xstate = cx_receive; … … 352 359 cuda_send_start(cuda); 353 360 } 354 361 355 362 memcpy(buf, cuda->rcv_buf, cuda->bidx); 356 363 *len = cuda->bidx; … … 364 371 * @param cuda CUDA instance 365 372 */ 366 static void cuda_irq_send_start(cuda_ instance_t *cuda)373 static void cuda_irq_send_start(cuda_t *cuda) 367 374 { 368 375 uint8_t b; … … 394 401 * @param cuda CUDA instance 395 402 */ 396 static void cuda_irq_send(cuda_ instance_t *cuda)403 static void cuda_irq_send(cuda_t *cuda) 397 404 { 398 405 if (cuda->bidx < cuda->snd_bytes) { … … 416 423 } 417 424 418 static void cuda_packet_handle(cuda_ instance_t *cuda, uint8_t *data, size_t len)425 static void cuda_packet_handle(cuda_t *cuda, uint8_t *data, size_t len) 419 426 { 420 427 if (data[0] != PT_ADB) … … 426 433 } 427 434 428 static void adb_packet_handle(cuda_ instance_t *cuda, uint8_t *data,429 size_t size,bool autopoll)435 static void adb_packet_handle(cuda_t *cuda, uint8_t *data, size_t size, 436 bool autopoll) 430 437 { 431 438 uint8_t dev_addr; 432 439 uint8_t reg_no; 433 440 uint16_t reg_val; 441 adb_dev_t *dev; 434 442 unsigned i; 435 443 … … 438 446 439 447 if (size != 3) { 440 printf("unrecognized packet, size=%zu\n", size);448 ddf_msg(LVL_WARN, "Unrecognized packet, size=%zu", size); 441 449 for (i = 0; i < size; ++i) { 442 printf("0x%02x", data[i]);450 ddf_msg(LVL_WARN, " 0x%02x", data[i]); 443 451 } 444 putchar('\n');445 452 return; 446 453 } 447 454 448 455 if (reg_no != 0) { 449 printf("unrecognized packet, size=%zu\n", size);456 ddf_msg(LVL_WARN, "Unrecognized packet, size=%zu", size); 450 457 for (i = 0; i < size; ++i) { 451 printf("0x%02x", data[i]);458 ddf_msg(LVL_WARN, " 0x%02x", data[i]); 452 459 } 453 putchar('\n');454 460 return; 455 461 } … … 457 463 reg_val = ((uint16_t) data[1] << 8) | (uint16_t) data[2]; 458 464 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); 464 472 async_msg_1(exch, ADB_REG_NOTIF, reg_val); 465 473 async_exchange_end(exch); 466 474 } 467 475 468 static void cuda_autopoll_set(cuda_ instance_t *cuda, bool enable)476 static void cuda_autopoll_set(cuda_t *cuda, bool enable) 469 477 { 470 478 cuda->snd_buf[0] = PT_CUDA; … … 477 485 } 478 486 479 static void cuda_send_start(cuda_ instance_t *cuda)487 static void cuda_send_start(cuda_t *cuda) 480 488 { 481 489 assert(cuda->xstate == cx_listen);
Note:
See TracChangeset
for help on using the changeset viewer.