18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#ifndef _NE_PCI_DEV_H_ 78c2ecf20Sopenharmony_ci#define _NE_PCI_DEV_H_ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/atomic.h> 108c2ecf20Sopenharmony_ci#include <linux/list.h> 118c2ecf20Sopenharmony_ci#include <linux/mutex.h> 128c2ecf20Sopenharmony_ci#include <linux/pci.h> 138c2ecf20Sopenharmony_ci#include <linux/pci_ids.h> 148c2ecf20Sopenharmony_ci#include <linux/wait.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci/** 178c2ecf20Sopenharmony_ci * DOC: Nitro Enclaves (NE) PCI device 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci/** 218c2ecf20Sopenharmony_ci * PCI_DEVICE_ID_NE - Nitro Enclaves PCI device id. 228c2ecf20Sopenharmony_ci */ 238c2ecf20Sopenharmony_ci#define PCI_DEVICE_ID_NE (0xe4c1) 248c2ecf20Sopenharmony_ci/** 258c2ecf20Sopenharmony_ci * PCI_BAR_NE - Nitro Enclaves PCI device MMIO BAR. 268c2ecf20Sopenharmony_ci */ 278c2ecf20Sopenharmony_ci#define PCI_BAR_NE (0x03) 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci/** 308c2ecf20Sopenharmony_ci * DOC: Device registers in the NE PCI device MMIO BAR 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci/** 348c2ecf20Sopenharmony_ci * NE_ENABLE - (1 byte) Register to notify the device that the driver is using 358c2ecf20Sopenharmony_ci * it (Read/Write). 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_ci#define NE_ENABLE (0x0000) 388c2ecf20Sopenharmony_ci#define NE_ENABLE_OFF (0x00) 398c2ecf20Sopenharmony_ci#define NE_ENABLE_ON (0x01) 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/** 428c2ecf20Sopenharmony_ci * NE_VERSION - (2 bytes) Register to select the device run-time version 438c2ecf20Sopenharmony_ci * (Read/Write). 448c2ecf20Sopenharmony_ci */ 458c2ecf20Sopenharmony_ci#define NE_VERSION (0x0002) 468c2ecf20Sopenharmony_ci#define NE_VERSION_MAX (0x0001) 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci/** 498c2ecf20Sopenharmony_ci * NE_COMMAND - (4 bytes) Register to notify the device what command was 508c2ecf20Sopenharmony_ci * requested (Write-Only). 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_ci#define NE_COMMAND (0x0004) 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci/** 558c2ecf20Sopenharmony_ci * NE_EVTCNT - (4 bytes) Register to notify the driver that a reply or a device 568c2ecf20Sopenharmony_ci * event is available (Read-Only): 578c2ecf20Sopenharmony_ci * - Lower half - command reply counter 588c2ecf20Sopenharmony_ci * - Higher half - out-of-band device event counter 598c2ecf20Sopenharmony_ci */ 608c2ecf20Sopenharmony_ci#define NE_EVTCNT (0x000c) 618c2ecf20Sopenharmony_ci#define NE_EVTCNT_REPLY_SHIFT (0) 628c2ecf20Sopenharmony_ci#define NE_EVTCNT_REPLY_MASK (0x0000ffff) 638c2ecf20Sopenharmony_ci#define NE_EVTCNT_REPLY(cnt) (((cnt) & NE_EVTCNT_REPLY_MASK) >> \ 648c2ecf20Sopenharmony_ci NE_EVTCNT_REPLY_SHIFT) 658c2ecf20Sopenharmony_ci#define NE_EVTCNT_EVENT_SHIFT (16) 668c2ecf20Sopenharmony_ci#define NE_EVTCNT_EVENT_MASK (0xffff0000) 678c2ecf20Sopenharmony_ci#define NE_EVTCNT_EVENT(cnt) (((cnt) & NE_EVTCNT_EVENT_MASK) >> \ 688c2ecf20Sopenharmony_ci NE_EVTCNT_EVENT_SHIFT) 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci/** 718c2ecf20Sopenharmony_ci * NE_SEND_DATA - (240 bytes) Buffer for sending the command request payload 728c2ecf20Sopenharmony_ci * (Read/Write). 738c2ecf20Sopenharmony_ci */ 748c2ecf20Sopenharmony_ci#define NE_SEND_DATA (0x0010) 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci/** 778c2ecf20Sopenharmony_ci * NE_RECV_DATA - (240 bytes) Buffer for receiving the command reply payload 788c2ecf20Sopenharmony_ci * (Read-Only). 798c2ecf20Sopenharmony_ci */ 808c2ecf20Sopenharmony_ci#define NE_RECV_DATA (0x0100) 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci/** 838c2ecf20Sopenharmony_ci * DOC: Device MMIO buffer sizes 848c2ecf20Sopenharmony_ci */ 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci/** 878c2ecf20Sopenharmony_ci * NE_SEND_DATA_SIZE / NE_RECV_DATA_SIZE - 240 bytes for send / recv buffer. 888c2ecf20Sopenharmony_ci */ 898c2ecf20Sopenharmony_ci#define NE_SEND_DATA_SIZE (240) 908c2ecf20Sopenharmony_ci#define NE_RECV_DATA_SIZE (240) 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci/** 938c2ecf20Sopenharmony_ci * DOC: MSI-X interrupt vectors 948c2ecf20Sopenharmony_ci */ 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci/** 978c2ecf20Sopenharmony_ci * NE_VEC_REPLY - MSI-X vector used for command reply notification. 988c2ecf20Sopenharmony_ci */ 998c2ecf20Sopenharmony_ci#define NE_VEC_REPLY (0) 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci/** 1028c2ecf20Sopenharmony_ci * NE_VEC_EVENT - MSI-X vector used for out-of-band events e.g. enclave crash. 1038c2ecf20Sopenharmony_ci */ 1048c2ecf20Sopenharmony_ci#define NE_VEC_EVENT (1) 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci/** 1078c2ecf20Sopenharmony_ci * enum ne_pci_dev_cmd_type - Device command types. 1088c2ecf20Sopenharmony_ci * @INVALID_CMD: Invalid command. 1098c2ecf20Sopenharmony_ci * @ENCLAVE_START: Start an enclave, after setting its resources. 1108c2ecf20Sopenharmony_ci * @ENCLAVE_GET_SLOT: Get the slot uid of an enclave. 1118c2ecf20Sopenharmony_ci * @ENCLAVE_STOP: Terminate an enclave. 1128c2ecf20Sopenharmony_ci * @SLOT_ALLOC : Allocate a slot for an enclave. 1138c2ecf20Sopenharmony_ci * @SLOT_FREE: Free the slot allocated for an enclave 1148c2ecf20Sopenharmony_ci * @SLOT_ADD_MEM: Add a memory region to an enclave slot. 1158c2ecf20Sopenharmony_ci * @SLOT_ADD_VCPU: Add a vCPU to an enclave slot. 1168c2ecf20Sopenharmony_ci * @SLOT_COUNT : Get the number of allocated slots. 1178c2ecf20Sopenharmony_ci * @NEXT_SLOT: Get the next slot in the list of allocated slots. 1188c2ecf20Sopenharmony_ci * @SLOT_INFO: Get the info for a slot e.g. slot uid, vCPUs count. 1198c2ecf20Sopenharmony_ci * @SLOT_ADD_BULK_VCPUS: Add a number of vCPUs, not providing CPU ids. 1208c2ecf20Sopenharmony_ci * @MAX_CMD: A gatekeeper for max possible command type. 1218c2ecf20Sopenharmony_ci */ 1228c2ecf20Sopenharmony_cienum ne_pci_dev_cmd_type { 1238c2ecf20Sopenharmony_ci INVALID_CMD = 0, 1248c2ecf20Sopenharmony_ci ENCLAVE_START = 1, 1258c2ecf20Sopenharmony_ci ENCLAVE_GET_SLOT = 2, 1268c2ecf20Sopenharmony_ci ENCLAVE_STOP = 3, 1278c2ecf20Sopenharmony_ci SLOT_ALLOC = 4, 1288c2ecf20Sopenharmony_ci SLOT_FREE = 5, 1298c2ecf20Sopenharmony_ci SLOT_ADD_MEM = 6, 1308c2ecf20Sopenharmony_ci SLOT_ADD_VCPU = 7, 1318c2ecf20Sopenharmony_ci SLOT_COUNT = 8, 1328c2ecf20Sopenharmony_ci NEXT_SLOT = 9, 1338c2ecf20Sopenharmony_ci SLOT_INFO = 10, 1348c2ecf20Sopenharmony_ci SLOT_ADD_BULK_VCPUS = 11, 1358c2ecf20Sopenharmony_ci MAX_CMD, 1368c2ecf20Sopenharmony_ci}; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci/** 1398c2ecf20Sopenharmony_ci * DOC: Device commands - payload structure for requests and replies. 1408c2ecf20Sopenharmony_ci */ 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci/** 1438c2ecf20Sopenharmony_ci * struct enclave_start_req - ENCLAVE_START request. 1448c2ecf20Sopenharmony_ci * @slot_uid: Slot unique id mapped to the enclave to start. 1458c2ecf20Sopenharmony_ci * @enclave_cid: Context ID (CID) for the enclave vsock device. 1468c2ecf20Sopenharmony_ci * If 0, CID is autogenerated. 1478c2ecf20Sopenharmony_ci * @flags: Flags for the enclave to start with (e.g. debug mode). 1488c2ecf20Sopenharmony_ci */ 1498c2ecf20Sopenharmony_cistruct enclave_start_req { 1508c2ecf20Sopenharmony_ci u64 slot_uid; 1518c2ecf20Sopenharmony_ci u64 enclave_cid; 1528c2ecf20Sopenharmony_ci u64 flags; 1538c2ecf20Sopenharmony_ci}; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci/** 1568c2ecf20Sopenharmony_ci * struct enclave_get_slot_req - ENCLAVE_GET_SLOT request. 1578c2ecf20Sopenharmony_ci * @enclave_cid: Context ID (CID) for the enclave vsock device. 1588c2ecf20Sopenharmony_ci */ 1598c2ecf20Sopenharmony_cistruct enclave_get_slot_req { 1608c2ecf20Sopenharmony_ci u64 enclave_cid; 1618c2ecf20Sopenharmony_ci}; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci/** 1648c2ecf20Sopenharmony_ci * struct enclave_stop_req - ENCLAVE_STOP request. 1658c2ecf20Sopenharmony_ci * @slot_uid: Slot unique id mapped to the enclave to stop. 1668c2ecf20Sopenharmony_ci */ 1678c2ecf20Sopenharmony_cistruct enclave_stop_req { 1688c2ecf20Sopenharmony_ci u64 slot_uid; 1698c2ecf20Sopenharmony_ci}; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci/** 1728c2ecf20Sopenharmony_ci * struct slot_alloc_req - SLOT_ALLOC request. 1738c2ecf20Sopenharmony_ci * @unused: In order to avoid weird sizeof edge cases. 1748c2ecf20Sopenharmony_ci */ 1758c2ecf20Sopenharmony_cistruct slot_alloc_req { 1768c2ecf20Sopenharmony_ci u8 unused; 1778c2ecf20Sopenharmony_ci}; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci/** 1808c2ecf20Sopenharmony_ci * struct slot_free_req - SLOT_FREE request. 1818c2ecf20Sopenharmony_ci * @slot_uid: Slot unique id mapped to the slot to free. 1828c2ecf20Sopenharmony_ci */ 1838c2ecf20Sopenharmony_cistruct slot_free_req { 1848c2ecf20Sopenharmony_ci u64 slot_uid; 1858c2ecf20Sopenharmony_ci}; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci/* TODO: Add flags field to the request to add memory region. */ 1888c2ecf20Sopenharmony_ci/** 1898c2ecf20Sopenharmony_ci * struct slot_add_mem_req - SLOT_ADD_MEM request. 1908c2ecf20Sopenharmony_ci * @slot_uid: Slot unique id mapped to the slot to add the memory region to. 1918c2ecf20Sopenharmony_ci * @paddr: Physical address of the memory region to add to the slot. 1928c2ecf20Sopenharmony_ci * @size: Memory size, in bytes, of the memory region to add to the slot. 1938c2ecf20Sopenharmony_ci */ 1948c2ecf20Sopenharmony_cistruct slot_add_mem_req { 1958c2ecf20Sopenharmony_ci u64 slot_uid; 1968c2ecf20Sopenharmony_ci u64 paddr; 1978c2ecf20Sopenharmony_ci u64 size; 1988c2ecf20Sopenharmony_ci}; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci/** 2018c2ecf20Sopenharmony_ci * struct slot_add_vcpu_req - SLOT_ADD_VCPU request. 2028c2ecf20Sopenharmony_ci * @slot_uid: Slot unique id mapped to the slot to add the vCPU to. 2038c2ecf20Sopenharmony_ci * @vcpu_id: vCPU ID of the CPU to add to the enclave. 2048c2ecf20Sopenharmony_ci * @padding: Padding for the overall data structure. 2058c2ecf20Sopenharmony_ci */ 2068c2ecf20Sopenharmony_cistruct slot_add_vcpu_req { 2078c2ecf20Sopenharmony_ci u64 slot_uid; 2088c2ecf20Sopenharmony_ci u32 vcpu_id; 2098c2ecf20Sopenharmony_ci u8 padding[4]; 2108c2ecf20Sopenharmony_ci}; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci/** 2138c2ecf20Sopenharmony_ci * struct slot_count_req - SLOT_COUNT request. 2148c2ecf20Sopenharmony_ci * @unused: In order to avoid weird sizeof edge cases. 2158c2ecf20Sopenharmony_ci */ 2168c2ecf20Sopenharmony_cistruct slot_count_req { 2178c2ecf20Sopenharmony_ci u8 unused; 2188c2ecf20Sopenharmony_ci}; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci/** 2218c2ecf20Sopenharmony_ci * struct next_slot_req - NEXT_SLOT request. 2228c2ecf20Sopenharmony_ci * @slot_uid: Slot unique id of the next slot in the iteration. 2238c2ecf20Sopenharmony_ci */ 2248c2ecf20Sopenharmony_cistruct next_slot_req { 2258c2ecf20Sopenharmony_ci u64 slot_uid; 2268c2ecf20Sopenharmony_ci}; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci/** 2298c2ecf20Sopenharmony_ci * struct slot_info_req - SLOT_INFO request. 2308c2ecf20Sopenharmony_ci * @slot_uid: Slot unique id mapped to the slot to get information about. 2318c2ecf20Sopenharmony_ci */ 2328c2ecf20Sopenharmony_cistruct slot_info_req { 2338c2ecf20Sopenharmony_ci u64 slot_uid; 2348c2ecf20Sopenharmony_ci}; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci/** 2378c2ecf20Sopenharmony_ci * struct slot_add_bulk_vcpus_req - SLOT_ADD_BULK_VCPUS request. 2388c2ecf20Sopenharmony_ci * @slot_uid: Slot unique id mapped to the slot to add vCPUs to. 2398c2ecf20Sopenharmony_ci * @nr_vcpus: Number of vCPUs to add to the slot. 2408c2ecf20Sopenharmony_ci */ 2418c2ecf20Sopenharmony_cistruct slot_add_bulk_vcpus_req { 2428c2ecf20Sopenharmony_ci u64 slot_uid; 2438c2ecf20Sopenharmony_ci u64 nr_vcpus; 2448c2ecf20Sopenharmony_ci}; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci/** 2478c2ecf20Sopenharmony_ci * struct ne_pci_dev_cmd_reply - NE PCI device command reply. 2488c2ecf20Sopenharmony_ci * @rc : Return code of the logic that processed the request. 2498c2ecf20Sopenharmony_ci * @padding0: Padding for the overall data structure. 2508c2ecf20Sopenharmony_ci * @slot_uid: Valid for all commands except SLOT_COUNT. 2518c2ecf20Sopenharmony_ci * @enclave_cid: Valid for ENCLAVE_START command. 2528c2ecf20Sopenharmony_ci * @slot_count : Valid for SLOT_COUNT command. 2538c2ecf20Sopenharmony_ci * @mem_regions: Valid for SLOT_ALLOC and SLOT_INFO commands. 2548c2ecf20Sopenharmony_ci * @mem_size: Valid for SLOT_INFO command. 2558c2ecf20Sopenharmony_ci * @nr_vcpus: Valid for SLOT_INFO command. 2568c2ecf20Sopenharmony_ci * @flags: Valid for SLOT_INFO command. 2578c2ecf20Sopenharmony_ci * @state: Valid for SLOT_INFO command. 2588c2ecf20Sopenharmony_ci * @padding1: Padding for the overall data structure. 2598c2ecf20Sopenharmony_ci */ 2608c2ecf20Sopenharmony_cistruct ne_pci_dev_cmd_reply { 2618c2ecf20Sopenharmony_ci s32 rc; 2628c2ecf20Sopenharmony_ci u8 padding0[4]; 2638c2ecf20Sopenharmony_ci u64 slot_uid; 2648c2ecf20Sopenharmony_ci u64 enclave_cid; 2658c2ecf20Sopenharmony_ci u64 slot_count; 2668c2ecf20Sopenharmony_ci u64 mem_regions; 2678c2ecf20Sopenharmony_ci u64 mem_size; 2688c2ecf20Sopenharmony_ci u64 nr_vcpus; 2698c2ecf20Sopenharmony_ci u64 flags; 2708c2ecf20Sopenharmony_ci u16 state; 2718c2ecf20Sopenharmony_ci u8 padding1[6]; 2728c2ecf20Sopenharmony_ci}; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci/** 2758c2ecf20Sopenharmony_ci * struct ne_pci_dev - Nitro Enclaves (NE) PCI device. 2768c2ecf20Sopenharmony_ci * @cmd_reply_avail: Variable set if a reply has been sent by the 2778c2ecf20Sopenharmony_ci * PCI device. 2788c2ecf20Sopenharmony_ci * @cmd_reply_wait_q: Wait queue for handling command reply from the 2798c2ecf20Sopenharmony_ci * PCI device. 2808c2ecf20Sopenharmony_ci * @enclaves_list: List of the enclaves managed by the PCI device. 2818c2ecf20Sopenharmony_ci * @enclaves_list_mutex: Mutex for accessing the list of enclaves. 2828c2ecf20Sopenharmony_ci * @event_wq: Work queue for handling out-of-band events 2838c2ecf20Sopenharmony_ci * triggered by the Nitro Hypervisor which require 2848c2ecf20Sopenharmony_ci * enclave state scanning and propagation to the 2858c2ecf20Sopenharmony_ci * enclave process. 2868c2ecf20Sopenharmony_ci * @iomem_base : MMIO region of the PCI device. 2878c2ecf20Sopenharmony_ci * @notify_work: Work item for every received out-of-band event. 2888c2ecf20Sopenharmony_ci * @pci_dev_mutex: Mutex for accessing the PCI device MMIO space. 2898c2ecf20Sopenharmony_ci * @pdev: PCI device data structure. 2908c2ecf20Sopenharmony_ci */ 2918c2ecf20Sopenharmony_cistruct ne_pci_dev { 2928c2ecf20Sopenharmony_ci atomic_t cmd_reply_avail; 2938c2ecf20Sopenharmony_ci wait_queue_head_t cmd_reply_wait_q; 2948c2ecf20Sopenharmony_ci struct list_head enclaves_list; 2958c2ecf20Sopenharmony_ci struct mutex enclaves_list_mutex; 2968c2ecf20Sopenharmony_ci struct workqueue_struct *event_wq; 2978c2ecf20Sopenharmony_ci void __iomem *iomem_base; 2988c2ecf20Sopenharmony_ci struct work_struct notify_work; 2998c2ecf20Sopenharmony_ci struct mutex pci_dev_mutex; 3008c2ecf20Sopenharmony_ci struct pci_dev *pdev; 3018c2ecf20Sopenharmony_ci}; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci/** 3048c2ecf20Sopenharmony_ci * ne_do_request() - Submit command request to the PCI device based on the command 3058c2ecf20Sopenharmony_ci * type and retrieve the associated reply. 3068c2ecf20Sopenharmony_ci * @pdev: PCI device to send the command to and receive the reply from. 3078c2ecf20Sopenharmony_ci * @cmd_type: Command type of the request sent to the PCI device. 3088c2ecf20Sopenharmony_ci * @cmd_request: Command request payload. 3098c2ecf20Sopenharmony_ci * @cmd_request_size: Size of the command request payload. 3108c2ecf20Sopenharmony_ci * @cmd_reply: Command reply payload. 3118c2ecf20Sopenharmony_ci * @cmd_reply_size: Size of the command reply payload. 3128c2ecf20Sopenharmony_ci * 3138c2ecf20Sopenharmony_ci * Context: Process context. This function uses the ne_pci_dev mutex to handle 3148c2ecf20Sopenharmony_ci * one command at a time. 3158c2ecf20Sopenharmony_ci * Return: 3168c2ecf20Sopenharmony_ci * * 0 on success. 3178c2ecf20Sopenharmony_ci * * Negative return value on failure. 3188c2ecf20Sopenharmony_ci */ 3198c2ecf20Sopenharmony_ciint ne_do_request(struct pci_dev *pdev, enum ne_pci_dev_cmd_type cmd_type, 3208c2ecf20Sopenharmony_ci void *cmd_request, size_t cmd_request_size, 3218c2ecf20Sopenharmony_ci struct ne_pci_dev_cmd_reply *cmd_reply, 3228c2ecf20Sopenharmony_ci size_t cmd_reply_size); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci/* Nitro Enclaves (NE) PCI device driver */ 3258c2ecf20Sopenharmony_ciextern struct pci_driver ne_pci_driver; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci#endif /* _NE_PCI_DEV_H_ */ 328