win-pvdrivers

view xenpci/xenpci.h @ 464:4f1c7b79948b

Updates to support a different configuration method for xenscsi
author James Harper <james.harper@bendigoit.com.au>
date Thu Nov 27 09:28:00 2008 +1100 (2008-11-27)
parents 605747e0db9c
children 3d4ed6b566a0
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
20 #if !defined(_XENPCI_H_)
21 #define _XENPCI_H_
23 #define __attribute__(arg) /* empty */
24 #define EISCONN 127
26 #include <ntddk.h>
28 #ifdef __MINGW32__
29 #include "../mingw/mingw_extras.h"
30 #else
31 #define DDKAPI
32 #include <wdm.h>
33 //#include <wdf.h>
34 #include <initguid.h>
35 #include <wdmguid.h>
36 #include <errno.h>
37 #define NTSTRSAFE_LIB
38 #include <ntstrsafe.h>
39 #endif
41 #define __DRIVER_NAME "XenPCI"
43 #include <xen_windows.h>
44 #include <memory.h>
45 #include <grant_table.h>
46 #include <event_channel.h>
47 #include <hvm/params.h>
48 #include <hvm/hvm_op.h>
49 #include <sched.h>
50 #include <io/xenbus.h>
52 #include <xen_public.h>
54 //{C828ABE9-14CA-4445-BAA6-82C2376C6518}
55 DEFINE_GUID( GUID_XENPCI_DEVCLASS, 0xC828ABE9, 0x14CA, 0x4445, 0xBA, 0xA6, 0x82, 0xC2, 0x37, 0x6C, 0x65, 0x18);
57 #define XENPCI_POOL_TAG (ULONG) 'XenP'
59 #define NR_RESERVED_ENTRIES 8
60 #define NR_GRANT_FRAMES 32
61 #define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
63 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
65 #define EVT_ACTION_TYPE_EMPTY 0
66 #define EVT_ACTION_TYPE_NORMAL 1
67 #define EVT_ACTION_TYPE_DPC 2
68 #define EVT_ACTION_TYPE_IRQ 3
69 #define EVT_ACTION_TYPE_SUSPEND 4
71 typedef struct _ev_action_t {
72 PKSERVICE_ROUTINE ServiceRoutine;
73 PVOID ServiceContext;
74 CHAR description[128];
75 ULONG type; /* EVT_ACTION_TYPE_* */
76 KDPC Dpc;
77 ULONG vector;
78 ULONG count;
79 PVOID xpdd;
80 } ev_action_t;
82 typedef struct _XENBUS_WATCH_RING
83 {
84 char Path[128];
85 char Token[10];
86 } XENBUS_WATCH_RING;
88 typedef struct _XENBUS_REQ_INFO
89 {
90 int In_Use:1;
91 KEVENT WaitEvent;
92 void *Reply;
93 } XENBUS_REQ_INFO;
95 typedef struct _XENBUS_WATCH_ENTRY {
96 char Path[128];
97 PXENBUS_WATCH_CALLBACK ServiceRoutine;
98 PVOID ServiceContext;
99 int Count;
100 int Active;
101 //int RemovePending;
102 //int Running;
103 //KEVENT CompleteEvent;
104 } XENBUS_WATCH_ENTRY, *PXENBUS_WATCH_ENTRY;
106 #define NR_EVENTS 1024
107 #define WATCH_RING_SIZE 128
108 #define NR_XB_REQS 32
109 #define MAX_WATCH_ENTRIES 128
111 #define CHILD_STATE_EMPTY 0
112 #define CHILD_STATE_DELETED 1
113 #define CHILD_STATE_ADDED 2
115 // TODO: tidy up & organize this struct
117 typedef enum {
118 Unknown = 0,
119 NotStarted,
120 Started,
121 StopPending,
122 Stopped,
123 RemovePending,
124 SurpriseRemovePending,
125 Removed
126 } DEVICE_PNP_STATE;
128 typedef struct
129 {
130 PDEVICE_OBJECT fdo;
131 PDEVICE_OBJECT pdo;
132 PDEVICE_OBJECT lower_do;
134 DEVICE_PNP_STATE current_pnp_state;
135 DEVICE_PNP_STATE previous_pnp_state;
136 DEVICE_POWER_STATE device_power_state;
137 SYSTEM_POWER_STATE system_power_state;
139 ULONG device_usage_paging;
140 ULONG device_usage_dump;
141 ULONG device_usage_hibernation;
142 } XENPCI_COMMON, *PXENPCI_COMMON;
144 static __inline void INIT_PNP_STATE(PXENPCI_COMMON common)
145 {
146 common->current_pnp_state = NotStarted;
147 common->previous_pnp_state = NotStarted;
148 }
150 static __inline void SET_PNP_STATE(PXENPCI_COMMON common, DEVICE_PNP_STATE state)
151 {
152 common->previous_pnp_state = common->current_pnp_state;
153 common->current_pnp_state = state;
154 }
156 static __inline void REVERT_PNP_STATE(PXENPCI_COMMON common)
157 {
158 common->current_pnp_state = common->previous_pnp_state;
159 }
161 #define SHUTDOWN_RING_SIZE 128
163 #define SUSPEND_STATE_NONE 0 /* no suspend in progress */
164 #define SUSPEND_STATE_SCHEDULED 1 /* suspend scheduled */
165 #define SUSPEND_STATE_HIGH_IRQL 2 /* all processors are at high IRQL and spinning */
166 #define SUSPEND_STATE_RESUMING 3 /* we are the other side of the suspend and things are starting to get back to normal */
168 typedef struct {
169 XENPCI_COMMON common;
171 BOOLEAN XenBus_ShuttingDown;
173 PKINTERRUPT interrupt;
174 ULONG irq_number;
175 ULONG irq_vector;
176 KIRQL irq_level;
177 KINTERRUPT_MODE irq_mode;
178 KAFFINITY irq_affinity;
180 PHYSICAL_ADDRESS shared_info_area_unmapped;
181 shared_info_t *shared_info_area;
182 xen_ulong_t evtchn_pending_pvt[sizeof(xen_ulong_t) * 8];
183 xen_ulong_t evtchn_pending_suspend[sizeof(xen_ulong_t) * 8];
184 evtchn_port_t suspend_evtchn;
185 BOOLEAN interrupts_masked;
187 PHYSICAL_ADDRESS platform_mmio_addr;
188 ULONG platform_mmio_orig_len;
189 ULONG platform_mmio_len;
190 ULONG platform_mmio_alloc;
191 USHORT platform_mmio_flags;
193 ULONG platform_ioport_addr;
194 ULONG platform_ioport_len;
196 char *hypercall_stubs;
198 evtchn_port_t xen_store_evtchn;
200 grant_entry_t *gnttab_table;
201 PHYSICAL_ADDRESS gnttab_table_physical;
202 grant_ref_t *gnttab_list;
203 int gnttab_list_free;
204 /* this is the maximum number of grant frames we have memory allocated for */
205 /* after a resume it may not be the actual number of grant frames we have though */
206 ULONG max_grant_frames;
208 ev_action_t ev_actions[NR_EVENTS];
209 // unsigned long bound_ports[NR_EVENTS/(8*sizeof(unsigned long))];
211 PKTHREAD XenBus_ReadThread;
212 KEVENT XenBus_ReadThreadEvent;
213 PKTHREAD XenBus_WatchThread;
214 KEVENT XenBus_WatchThreadEvent;
216 KSPIN_LOCK xenbus_id_lock;
217 KEVENT xenbus_id_event;
219 XENBUS_WATCH_RING XenBus_WatchRing[WATCH_RING_SIZE];
220 int XenBus_WatchRingReadIndex;
221 int XenBus_WatchRingWriteIndex;
223 struct xenstore_domain_interface *xen_store_interface;
225 XENBUS_REQ_INFO req_info[NR_XB_REQS];
226 int nr_live_reqs;
227 XENBUS_WATCH_ENTRY XenBus_WatchEntries[MAX_WATCH_ENTRIES];
229 FAST_MUTEX watch_mutex;
230 FAST_MUTEX xenbus_mutex;
231 KSPIN_LOCK grant_lock;
233 //KGUARDED_MUTEX WatchHandlerMutex;
235 LIST_ENTRY child_list;
237 int suspend_state;
239 UNICODE_STRING interface_name;
240 BOOLEAN interface_open;
242 KSPIN_LOCK shutdown_ring_lock;
243 CHAR shutdown_ring[SHUTDOWN_RING_SIZE];
244 ULONG shutdown_prod;
245 ULONG shutdown_cons;
246 ULONG shutdown_start; /* the start of the most recent message on the ring */
247 PIRP shutdown_irp;
249 BOOLEAN log_interrupts;
250 } XENPCI_DEVICE_DATA, *PXENPCI_DEVICE_DATA;
252 typedef struct {
253 XENPCI_COMMON common;
254 PDEVICE_OBJECT bus_pdo;
255 PDEVICE_OBJECT bus_fdo;
256 BOOLEAN reported_missing;
257 char path[128];
258 char device[128];
259 ULONG index;
260 ULONG irq_number;
261 ULONG irq_vector;
262 KIRQL irq_level;
263 char backend_path[128];
264 //PVOID xenbus_request;
265 KEVENT backend_state_event;
266 ULONG backend_state;
267 PHYSICAL_ADDRESS config_page_phys;
268 ULONG config_page_length;
269 PUCHAR requested_resources_start;
270 PUCHAR requested_resources_ptr;
271 PUCHAR assigned_resources_start;
272 PUCHAR assigned_resources_ptr;
273 XENPCI_DEVICE_STATE device_state;
274 BOOLEAN restart_on_resume;
275 PXEN_COMM_IFACE comm_iface;
276 KSPIN_LOCK comm_iface_spinlock;
277 USHORT req_cons;
278 } XENPCI_PDO_DEVICE_DATA, *PXENPCI_PDO_DEVICE_DATA;
280 typedef struct
281 {
282 LIST_ENTRY entry;
283 int state;
284 PXENPCI_PDO_DEVICE_DATA context;
285 } XEN_CHILD, *PXEN_CHILD;
287 #ifdef __GNUC__
288 #define SWINT(x) if (intno == x) { asm ("int $"#x";"); return;}
289 #else
290 #define SWINT(x) if (intno == x) { __asm { int x } return; }
291 #endif
293 #if 0
294 #if defined(_X86_)
295 static __inline VOID
296 sw_interrupt(UCHAR intno)
297 {
298 //KdPrint((__DRIVER_NAME " Calling interrupt %02X\n", intno));
299 SWINT(0x10) SWINT(0x11) SWINT(0x12) SWINT(0x13) SWINT(0x14) SWINT(0x15) SWINT(0x16) SWINT(0x17)
300 SWINT(0x18) SWINT(0x19) SWINT(0x1A) SWINT(0x1B) SWINT(0x1C) SWINT(0x1D) SWINT(0x1E) SWINT(0x1F)
301 SWINT(0x20) SWINT(0x21) SWINT(0x22) SWINT(0x23) SWINT(0x24) SWINT(0x25) SWINT(0x26) SWINT(0x27)
302 SWINT(0x28) SWINT(0x29) SWINT(0x2A) SWINT(0x2B) SWINT(0x2C) SWINT(0x2D) SWINT(0x2E) SWINT(0x2F)
303 SWINT(0x30) SWINT(0x31) SWINT(0x32) SWINT(0x33) SWINT(0x34) SWINT(0x35) SWINT(0x36) SWINT(0x37)
304 SWINT(0x38) SWINT(0x39) SWINT(0x3A) SWINT(0x3B) SWINT(0x3C) SWINT(0x3D) SWINT(0x3E) SWINT(0x3F)
305 SWINT(0x40) SWINT(0x41) SWINT(0x42) SWINT(0x43) SWINT(0x44) SWINT(0x45) SWINT(0x46) SWINT(0x47)
306 SWINT(0x48) SWINT(0x49) SWINT(0x4A) SWINT(0x4B) SWINT(0x4C) SWINT(0x4D) SWINT(0x4E) SWINT(0x4F)
307 SWINT(0x50) SWINT(0x51) SWINT(0x52) SWINT(0x53) SWINT(0x54) SWINT(0x55) SWINT(0x56) SWINT(0x57)
308 SWINT(0x58) SWINT(0x59) SWINT(0x5A) SWINT(0x5B) SWINT(0x5C) SWINT(0x5D) SWINT(0x5E) SWINT(0x5F)
309 SWINT(0x60) SWINT(0x61) SWINT(0x62) SWINT(0x63) SWINT(0x64) SWINT(0x65) SWINT(0x66) SWINT(0x67)
310 SWINT(0x68) SWINT(0x69) SWINT(0x6A) SWINT(0x6B) SWINT(0x6C) SWINT(0x6D) SWINT(0x6E) SWINT(0x6F)
311 SWINT(0x70) SWINT(0x71) SWINT(0x72) SWINT(0x73) SWINT(0x74) SWINT(0x75) SWINT(0x76) SWINT(0x77)
312 SWINT(0x78) SWINT(0x79) SWINT(0x7A) SWINT(0x7B) SWINT(0x7C) SWINT(0x7D) SWINT(0x7E) SWINT(0x7F)
313 SWINT(0x80) SWINT(0x81) SWINT(0x82) SWINT(0x83) SWINT(0x84) SWINT(0x85) SWINT(0x86) SWINT(0x87)
314 SWINT(0x88) SWINT(0x89) SWINT(0x8A) SWINT(0x8B) SWINT(0x8C) SWINT(0x8D) SWINT(0x8E) SWINT(0x8F)
315 SWINT(0x90) SWINT(0x91) SWINT(0x92) SWINT(0x93) SWINT(0x94) SWINT(0x95) SWINT(0x96) SWINT(0x97)
316 SWINT(0x98) SWINT(0x99) SWINT(0x9A) SWINT(0x9B) SWINT(0x9C) SWINT(0x9D) SWINT(0x9E) SWINT(0x9F)
317 SWINT(0xA0) SWINT(0xA1) SWINT(0xA2) SWINT(0xA3) SWINT(0xA4) SWINT(0xA5) SWINT(0xA6) SWINT(0xA7)
318 SWINT(0xA8) SWINT(0xA9) SWINT(0xAA) SWINT(0xAB) SWINT(0xAC) SWINT(0xAD) SWINT(0xAE) SWINT(0xAF)
319 SWINT(0xB0) SWINT(0xB1) SWINT(0xB2) SWINT(0xB3) SWINT(0xB4) SWINT(0xB5) SWINT(0xB6) SWINT(0xB7)
320 SWINT(0xB8) SWINT(0xB9) SWINT(0xBA) SWINT(0xBB) SWINT(0xBC) SWINT(0xBD) SWINT(0xBE) SWINT(0xBF)
321 SWINT(0xC0) SWINT(0xC1) SWINT(0xC2) SWINT(0xC3) SWINT(0xC4) SWINT(0xC5) SWINT(0xC6) SWINT(0xC7)
322 SWINT(0xC8) SWINT(0xC9) SWINT(0xCA) SWINT(0xCB) SWINT(0xCC) SWINT(0xCD) SWINT(0xCE) SWINT(0xCF)
323 SWINT(0xD0) SWINT(0xD1) SWINT(0xD2) SWINT(0xD3) SWINT(0xD4) SWINT(0xD5) SWINT(0xD6) SWINT(0xD7)
324 SWINT(0xD8) SWINT(0xD9) SWINT(0xDA) SWINT(0xDB) SWINT(0xDC) SWINT(0xDD) SWINT(0xDE) SWINT(0xDF)
325 SWINT(0xE0) SWINT(0xE1) SWINT(0xE2) SWINT(0xE3) SWINT(0xE4) SWINT(0xE5) SWINT(0xE6) SWINT(0xE7)
326 SWINT(0xE8) SWINT(0xE9) SWINT(0xEA) SWINT(0xEB) SWINT(0xEC) SWINT(0xED) SWINT(0xEE) SWINT(0xEF)
327 SWINT(0xF0) SWINT(0xF1) SWINT(0xF2) SWINT(0xF3) SWINT(0xF4) SWINT(0xF5) SWINT(0xF6) SWINT(0xF7)
328 SWINT(0xF8) SWINT(0xF9) SWINT(0xFA) SWINT(0xFB) SWINT(0xFC) SWINT(0xFD) SWINT(0xFE) SWINT(0xFF)
330 /* not found */
331 KdPrint((__DRIVER_NAME " interrupt %02X not set up. Blame James.\n", intno));
332 KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000002, (ULONG)intno, 0x00000000, 0x00000000);
333 }
334 #else
335 VOID _sw_interrupt(UCHAR);
337 static __inline VOID
338 sw_interrupt(UCHAR intno)
339 {
340 _sw_interrupt(intno);
341 }
342 #endif
343 #endif
345 #include "hypercall.h"
347 #define XBT_NIL ((xenbus_transaction_t)0)
349 static __inline VOID
350 XenPci_FreeMem(PVOID Ptr)
351 {
352 ExFreePoolWithTag(Ptr, XENPCI_POOL_TAG);
353 }
355 NTSTATUS
356 hvm_get_stubs(PXENPCI_DEVICE_DATA xpdd);
357 NTSTATUS
358 hvm_free_stubs(PXENPCI_DEVICE_DATA xpdd);
360 NTSTATUS
361 XenPci_Power_Fdo(PDEVICE_OBJECT device_object, PIRP irp);
362 NTSTATUS
363 XenPci_Dummy_Fdo(PDEVICE_OBJECT device_object, PIRP irp);
364 NTSTATUS
365 XenPci_Pnp_Fdo(PDEVICE_OBJECT device_object, PIRP irp);
366 NTSTATUS
367 XenPci_Irp_Create_Fdo(PDEVICE_OBJECT device_object, PIRP irp);
368 NTSTATUS
369 XenPci_Irp_Close_Fdo(PDEVICE_OBJECT device_object, PIRP irp);
370 NTSTATUS
371 XenPci_Irp_Read_Fdo(PDEVICE_OBJECT device_object, PIRP irp);
372 NTSTATUS
373 XenPci_Irp_Cleanup_Fdo(PDEVICE_OBJECT device_object, PIRP irp);
374 NTSTATUS
375 XenPci_SystemControl_Fdo(PDEVICE_OBJECT device_object, PIRP irp);
377 NTSTATUS
378 XenPci_Power_Pdo(PDEVICE_OBJECT device_object, PIRP irp);
379 //NTSTATUS
380 //XenPci_Dummy_Pdo(PDEVICE_OBJECT device_object, PIRP irp);
381 NTSTATUS
382 XenPci_Pnp_Pdo(PDEVICE_OBJECT device_object, PIRP irp);
383 NTSTATUS
384 XenPci_Irp_Create_Pdo(PDEVICE_OBJECT device_object, PIRP irp);
385 NTSTATUS
386 XenPci_Irp_Close_Pdo(PDEVICE_OBJECT device_object, PIRP irp);
387 NTSTATUS
388 XenPci_Irp_Read_Pdo(PDEVICE_OBJECT device_object, PIRP irp);
389 NTSTATUS
390 XenPci_Irp_Cleanup_Pdo(PDEVICE_OBJECT device_object, PIRP irp);
391 NTSTATUS
392 XenPci_SystemControl_Pdo(PDEVICE_OBJECT device_object, PIRP irp);
394 NTSTATUS
395 XenPci_Pdo_Suspend(PDEVICE_OBJECT device_object);
396 NTSTATUS
397 XenPci_Pdo_Resume(PDEVICE_OBJECT device_object);
399 VOID
400 XenPci_DumpPdoConfig(PDEVICE_OBJECT device_object);
402 char *
403 XenBus_Read(PVOID Context, xenbus_transaction_t xbt, const char *path, char **value);
404 char *
405 XenBus_Write(PVOID Context, xenbus_transaction_t xbt, const char *path, const char *value);
406 char *
407 XenBus_Printf(PVOID Context, xenbus_transaction_t xbt, const char *path, const char *fmt, ...);
408 char *
409 XenBus_StartTransaction(PVOID Context, xenbus_transaction_t *xbt);
410 char *
411 XenBus_EndTransaction(PVOID Context, xenbus_transaction_t t, int abort, int *retry);
412 char *
413 XenBus_List(PVOID Context, xenbus_transaction_t xbt, const char *prefix, char ***contents);
414 char *
415 XenBus_AddWatch(PVOID Context, xenbus_transaction_t xbt, const char *Path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext);
416 char *
417 XenBus_RemWatch(PVOID Context, xenbus_transaction_t xbt, const char *Path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext);
418 //VOID
419 //XenBus_ThreadProc(PVOID StartContext);
420 NTSTATUS
421 XenBus_Init(PXENPCI_DEVICE_DATA xpdd);
422 NTSTATUS
423 XenBus_Close(PXENPCI_DEVICE_DATA xpdd);
424 NTSTATUS
425 XenBus_Start(PXENPCI_DEVICE_DATA xpdd);
426 NTSTATUS
427 XenBus_Stop(PXENPCI_DEVICE_DATA xpdd);
428 NTSTATUS
429 XenBus_Suspend(PXENPCI_DEVICE_DATA xpdd);
430 NTSTATUS
431 XenBus_Resume(PXENPCI_DEVICE_DATA xpdd);
432 NTSTATUS
433 XenBus_StopThreads(PXENPCI_DEVICE_DATA xpdd);
435 PHYSICAL_ADDRESS
436 XenPci_AllocMMIO(PXENPCI_DEVICE_DATA xpdd, ULONG len);
438 NTSTATUS
439 EvtChn_Init(PXENPCI_DEVICE_DATA xpdd);
440 NTSTATUS
441 EvtChn_ConnectInterrupt(PXENPCI_DEVICE_DATA xpdd);
442 NTSTATUS
443 EvtChn_Shutdown(PXENPCI_DEVICE_DATA xpdd);
445 NTSTATUS
446 EvtChn_Mask(PVOID Context, evtchn_port_t Port);
447 NTSTATUS
448 EvtChn_Unmask(PVOID Context, evtchn_port_t Port);
449 NTSTATUS
450 EvtChn_Bind(PVOID Context, evtchn_port_t Port, PKSERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext);
451 NTSTATUS
452 EvtChn_BindDpc(PVOID Context, evtchn_port_t Port, PKSERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext);
453 NTSTATUS
454 EvtChn_BindIrq(PVOID Context, evtchn_port_t Port, ULONG vector, PCHAR description);
455 evtchn_port_t
456 EvtChn_AllocIpi(PVOID context, ULONG vcpu);
457 NTSTATUS
458 EvtChn_Unbind(PVOID Context, evtchn_port_t Port);
459 NTSTATUS
460 EvtChn_Notify(PVOID Context, evtchn_port_t Port);
461 VOID
462 EvtChn_Close(PVOID Context, evtchn_port_t Port);
463 evtchn_port_t
464 EvtChn_AllocUnbound(PVOID Context, domid_t Domain);
465 BOOLEAN
466 EvtChn_AckEvent(PVOID context, evtchn_port_t port);
468 VOID
469 GntTbl_Init(PXENPCI_DEVICE_DATA xpdd);
470 VOID
471 GntTbl_InitMap(PXENPCI_DEVICE_DATA xpdd);
472 grant_ref_t
473 GntTbl_GrantAccess(PVOID Context, domid_t domid, uint32_t, int readonly, grant_ref_t ref);
474 BOOLEAN
475 GntTbl_EndAccess(PVOID Context, grant_ref_t ref, BOOLEAN keepref);
476 VOID
477 GntTbl_PutRef(PVOID Context, grant_ref_t ref);
478 grant_ref_t
479 GntTbl_GetRef(PVOID Context);
480 int
481 GntTbl_Map(PVOID Context, unsigned int start_idx, unsigned int end_idx);
482 #endif