00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdlib.h>
00022 #include <string.h>
00023
00024
00025 #include <l4/sys/types.h>
00026 #include <l4/sys/consts.h>
00027 #include <l4/env/errno.h>
00028 #include <l4/env/env.h>
00029 #include <l4/util/util.h>
00030 #include <l4/util/macros.h>
00031 #include <l4/l4rm/l4rm.h>
00032 #include <l4/dm_mem/dm_mem.h>
00033
00034
00035 #include <l4/dsi/dsi.h>
00036 #include "__sync.h"
00037 #include "__socket.h"
00038 #include "__config.h"
00039 #include "__debug.h"
00040 #include "__dataspace.h"
00041
00042
00043
00044
00045
00046
00047 static l4_threadid_t dsi_dm_id = L4_INVALID_ID;
00048
00049
00050
00051
00052 static l4_uint32_t cds_map_area = -1;
00053
00054
00055
00056
00057 static l4_uint32_t dds_map_area = -1;
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 static inline int
00073 __get_dm_id(void)
00074 {
00075 dsi_dm_id = l4env_get_default_dsm();
00076 if (l4_is_invalid_id(dsi_dm_id))
00077 {
00078 Panic("DSI: no dataspace manager found");
00079 dsi_dm_id = L4_INVALID_ID;
00080 return -1;
00081 }
00082 return 0;
00083 }
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 static inline l4_size_t
00095 __get_ctrl_ds_size(dsi_stream_cfg_t cfg)
00096 {
00097 return sizeof(dsi_ctrl_header_t) +
00098 cfg.num_packets * sizeof(dsi_packet_t) +
00099 cfg.num_packets * cfg.max_sg * sizeof(dsi_sg_elem_t);
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 static void
00114 __init_ctrl_ds(l4_addr_t map_addr, l4_size_t size, dsi_stream_cfg_t cfg)
00115 {
00116 dsi_ctrl_header_t * header;
00117 dsi_packet_t * packets;
00118 dsi_sg_elem_t * sg_elems;
00119 int i;
00120
00121 LOGdL(DEBUG_CTRL_DS, "total size %u, header size %u\n" \
00122 " %u packets of size %u\n" \
00123 " %u sg elems of size %u",
00124 size, sizeof(dsi_ctrl_header_t),
00125 cfg.num_packets, sizeof(dsi_packet_t),
00126 cfg.num_packets * cfg.max_sg, sizeof(dsi_sg_elem_t));
00127
00128
00129 header = (dsi_ctrl_header_t *)map_addr;
00130 packets = (dsi_packet_t *)(map_addr + sizeof(dsi_ctrl_header_t));
00131 sg_elems = (dsi_sg_elem_t *)(map_addr + sizeof(dsi_ctrl_header_t) +
00132 cfg.num_packets * sizeof(dsi_packet_t));
00133
00134
00135 memset(header, 0, size);
00136
00137
00138 header->num_packets = cfg.num_packets;
00139 header->num_sg_elems = cfg.num_packets * cfg.max_sg;
00140 header->max_sg_len = cfg.max_sg;
00141 header->packets_committed = 0;
00142
00143
00144 for (i = 0; i < cfg.num_packets; i++)
00145 {
00146 packets[i].tx_sem = DSI_SEMAPHORE_UNLOCKED;
00147 packets[i].rx_sem = DSI_SEMAPHORE_LOCKED;
00148 }
00149
00150
00151 for (i = 0; i < cfg.num_packets * cfg.max_sg; i++)
00152 sg_elems[i].flags = DSI_SG_ELEM_UNUSED;
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 static int
00170 __map_ctrl_ds(dsi_socket_t * socket, dsi_stream_cfg_t cfg)
00171 {
00172 int ret;
00173 l4_size_t size;
00174 void *map_addr;
00175
00176
00177 ret = l4dm_mem_size(&socket->ctrl_ds, &size);
00178 if (ret < 0)
00179 {
00180 LOG_Error("DSI: get dataspace size failed: %s (%d)",
00181 l4env_errstr(ret), ret);
00182 return -L4_EINVAL;
00183 }
00184
00185 LOGdL(DEBUG_CTRL_DS,"attaching ctrl dataspace, ds %d at "l4util_idfmt", size %d",
00186 socket->ctrl_ds.id, l4util_idstr(socket->ctrl_ds.manager), size);
00187
00188
00189 if (cds_map_area != -1)
00190 ret = l4rm_area_attach(&socket->ctrl_ds, cds_map_area, size, 0,
00191 L4DM_RW | L4RM_MAP, &map_addr);
00192 else
00193 ret = l4rm_attach(&socket->ctrl_ds,size, 0, L4DM_RW | L4RM_MAP,
00194 &map_addr);
00195 if (ret < 0)
00196 {
00197 LOG_Error("DSI: attach dataspace failed: %s (%d)",
00198 l4env_errstr(ret), ret);
00199 return ret;
00200 }
00201
00202
00203 socket->header = (dsi_ctrl_header_t *)map_addr;
00204 socket->packets = (dsi_packet_t *)((unsigned)map_addr +
00205 sizeof(dsi_ctrl_header_t));
00206 socket->sg_lists = (dsi_sg_elem_t *)((unsigned)map_addr +
00207 sizeof(dsi_ctrl_header_t) +
00208 cfg.num_packets * sizeof(dsi_packet_t));
00209
00210 LOGdL(DEBUG_CTRL_DS, "attached crtl ds to 0x%08lx \n" \
00211 " header at 0x%08lx\n" \
00212 " packets at 0x%08lx\n" \
00213 " sg_lists at 0x%08lx",
00214 (l4_addr_t)map_addr,(l4_addr_t)socket->header,
00215 (l4_addr_t)socket->packets, (l4_addr_t)socket->sg_lists);
00216
00217
00218 return 0;
00219 }
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 int
00245 dsi_create_ctrl_area(dsi_socket_t * socket, dsi_jcp_stream_t jcp_stream,
00246 dsi_stream_cfg_t cfg)
00247 {
00248 int ret;
00249 l4_size_t size = __get_ctrl_ds_size(cfg);
00250
00251
00252 Assert(socket != NULL);
00253
00254
00255 if (l4_thread_equal(dsi_dm_id,L4_INVALID_ID))
00256 {
00257 if (__get_dm_id())
00258 return -DSI_ENODSM;
00259 }
00260 ASSERT(!l4_thread_equal(dsi_dm_id,L4_INVALID_ID));
00261
00262
00263 size = l4_round_page(size);
00264
00265
00266 ret = l4dm_mem_open(dsi_dm_id, size, 0, 0, "DSI ctrl area",
00267 &socket->ctrl_ds);
00268 if (ret < 0)
00269 {
00270 LOG_Error("DSI: dataspace allocation failed: %s (%d)",
00271 l4env_errstr(ret), ret);
00272 return ret;
00273 }
00274
00275 LOGdL(DEBUG_CTRL_DS, "ds %d at "l4util_idfmt,
00276 socket->ctrl_ds.id, l4util_idstr(socket->ctrl_ds.manager));
00277
00278
00279 ret = __map_ctrl_ds(socket, cfg);
00280 if (ret)
00281 {
00282
00283 l4dm_close(&socket->ctrl_ds);
00284 return ret;
00285 }
00286
00287
00288 __init_ctrl_ds((l4_addr_t)socket->header, size, cfg);
00289
00290
00291 socket->num_packets = socket->header->num_packets;
00292 socket->num_sg_elems = socket->header->num_sg_elems;
00293
00294
00295 return 0;
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 int
00317 dsi_set_ctrl_area(dsi_socket_t * socket, l4dm_dataspace_t ctrl_ds,
00318 dsi_jcp_stream_t jcp_stream, dsi_stream_cfg_t cfg)
00319 {
00320 int ret;
00321 l4_size_t size,s;
00322 l4_addr_t map;
00323
00324
00325 Assert(socket != NULL);
00326
00327
00328 ret = l4dm_check_rights(&ctrl_ds, L4DM_RW);
00329 if (ret < 0)
00330 {
00331 LOG_Error("DSI: invalid dataspace: %s (%d)", l4env_errstr(ret), ret);
00332 return ret;
00333 }
00334
00335
00336 socket->ctrl_ds = ctrl_ds;
00337
00338
00339 ret = __map_ctrl_ds(socket, cfg);
00340 if (ret)
00341 {
00342
00343 return ret;
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353 socket->num_packets = socket->header->num_packets;
00354 socket->num_sg_elems = socket->header->num_sg_elems;
00355
00356
00357 if ((cfg.num_packets != socket->num_packets) ||
00358 (socket->num_sg_elems != cfg.max_sg * socket->num_packets))
00359 {
00360 LOG_Error("DSI: configuration mismatch in control area");
00361
00362
00363 size = sizeof(dsi_ctrl_header_t) +
00364 socket->num_packets * sizeof(dsi_packet_t) +
00365 socket->num_sg_elems * sizeof(dsi_sg_elem_t);
00366
00367 l4dm_mem_size(&socket->ctrl_ds, &s);
00368 if (size > s)
00369 {
00370 Panic("DSI: size mismatch");
00371 return -L4_EINVAL;
00372 }
00373
00374
00375 LOG_printf("DSI: adjusting packet / scatter gather list pointers\n");
00376 map = (l4_addr_t)socket->header;
00377 socket->packets = (dsi_packet_t *)(map + sizeof(dsi_ctrl_header_t));
00378 socket->sg_lists = (dsi_sg_elem_t *)
00379 (map + sizeof(dsi_ctrl_header_t) +
00380 socket->num_packets * sizeof(dsi_packet_t));
00381 }
00382
00383 return 0;
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398 int
00399 dsi_release_ctrl_area(dsi_socket_t * socket)
00400 {
00401 int ret;
00402 int error = 0;
00403
00404 LOGdL(DEBUG_CTRL_DS,"detaching control area (ds %d at "l4util_idfmt")",
00405 socket->ctrl_ds.id, l4util_idstr(socket->ctrl_ds.manager));
00406
00407
00408 ret = l4rm_detach(socket->header);
00409 if (ret < 0)
00410 {
00411 LOG_Error("DSI: detach control dataspace failed: %s (%d)",
00412 l4env_errstr(ret), ret);
00413 error = ret;
00414 }
00415
00416 if (socket->flags & DSI_SOCKET_FREE_CTRL)
00417 {
00418
00419 ret = l4dm_close(&socket->ctrl_ds);
00420 if (ret < 0)
00421 {
00422 LOG_Error("DSI: close control dataspace failed: %s (%d)",
00423 l4env_errstr(ret), ret);
00424 error = ret;
00425 }
00426 }
00427
00428
00429 return error;
00430 }
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 int
00449 dsi_set_data_area(dsi_socket_t * socket, l4dm_dataspace_t data_ds)
00450 {
00451 int ret,i;
00452 l4_size_t size;
00453 void * map;
00454 l4dm_dataspace_t ds;
00455 l4_uint32_t flags;
00456
00457
00458 Assert(socket != NULL);
00459
00460 if (IS_RECEIVE_SOCKET(socket) && (socket->flags & DSI_SOCKET_COPY))
00461 {
00462
00463 ret = l4dm_mem_size(&data_ds,&size);
00464 if (ret < 0)
00465 {
00466 LOG_Error("DSI: get dataspace size failed: %s (%d)",
00467 l4env_errstr(ret), ret);
00468 return -L4_EINVAL;
00469 }
00470
00471 LOGdL(DEBUG_DATA_DS,"allocate data_ds, size %u",size);
00472
00473
00474 if (l4_thread_equal(dsi_dm_id,L4_INVALID_ID))
00475 {
00476 if (__get_dm_id())
00477 return -DSI_ENODSM;
00478 }
00479 ASSERT(!l4_thread_equal(dsi_dm_id,L4_INVALID_ID));
00480
00481
00482 if (l4dm_mem_ds_is_contiguous(&data_ds))
00483 ret = l4dm_mem_open(dsi_dm_id,size,0,L4DM_CONTIGUOUS,"DSI data",&ds);
00484 else
00485 ret = l4dm_mem_open(dsi_dm_id,size,0,0,"DSI data",&ds);
00486 if (ret < 0)
00487 {
00488 LOG_Error("DSI: dataspace allocation failed: %s (%d)!",
00489 l4env_errstr(ret), ret);
00490 return ret;
00491 }
00492
00493
00494 socket->flags |= DSI_SOCKET_FREE_DATA;
00495 }
00496 else
00497 {
00498
00499 ret = l4dm_check_rights(&data_ds,L4DM_RW);
00500 if (ret < 0)
00501 {
00502 LOG_Error("DSI: invalid data dataspace: %s (%d)!",
00503 l4env_errstr(ret), ret);
00504 return ret;
00505 }
00506 ds = data_ds;
00507 }
00508
00509 LOGdL(DEBUG_DATA_DS,"attaching data area, ds %d at "l4util_idfmt,
00510 data_ds.id,l4util_idstr(data_ds.manager));
00511
00512
00513 ret = l4dm_mem_size(&ds,&size);
00514 if (ret < 0)
00515 {
00516 LOG_Error("DSI: get dataspace size failed: %s (%d)",
00517 l4env_errstr(ret), ret);
00518 return -L4_EINVAL;
00519 }
00520
00521
00522
00523
00524
00525
00526
00527
00528 i = 0;
00529 while (size > (1 << i))
00530 i++;
00531
00532 flags = L4RM_LOG2_ALIGNED | L4RM_LOG2_ALLOC;
00533 if (!(socket->flags & DSI_SOCKET_MAP))
00534 {
00535 flags |= L4RM_MAP;
00536 if (IS_RECEIVE_SOCKET(socket) && !(socket->flags & DSI_SOCKET_COPY))
00537 flags |= L4DM_RO;
00538 else
00539 flags |= L4DM_RW;
00540 }
00541
00542
00543 if (dds_map_area != -1)
00544 ret = l4rm_area_attach(&ds,dds_map_area,size,0,flags,&map);
00545 else
00546 ret = l4rm_attach(&ds,size,0,flags,&map);
00547 if (ret)
00548 {
00549 LOG_Error("DSI: attach data dataspace failed: %s (%d)",
00550 l4env_errstr(ret), ret);
00551 return ret;
00552 }
00553
00554
00555 socket->data_ds = ds;
00556 socket->data_area = map;
00557 socket->data_size = size;
00558 socket->data_map_size = i;
00559 socket->next_buf = map;
00560
00561 LOGdL(DEBUG_DATA_DS, "attached data ds to addr 0x%08lx", (l4_addr_t)map);
00562
00563
00564 return 0;
00565 }
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 int
00577 dsi_release_data_area(dsi_socket_t * socket)
00578 {
00579 int ret;
00580 int error = 0;
00581
00582 LOGdL(DEBUG_DATA_DS, "detaching data area (ds %d at "l4util_idfmt")",
00583 socket->data_ds.id, l4util_idstr(socket->data_ds.manager));
00584
00585
00586 ret = l4rm_detach(socket->data_area);
00587 if (ret < 0)
00588 {
00589 LOG_Error("DSI: detach data dataspace failed: %s (%d)",
00590 l4env_errstr(ret), ret);
00591 error = ret;
00592 }
00593
00594 if (socket->flags & DSI_SOCKET_FREE_DATA)
00595 {
00596
00597 ret = l4dm_close(&socket->data_ds);
00598 if (ret < 0)
00599 {
00600 LOG_Error("DSI: close data dataspace failed: %s (%d)",
00601 l4env_errstr(ret), ret);
00602 error = ret;
00603 }
00604 }
00605
00606
00607 return error;
00608 }
00609
00610
00611
00612
00613
00614
00615 void
00616 dsi_init_dataspaces(void)
00617 {
00618 int ret;
00619
00620 #if DSI_USE_CDS_AREA
00621
00622 ret = l4rm_area_reserve_region(DSI_CDS_MAP_START,DSI_CDS_MAP_SIZE,
00623 0,&cds_map_area);
00624 if (ret)
00625 {
00626 LOG_Error("DSI: failed to reserve map area for control dataspaces: "
00627 "%s (%d)", l4env_errstr(ret), ret);
00628 cds_map_area = -1;
00629 }
00630 #endif
00631
00632 #if DSI_USE_DDS_AREA
00633
00634 ret = l4rm_area_reserve_region(DSI_DDS_MAP_START,DSI_DDS_MAP_SIZE,
00635 0,&dds_map_area);
00636 if (ret)
00637 {
00638 LOG_Error("DSI: failed to reserve map area for data dataspaces: "
00639 "%s (%d)", l4env_errstr(ret), ret);
00640 dds_map_area = -1;
00641 }
00642 #endif
00643 }
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664 int
00665 dsi_socket_share_ds(dsi_socket_t * socket, l4_threadid_t client)
00666 {
00667 int ret;
00668 int error = 0;
00669
00670
00671 if (!dsi_is_valid_socket(socket))
00672 return -L4_EINVAL;
00673
00674 if (!l4dm_is_invalid_ds(socket->data_ds))
00675 {
00676 ret = l4dm_share(&socket->data_ds,client,L4DM_RW);
00677 if (ret < 0)
00678 error = ret;
00679 }
00680
00681 if (!l4dm_is_invalid_ds(socket->ctrl_ds))
00682 {
00683 ret = l4dm_share(&socket->ctrl_ds,client,L4DM_RW);
00684 if (ret < 0)
00685 error = ret;
00686 }
00687
00688
00689 return error;
00690 }
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700 void
00701 dsi_ds_set_dataspace_manager(l4_threadid_t id)
00702 {
00703
00704 dsi_dm_id = id;
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723 int
00724 dsi_ds_setup_ctrl_dataspace(l4dm_dataspace_t * ds, dsi_stream_cfg_t cfg)
00725 {
00726 l4_size_t size = __get_ctrl_ds_size(cfg);
00727 l4_size_t ds_size;
00728 int ret;
00729 void * map_addr;
00730
00731
00732 ret = l4dm_mem_size(ds, &ds_size);
00733 if (ret < 0)
00734 return ret;
00735
00736 if (ds_size < size)
00737 {
00738 LOG_Error("dataspace too small!");
00739 return -L4_EINVAL;
00740 }
00741
00742
00743 ret = l4rm_attach(ds, size, 0, L4DM_RW | L4RM_MAP, &map_addr);
00744 if (ret < 0)
00745 {
00746 LOG_Error("attach dataspace failed: %s (%d)!", l4env_errstr(ret), ret);
00747 return ret;
00748 }
00749
00750
00751 __init_ctrl_ds((l4_addr_t)map_addr, size, cfg);
00752
00753
00754 l4rm_detach(map_addr);
00755
00756 return 0;
00757 }
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771 int
00772 dsi_ds_create_ctrl_dataspace(dsi_stream_cfg_t cfg, l4dm_dataspace_t * ds)
00773 {
00774 l4_size_t size = __get_ctrl_ds_size(cfg);
00775 l4_addr_t map_addr;
00776
00777
00778 map_addr = (l4_addr_t)l4dm_mem_ds_allocate(size, L4DM_RW | L4RM_MAP, ds);
00779 if (map_addr == 0)
00780 return -L4_ENOMEM;
00781
00782
00783 __init_ctrl_ds((l4_addr_t)map_addr, size, cfg);
00784
00785
00786 l4rm_detach((void *)map_addr);
00787
00788
00789 return 0;
00790 }