libxcoder 5.6.0
Loading...
Searching...
No Matches
ni_nvme.c
Go to the documentation of this file.
1/*******************************************************************************
2 *
3 * Copyright (C) 2022 NETINT Technologies
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18 * SOFTWARE.
19 *
20 ******************************************************************************/
21
22/*!*****************************************************************************
23 * \file ni_nvme.c
24 *
25 * \brief Private definitions for interfacing with NETINT video processing
26 * devices over NVMe
27 ******************************************************************************/
28
29#include <stdint.h>
30#include <string.h>
31#include <stdio.h>
32#include <errno.h>
33
34#ifdef _WIN32
35 #include <windows.h>
36#include <ntddstor.h>
37#include <winioctl.h>
38#include <Ntddscsi.h>
39#elif __linux__ || __APPLE__
40#if __linux__
41#include <linux/types.h>
42#endif
43#include <sys/ioctl.h>
44#include <sys/stat.h>
45#include <unistd.h>
46#endif
47
48#include "ni_nvme.h"
49#include "ni_util.h"
50
51#define ROUND_TO_ULONG(x) ni_round_up(x,sizeof(uint32_t))
52
53/*!******************************************************************************
54 * \brief Check f/w error return code, and if it's a fatal one, terminate
55 * application's decoding/encoding processing by sending
56 * self a SIGTERM signal. Application shall handle this gracefully.
57 *
58 * \param
59 *
60 * \return 1 (or non-zero) if need to terminate, 0 otherwise
61 ******************************************************************************/
62ni_retcode_t ni_nvme_check_error_code(int rc, int opcode, uint32_t xcoder_type,
63 uint32_t hw_id, uint32_t *p_instance_id)
64{
65 const char* type_str = GET_XCODER_DEVICE_TYPE_STR(xcoder_type);
66
67 switch (rc)
68 {
70 return NI_RETCODE_SUCCESS;
73 "Hardware %u %s experiencing insufficient resource (instance %u opcode %x)!\n",
74 hw_id, type_str, *p_instance_id, opcode);
78 "Hardware %u %s failed to open session due to invalid "
79 "combination of "
80 "parameter values given (instance %u opcode %x)!\n",
81 hw_id, type_str, *p_instance_id, opcode);
85 "Hardware %u %s got stream error (instance %u opcode %x)!\n",
86 hw_id, type_str, *p_instance_id, opcode);
90 "Error: Hardware %u %s doesn't support Interlaced video (instance %u opcode %x)!\n",
91 hw_id, type_str, *p_instance_id, opcode);
93 default:
94 if (xcoder_type == NI_DEVICE_TYPE_AI)
95 {
96 ni_log(NI_LOG_ERROR, "Error rc = %d, %s, op = %02x, %s %u.0x%x\n",
97 rc, ni_ai_errno_to_str(rc), opcode,
98 type_str, hw_id, *p_instance_id);
99 } else
100 {
102 "Error rc = 0x%x, op = %02x, %s %u.%u terminating?\n", rc,
103 opcode, type_str, hw_id,
104 *p_instance_id);
105 }
106 return NI_RETCODE_FAILURE;
107 }
108}
109
110#ifdef __linux__
111
112/*!******************************************************************************
113 * \brief Submit a nvme admin passthrough command to the driver
114 *
115 * \param
116 *
117 * \return
118 *******************************************************************************/
119int32_t
120ni_nvme_send_admin_pass_through_command(ni_device_handle_t handle,
121 ni_nvme_passthrough_cmd_t *p_cmd)
122{
123 ni_log(NI_LOG_TRACE, "%s: handle=%d\n", __func__, handle);
124 ni_log(NI_LOG_TRACE, "opcode: %02x\n", p_cmd->opcode);
125 ni_log(NI_LOG_TRACE, "flags: %02x\n", p_cmd->flags);
126 ni_log(NI_LOG_TRACE, "rsvd1: %04x\n", p_cmd->rsvd1);
127 ni_log(NI_LOG_TRACE, "nsid: %08x\n", p_cmd->nsid);
128 ni_log(NI_LOG_TRACE, "cdw2: %08x\n", p_cmd->cdw2);
129 ni_log(NI_LOG_TRACE, "cdw3: %08x\n", p_cmd->cdw3);
130 //ni_log(NI_LOG_TRACE, "metadata: %"PRIx64"\n", p_cmd->metadata);
131 //ni_log(NI_LOG_TRACE, "addr: %"PRIx64"\n", p_cmd->addr);
132 ni_log(NI_LOG_TRACE, "metadata_len: %08x\n", p_cmd->metadata_len);
133 ni_log(NI_LOG_TRACE, "data_len: %08x\n", p_cmd->data_len);
134 ni_log(NI_LOG_TRACE, "cdw10: %08x\n", p_cmd->cdw10);
135 ni_log(NI_LOG_TRACE, "cdw11: %08x\n", p_cmd->cdw11);
136 ni_log(NI_LOG_TRACE, "cdw12: %08x\n", p_cmd->cdw12);
137 ni_log(NI_LOG_TRACE, "cdw13: %08x\n", p_cmd->cdw13);
138 ni_log(NI_LOG_TRACE, "cdw14: %08x\n", p_cmd->cdw14);
139 ni_log(NI_LOG_TRACE, "cdw15: %08x\n", p_cmd->cdw15);
140 ni_log(NI_LOG_TRACE, "timeout_ms: %08x\n", p_cmd->timeout_ms);
141 ni_log(NI_LOG_TRACE, "result: %08x\n", p_cmd->result);
142
143 return ioctl(handle, NVME_IOCTL_ADMIN_CMD, p_cmd);
144}
145
146/*!******************************************************************************
147 * \brief Submit a nvme io passthrough command to the driver
148 *
149 * \param
150 *
151 * \return
152 *******************************************************************************/
153int32_t ni_nvme_send_io_pass_through_command(ni_device_handle_t handle,
154 ni_nvme_passthrough_cmd_t *p_cmd)
155{
156 ni_log(NI_LOG_TRACE, "%s: handle=%d\n", __func__, handle);
157 ni_log(NI_LOG_TRACE, "opcode: %02x\n", p_cmd->opcode);
158 ni_log(NI_LOG_TRACE, "flags: %02x\n", p_cmd->flags);
159 ni_log(NI_LOG_TRACE, "rsvd1: %04x\n", p_cmd->rsvd1);
160 ni_log(NI_LOG_TRACE, "nsid: %08x\n", p_cmd->nsid);
161 ni_log(NI_LOG_TRACE, "cdw2: %08x\n", p_cmd->cdw2);
162 ni_log(NI_LOG_TRACE, "cdw3: %08x\n", p_cmd->cdw3);
163 // ni_log(NI_LOG_TRACE, "metadata: %"PRIx64"\n", p_cmd->metadata);
164 // ni_log(NI_LOG_TRACE, "addr: %"PRIx64"\n", p_cmd->addr);
165 ni_log(NI_LOG_TRACE, "metadata_len: %08x\n", p_cmd->metadata_len);
166 ni_log(NI_LOG_TRACE, "data_len: %08x\n", p_cmd->data_len);
167 ni_log(NI_LOG_TRACE, "cdw10: %08x\n", p_cmd->cdw10);
168 ni_log(NI_LOG_TRACE, "cdw11: %08x\n", p_cmd->cdw11);
169 ni_log(NI_LOG_TRACE, "cdw12: %08x\n", p_cmd->cdw12);
170 ni_log(NI_LOG_TRACE, "cdw13: %08x\n", p_cmd->cdw13);
171 ni_log(NI_LOG_TRACE, "cdw14: %08x\n", p_cmd->cdw14);
172 ni_log(NI_LOG_TRACE, "cdw15: %08x\n", p_cmd->cdw15);
173 ni_log(NI_LOG_TRACE, "timeout_ms: %08x\n", p_cmd->timeout_ms);
174 ni_log(NI_LOG_TRACE, "result: %08x\n", p_cmd->result);
175
176 return ioctl(handle, NVME_IOCTL_IO_CMD, p_cmd);
177}
178
179#endif //__linux__ defined
180
181#ifdef _WIN32
182
183#define ROUND_TO_DWORD_PTR(x) ni_round_up(x,sizeof(PDWORD))
184
185static ni_retcode_t ni_nvme_get_identity(HANDLE handle, HANDLE event_handle,
186 PVOID p_identity)
187{
188 uint32_t lba = IDENTIFY_DEVICE_R;
189 DWORD data_len = NI_NVME_IDENTITY_CMD_DATA_SZ;
190 return ni_nvme_send_read_cmd(handle, event_handle, p_identity, data_len,
191 lba);
192}
193
195(
196 char ni_devices[][NI_MAX_DEVICE_NAME_LEN],
197 int max_handles
198)
199{
200 TCHAR port_name_buffer[NI_MAX_DEVICE_NAME_LEN] = {0};
201 LPTSTR p_scsi_path = "\\\\.\\PHYSICALDRIVE";
202 LPCTSTR p_format = "%s%d";
203 PUCHAR p_buffer = NULL;
204 ni_retcode_t rc;
205 CHAR firmware_revision[8] = {0};
206 int device_count = 0;
207 int scsi_port = 0;
208 DWORD retval;
209 DWORD data_len = NI_NVME_IDENTITY_CMD_DATA_SZ;
210 CHAR serial_num[20] = {0};
211 CHAR model_name[40] = {0};
212 ni_nvme_identity_t *p_ni_identity = NULL;
213
214 ni_log(NI_LOG_DEBUG, "Searching for NETINT NVMe devices ...\n\n");
215
216 if (ni_posix_memalign((void **)(&p_buffer), sysconf(_SC_PAGESIZE),
217 data_len))
218 {
219 ni_log(NI_LOG_ERROR, "ERROR %d: %s() alloc buffer failed\n", NI_ERRNO,
220 __func__);
222 }
223
224 memset(p_buffer, 0, data_len);
225 ni_event_handle_t event_handle = NULL;
226
227 for (scsi_port = 0; scsi_port < max_handles; scsi_port++)
228 {
229 wsprintf(port_name_buffer, p_format, p_scsi_path, scsi_port);
230 HANDLE handle =
231 CreateFile(port_name_buffer, GENERIC_READ | GENERIC_WRITE,
232 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
233 FILE_ATTRIBUTE_NORMAL, NULL);
234 if (INVALID_HANDLE_VALUE == handle)
235 {
236 retval = NI_ERRNO;
237 ni_log(NI_LOG_DEBUG, "Bad handle, ret=%d\n", retval);
238 }
239 else
240 {
241 DISK_GEOMETRY_EX disk_geometry = { 0 };
242 DWORD bytes_returned;
243 if (DeviceIoControl(
244 handle,
245 IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
246 NULL,
247 0,
248 &disk_geometry,
249 sizeof(disk_geometry),
250 &bytes_returned,
251 NULL))
252 {
253 LONGLONG disk_size = disk_geometry.DiskSize.QuadPart;
255 {
256 ZeroMemory(p_buffer, data_len);
257 rc = ni_nvme_get_identity(handle, event_handle, p_buffer);
258 }
259 else
260 {
261 ni_log(NI_LOG_DEBUG,"port %s size: %.2f is not NETINT card\n",
262 port_name_buffer, (double)disk_size);
264 }
265 } else {
267 }
268
269 if (NI_RETCODE_SUCCESS == rc)
270 {
271 ni_nvme_identity_t *p_ni_id_data =
272 (ni_nvme_identity_t *)p_buffer;
274 "Identity information retrieved from the device "
275 "at port %s\n",
276 port_name_buffer);
278 " VID: 0x%x \n SSVID: 0x%x \n",
279 p_ni_id_data->ui16Vid, p_ni_id_data->ui16Ssvid);
280
281 if (NETINT_PCI_VENDOR_ID == p_ni_id_data->ui16Vid &&
282 NETINT_PCI_VENDOR_ID == p_ni_id_data->ui16Ssvid &&
283 is_supported_xcoder(p_ni_id_data->device_is_xcoder))
284 {
285 /* make the fw revision/model name/serial num to string*/
286 memset(firmware_revision, 0, sizeof(firmware_revision));
287 memcpy(firmware_revision, p_ni_id_data->ai8Fr,
288 sizeof(firmware_revision));
289 firmware_revision[sizeof(firmware_revision) - 1] = 0;
290
291 memset(model_name, 0, sizeof(model_name));
292 memcpy(model_name, p_ni_id_data->ai8Mn, sizeof(model_name));
293 model_name[sizeof(model_name) - 1] = 0;
294
295 memset(serial_num, 0, sizeof(serial_num));
296 memcpy(serial_num, p_ni_id_data->ai8Sn, sizeof(serial_num));
297 serial_num[sizeof(serial_num) - 1] = 0;
298 ni_log(NI_LOG_DEBUG, " Device Model: %s \n",
299 model_name);
300 ni_log(NI_LOG_DEBUG, " Firmware Rev: %s \n",
301 firmware_revision);
302 ni_log(NI_LOG_DEBUG, " Serial Number: %s \n",
303 serial_num);
305 "NETINT %s NVMe video transcoder identified "
306 "at port %s\n\n",
307 model_name, port_name_buffer);
308 ni_strncpy(ni_devices[device_count++], NI_MAX_DEVICE_NAME_LEN, port_name_buffer,
310 } else
311 {
313 "Device at port %s %d is not a NETINT NVMe device\n",
314 port_name_buffer, p_ni_id_data->device_is_xcoder);
315 }
316 CloseHandle(handle);
317 } else
318 {
319 retval = NI_ERRNO;
320 ni_log(
322 "Device at port %s is not a NETINT NVMe device,ret=%d\n\n",
323 port_name_buffer, retval);
324 CloseHandle(handle);
325 }
326 }
327 } // end for loop
328
329 if (p_buffer)
330 {
331 ni_aligned_free(p_buffer);
332 }
333
335 "Total Number of NETINT NVMe Transcoders identified: %d \n\n",
336 device_count);
337 return device_count;
338}
339
340#endif //_WIN32 defined
341
342#ifndef XCODER_IO_RW_ENABLED
343/*!******************************************************************************
344 * \brief Compose a nvme admin command
345 *
346 * \param
347 *
348 * \return
349 *******************************************************************************/
351 ni_device_handle_t handle,
352 ni_nvme_command_t *p_ni_nvme_cmd,
353 uint32_t data_len, void *p_data,
354 uint32_t *p_result)
355{
356 int32_t rc = -1;
357#ifdef _WIN32
358 //Windows inbox driver requires to send identity through different
359 //api than regular pass through commands
360 if (nvme_admin_cmd_identify == opcode)
361 {
362 rc = ni_nvme_get_identity(handle, NI_INVALID_EVENT_HANDLE, p_data);
363 *p_result = NI_RETCODE_SUCCESS;
364 }
365#elif __APPLE__
366#else
367 ni_nvme_passthrough_cmd_t nvme_cmd = {0};
368
369 nvme_cmd.opcode = opcode;
370 nvme_cmd.cdw10 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw10);
371 nvme_cmd.cdw11 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw11);
372 nvme_cmd.cdw12 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw12);
373 nvme_cmd.cdw13 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw13);
374 nvme_cmd.cdw14 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw14);
375 nvme_cmd.cdw15 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw15);
376 nvme_cmd.addr = (__u64)ni_htonll((uintptr_t)p_data);
377 nvme_cmd.data_len = ni_htonl(data_len);
378
379 rc = ni_nvme_send_admin_pass_through_command(handle, &nvme_cmd);
380
381 *p_result = ni_htonl(nvme_cmd.result);
382#endif
383
384 ni_log(NI_LOG_DEBUG, "%s: handle=%" PRIx64 ", result=%08x, rc=%d\n",
385 __func__, (int64_t)handle, (uint32_t)(*p_result), rc);
386
387 return rc;
388}
389
390/*!******************************************************************************
391 * \brief Compose a nvme io command
392 *
393 * \param
394 *
395 * \return
396 *******************************************************************************/
397int32_t ni_nvme_send_io_cmd(ni_nvme_opcode_t opcode, ni_device_handle_t handle,
398 ni_nvme_command_t *p_ni_nvme_cmd, uint32_t data_len,
399 void *p_data, uint32_t *p_result)
400{
401 int32_t rc = -1;
402#ifdef _WIN32
403#elif __APPLE__
404#else
405 ni_nvme_passthrough_cmd_t nvme_cmd;
406 //int32_t *p_addr = NULL;
407
408 memset(&nvme_cmd, 0, sizeof(nvme_cmd));
409 nvme_cmd.opcode = opcode;
410 nvme_cmd.nsid = ni_htonl(1);
411 nvme_cmd.addr = (__u64)ni_htonll((uintptr_t)p_data);
412 nvme_cmd.data_len = ni_htonl(data_len);
413 nvme_cmd.cdw2 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw2);
414 nvme_cmd.cdw3 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw3);
415 nvme_cmd.cdw10 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw10);
416 nvme_cmd.cdw11 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw11);
417 nvme_cmd.cdw12 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw12);
418 nvme_cmd.cdw13 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw13);
419 nvme_cmd.cdw14 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw14);
420 nvme_cmd.cdw15 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw15);
421
422 rc = ni_nvme_send_io_pass_through_command(handle, &nvme_cmd);
423
424 //p_addr = &nvme_cmd.result;
425 //*!pResult = *p_addr;
426 *p_result = ni_htonl(nvme_cmd.result);
427#endif
428
429 ni_log(NI_LOG_DEBUG, "%s: handle=%" PRIx64 ", result=%08x, rc=%d\n",
430 __func__, (int64_t)handle, (uint32_t)(*p_result), rc);
431
432 return rc;
433}
434#endif
435
436#ifdef __linux__
437
438/*!******************************************************************************
439 * \brief Compose a nvme io through admin command
440 *
441 * \param
442 *
443 * \return
444 *******************************************************************************/
446 ni_device_handle_t handle,
447 ni_nvme_command_t *p_ni_nvme_cmd,
448 uint32_t data_len, void *p_data,
449 uint32_t *p_result)
450{
451 int32_t rc;
452 ni_nvme_passthrough_cmd_t nvme_cmd = {0};
453
454 nvme_cmd.opcode = opcode;
455 nvme_cmd.nsid = ni_htonl(1);
456 nvme_cmd.addr = (__u64)ni_htonll((uintptr_t)p_data);
457 nvme_cmd.data_len = ni_htonl(data_len);
458 nvme_cmd.cdw10 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw10);
459 nvme_cmd.cdw11 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw11);
460 nvme_cmd.cdw12 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw12);
461 nvme_cmd.cdw13 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw13);
462 nvme_cmd.cdw14 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw14);
463 nvme_cmd.cdw15 = (__u32)ni_htonl(p_ni_nvme_cmd->cdw15);
464
465 rc = ni_nvme_send_admin_pass_through_command(handle, &nvme_cmd);
466
467 //p_addr = &nvme_cmd.result;
468 //*!pResult = *p_addr;
469 *p_result = ni_htonl(nvme_cmd.result);
470
471 ni_log(NI_LOG_DEBUG, "%s: handle=%d, result=%08x, rc=%d\n", __func__,
472 handle, *p_result, rc);
473
474 return rc;
475}
476#endif //__linux__ defined
477
478/*!******************************************************************************
479 * \brief parse the lba opcode, subtype, option
480 * It's called only if a I/O read/write fails,
481 * so just use the print level "NI_LOG_ERROR" now.
482 *
483 * \param lba is 4k aligned
484 *
485 * \return
486 *******************************************************************************/
487void ni_parse_lba(uint64_t lba)
488{
489 uint64_t lba_high = (lba >> NI_INSTANCE_TYPE_OFFSET);
490 uint64_t lba_low = (lba & 0x3FFFF);
491 uint8_t device_type = (lba_high & NI_DEVICE_TYPE_ENCODER);
492 uint16_t session_id = (uint16_t)(
494 if (device_type == NI_DEVICE_TYPE_ENCODER)
495 {
497 "encoder lba:0x%" PRIx64 "(4K-aligned), 0x%" PRIx64
498 "(512B-aligned), session ID:%u\n",
499 lba, ((uint64_t)lba << 3), session_id);
500 if (lba_low >= WR_OFFSET_IN_4K)
501 {
502 ni_log(NI_LOG_ERROR, "encoder send frame failed\n");
503 } else if (lba_low >= RD_OFFSET_IN_4K)
504 {
505 ni_log(NI_LOG_ERROR, "encoder receive packet failed\n");
506 } else
507 {
509 "encoder ctrl command failed: op-0x%x, "
510 "subtype-0x%x, option-0x%x\n",
511 (uint32_t)(
512 ((lba_low - START_OFFSET_IN_4K) >> NI_OP_BIT_OFFSET) +
513 0xD0),
514 (uint32_t)((lba_low >> NI_SUB_BIT_OFFSET) & 0xF),
515 (uint32_t)(lba_low & 0xF));
516 }
517 }
518 else
519 {
521 "decoder lba:0x%" PRIx64 "(4K-aligned), 0x%" PRIx64
522 "(512B-aligned), session ID:%u\n",
523 lba, ((uint64_t)lba << 3), session_id);
524 if (lba_low >= WR_OFFSET_IN_4K)
525 {
526 ni_log(NI_LOG_ERROR, "decoder send packet failed\n");
527 } else if (lba_low >= RD_OFFSET_IN_4K)
528 {
529 ni_log(NI_LOG_ERROR, "decoder receive frame failed\n");
530 } else
531 {
533 "decoder ctrl command failed: op-0x%x, "
534 "subtype-0x%x, option-0x%x\n",
535 (uint32_t)(
536 ((lba_low - START_OFFSET_IN_4K) >> NI_OP_BIT_OFFSET) +
537 0xD0),
538 (uint32_t)((lba_low >> NI_SUB_BIT_OFFSET) & 0xF),
539 (uint32_t)(lba_low & 0xF));
540 }
541 }
542}
543
544/*!******************************************************************************
545 * \brief Compose an io read command
546 *
547 * \param
548 *
549 * \return value < 0, failed, return failure code.
550 * value >= 0, success,
551 * windows return success code,
552 * linux return actural size
553 *******************************************************************************/
554int32_t ni_nvme_send_read_cmd(ni_device_handle_t handle,
555 ni_event_handle_t event_handle, void *p_data,
556 uint32_t data_len, uint32_t lba)
557{
558 int32_t rc;
559 uint64_t offset = (uint64_t)lba << LBA_BIT_OFFSET;
560
561 if (!p_data)
562 {
563 ni_log(NI_LOG_ERROR, "%s: ERROR: invalid parameter: p_data=%p\n", __func__, p_data);
565 }
566
567#ifdef _WIN32
568 uint32_t offset_l = (uint32_t)(offset & 0xFFFFFFFF);
569 DWORD offset_h = (DWORD)(offset >> 32);
570 OVERLAPPED overlap;
572 "%s: handle=%" PRIx64 ", lba=0x%lx, len=%d,offset:0x%x,0x%x\n",
573 __func__, (int64_t)handle, ((uint64_t)lba << 3), data_len, offset_l, offset_h);
574 memset(&overlap, 0, sizeof(overlap));
575 overlap.Offset = offset_l;
576 overlap.OffsetHigh = offset_h;
577
578 DWORD data_len_; //data real count
579 rc = ReadFile(handle, p_data, data_len, &data_len_, &overlap);
580 ni_log(NI_LOG_TRACE, "rc=%d,actlen=%d\n", rc, data_len_);
581 if (rc == FALSE)
582 {
583 rc = NI_ERRNO;
585 "%s() ReadFile handle=%" PRIx64 ", event_handle="
586 "%" PRIx64 ", lba=0x%lx, len=%d, rc=%d\n",
587 __func__, (int64_t)handle, (int64_t)event_handle, ((uint64_t)lba << 3),
588 data_len, rc);
589 ni_log(NI_LOG_ERROR, "ERROR %d: %s() failed\n", rc, __func__);
591 } else
592 {
594 }
595#else
596 if (!handle || handle == NI_INVALID_DEVICE_HANDLE)
597 {
598 //if we can make sure that all handles are initialized to NI_INVALID_DEVICE_HANDLE
599 //we can remove the condition !handle
600 ni_log(NI_LOG_ERROR, "%s: ERROR: invalid parameters: handle=%" PRId32 "\n", __func__, handle);
602 }
603
604 if (((uintptr_t)p_data) % NI_MEM_PAGE_ALIGNMENT)
605 {
607 "%s: Buffer not %d aligned = %p! Reading to aligned memory "
608 "and copying.\n",
609 __func__, NI_MEM_PAGE_ALIGNMENT, p_data);
610 void *p_buf = NULL;
611 if (ni_posix_memalign(&p_buf, sysconf(_SC_PAGESIZE), data_len))
612 {
614 "ERROR %d: %s() alloc data buffer failed\n", NI_ERRNO,
615 __func__);
617 }
618 else
619 {
620 rc = pread(handle, p_buf, data_len, offset);
621 if (rc >= 0)//copy only if anything has been read
622 {
623 memcpy(p_data, p_buf, data_len);
624 }
625 ni_aligned_free(p_buf);
626 }
627 } else
628 {
629 rc = pread(handle, p_data, data_len, offset);
630 }
632 "%s: handle=%" PRIx64
633 ", offset 0x%lx, lba=0x%lx, len=%d, rc=%d\n",
634 __func__, (int64_t)handle, offset, ((uint64_t)lba << 3), data_len, rc);
635 if (rc < 0 || rc != data_len)
636 {
638 "ERROR %d: %s failed, lba=0x%lx, len=%u, rc=%d, error=%d\n",
639 NI_ERRNO, __func__, ((uint64_t)lba << 3), data_len, rc, NI_ERRNO);
640 ni_parse_lba(lba);
642 } else
643 {
645 }
646#endif
647 return rc;
648}
649
650/*!******************************************************************************
651 * \brief Compose a io write command
652 *
653 * \param
654 *
655 * \return value < 0, failed, return failure code.
656 * value >= 0, success,
657 * windows return success code,
658 * linux return actural size
659 *******************************************************************************/
660int32_t ni_nvme_send_write_cmd(ni_device_handle_t handle,
661 ni_event_handle_t event_handle, void *p_data,
662 uint32_t data_len, uint32_t lba)
663{
664 int32_t rc;
665 uint64_t offset = (uint64_t)lba << LBA_BIT_OFFSET;
666
667 if (!p_data)
668 {
669 ni_log(NI_LOG_ERROR, "%s: ERROR: invalid parameter: p_data=%p\n", __func__, p_data);
671 }
672
673#ifdef _WIN32
674 uint32_t offset_l = (uint32_t)(offset & 0xFFFFFFFF);
675 DWORD offset_h = (DWORD)(offset >> 32);
676 DWORD data_len_; //data real count
677 OVERLAPPED overlap;
678
680 "%s: handle=%" PRIx64 ", lba=0x%lx, len=%d,offset:0x%x,0x%x\n",
681 __func__, (int64_t)handle, ((uint64_t)lba << 3), data_len, offset_l, offset_h);
682
683 memset(&overlap, 0, sizeof(overlap));
684 overlap.Offset = offset_l;
685 overlap.OffsetHigh = offset_h;
686
687 rc = WriteFile(handle, p_data, data_len, &data_len_, &overlap);
688 ni_log(NI_LOG_TRACE, "rc=%d,actlen=%d\n", rc, data_len_);
689 if (rc == FALSE)
690 {
691 rc = NI_ERRNO;
693 "%s() WriteFile handle=%" PRIx64 ", event_handle="
694 "%" PRIx64 ", lba=0x%lx, len=%d, rc=%d\n",
695 __func__, (int64_t)handle, (int64_t)event_handle, ((uint64_t)lba << 3),
696 data_len, rc);
697 ni_log(NI_LOG_ERROR, "ERROR %d: ni_nvme_send_write_cmd() failed\n", rc);
699 } else
700 {
702 }
703#else
704 if (!handle || handle == NI_INVALID_DEVICE_HANDLE)
705 {
706 //if we can make sure that all handles are initialized to NI_INVALID_DEVICE_HANDLE
707 //we can remove the condition !handle
708 ni_log(NI_LOG_ERROR, "%s: ERROR: invalid parameters: handle=%" PRId32 "\n", __func__, handle);
710 }
711
712 if (((uintptr_t)p_data) % NI_MEM_PAGE_ALIGNMENT)
713 {
715 "%s: Buffer not %d aligned = %p! Copying to aligned memory "
716 "and writing.\n",
717 __func__, NI_MEM_PAGE_ALIGNMENT, p_data);
718 void *p_buf = NULL;
719 if (ni_posix_memalign(&p_buf, sysconf(_SC_PAGESIZE), data_len))
720 {
722 "ERROR %d: %s() alloc data buffer failed\n", NI_ERRNO,
723 __func__);
725 }
726 else
727 {
728 memcpy(p_buf, p_data, data_len);
729 rc = pwrite(handle, p_buf, data_len, offset);
730 ni_aligned_free(p_buf);
731 }
732 }
733 else
734 {
735 rc = pwrite(handle, p_data, data_len, offset);
736 }
738 "%s: handle=%" PRIx64 ", lba=0x%lx, len=%d, rc=%d\n", __func__,
739 (int64_t)handle, ((uint64_t)lba << 3), data_len, rc);
740 if ((rc < 0) || (rc != data_len))
741 {
743 "ERROR %d: %s failed, lba=0x%lx, len=%u, rc=%d, error=%d\n",
744 NI_ERRNO, __func__, ((uint64_t)lba << 3), data_len, rc, NI_ERRNO);
745 ni_parse_lba(lba);
747 } else
748 {
750 }
751#endif
752 return rc;
753}
754
755//linux aio
756#ifdef __linux__
757void ni_nvme_setup_aio_iocb(ni_device_handle_t handle, ni_iocb_t *iocb,
758 void *p_data, uint32_t data_len, uint32_t lba,
759 int write)
760{
761 memset(iocb, 0, sizeof(ni_iocb_t));
762 iocb->aio_fildes = handle;
763 iocb->aio_lio_opcode = write ? IOCB_CMD_PWRITE : IOCB_CMD_PREAD;
764 iocb->aio_reqprio = 0;
765 iocb->aio_buf = (uint64_t)p_data;
766 iocb->aio_nbytes = data_len;
767 iocb->aio_offset = (uint64_t)lba << LBA_BIT_OFFSET;
768}
769
770int32_t ni_nvme_batch_cmd_aio(ni_aio_context_t ctx, ni_iocb_t **iocbs,
771 ni_io_event_t *events, int iocb_num)
772{
773 int32_t rc;
774 int i;
775
776 for (i = 0; i < iocb_num; i++) {
777 ni_iocb_t *iocb = iocbs[i];
778 ni_log(NI_LOG_TRACE, "%s: iocb %d, fdes %d, opcode %d, buf 0x%llx,"
779 " nbytes %llu, offset 0x%llx\n", i, iocb->aio_fildes, iocb->aio_lio_opcode,
780 iocb->aio_buf, iocb->aio_nbytes, iocb->aio_offset);
781 }
782
783 rc = ni_aio_submit(ctx, iocb_num, iocbs);
784 if (rc != iocb_num) {
785 ni_log(NI_LOG_ERROR, "%s: ERROR: failed to submit enough aio iocb, rc=%d\n", __func__,
786 rc);
788 }
789
790 rc = ni_aio_getevents(ctx, iocb_num, iocb_num, events, NULL);
791 if (rc != iocb_num) {
792 ni_log(NI_LOG_ERROR, "%s: ERROR: failed to get events, rc=%d\n", __func__, rc);
794 } else {
795 for (i = 0; i < iocb_num; i++) {
796 ni_io_event_t *evt = &events[i];
797 ni_iocb_t *iocb = (ni_iocb_t *)evt->obj;
798 if (iocb->aio_nbytes != evt->res) {
799 ni_log(NI_LOG_ERROR, "ERROR %s(): failed to write data, size %llu, res %lld\n",
800 __func__, iocb->aio_nbytes, evt->res);
802 }
803 }
805 }
806
807 return rc;
808}
809#endif
#define NI_MAX_DEVICE_NAME_LEN
Definition ni_defs.h:236
@ NI_DEVICE_TYPE_AI
Definition ni_defs.h:363
@ NI_DEVICE_TYPE_ENCODER
Definition ni_defs.h:361
#define NI_ERRNO
Definition ni_defs.h:229
#define NETINT_PCI_VENDOR_ID
Definition ni_defs.h:129
#define NI_MEM_PAGE_ALIGNMENT
Definition ni_defs.h:263
#define GET_XCODER_DEVICE_TYPE_STR(t)
Definition ni_defs.h:433
enum _ni_nvme_opcode ni_nvme_opcode_t
ni_retcode_t
Definition ni_defs.h:442
@ NI_RETCODE_NVME_SC_STREAM_ERROR
Definition ni_defs.h:561
@ NI_RETCODE_FAILURE
Definition ni_defs.h:444
@ NI_RETCODE_NVME_SC_INTERLACED_NOT_SUPPORTED
Definition ni_defs.h:562
@ NI_RETCODE_NVME_SC_INVALID_PARAMETER
Definition ni_defs.h:560
@ NI_RETCODE_ERROR_STREAM_ERROR
Definition ni_defs.h:540
@ NI_RETCODE_SUCCESS
Definition ni_defs.h:443
@ NI_RETCODE_ERROR_RESOURCE_UNAVAILABLE
Definition ni_defs.h:450
@ NI_RETCODE_ERROR_NVME_CMD_FAILED
Definition ni_defs.h:448
@ NI_RETCODE_NVME_SC_VPU_RSRC_INSUFFICIENT
Definition ni_defs.h:564
@ NI_RETCODE_ERROR_MEM_ALOC
Definition ni_defs.h:447
@ NI_RETCODE_INVALID_PARAM
Definition ni_defs.h:445
void ni_log(ni_log_level_t level, const char *fmt,...)
print log message using ni_log_callback
Definition ni_log.c:183
@ NI_LOG_DEBUG
Definition ni_log.h:64
@ NI_LOG_TRACE
Definition ni_log.h:65
@ NI_LOG_ERROR
Definition ni_log.h:62
@ NI_LOG_INFO
Definition ni_log.h:63
void ni_parse_lba(uint64_t lba)
parse the lba opcode, subtype, option It's called only if a I/O read/write fails, so just use the pri...
Definition ni_nvme.c:487
int32_t ni_nvme_send_read_cmd(ni_device_handle_t handle, ni_event_handle_t event_handle, void *p_data, uint32_t data_len, uint32_t lba)
Compose an io read command.
Definition ni_nvme.c:554
int32_t ni_nvme_send_admin_cmd(ni_nvme_admin_opcode_t opcode, ni_device_handle_t handle, ni_nvme_command_t *p_ni_nvme_cmd, uint32_t data_len, void *p_data, uint32_t *p_result)
Compose a nvme admin command.
Definition ni_nvme.c:350
int32_t ni_nvme_send_write_cmd(ni_device_handle_t handle, ni_event_handle_t event_handle, void *p_data, uint32_t data_len, uint32_t lba)
Compose a io write command.
Definition ni_nvme.c:660
int32_t ni_nvme_send_io_cmd(ni_nvme_opcode_t opcode, ni_device_handle_t handle, ni_nvme_command_t *p_ni_nvme_cmd, uint32_t data_len, void *p_data, uint32_t *p_result)
Compose a nvme io command.
Definition ni_nvme.c:397
ni_retcode_t ni_nvme_check_error_code(int rc, int opcode, uint32_t xcoder_type, uint32_t hw_id, uint32_t *p_instance_id)
Check f/w error return code, and if it's a fatal one, terminate application's decoding/encoding proce...
Definition ni_nvme.c:62
Private definitions for interfacing with NETINT video processing devices over NVMe.
int32_t ni_nvme_send_io_cmd_thru_admin_queue(ni_nvme_admin_opcode_t opcode, ni_device_handle_t fd, ni_nvme_command_t *p_ni_nvme_cmd, uint32_t data_len, void *data, uint32_t *pResult)
#define LBA_BIT_OFFSET
Definition ni_nvme.h:625
@ nvme_admin_cmd_identify
Definition ni_nvme.h:306
#define NI_INSTANCE_TYPE_OFFSET
Definition ni_nvme.h:630
#define NI_OP_BIT_OFFSET
Definition ni_nvme.h:629
#define WR_OFFSET_IN_4K
Definition ni_nvme.h:645
#define IDENTIFY_DEVICE_R
Definition ni_nvme.h:687
#define START_OFFSET_IN_4K
Definition ni_nvme.h:638
enum _ni_nvme_admin_opcode ni_nvme_admin_opcode_t
#define NI_NVME_IDENTITY_CMD_DATA_SZ
Definition ni_nvme.h:38
int ni_nvme_enumerate_devices(char ni_devices[][NI_MAX_DEVICE_NAME_LEN], int max_handles)
#define NI_SESSION_ID_OFFSET
Definition ni_nvme.h:631
#define RD_OFFSET_IN_4K
Definition ni_nvme.h:642
#define NI_SUB_BIT_OFFSET
Definition ni_nvme.h:628
ni_retcode_t ni_strncpy(char *dest, size_t dmax, const char *src, size_t slen)
Definition ni_util.c:518
int ni_posix_memalign(void **memptr, size_t alignment, size_t size)
Allocate aligned memory.
Definition ni_util.c:202
const char * ni_ai_errno_to_str(int rc)
return error string according to error code from firmware
Definition ni_util.c:4950
Utility definitions.
#define ni_aligned_free(p_memptr)
Definition ni_util.h:400
uint32_t cdw10
Definition ni_nvme.h:44
uint32_t cdw13
Definition ni_nvme.h:47
uint32_t cdw12
Definition ni_nvme.h:46
uint32_t cdw15
Definition ni_nvme.h:49
uint32_t cdw3
Definition ni_nvme.h:43
uint32_t cdw2
Definition ni_nvme.h:42
uint32_t cdw11
Definition ni_nvme.h:45
uint32_t cdw14
Definition ni_nvme.h:48
uint8_t ai8Fr[8]
Definition ni_nvme.h:97
uint16_t ui16Ssvid
Definition ni_nvme.h:94
uint8_t ai8Sn[20]
Definition ni_nvme.h:95
uint8_t device_is_xcoder
Definition ni_nvme.h:155
uint16_t ui16Vid
Definition ni_nvme.h:93
uint8_t ai8Mn[40]
Definition ni_nvme.h:96